* COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
* PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
* FILE: dirctl.c
- * PURPOSE:
+ * PURPOSE:
* PROGRAMMER: Mark Piper, Matt Wu, Bo Brantén.
- * HOMEPAGE:
- * UPDATE HISTORY:
+ * HOMEPAGE:
+ * UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
PVOID pContext);
typedef struct _RFSD_CALLBACK_CONTEXT {
-
- PRFSD_VCB Vcb;
+
+ PRFSD_VCB Vcb;
PRFSD_CCB Ccb;
PRFSD_KEY_IN_MEMORY pDirectoryKey;
ULONG idxStartingDentry; // The dentry at which the callback should beging triggering output to the Buffer
ULONG idxCurrentDentry; // The current dentry (relative to entire set of dentrys, across all spans)
- // These parameters are forwarded to ProcessDirectoryEntry
+ // These parameters are forwarded to ProcessDirectoryEntry
FILE_INFORMATION_CLASS FileInformationClass; // [s]
PVOID Buffer; // [s]
ULONG BufferLength; // [s]
BOOLEAN ReturnSingleEntry; // [s]
- PULONG pUsedLength;
- PVOID pPreviousEntry;
-
+ PULONG pUsedLength;
+ PVOID pPreviousEntry;
+
} RFSD_CALLBACK_CONTEXT, *PRFSD_CALLBACK_CONTEXT;
#ifdef ALLOC_PRAGMA
case FileDirectoryInformation:
return sizeof(FILE_DIRECTORY_INFORMATION);
break;
-
+
case FileFullDirectoryInformation:
return sizeof(FILE_FULL_DIR_INFORMATION);
break;
-
+
case FileBothDirectoryInformation:
return sizeof(FILE_BOTH_DIR_INFORMATION);
break;
-
+
case FileNamesInformation:
return sizeof(FILE_NAMES_INFORMATION);
break;
-
+
default:
break;
}
}
// Given the incoming key for this dentry, load the corresponding stat data.
- {
- RFSD_KEY_IN_MEMORY key;
- key.k_dir_id = Key_ParentDirectoryID;
- key.k_objectid = Key_ObjectID;
+ {
+ RFSD_KEY_IN_MEMORY key;
+ key.k_dir_id = Key_ParentDirectoryID;
+ key.k_objectid = Key_ObjectID;
if(!RfsdLoadInode(Vcb, &key, &inode)) {
RfsdPrint((DBG_ERROR, "RfsdPricessDirEntry: Loading stat data %xh, %xh error.\n", Key_ParentDirectoryID, Key_ObjectID));
// Link the previous entry into this entry
if (pPreviousEntry) {
// NOTE: All entries begin with NextEntryOffset, so it doesn't matter what type I cast to.
- ((PFILE_NAMES_INFORMATION) (pPreviousEntry))->NextEntryOffset =
+ ((PFILE_NAMES_INFORMATION) (pPreviousEntry))->NextEntryOffset =
(ULONG) ((PUCHAR) Buffer + UsedLength - (PUCHAR) (pPreviousEntry));
}
FDI->FileNameLength = NameLength;
RtlCopyMemory(FDI->FileName, pName->Buffer, NameLength);
- dwBytes = InfoLength + NameLength - sizeof(WCHAR);
+ dwBytes = InfoLength + NameLength - sizeof(WCHAR);
break;
-
+
case FileFullDirectoryInformation:
FFI = (PFILE_FULL_DIR_INFORMATION) ((PUCHAR)Buffer + UsedLength);
FFI->FileNameLength = NameLength;
RtlCopyMemory(FFI->FileName, pName->Buffer, NameLength);
- dwBytes = InfoLength + NameLength - sizeof(WCHAR);
+ dwBytes = InfoLength + NameLength - sizeof(WCHAR);
break;
-
+
case FileBothDirectoryInformation:
FBI = (PFILE_BOTH_DIR_INFORMATION) ((PUCHAR)Buffer + UsedLength);
FBI->FileNameLength = NameLength;
RtlCopyMemory(FBI->FileName, pName->Buffer, NameLength);
- dwBytes = InfoLength + NameLength - sizeof(WCHAR);
+ dwBytes = InfoLength + NameLength - sizeof(WCHAR);
break;
-
+
case FileNamesInformation:
- FNI = (PFILE_NAMES_INFORMATION) ((PUCHAR)Buffer + UsedLength);
+ FNI = (PFILE_NAMES_INFORMATION) ((PUCHAR)Buffer + UsedLength);
FNI->NextEntryOffset = 0;
FNI->FileNameLength = NameLength;
RtlCopyMemory(FNI->FileName, pName->Buffer, NameLength);
- dwBytes = InfoLength + NameLength - sizeof(WCHAR);
+ dwBytes = InfoLength + NameLength - sizeof(WCHAR);
break;
-
+
default:
break;
}
_SEH2_TRY {
ASSERT(IrpContext);
-
+
ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
(IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
-
+
DeviceObject = IrpContext->DeviceObject;
-
+
//
// This request is not allowed on the main device object
//
Status = STATUS_INVALID_DEVICE_REQUEST;
_SEH2_LEAVE;
}
-
+
Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
-
+
ASSERT(Vcb != NULL);
-
+
ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
(Vcb->Identifier.Size == sizeof(RFSD_VCB)));
ASSERT(IsMounted(Vcb));
FileObject = IrpContext->FileObject;
-
+
Fcb = (PRFSD_FCB) FileObject->FsContext;
pQueryKey = &(Fcb->RfsdMcb->Key);
-
+
ASSERT(Fcb);
-
- KdPrint(("QueryDirectory on Key {%x,%x,%x,%x}\n",
+
+ KdPrint(("QueryDirectory on Key {%x,%x,%x,%x}\n",
pQueryKey->k_dir_id, pQueryKey->k_objectid, pQueryKey->k_offset, pQueryKey->k_type));
//
Status = STATUS_INVALID_PARAMETER;
_SEH2_LEAVE;
}
-
+
ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
(Fcb->Identifier.Size == sizeof(RFSD_FCB)));
-
+
if (!IsDirectory(Fcb)) {
Status = STATUS_INVALID_PARAMETER;
_SEH2_LEAVE;
}
-
+
Ccb = (PRFSD_CCB) FileObject->FsContext2;
-
+
ASSERT(Ccb);
-
+
ASSERT((Ccb->Identifier.Type == RFSDCCB) &&
(Ccb->Identifier.Size == sizeof(RFSD_CCB)));
-
+
Irp = IrpContext->Irp;
-
+
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
-
+
#ifndef _GNU_NTIFS_
-
+
FileInformationClass =
IoStackLocation->Parameters.QueryDirectory.FileInformationClass;
-
+
Length = IoStackLocation->Parameters.QueryDirectory.Length;
-
+
FileName = IoStackLocation->Parameters.QueryDirectory.FileName;
-
+
FileIndex = IoStackLocation->Parameters.QueryDirectory.FileIndex;
RestartScan = FlagOn(IoStackLocation->Flags, SL_RESTART_SCAN);
ReturnSingleEntry = FlagOn(IoStackLocation->Flags, SL_RETURN_SINGLE_ENTRY);
IndexSpecified = FlagOn(IoStackLocation->Flags, SL_INDEX_SPECIFIED);
-
+
#else // _GNU_NTIFS_
-
+
FileInformationClass = ((PEXTENDED_IO_STACK_LOCATION)
IoStackLocation)->Parameters.QueryDirectory.FileInformationClass;
-
+
Length = ((PEXTENDED_IO_STACK_LOCATION)
IoStackLocation)->Parameters.QueryDirectory.Length;
-
+
FileName = ((PEXTENDED_IO_STACK_LOCATION)
IoStackLocation)->Parameters.QueryDirectory.FileName;
-
+
FileIndex = ((PEXTENDED_IO_STACK_LOCATION)
IoStackLocation)->Parameters.QueryDirectory.FileIndex;
IndexSpecified = FlagOn(((PEXTENDED_IO_STACK_LOCATION)
IoStackLocation)->Flags, SL_INDEX_SPECIFIED);
-
+
#endif // _GNU_NTIFS_
-
+
/*
if (!Irp->MdlAddress && Irp->UserBuffer) {
ProbeForWrite(Irp->UserBuffer, Length, 1);
Status = STATUS_INVALID_USER_BUFFER;
_SEH2_LEAVE;
}
-
+
// Check if we have a synchronous or asynchronous request...
if (!IrpContext->IsSynchronous) {
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
-
+
if (!ExAcquireResourceSharedLite(
&Fcb->MainResource,
IrpContext->IsSynchronous )) {
}
FcbResourceAcquired = TRUE;
-
+
if (FileName != NULL) {
// The caller provided a FileName to search on...
FirstQuery = FALSE;
} else {
FirstQuery = TRUE;
-
+
// Set up the DirectorySearchPattern to simply be an uppercase copy of the FileName.
Ccb->DirectorySearchPattern.Length =
Ccb->DirectorySearchPattern.MaximumLength =
FileName->Length;
-
+
Ccb->DirectorySearchPattern.Buffer =
ExAllocatePoolWithTag(PagedPool, FileName->Length, RFSD_POOL_TAG);
-
+
if (Ccb->DirectorySearchPattern.Buffer == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
_SEH2_LEAVE;
// (The FileName and CCB's DirectorySearchPattern were null)
FirstQuery = TRUE;
-
+
Ccb->DirectorySearchPattern.Length =
Ccb->DirectorySearchPattern.MaximumLength = 2;
-
+
Ccb->DirectorySearchPattern.Buffer =
ExAllocatePoolWithTag(PagedPool, 2, RFSD_POOL_TAG);
-
+
if (Ccb->DirectorySearchPattern.Buffer == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
_SEH2_LEAVE;
}
-
+
RtlCopyMemory(
Ccb->DirectorySearchPattern.Buffer,
L"*\0", 2);
}
-
+
if (!IndexSpecified) {
if (RestartScan || FirstQuery) {
FileIndex = Fcb->RfsdMcb->DeOffset = 0;
FileIndex = Ccb->CurrentByteOffset;
}
}
-
-
+
+
RtlZeroMemory(Buffer, Length);
// Leave if a previous query has already read the entire contents of the directory
if (Fcb->Inode->i_size <= FileIndex) {
Status = STATUS_NO_MORE_FILES;
_SEH2_LEAVE;
- }
-
- ////////
-
+ }
+
+ ////////
+
// Construct a context for the call, and call to parse the entire file system tree.
// A callback will be triggered on any direntry span belonging to DirectoryKey.
// This callback will fill the requested section of the user buffer.
RfsdParseFilesystemTree(Vcb, pQueryKey, Vcb->SuperBlock->s_root_block, &RfsdDirectoryCallback, &CallbackContext);
}
-
+
//================================================================
if (!UsedLength) {
}
} _SEH2_FINALLY {
-
+
if (FcbResourceAcquired) {
ExReleaseResourceForThreadLite(
&Fcb->MainResource,
ExGetCurrentResourceThread() );
}
-
+
if (!IrpContext->ExceptionInProgress) {
if (Status == STATUS_PENDING) {
Status = RfsdLockUserBuffer(
IrpContext->Irp,
Length,
IoWriteAccess );
-
+
if (NT_SUCCESS(Status)) {
Status = RfsdQueueRequest(IrpContext);
} else {
}
}
} _SEH2_END;
-
+
return Status;
}
ASSERT(Fcb);
if (Fcb->Identifier.Type == RFSDVCB) {
- DbgBreak();
+ DbgBreak();
CompleteRequest = TRUE;
Status = STATUS_INVALID_PARAMETER;
_SEH2_LEAVE;
}
}
- Offset = (USHORT) ( FullName->Length -
+ Offset = (USHORT) ( FullName->Length -
Fcb->RfsdMcb->ShortName.Length);
FsRtlNotifyFullReportChange( Vcb->NotifySync,
PAGED_CODE();
ASSERT(IrpContext);
-
+
ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
(IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
-
+
switch (IrpContext->MinorFunction) {
case IRP_MN_QUERY_DIRECTORY:
case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
Status = RfsdNotifyChangeDirectory(IrpContext);
break;
-
+
default:
Status = STATUS_INVALID_DEVICE_REQUEST;
RfsdCompleteIrpContext(IrpContext, Status);
}
-
+
return Status;
}
Status = STATUS_INSUFFICIENT_RESOURCES;
_SEH2_LEAVE;
}
-
+
dwBytes = 0;
bRet = TRUE;
if (pTarget->inode) {
if (pTarget->name_len == 1 && pTarget->name[0] == '.') {
- } else if (pTarget->name_len == 2 && pTarget->name[0] == '.' &&
+ } else if (pTarget->name_len == 2 && pTarget->name[0] == '.' &&
pTarget->name[1] == '.') {
} else {
bRet = FALSE;
// Load the block
pBlockBuffer = RfsdAllocateAndLoadBlock(pCallbackContext->Vcb, BlockNumber);
- if (!pBlockBuffer) { Status = STATUS_INSUFFICIENT_RESOURCES; goto out; }
+ if (!pBlockBuffer) { Status = STATUS_INSUFFICIENT_RESOURCES; goto out; }
// Construct the item key to search for
DirectoryKey = *(pCallbackContext->pDirectoryKey);
// Get the item header and its information
Status = RfsdFindItemHeaderInBlock(
pCallbackContext->Vcb, &DirectoryKey, pBlockBuffer,
- ( &pDirectoryItemHeader ), //<
+ ( &pDirectoryItemHeader ), //<
&CompareKeysWithoutOffset
- );
+ );
// If this block doesn't happen to contain a directory item, skip it.
if ( (Status == STATUS_NO_SUCH_MEMBER) || !pDirectoryItemHeader )
- {
+ {
KdPrint(("Block %i did not contain the appropriate diritem header\n", BlockNumber));
- Status = STATUS_SUCCESS; goto out;
+ Status = STATUS_SUCCESS; goto out;
}
-
+
RfsdPrint((DBG_INFO, "Found %i dentries in block\n", pDirectoryItemHeader->u.ih_entry_count));
// Calculate if the requested result will be from this dentry span
// If the end of this span is not greater than the requested start, it can be skipped.
if ( !( (pCallbackContext->idxCurrentDentry + (USHORT)(pDirectoryItemHeader->u.ih_entry_count)) > pCallbackContext->idxStartingDentry ) )
- {
+ {
RfsdPrint((DBG_TRACE, "SKIPPING block\n"));
pCallbackContext->idxCurrentDentry += pDirectoryItemHeader->u.ih_entry_count;
// Skip ahead to the starting dentry in this span.
ULONG idxDentryInSpan = pCallbackContext->idxStartingDentry - pCallbackContext->idxCurrentDentry;
pCallbackContext->idxCurrentDentry += idxDentryInSpan;
-
+
RfsdPrint((DBG_TRACE, "Sarting dentry: %i. skipped to %i dentry in span\n", pCallbackContext->idxStartingDentry, idxDentryInSpan));
-
+
offsetDentry_toSequentialSpan = pCallbackContext->idxCurrentDentry * sizeof(RFSD_DENTRY_HEAD);
// Setup the item buffer
- pDirectoryItemBuffer = (PUCHAR) pBlockBuffer + pDirectoryItemHeader->ih_item_location;
+ pDirectoryItemBuffer = (PUCHAR) pBlockBuffer + pDirectoryItemHeader->ih_item_location;
while (bRun
PRFSD_DENTRY_HEAD pCurrentDentry;
USHORT InodeFileNameLength = 0;
- // Read a directory entry from the buffered directory item (from the file associated with the filled inode)
- pCurrentDentry = (PRFSD_DENTRY_HEAD) (pDirectoryItemBuffer + (idxDentryInSpan * sizeof(RFSD_DENTRY_HEAD) ));
-
+ // Read a directory entry from the buffered directory item (from the file associated with the filled inode)
+ pCurrentDentry = (PRFSD_DENTRY_HEAD) (pDirectoryItemBuffer + (idxDentryInSpan * sizeof(RFSD_DENTRY_HEAD) ));
+
// Skip the directory entry for the parent of the root directory (because it should not be shown, and has no stat data)
// (NOTE: Any change made here should also be mirrored in RfsdScanDirCallback)
if (pCurrentDentry->deh_dir_id == 0 /*&& pCurrentDentry->deh_objectid == 1*/)
{ goto ProcessNextEntry; }
-
+
// Pull the name of the file out from the buffer.
// NOTE: The filename is not gauranteed to be null-terminated, and so the end may implicitly be the start of the previous entry.
OemName.Buffer = (PUCHAR) pDirectoryItemBuffer + pCurrentDentry->deh_location;
// Calculate the name's unicode length, allocate memory, and convert the codepaged name to unicode
- InodeFileNameLength = (USHORT) RfsdOEMToUnicodeSize(&OemName);
+ InodeFileNameLength = (USHORT) RfsdOEMToUnicodeSize(&OemName);
InodeFileName.Length = 0;
InodeFileName.MaximumLength = InodeFileNameLength + 2;
-
- if (InodeFileNameLength <= 0)
+
+ if (InodeFileNameLength <= 0)
{ break; }
InodeFileName.Buffer = ExAllocatePoolWithTag(
}
RtlZeroMemory(InodeFileName.Buffer, InodeFileNameLength + 2);
-
+
Status = RfsdOEMToUnicode( &InodeFileName, &OemName );
- if (!NT_SUCCESS(Status)) { Status = STATUS_INTERNAL_ERROR; goto out; } // TODO: CHECK IF TIHS OK
+ if (!NT_SUCCESS(Status)) { Status = STATUS_INTERNAL_ERROR; goto out; } // TODO: CHECK IF TIHS OK
////////////// END OF MY PART
if (FsRtlDoesNameContainWildCards(
&InodeFileName,
TRUE) ) {
// The name either contains wild cards, or matches the directory search pattern...
-
+
{
ULONG dwBytesWritten;
dwBytesWritten = RfsdProcessDirEntry(
}
}
}
-
+
if (InodeFileName.Buffer) {
ExFreePool(InodeFileName.Buffer);
InodeFileName.Buffer = NULL;
}
- ProcessNextEntry:
+ ProcessNextEntry:
pPrevDentry = pCurrentDentry;
if (bRun)
{
- ++idxDentryInSpan;
+ ++idxDentryInSpan;
++(pCallbackContext->idxCurrentDentry);
++(pCallbackContext->idxStartingDentry);
offsetDentry_toSequentialSpan += sizeof(RFSD_DENTRY_HEAD);
// Store the current position, so that it will be available for the next call
pCallbackContext->Ccb->CurrentByteOffset = offsetDentry_toSequentialSpan;
}
-
+
if ( ( *(pCallbackContext->pUsedLength) > 0) && pCallbackContext->ReturnSingleEntry) {
Status = STATUS_EVENT_DONE;
break;
}
-
+
}
}
- out:
+ out:
if (pBlockBuffer) ExFreePool(pBlockBuffer);
if (InodeFileName.Buffer) ExFreePool(InodeFileName.Buffer);