Author: pschweitzer
Date: Sun Dec 7 17:59:58 2014
New Revision: 65584
URL: http://svn.reactos.org/svn/reactos?rev=65584&view=rev
Log:
[NTOSKRNL]
Implement support for (some) reparse points in Io manager. Ob should be already fine.
- Implement the IopDoNameTransmogrify() function. This one is responsible for checking the correct data for the reparse point and to update the path name in the file object. It will also free the memory buffer allocated by the driver to communicate the reparse information.
- Fix the support for reparse points in IopCompleteRequest(). If we receive reparse status + reparse tag we know, we call IopDoNameTransmogrify() to update file objet.
- Fix the support for reparse points in IopParseDevice() (oh! you again? :-)). When we complete the IRP ourselves, act as in IopCompleteRequest(). Then, we properly update objects manipulated by Io for the create request and we return STATUS_REPARSE so that Ob can update and recall us afterwards so that we complete.
Some parts are left unimplemented when it comes to reparse tags which are not IO_REPARSE_TAG_MOUNT_POINT. But still less than previously ;-).
Modified:
trunk/reactos/ntoskrnl/io/iomgr/file.c
trunk/reactos/ntoskrnl/io/iomgr/irp.c
Modified: trunk/reactos/ntoskrnl/io/iomgr/file.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/file.c?r…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/file.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/file.c [iso-8859-1] Sun Dec 7 17:59:58 2014
@@ -160,6 +160,107 @@
InterlockedIncrement(&DeviceObject->ReferenceCount);
return STATUS_SUCCESS;
}
+}
+
+VOID
+NTAPI
+IopDoNameTransmogrify(IN PIRP Irp,
+ IN PFILE_OBJECT FileObject,
+ IN PREPARSE_DATA_BUFFER DataBuffer)
+{
+ PWSTR Buffer;
+ USHORT Length;
+ USHORT RequiredLength;
+ PWSTR NewBuffer;
+
+ PAGED_CODE();
+
+ ASSERT(Irp->IoStatus.Status == STATUS_REPARSE);
+ ASSERT(Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT);
+ ASSERT(Irp->Tail.Overlay.AuxiliaryBuffer != NULL);
+ ASSERT(DataBuffer != NULL);
+ ASSERT(DataBuffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT);
+ ASSERT(DataBuffer->ReparseDataLength < MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
+ ASSERT(DataBuffer->Reserved < MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
+
+ /* First of all, validate data */
+ if (DataBuffer->ReparseDataLength < REPARSE_DATA_BUFFER_HEADER_SIZE ||
+ (DataBuffer->SymbolicLinkReparseBuffer.PrintNameLength +
+ DataBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength +
+ FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer[0])) > MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
+ {
+ Irp->IoStatus.Status = STATUS_IO_REPARSE_DATA_INVALID;
+ }
+
+ /* Everything went right */
+ if (NT_SUCCESS(Irp->IoStatus.Status))
+ {
+ /* Compute buffer & length */
+ Buffer = (PWSTR)((ULONG_PTR)DataBuffer->MountPointReparseBuffer.PathBuffer +
+ DataBuffer->MountPointReparseBuffer.SubstituteNameOffset);
+ Length = DataBuffer->MountPointReparseBuffer.SubstituteNameLength;
+
+ /* Check we don't overflow */
+ if ((MAXUSHORT - DataBuffer->Reserved) <= (Length + sizeof(UNICODE_NULL)))
+ {
+ Irp->IoStatus.Status = STATUS_IO_REPARSE_DATA_INVALID;
+ }
+ else
+ {
+ /* Compute how much mem we'll need */
+ RequiredLength = DataBuffer->Reserved + Length + sizeof(UNICODE_NULL);
+
+ /* Check if FileObject can already hold what we need */
+ if (FileObject->FileName.MaximumLength >= RequiredLength)
+ {
+ NewBuffer = FileObject->FileName.Buffer;
+ }
+ else
+ {
+ /* Allocate otherwise */
+ NewBuffer = ExAllocatePoolWithTag(PagedPool, RequiredLength, TAG_IO_NAME);
+ if (NewBuffer == NULL)
+ {
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ }
+ }
+
+ /* Everything went right */
+ if (NT_SUCCESS(Irp->IoStatus.Status))
+ {
+ /* Copy reserved */
+ if (DataBuffer->Reserved)
+ {
+ RtlMoveMemory((PWSTR)((ULONG_PTR)NewBuffer + Length),
+ (PWSTR)((ULONG_PTR)FileObject->FileName.Buffer + FileObject->FileName.Length - DataBuffer->Reserved),
+ DataBuffer->Reserved);
+ }
+
+ /* Then, buffer */
+ if (Length)
+ {
+ RtlCopyMemory(NewBuffer, Buffer, Length);
+ }
+
+ /* And finally replace buffer if new one was allocated */
+ FileObject->FileName.Length = RequiredLength - sizeof(UNICODE_NULL);
+ if (NewBuffer != FileObject->FileName.Buffer)
+ {
+ if (FileObject->FileName.Buffer)
+ {
+ ExFreePoolWithTag(FileObject->FileName.Buffer, TAG_IO_NAME);
+ }
+
+ FileObject->FileName.Buffer = NewBuffer;
+ FileObject->FileName.MaximumLength = RequiredLength;
+ FileObject->FileName.Buffer[RequiredLength / sizeof(WCHAR) - 1] = UNICODE_NULL;
+ }
+ }
+
+ /* We don't need them anymore - it was allocated by the driver */
+ ExFreePool(DataBuffer);
}
NTSTATUS
@@ -206,6 +307,23 @@
/* Validate the open packet */
if (!IopValidateOpenPacket(OpenPacket)) return STATUS_OBJECT_TYPE_MISMATCH;
+ /* Valide reparse point in case we traversed a mountpoint */
+ if (OpenPacket->TraversedMountPoint)
+ {
+ /* This is a reparse point we understand */
+ ASSERT(OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT);
+
+ /* Make sure we're dealing with correct DO */
+ if (OriginalDeviceObject->DeviceType != FILE_DEVICE_DISK &&
+ OriginalDeviceObject->DeviceType != FILE_DEVICE_CD_ROM &&
+ OriginalDeviceObject->DeviceType != FILE_DEVICE_VIRTUAL_DISK &&
+ OriginalDeviceObject->DeviceType != FILE_DEVICE_TAPE)
+ {
+ OpenPacket->FinalStatus = STATUS_IO_REPARSE_DATA_INVALID;
+ return STATUS_IO_REPARSE_DATA_INVALID;
+ }
+ }
+
/* Check if we have a related file object */
if (OpenPacket->RelatedFileObject)
{
@@ -404,6 +522,7 @@
/* Check if we can simply use a dummy file */
UseDummyFile = ((OpenPacket->QueryOnly) || (OpenPacket->DeleteOnly));
+#if 1
/* FIXME: Small hack still exists, have to check why...
* This is triggered multiple times by usetup and then once per boot.
*/
@@ -424,6 +543,7 @@
WRITE_DAC));
DirectOpen = TRUE;
}
+#endif
/* Check if this is a direct open */
if (!(RemainingName->Length) &&
@@ -482,6 +602,12 @@
/* Get the attached device */
DeviceObject = IoGetAttachedDevice(DeviceObject);
}
+ }
+
+ /* If we traversed a mount point, reset the information */
+ if (OpenPacket->TraversedMountPoint)
+ {
+ OpenPacket->TraversedMountPoint = FALSE;
}
/* Check if this is a secure FSD */
@@ -740,6 +866,26 @@
ASSERT(!Irp->PendingReturned);
ASSERT(!Irp->MdlAddress);
+ /* Handle name change if required */
+ if (Status == STATUS_REPARSE)
+ {
+ /* Check this is a mount point */
+ if (OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT)
+ {
+ PREPARSE_DATA_BUFFER ReparseData;
+
+ /* Reparse point attributes were passed by the driver in the auxiliary buffer */
+ ASSERT(Irp->Tail.Overlay.AuxiliaryBuffer != NULL);
+ ReparseData = (PREPARSE_DATA_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer;
+
+ ASSERT(ReparseData->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT);
+ ASSERT(ReparseData->ReparseDataLength < MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
+ ASSERT(ReparseData->Reserved < MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
+
+ IopDoNameTransmogrify(Irp, FileObject, ReparseData);
+ }
+ }
+
/* Completion happens at APC_LEVEL */
KeRaiseIrql(APC_LEVEL, &OldIrql);
@@ -805,7 +951,90 @@
}
else if (Status == STATUS_REPARSE)
{
- /* FIXME: We don't handle this at all! */
+ if (OpenPacket->Information == IO_REPARSE ||
+ OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT)
+ {
+ /* Update CompleteName with reparse info which got updated in IopDoNameTransmogrify() */
+ if (CompleteName->MaximumLength < FileObject->FileName.Length)
+ {
+ PWSTR NewCompleteName;
+
+ /* Allocate a new buffer for the string */
+ NewCompleteName = ExAllocatePoolWithTag(PagedPool, FileObject->FileName.Length, TAG_IO_NAME);
+ if (NewCompleteName == NULL)
+ {
+ OpenPacket->FinalStatus = STATUS_INSUFFICIENT_RESOURCES;
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Release the old one */
+ if (CompleteName->Buffer != NULL)
+ {
+ ExFreePoolWithTag(CompleteName->Buffer, TAG_IO_NAME);
+ }
+
+ /* And setup the new one */
+ CompleteName->Buffer = NewCompleteName;
+ CompleteName->MaximumLength = FileObject->FileName.Length;
+ }
+
+ /* Copy our new complete name */
+ RtlCopyUnicodeString(CompleteName, &FileObject->FileName);
+
+ if (OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT)
+ {
+ OpenPacket->RelatedFileObject = NULL;
+ }
+ }
+
+ /* Check if we have a name */
+ if (FileObject->FileName.Length)
+ {
+ /* Free it */
+ ExFreePoolWithTag(FileObject->FileName.Buffer, TAG_IO_NAME);
+ FileObject->FileName.Length = 0;
+ }
+
+ /* Clear its device object */
+ FileObject->DeviceObject = NULL;
+
+ /* Clear the file object in the open packet */
+ OpenPacket->FileObject = NULL;
+
+ /* Dereference the file object */
+ if (!UseDummyFile) ObDereferenceObject(FileObject);
+
+ /* Dereference the device object */
+ IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
+
+ /* Unless the driver cancelled the open, dereference the VPB */
+ if (Vpb != NULL) IopDereferenceVpbAndFree(Vpb);
+
+ if (OpenPacket->Information != IO_REMOUNT)
+ {
+ OpenPacket->RelatedFileObject = NULL;
+
+ /* Inform we traversed a mount point for later attempt */
+ if (OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT)
+ {
+ OpenPacket->TraversedMountPoint = 1;
+ }
+
+ /* In case we override checks, but got this on volume open, fail hard */
+ if (OpenPacket->Override)
+ {
+ KeBugCheckEx(DRIVER_RETURNED_STATUS_REPARSE_FOR_VOLUME_OPEN,
+ (ULONG_PTR)OriginalDeviceObject,
+ (ULONG_PTR)DeviceObject,
+ (ULONG_PTR)CompleteName,
+ OpenPacket->Information);
+ }
+
+ /* Return to IO/OB so that information can be upgraded */
+ return STATUS_REPARSE;
+ }
+
+ /* FIXME: At that point, we should loop again and reattempt an opening */
ASSERT(FALSE);
}
Modified: trunk/reactos/ntoskrnl/io/iomgr/irp.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/irp.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/irp.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/irp.c [iso-8859-1] Sun Dec 7 17:59:58 2014
@@ -264,9 +264,15 @@
if ((Irp->IoStatus.Status == STATUS_REPARSE) &&
(Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT))
{
- /* We should never get this yet */
- UNIMPLEMENTED_DBGBREAK("Reparse support not yet present!\n");
- return;
+ PREPARSE_DATA_BUFFER ReparseData;
+
+ ReparseData = (PREPARSE_DATA_BUFFER)*SystemArgument2;
+
+ ASSERT(ReparseData->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT);
+ ASSERT(ReparseData->ReparseDataLength < MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
+ ASSERT(ReparseData->Reserved < MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
+
+ IopDoNameTransmogrify(Irp, FileObject, ReparseData);
}
}
Author: aandrejevic
Date: Sun Dec 7 17:53:08 2014
New Revision: 65583
URL: http://svn.reactos.org/svn/reactos?rev=65583&view=rev
Log:
[SHELL32:ICONS]
Replace the old "My Computer" icon with a new one.
New icon by: Ismael Ferreras Morezuelas.
CORE-8890 #resolve #comment Committed in revision r65583. Thanks!
Modified:
trunk/reactos/dll/win32/shell32/res/icons/16.ico
Modified: trunk/reactos/dll/win32/shell32/res/icons/16.ico
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/res/icon…
==============================================================================
Binary files - no diff available.
Author: pschweitzer
Date: Sun Dec 7 16:54:27 2014
New Revision: 65582
URL: http://svn.reactos.org/svn/reactos?rev=65582&view=rev
Log:
[BUGCODES]
Add bug check code 0xF9 DRIVER_RETURNED_STATUS_REPARSE_FOR_VOLUME_OPEN
Ref: http://msdn.microsoft.com/en-us/library/windows/hardware/ff560396%28v=vs.85…
Modified:
trunk/reactos/include/reactos/mc/bugcodes.mc
Modified: trunk/reactos/include/reactos/mc/bugcodes.mc
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/mc/bugcode…
==============================================================================
--- trunk/reactos/include/reactos/mc/bugcodes.mc [iso-8859-1] (original)
+++ trunk/reactos/include/reactos/mc/bugcodes.mc [iso-8859-1] Sun Dec 7 16:54:27 2014
@@ -1586,6 +1586,14 @@
An initialization failure occurred while attempting to boot from the RAM disk.
.
+MessageId=0xF9
+Severity=Success
+Facility=System
+SymbolicName=DRIVER_RETURNED_STATUS_REPARSE_FOR_VOLUME_OPEN
+Language=English
+STATUS_REPARSE was returned from a FSD when trying to open a volume.
+.
+
MessageId=0xFA
Severity=Success
Facility=System
Author: pschweitzer
Date: Sun Dec 7 14:16:13 2014
New Revision: 65581
URL: http://svn.reactos.org/svn/reactos?rev=65581&view=rev
Log:
[NTFS]
Implement NtfsFsdDeviceControl()
Added:
trunk/reactos/drivers/filesystems/ntfs/devctl.c (with props)
Modified:
trunk/reactos/drivers/filesystems/ntfs/CMakeLists.txt
trunk/reactos/drivers/filesystems/ntfs/ntfs.c
trunk/reactos/drivers/filesystems/ntfs/ntfs.h
Modified: trunk/reactos/drivers/filesystems/ntfs/CMakeLists.txt
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ntfs/C…
==============================================================================
--- trunk/reactos/drivers/filesystems/ntfs/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ntfs/CMakeLists.txt [iso-8859-1] Sun Dec 7 14:16:13 2014
@@ -4,6 +4,7 @@
blockdev.c
close.c
create.c
+ devctl.c
dirctl.c
dispatch.c
fastio.c
Added: trunk/reactos/drivers/filesystems/ntfs/devctl.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ntfs/d…
==============================================================================
--- trunk/reactos/drivers/filesystems/ntfs/devctl.c (added)
+++ trunk/reactos/drivers/filesystems/ntfs/devctl.c [iso-8859-1] Sun Dec 7 14:16:13 2014
@@ -0,0 +1,46 @@
+/*
+ * ReactOS kernel
+ * Copyright (C) 2014 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: drivers/filesystem/ntfs/devctl.c
+ * PURPOSE: NTFS filesystem driver
+ * PROGRAMMERS: Pierre Schweitzer (pierre(a)reactos.org)
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "ntfs.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/* FUNCTIONS ****************************************************************/
+
+NTSTATUS
+NTAPI
+NtfsFsdDeviceControl(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ PDEVICE_EXTENSION DeviceExt;
+
+ DeviceExt = DeviceObject->DeviceExtension;
+ IoSkipCurrentIrpStackLocation(Irp);
+
+ return IoCallDriver(DeviceExt->StorageDevice, Irp);
+}
Propchange: trunk/reactos/drivers/filesystems/ntfs/devctl.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/drivers/filesystems/ntfs/ntfs.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ntfs/n…
==============================================================================
--- trunk/reactos/drivers/filesystems/ntfs/ntfs.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ntfs/ntfs.c [iso-8859-1] Sun Dec 7 14:16:13 2014
@@ -135,6 +135,7 @@
DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = NtfsFsdDispatch;
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = NtfsFsdDirectoryControl;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = NtfsFsdFileSystemControl;
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NtfsFsdDeviceControl;
return;
}
Modified: trunk/reactos/drivers/filesystems/ntfs/ntfs.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ntfs/n…
==============================================================================
--- trunk/reactos/drivers/filesystems/ntfs/ntfs.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ntfs/ntfs.h [iso-8859-1] Sun Dec 7 14:16:13 2014
@@ -519,6 +519,14 @@
PIRP Irp);
+/* devctl.c */
+
+DRIVER_DISPATCH NtfsFsdDeviceControl;
+NTSTATUS NTAPI
+NtfsFsdDeviceControl(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp);
+
+
/* dirctl.c */
DRIVER_DISPATCH NtfsFsdDirectoryControl;
Author: pschweitzer
Date: Sun Dec 7 14:05:47 2014
New Revision: 65580
URL: http://svn.reactos.org/svn/reactos?rev=65580&view=rev
Log:
[NTFS]
Allow direct opening of a reparse point, but don't handle yet reparse itself
Modified:
trunk/reactos/drivers/filesystems/ntfs/create.c
Modified: trunk/reactos/drivers/filesystems/ntfs/create.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ntfs/c…
==============================================================================
--- trunk/reactos/drivers/filesystems/ntfs/create.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ntfs/create.c [iso-8859-1] Sun Dec 7 14:05:47 2014
@@ -245,6 +245,23 @@
return STATUS_NOT_A_DIRECTORY;
}
+ /* Properly handle reparse points:
+ * - likely overwrite FO name
+ * - return STATUS_REPARSE to IO manager
+ * - Do we have to attach reparse data to Irp->Tail.Overlay.AuxiliaryBuffer?
+ * See: http://www.osronline.com/showThread.cfm?link=6623
+ *
+ * If it is a reparse point & FILE_OPEN_REPARSE_POINT, then allow opening it
+ * as a normal file.
+ */
+ if (NtfsFCBIsReparsePoint(Fcb) &&
+ ((RequestedOptions & FILE_OPEN_REPARSE_POINT) != FILE_OPEN_REPARSE_POINT))
+ {
+ DPRINT1("Reparse point not handled!\n");
+ NtfsCloseFile(DeviceExt, FileObject);
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
/* HUGLY HACK: remain RO so far... */
if (RequestedDisposition == FILE_OVERWRITE ||
RequestedDisposition == FILE_OVERWRITE_IF ||