Esempio n. 1
0
NTSTATUS
FFSInitializeVcb(
	IN PFFS_IRP_CONTEXT IrpContext, 
	IN PFFS_VCB         Vcb, 
	IN PFFS_SUPER_BLOCK FFSSb,
	IN PDEVICE_OBJECT   TargetDevice,
	IN PDEVICE_OBJECT   VolumeDevice,
	IN PVPB             Vpb)
{
	BOOLEAN                     VcbResourceInitialized = FALSE;
	USHORT                      VolumeLabelLength;
	ULONG                       IoctlSize;
	BOOLEAN                     NotifySyncInitialized = FALSE;
	LONGLONG                    DiskSize;
	LONGLONG                    PartSize;
	NTSTATUS                    Status = STATUS_UNSUCCESSFUL;
	UNICODE_STRING              RootNode;
	USHORT                      Buffer[2];
	ULONG                       ChangeCount;

	__try
	{
		if (!Vpb)
		{
			Status = STATUS_DEVICE_NOT_READY;
			__leave;
		}

		Buffer[0] = L'\\';
		Buffer[1] = 0;

		RootNode.Buffer = Buffer;
		RootNode.MaximumLength = RootNode.Length = 2;

		Vcb->McbTree = FFSAllocateMcb(Vcb, &RootNode,
				FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NORMAL);

		if (!Vcb->McbTree)
		{
			__leave;
		}

#if FFS_READ_ONLY
		SetFlag(Vcb->Flags, VCB_READ_ONLY);
#endif //READ_ONLY

		if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_REMOVABLE_MEDIA))
		{
			SetFlag(Vcb->Flags, VCB_REMOVABLE_MEDIA);
		}

		if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_FLOPPY_DISKETTE))
		{
			SetFlag(Vcb->Flags, VCB_FLOPPY_DISK);
		}
#if 0
		if (IsFlagOn(FFSGlobal->Flags, FFS_SUPPORT_WRITING))
		{
			if (IsFlagOn(FFSGlobal->Flags, FFS_SUPPORT_WRITING))
			{
				ClearFlag(Vcb->Flags, VCB_READ_ONLY);
			}
			else
			{
				SetFlag(Vcb->Flags, VCB_READ_ONLY);
			}
		}
		else
#endif
		{
			SetFlag(Vcb->Flags, VCB_READ_ONLY);
		}

		ExInitializeResourceLite(&Vcb->MainResource);
		ExInitializeResourceLite(&Vcb->PagingIoResource);

		ExInitializeResourceLite(&Vcb->McbResource);

		VcbResourceInitialized = TRUE;

		Vcb->McbTree->Inode = FFS_ROOT_INO;

		Vcb->Vpb = Vpb;

		Vcb->RealDevice = Vpb->RealDevice;
		Vpb->DeviceObject = VolumeDevice;

		{
			UNICODE_STRING      LabelName;
			OEM_STRING          OemName;

			LabelName.MaximumLength = 16 * 2;
			LabelName.Length    = 0;
			LabelName.Buffer    = Vcb->Vpb->VolumeLabel;

			RtlZeroMemory(LabelName.Buffer, LabelName.MaximumLength);

			VolumeLabelLength = 16;

			while((VolumeLabelLength > 0) &&
					((FFSSb->fs_volname[VolumeLabelLength-1] == 0x00) ||
					 (FFSSb->fs_volname[VolumeLabelLength-1] == 0x20)))
			{
				VolumeLabelLength--;
			}

			OemName.Buffer = FFSSb->fs_volname;
			OemName.MaximumLength = 16;
			OemName.Length = VolumeLabelLength;

			Status = FFSOEMToUnicode(&LabelName,
					&OemName);

			if (!NT_SUCCESS(Status))
			{
				__leave;
			}

			Vpb->VolumeLabelLength = LabelName.Length;
		}

		Vpb->SerialNumber = ((ULONG*)FFSSb->fs_id)[0] + ((ULONG*)FFSSb->fs_id)[1] +
			((ULONG*)FFSSb->fs_id)[2];


		Vcb->StreamObj = IoCreateStreamFileObject(NULL, Vcb->Vpb->RealDevice);

		if (Vcb->StreamObj)
		{
			Vcb->StreamObj->SectionObjectPointer = &(Vcb->SectionObject);
			Vcb->StreamObj->Vpb = Vcb->Vpb;
			Vcb->StreamObj->ReadAccess = TRUE;
			if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
			{
				Vcb->StreamObj->WriteAccess = TRUE;
				Vcb->StreamObj->DeleteAccess = TRUE;
			}
			else
			{
				Vcb->StreamObj->WriteAccess = TRUE;
				Vcb->StreamObj->DeleteAccess = TRUE;
			}
			Vcb->StreamObj->FsContext = (PVOID) Vcb;
			Vcb->StreamObj->FsContext2 = NULL;
			Vcb->StreamObj->Vpb = Vcb->Vpb;

			SetFlag(Vcb->StreamObj->Flags, FO_NO_INTERMEDIATE_BUFFERING);
		}
		else
		{
			__leave;
		}

		InitializeListHead(&Vcb->FcbList);

		InitializeListHead(&Vcb->NotifyList);

		FsRtlNotifyInitializeSync(&Vcb->NotifySync);

		NotifySyncInitialized = TRUE;

		Vcb->DeviceObject = VolumeDevice;

		Vcb->TargetDeviceObject = TargetDevice;

		Vcb->OpenFileHandleCount = 0;

		Vcb->ReferenceCount = 0;

		Vcb->ffs_super_block = FFSSb;

		Vcb->Header.NodeTypeCode = (USHORT) FFSVCB;
		Vcb->Header.NodeByteSize = sizeof(FFS_VCB);
		Vcb->Header.IsFastIoPossible = FastIoIsNotPossible;
		Vcb->Header.Resource = &(Vcb->MainResource);
		Vcb->Header.PagingIoResource = &(Vcb->PagingIoResource);

		Vcb->Vpb->SerialNumber = 'PS';

		DiskSize =
			Vcb->DiskGeometry.Cylinders.QuadPart *
			Vcb->DiskGeometry.TracksPerCylinder *
			Vcb->DiskGeometry.SectorsPerTrack *
			Vcb->DiskGeometry.BytesPerSector;

		IoctlSize = sizeof(PARTITION_INFORMATION);

		Status = FFSDiskIoControl(
					TargetDevice,
					IOCTL_DISK_GET_PARTITION_INFO,
					NULL,
					0,
					&Vcb->PartitionInformation,
					&IoctlSize);

		PartSize = Vcb->PartitionInformation.PartitionLength.QuadPart;

		if (!NT_SUCCESS(Status))
		{
			Vcb->PartitionInformation.StartingOffset.QuadPart = 0;

			Vcb->PartitionInformation.PartitionLength.QuadPart =
				DiskSize;

			PartSize = DiskSize;

			Status = STATUS_SUCCESS;
		}

		IoctlSize = sizeof(ULONG);
		Status = FFSDiskIoControl(
					TargetDevice,
					IOCTL_DISK_CHECK_VERIFY,
					NULL,
					0,
					&ChangeCount,
					&IoctlSize);

		if (!NT_SUCCESS(Status))
		{
			__leave;
		}

		Vcb->ChangeCount = ChangeCount;

		Vcb->Header.AllocationSize.QuadPart =
			Vcb->Header.FileSize.QuadPart = PartSize;

		Vcb->Header.ValidDataLength.QuadPart = 
			(LONGLONG)(0x7fffffffffffffff);
		/*
		Vcb->Header.AllocationSize.QuadPart = (LONGLONG)(ffs_super_block->s_blocks_count - ffs_super_block->s_free_blocks_count)
			* (FFS_MIN_BLOCK << ffs_super_block->s_log_block_size);
			Vcb->Header.FileSize.QuadPart = Vcb->Header.AllocationSize.QuadPart;
			Vcb->Header.ValidDataLength.QuadPart = Vcb->Header.AllocationSize.QuadPart;
		*/

		{
			CC_FILE_SIZES FileSizes;

			FileSizes.AllocationSize.QuadPart =
				FileSizes.FileSize.QuadPart =
				Vcb->Header.AllocationSize.QuadPart;

			FileSizes.ValidDataLength.QuadPart= (LONGLONG)(0x7fffffffffffffff);

			CcInitializeCacheMap(Vcb->StreamObj,
					&FileSizes,
					TRUE,
					&(FFSGlobal->CacheManagerNoOpCallbacks),
					Vcb);
		}
#if 0 //	LoadGroup XXX
		if (!FFSLoadGroup(Vcb))
		{
			Status = STATUS_UNSUCCESSFUL;
			__leave;
		}
#endif
		FsRtlInitializeLargeMcb(&(Vcb->DirtyMcbs), PagedPool);
		InitializeListHead(&(Vcb->McbList));

		if (IsFlagOn(FFSGlobal->Flags, FFS_CHECKING_BITMAP))
		{
			FFSCheckBitmapConsistency(IrpContext, Vcb);
		}

		{
			ULONG   dwData[FFS_BLOCK_TYPES] = {NDADDR, 1, 1, 1};
			ULONG   dwMeta[FFS_BLOCK_TYPES] = {0, 0, 0, 0};
			ULONG   i;

			if (FS_VERSION == 1)
			{
				for (i = 0; i < FFS_BLOCK_TYPES; i++)
				{
					dwData[i] = dwData[i] << ((BLOCK_BITS - 2) * i);

					if (i > 0)
					{
						dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 2));
					}

					Vcb->dwData[i] = dwData[i];
					Vcb->dwMeta[i] = dwMeta[i];
				}
			}
			else
			{
				for (i = 0; i < FFS_BLOCK_TYPES; i++)
				{
					dwData[i] = dwData[i] << ((BLOCK_BITS - 3) * i);

					if (i > 0)
					{
						dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 3));
					}

					Vcb->dwData[i] = dwData[i];
					Vcb->dwMeta[i] = dwMeta[i];
				}
			}
		}

		SetFlag(Vcb->Flags, VCB_INITIALIZED);
	}

	__finally
	{
		if (!NT_SUCCESS(Status))
		{
			if (NotifySyncInitialized)
			{
				FsRtlNotifyUninitializeSync(&Vcb->NotifySync);
			}

			if (Vcb->ffs_super_block)
			{
				ExFreePool(Vcb->ffs_super_block);
				Vcb->ffs_super_block = NULL;
			}

			if (VcbResourceInitialized)
			{
				ExDeleteResourceLite(&Vcb->MainResource);
				ExDeleteResourceLite(&Vcb->PagingIoResource);
			}
		}
	}

	return Status;
}
Esempio n. 2
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSQueryDirectory(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	PDEVICE_OBJECT          DeviceObject;
	NTSTATUS                Status = STATUS_UNSUCCESSFUL;
	PFFS_VCB                Vcb = 0;
	PFILE_OBJECT            FileObject;
	PFFS_FCB                Fcb = 0;
	PFFS_CCB                Ccb;
	PIRP                    Irp;
	PIO_STACK_LOCATION      IoStackLocation;
	FILE_INFORMATION_CLASS  FileInformationClass;
	ULONG                   Length;
	PUNICODE_STRING         FileName;
	ULONG                   FileIndex;
	BOOLEAN                 RestartScan;
	BOOLEAN                 ReturnSingleEntry;
	BOOLEAN                 IndexSpecified;
	PUCHAR                  Buffer;
	BOOLEAN                 FirstQuery;
	PFFSv1_INODE            dinode1 = NULL;
	PFFSv2_INODE            dinode2 = NULL;
	BOOLEAN                 FcbResourceAcquired = FALSE;
	ULONG                   UsedLength = 0;
	USHORT                  InodeFileNameLength;
	UNICODE_STRING          InodeFileName;
	PFFS_DIR_ENTRY          pDir = NULL;
	ULONG                   dwBytes;
	ULONG                   dwTemp = 0;
	ULONG                   dwSize = 0;
	ULONG                   dwReturn = 0;
	BOOLEAN                 bRun = TRUE;
	ULONG                   ByteOffset;

    PAGED_CODE();

	InodeFileName.Buffer = NULL;

	_SEH2_TRY
	{
		ASSERT(IrpContext);

		ASSERT((IrpContext->Identifier.Type == FFSICX) &&
				(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));

		DeviceObject = IrpContext->DeviceObject;

		//
		// This request is not allowed on the main device object
		//
		if (DeviceObject == FFSGlobal->DeviceObject)
		{
			Status = STATUS_INVALID_DEVICE_REQUEST;
			_SEH2_LEAVE;
		}

		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

		ASSERT((Vcb->Identifier.Type == FFSVCB) &&
				(Vcb->Identifier.Size == sizeof(FFS_VCB)));

		ASSERT(IsMounted(Vcb));

		FileObject = IrpContext->FileObject;

		Fcb = (PFFS_FCB)FileObject->FsContext;

		ASSERT(Fcb);

		//
		// This request is not allowed on volumes
		//
		if (Fcb->Identifier.Type == FFSVCB)
		{
			Status = STATUS_INVALID_PARAMETER;
			_SEH2_LEAVE;
		}

		ASSERT((Fcb->Identifier.Type == FFSFCB) &&
				(Fcb->Identifier.Size == sizeof(FFS_FCB)));

		if (!IsDirectory(Fcb))
		{
			Status = STATUS_INVALID_PARAMETER;
			_SEH2_LEAVE;
		}

		Ccb = (PFFS_CCB)FileObject->FsContext2;

		ASSERT(Ccb);

		ASSERT((Ccb->Identifier.Type == FFSCCB) &&
				(Ccb->Identifier.Size == sizeof(FFS_CCB)));

		Irp = IrpContext->Irp;

		IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)

		FileInformationClass =
			IoStackLocation->Parameters.QueryDirectory.FileInformationClass;

		Length = IoStackLocation->Parameters.QueryDirectory.Length;

		FileName = IoStackLocation->Parameters.QueryDirectory.FileName;

		FileIndex = IoStackLocation->Parameters.QueryDirectory.FileIndex;

#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;

#endif // _GNU_NTIFS_

		RestartScan = FlagOn(IoStackLocation->Flags, SL_RESTART_SCAN);
		ReturnSingleEntry = FlagOn(IoStackLocation->Flags, SL_RETURN_SINGLE_ENTRY);
		IndexSpecified = FlagOn(IoStackLocation->Flags, SL_INDEX_SPECIFIED);
		/*
		if (!Irp->MdlAddress && Irp->UserBuffer)
		{
			ProbeForWrite(Irp->UserBuffer, Length, 1);
		}
		*/
		Buffer = FFSGetUserBuffer(Irp);

		if (Buffer == NULL)
		{
			FFSBreakPoint();
			Status = STATUS_INVALID_USER_BUFFER;
			_SEH2_LEAVE;
		}

		if (!IrpContext->IsSynchronous)
		{
			Status = STATUS_PENDING;
			_SEH2_LEAVE;
		}

		if (!ExAcquireResourceSharedLite(
					&Fcb->MainResource,
					IrpContext->IsSynchronous))
		{
			Status = STATUS_PENDING;
			_SEH2_LEAVE;
		}

		FcbResourceAcquired = TRUE;

		if (FileName != NULL)
		{
			if (Ccb->DirectorySearchPattern.Buffer != NULL)
			{
				FirstQuery = FALSE;
			}
			else
			{
				FirstQuery = TRUE;

				Ccb->DirectorySearchPattern.Length =
					Ccb->DirectorySearchPattern.MaximumLength =
					FileName->Length;

				Ccb->DirectorySearchPattern.Buffer =
					ExAllocatePoolWithTag(PagedPool, FileName->Length, FFS_POOL_TAG);

				if (Ccb->DirectorySearchPattern.Buffer == NULL)
				{
					Status = STATUS_INSUFFICIENT_RESOURCES;
					_SEH2_LEAVE;
				}

				Status = RtlUpcaseUnicodeString(
						&(Ccb->DirectorySearchPattern),
						FileName,
						FALSE);

				if (!NT_SUCCESS(Status))
					_SEH2_LEAVE;
			}
		}
		else if (Ccb->DirectorySearchPattern.Buffer != NULL)
		{
			FirstQuery = FALSE;
			FileName = &Ccb->DirectorySearchPattern;
		}
		else
		{
			FirstQuery = TRUE;

			Ccb->DirectorySearchPattern.Length =
				Ccb->DirectorySearchPattern.MaximumLength = 2;

			Ccb->DirectorySearchPattern.Buffer =
				ExAllocatePoolWithTag(PagedPool, 2, FFS_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->FFSMcb->DeOffset = 0;
			}
			else
			{
				FileIndex = Ccb->CurrentByteOffset;
			}
		}

		if (FS_VERSION == 1)
		{
			dinode1 = (PFFSv1_INODE)ExAllocatePoolWithTag(
					PagedPool,
					DINODE1_SIZE, FFS_POOL_TAG);

			if (dinode1 == NULL)
			{
				Status = STATUS_INSUFFICIENT_RESOURCES;
				_SEH2_LEAVE;
			}

			RtlZeroMemory(Buffer, Length);

			if (Fcb->dinode1->di_size <= FileIndex)
			{
				Status = STATUS_NO_MORE_FILES;
				_SEH2_LEAVE;
			}
		}
		else
		{
			dinode2 = (PFFSv2_INODE)ExAllocatePoolWithTag(
					PagedPool,
					DINODE2_SIZE, FFS_POOL_TAG);

			if (dinode2 == NULL)
			{
				Status = STATUS_INSUFFICIENT_RESOURCES;
				_SEH2_LEAVE;
			}

			RtlZeroMemory(Buffer, Length);

			if (Fcb->dinode2->di_size <= FileIndex)
			{
				Status = STATUS_NO_MORE_FILES;
				_SEH2_LEAVE;
			}
		}

		pDir = ExAllocatePoolWithTag(PagedPool,
				sizeof(FFS_DIR_ENTRY), FFS_POOL_TAG);
		if (!pDir)
		{
			Status = STATUS_INSUFFICIENT_RESOURCES;
			_SEH2_LEAVE;
		}


		if (FS_VERSION == 1)
		{
			dwBytes = 0;
			dwSize = (ULONG)Fcb->dinode1->di_size - FileIndex -
				(sizeof(FFS_DIR_ENTRY) - FFS_NAME_LEN + 1);

			ByteOffset = FileIndex;

			dwTemp = 0;

			while (bRun && UsedLength < Length  && dwBytes < dwSize)
			{
				OEM_STRING  OemName;

				RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY));

				Status = FFSv1ReadInode(
							NULL,
							Vcb,
							Fcb->dinode1,
							ByteOffset,
							(PVOID)pDir,
							sizeof(FFS_DIR_ENTRY),
							&dwReturn);

				if (!NT_SUCCESS(Status))
				{
					_SEH2_LEAVE;
				}

				if (!pDir->d_ino)
				{
					if (pDir->d_reclen == 0)
					{
						FFSBreakPoint();
						_SEH2_LEAVE;
					}

					goto ProcessNextEntryv1;
				}

				OemName.Buffer = pDir->d_name;
				OemName.Length = (pDir->d_namlen & 0xff);
				OemName.MaximumLength = OemName.Length;

#if 0
/*
				//
				// We could not filter the files: "." and ".."
				//

				if ((OemName.Length >) 1 && OemName.Buffer[0] == '.')
				{
					if ( OemName.Length == 2 && OemName.Buffer[1] == '.')
					{
					}
					else
					{
						goto ProcessNextEntry1;
					}
				}
*/
#endif

				InodeFileNameLength = (USHORT)
					RtlOemStringToUnicodeSize(&OemName);

				InodeFileName.Length = 0;
				InodeFileName.MaximumLength = InodeFileNameLength + 2;

				if (InodeFileNameLength <= 0)
				{
					break;
				}

				InodeFileName.Buffer = ExAllocatePoolWithTag(
						PagedPool,
						InodeFileNameLength + 2, FFS_POOL_TAG);

				if (!InodeFileName.Buffer)
				{
					Status = STATUS_INSUFFICIENT_RESOURCES;
					_SEH2_LEAVE;
				}

				RtlZeroMemory(
						InodeFileName.Buffer, 
						InodeFileNameLength + 2);

				Status = FFSOEMToUnicode(&InodeFileName,
						&OemName);

				if (!NT_SUCCESS(Status))
				{
					_SEH2_LEAVE;
				}

				if (FsRtlDoesNameContainWildCards(
							&(Ccb->DirectorySearchPattern)) ?
						FsRtlIsNameInExpression(
							&(Ccb->DirectorySearchPattern),
							&InodeFileName,
							TRUE,
							NULL) :
						!RtlCompareUnicodeString(
							&(Ccb->DirectorySearchPattern),
							&InodeFileName,
							TRUE))
				{
					dwReturn = FFSProcessDirEntry(
							Vcb, FileInformationClass,
							pDir->d_ino,
							Buffer,
							UsedLength, 
							Length - UsedLength,
							(FileIndex + dwBytes),
							&InodeFileName,
							ReturnSingleEntry);

					if (dwReturn <= 0)
					{
						bRun = FALSE;
					}
					else
					{
						dwTemp = UsedLength;
						UsedLength += dwReturn;
					}
				}

				if (InodeFileName.Buffer != NULL)
				{
					ExFreePool(InodeFileName.Buffer);
					InodeFileName.Buffer = NULL;
				}

ProcessNextEntryv1:

				if (bRun)
				{
					dwBytes +=pDir->d_reclen;
					Ccb->CurrentByteOffset = FileIndex + dwBytes;
				}

				if (UsedLength && ReturnSingleEntry)
				{
					Status = STATUS_SUCCESS;
					_SEH2_LEAVE;
				}

				ByteOffset = FileIndex + dwBytes;
			}
		}
		else
		{
			dwBytes = 0;
			dwSize = (ULONG)Fcb->dinode2->di_size - FileIndex -
				(sizeof(FFS_DIR_ENTRY) - FFS_NAME_LEN + 1);

			ByteOffset = FileIndex;

			dwTemp = 0;

			while (bRun && UsedLength < Length  && dwBytes < dwSize)
			{
				OEM_STRING  OemName;

				RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY));

				Status = FFSv2ReadInode(
							NULL,
							Vcb,
							Fcb->dinode2,
							ByteOffset,
							(PVOID)pDir,
							sizeof(FFS_DIR_ENTRY),
							&dwReturn);

				if (!NT_SUCCESS(Status))
				{
					_SEH2_LEAVE;
				}

				if (!pDir->d_ino)
				{
					if (pDir->d_reclen == 0)
					{
						FFSBreakPoint();
						_SEH2_LEAVE;
					}

					goto ProcessNextEntryv2;
				}

				OemName.Buffer = pDir->d_name;
				OemName.Length = (pDir->d_namlen & 0xff);
				OemName.MaximumLength = OemName.Length;
#if 0
/*
				//
				// We could not filter the files: "." and ".."
				//

				if ((OemName.Length >) 1 && OemName.Buffer[0] == '.')
				{
					if ( OemName.Length == 2 && OemName.Buffer[1] == '.')
					{
					}
					else
					{
						goto ProcessNextEntry2;
					}
				}
*/
#endif

				InodeFileNameLength = (USHORT)
					RtlOemStringToUnicodeSize(&OemName);

				InodeFileName.Length = 0;
				InodeFileName.MaximumLength = InodeFileNameLength + 2;

				if (InodeFileNameLength <= 0)
				{
					break;
				}

				InodeFileName.Buffer = ExAllocatePoolWithTag(
						PagedPool,
						InodeFileNameLength + 2, FFS_POOL_TAG);

				if (!InodeFileName.Buffer)
				{
					Status = STATUS_INSUFFICIENT_RESOURCES;
					_SEH2_LEAVE;
				}

				RtlZeroMemory(
						InodeFileName.Buffer, 
						InodeFileNameLength + 2);

				Status = FFSOEMToUnicode(&InodeFileName,
						&OemName);

				if (!NT_SUCCESS(Status))
				{
					_SEH2_LEAVE;
				}

				if (FsRtlDoesNameContainWildCards(
							&(Ccb->DirectorySearchPattern)) ?
						FsRtlIsNameInExpression(
							&(Ccb->DirectorySearchPattern),
							&InodeFileName,
							TRUE,
							NULL) :
						!RtlCompareUnicodeString(
							&(Ccb->DirectorySearchPattern),
							&InodeFileName,
							TRUE))
				{
					dwReturn = FFSProcessDirEntry(
							Vcb, FileInformationClass,
							pDir->d_ino,
							Buffer,
							UsedLength, 
							Length - UsedLength,
							(FileIndex + dwBytes),
							&InodeFileName,
							ReturnSingleEntry);

					if (dwReturn <= 0)
					{
						bRun = FALSE;
					}
					else
					{
						dwTemp = UsedLength;
						UsedLength += dwReturn;
					}
				}

				if (InodeFileName.Buffer != NULL)
				{
					ExFreePool(InodeFileName.Buffer);
					InodeFileName.Buffer = NULL;
				}

ProcessNextEntryv2:

				if (bRun)
				{
					dwBytes +=pDir->d_reclen;
					Ccb->CurrentByteOffset = FileIndex + dwBytes;
				}

				if (UsedLength && ReturnSingleEntry)
				{
					Status = STATUS_SUCCESS;
					_SEH2_LEAVE;
				}

				ByteOffset = FileIndex + dwBytes;
			}
		}

		FileIndex += dwBytes;

		((PULONG)((PUCHAR)Buffer + dwTemp)) [0] = 0;

		if (!UsedLength)
		{
			if (FirstQuery)
			{
				Status = STATUS_NO_SUCH_FILE;
			}
			else
			{
				Status = STATUS_NO_MORE_FILES;
			}
		}
		else
		{
			Status = STATUS_SUCCESS;
		}
	}

	_SEH2_FINALLY
	{

		if (FcbResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Fcb->MainResource,
					ExGetCurrentResourceThread());
		}

		if (FS_VERSION == 1)
		{
			if (dinode1 != NULL)
			{
				ExFreePool(dinode1);
			}
		}
		else
		{
			if (dinode2 != NULL)
			{
				ExFreePool(dinode2);
			}
		}

		if (pDir != NULL)
		{
			ExFreePool(pDir);
			pDir = NULL;
		}

		if (InodeFileName.Buffer != NULL)
		{
			ExFreePool(InodeFileName.Buffer);
		}

		if (!IrpContext->ExceptionInProgress)
		{
			if (Status == STATUS_PENDING)
			{
				Status = FFSLockUserBuffer(
						IrpContext->Irp,
						Length,
						IoWriteAccess);

				if (NT_SUCCESS(Status))
				{
					Status = FFSQueueRequest(IrpContext);
				}
				else
				{
					FFSCompleteIrpContext(IrpContext, Status);
				}
			}
			else
			{
				IrpContext->Irp->IoStatus.Information = UsedLength;
				FFSCompleteIrpContext(IrpContext, Status);
			}
		}
	} _SEH2_END;

	return Status;
}