mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
* Moved symbolic link implementation to the object manager.
* Free target string when the link object is deleted. * Create a type object for symbolic links. * Use different security descriptors for protected and unprotected symbolic links. svn path=/trunk/; revision=4198
This commit is contained in:
parent
97049b595e
commit
31f87c95ae
7 changed files with 422 additions and 353 deletions
|
@ -1,4 +1,4 @@
|
|||
# $Id: Makefile,v 1.90 2003/01/15 19:58:06 chorns Exp $
|
||||
# $Id: Makefile,v 1.91 2003/02/25 16:49:43 ekohl Exp $
|
||||
#
|
||||
# ReactOS Operating System
|
||||
#
|
||||
|
@ -215,7 +215,8 @@ OBJECTS_OB = \
|
|||
ob/namespc.o \
|
||||
ob/ntobj.o \
|
||||
ob/object.o \
|
||||
ob/security.o
|
||||
ob/security.o \
|
||||
ob/symlink.o
|
||||
|
||||
# Process Manager (Ps)
|
||||
OBJECTS_PS = \
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: io.h,v 1.28 2003/02/25 16:43:45 ekohl Exp $
|
||||
/* $Id: io.h,v 1.29 2003/02/25 16:50:46 ekohl Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -228,8 +228,6 @@ typedef struct _DEVICETREE_TRAVERSE_CONTEXT
|
|||
|
||||
extern PDEVICE_NODE IopRootDeviceNode;
|
||||
|
||||
//extern POBJECT_TYPE IoSymbolicLinkType;
|
||||
|
||||
VOID
|
||||
PnpInit(VOID);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: iomgr.c,v 1.30 2002/11/05 20:24:33 hbirr Exp $
|
||||
/* $Id: iomgr.c,v 1.31 2003/02/25 16:48:32 ekohl Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -261,7 +261,6 @@ VOID IoInit (VOID)
|
|||
* Initialize remaining subsubsystem
|
||||
*/
|
||||
IoInitCancelHandling();
|
||||
IoInitSymbolicLinkImplementation();
|
||||
IoInitFileSystemImplementation();
|
||||
IoInitVpbImplementation();
|
||||
IoInitShutdownNotification();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: symlink.c,v 1.31 2002/09/08 10:23:26 chorns Exp $
|
||||
/* $Id: symlink.c,v 1.32 2003/02/25 16:48:32 ekohl Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -11,169 +11,18 @@
|
|||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <limits.h>
|
||||
#include <ddk/ntddk.h>
|
||||
#include <internal/pool.h>
|
||||
#include <internal/se.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CSHORT Type;
|
||||
CSHORT Size;
|
||||
UNICODE_STRING TargetName;
|
||||
OBJECT_ATTRIBUTES Target;
|
||||
} SYMLNK_OBJECT, *PSYMLNK_OBJECT;
|
||||
|
||||
POBJECT_TYPE IoSymbolicLinkType = NULL;
|
||||
|
||||
static GENERIC_MAPPING IopSymbolicLinkMapping = {
|
||||
STANDARD_RIGHTS_READ|SYMBOLIC_LINK_QUERY,
|
||||
STANDARD_RIGHTS_WRITE,
|
||||
STANDARD_RIGHTS_EXECUTE|SYMBOLIC_LINK_QUERY,
|
||||
SYMBOLIC_LINK_ALL_ACCESS};
|
||||
|
||||
#define TAG_SYMLINK_TTARGET TAG('S', 'Y', 'T', 'T')
|
||||
#define TAG_SYMLINK_TARGET TAG('S', 'Y', 'M', 'T')
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME INTERNAL
|
||||
* IopCreateSymbolicLink
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* RETURNN VALUE
|
||||
* Status.
|
||||
*
|
||||
* REVISIONS
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
IopCreateSymbolicLink(PVOID Object,
|
||||
PVOID Parent,
|
||||
PWSTR RemainingPath,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
{
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME INTERNAL
|
||||
* IopParseSymbolicLink
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* RETURN VALUE
|
||||
*
|
||||
* REVISIONS
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
IopParseSymbolicLink(PVOID Object,
|
||||
PVOID * NextObject,
|
||||
PUNICODE_STRING FullPath,
|
||||
PWSTR * RemainingPath,
|
||||
ULONG Attributes)
|
||||
{
|
||||
PSYMLNK_OBJECT SymlinkObject = (PSYMLNK_OBJECT) Object;
|
||||
UNICODE_STRING TargetPath;
|
||||
|
||||
DPRINT("IopParseSymbolicLink (RemainingPath %S)\n", *RemainingPath);
|
||||
/*
|
||||
* Stop parsing if the entire path has been parsed and
|
||||
* the desired object is a symbolic link object.
|
||||
*/
|
||||
if (((*RemainingPath == NULL) || (**RemainingPath == 0)) &&
|
||||
(Attributes & OBJ_OPENLINK))
|
||||
{
|
||||
DPRINT("Parsing stopped!\n");
|
||||
*NextObject = NULL;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* build the expanded path */
|
||||
TargetPath.MaximumLength = SymlinkObject->TargetName.Length + sizeof(WCHAR);
|
||||
if (RemainingPath && *RemainingPath)
|
||||
{
|
||||
TargetPath.MaximumLength += (wcslen(*RemainingPath) * sizeof(WCHAR));
|
||||
}
|
||||
TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR);
|
||||
TargetPath.Buffer = ExAllocatePoolWithTag(NonPagedPool,
|
||||
TargetPath.MaximumLength,
|
||||
TAG_SYMLINK_TTARGET);
|
||||
wcscpy(TargetPath.Buffer, SymlinkObject->TargetName.Buffer);
|
||||
if (RemainingPath && *RemainingPath)
|
||||
{
|
||||
wcscat(TargetPath.Buffer, *RemainingPath);
|
||||
}
|
||||
|
||||
/* transfer target path buffer into FullPath */
|
||||
RtlFreeUnicodeString(FullPath);
|
||||
FullPath->Length = TargetPath.Length;
|
||||
FullPath->MaximumLength = TargetPath.MaximumLength;
|
||||
FullPath->Buffer = TargetPath.Buffer;
|
||||
|
||||
/* reinitialize RemainingPath for reparsing */
|
||||
*RemainingPath = FullPath->Buffer;
|
||||
|
||||
*NextObject = NULL;
|
||||
return STATUS_REPARSE;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* NAME INTERNAL
|
||||
* IoInitSymbolicLinkImplementation
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* ARGUMENTS
|
||||
* None.
|
||||
*
|
||||
* RETURNN VALUE
|
||||
* None.
|
||||
*
|
||||
* REVISIONS
|
||||
*/
|
||||
VOID IoInitSymbolicLinkImplementation (VOID)
|
||||
{
|
||||
IoSymbolicLinkType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
||||
|
||||
IoSymbolicLinkType->Tag = TAG('S', 'Y', 'M', 'T');
|
||||
IoSymbolicLinkType->TotalObjects = 0;
|
||||
IoSymbolicLinkType->TotalHandles = 0;
|
||||
IoSymbolicLinkType->MaxObjects = ULONG_MAX;
|
||||
IoSymbolicLinkType->MaxHandles = ULONG_MAX;
|
||||
IoSymbolicLinkType->PagedPoolCharge = 0;
|
||||
IoSymbolicLinkType->NonpagedPoolCharge = sizeof (SYMLNK_OBJECT);
|
||||
IoSymbolicLinkType->Mapping = &IopSymbolicLinkMapping;
|
||||
IoSymbolicLinkType->Dump = NULL;
|
||||
IoSymbolicLinkType->Open = NULL;
|
||||
IoSymbolicLinkType->Close = NULL;
|
||||
IoSymbolicLinkType->Delete = NULL;
|
||||
IoSymbolicLinkType->Parse = IopParseSymbolicLink;
|
||||
IoSymbolicLinkType->Security = NULL;
|
||||
IoSymbolicLinkType->QueryName = NULL;
|
||||
IoSymbolicLinkType->OkayToClose = NULL;
|
||||
IoSymbolicLinkType->Create = IopCreateSymbolicLink;
|
||||
IoSymbolicLinkType->DuplicationNotify = NULL;
|
||||
|
||||
RtlInitUnicodeStringFromLiteral(&IoSymbolicLinkType->TypeName,
|
||||
L"SymbolicLink");
|
||||
}
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* NtOpenSymbolicLinkObject
|
||||
* IoCreateSymbolicLink
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
|
@ -185,62 +34,36 @@ VOID IoInitSymbolicLinkImplementation (VOID)
|
|||
*
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName,
|
||||
PUNICODE_STRING DeviceName)
|
||||
{
|
||||
DPRINT("NtOpenSymbolicLinkObject (Name %wZ)\n",
|
||||
ObjectAttributes->ObjectName);
|
||||
|
||||
return(ObOpenObjectByName(ObjectAttributes,
|
||||
IoSymbolicLinkType,
|
||||
NULL,
|
||||
UserMode,
|
||||
DesiredAccess,
|
||||
NULL,
|
||||
LinkHandle));
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* NtQuerySymbolicLinkObject
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* RETURN VALUE
|
||||
*
|
||||
* REVISIONS
|
||||
*
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtQuerySymbolicLinkObject(IN HANDLE LinkHandle,
|
||||
IN OUT PUNICODE_STRING LinkTarget,
|
||||
OUT PULONG ReturnedLength OPTIONAL)
|
||||
{
|
||||
PSYMLNK_OBJECT SymlinkObject;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
HANDLE Handle;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = ObReferenceObjectByHandle(LinkHandle,
|
||||
SYMBOLIC_LINK_QUERY,
|
||||
IoSymbolicLinkType,
|
||||
UserMode,
|
||||
(PVOID *)&SymlinkObject,
|
||||
NULL);
|
||||
assert_irql(PASSIVE_LEVEL);
|
||||
|
||||
DPRINT("IoCreateSymbolicLink(SymbolicLinkName %wZ, DeviceName %wZ)\n",
|
||||
SymbolicLinkName,
|
||||
DeviceName);
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
SymbolicLinkName,
|
||||
OBJ_PERMANENT,
|
||||
NULL,
|
||||
SePublicDefaultSd);
|
||||
|
||||
Status = NtCreateSymbolicLinkObject(&Handle,
|
||||
SYMBOLIC_LINK_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
DeviceName);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtCreateSymbolicLinkObject() failed (Status %lx)\n", Status);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
RtlCopyUnicodeString(LinkTarget,
|
||||
SymlinkObject->Target.ObjectName);
|
||||
if (ReturnedLength != NULL)
|
||||
{
|
||||
*ReturnedLength = SymlinkObject->Target.Length;
|
||||
}
|
||||
ObDereferenceObject(SymlinkObject);
|
||||
NtClose(Handle);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
@ -263,83 +86,54 @@ NTSTATUS STDCALL
|
|||
IoCreateUnprotectedSymbolicLink(PUNICODE_STRING SymbolicLinkName,
|
||||
PUNICODE_STRING DeviceName)
|
||||
{
|
||||
return(IoCreateSymbolicLink(SymbolicLinkName,
|
||||
DeviceName));
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* IoCreateSymbolicLink
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* RETURN VALUE
|
||||
*
|
||||
* REVISIONS
|
||||
*
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName,
|
||||
PUNICODE_STRING DeviceName)
|
||||
{
|
||||
SECURITY_DESCRIPTOR SecurityDescriptor;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
PSYMLNK_OBJECT SymbolicLink;
|
||||
HANDLE Handle;
|
||||
NTSTATUS Status;
|
||||
|
||||
assert_irql(PASSIVE_LEVEL);
|
||||
|
||||
DPRINT(
|
||||
"IoCreateSymbolicLink(SymbolicLinkName %S, DeviceName %S)\n",
|
||||
SymbolicLinkName->Buffer,
|
||||
DeviceName->Buffer
|
||||
);
|
||||
DPRINT("IoCreateUnprotectedSymbolicLink(SymbolicLinkName %wZ, DeviceName %wZ)\n",
|
||||
SymbolicLinkName,
|
||||
DeviceName);
|
||||
|
||||
InitializeObjectAttributes(
|
||||
& ObjectAttributes,
|
||||
Status = RtlCreateSecurityDescriptor(&SecurityDescriptor,
|
||||
SECURITY_DESCRIPTOR_REVISION);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("RtlCreateSecurityDescriptor() failed (Status %lx)\n", Status);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
Status = RtlSetDaclSecurityDescriptor(&SecurityDescriptor,
|
||||
TRUE,
|
||||
NULL,
|
||||
TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("RtlSetDaclSecurityDescriptor() failed (Status %lx)\n", Status);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
SymbolicLinkName,
|
||||
OBJ_PERMANENT,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
Status = ObCreateObject(
|
||||
NULL,
|
||||
&SecurityDescriptor);
|
||||
|
||||
Status = NtCreateSymbolicLinkObject(&Handle,
|
||||
SYMBOLIC_LINK_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
IoSymbolicLinkType,
|
||||
(PVOID*)&SymbolicLink
|
||||
);
|
||||
DeviceName);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtCreateSymbolicLinkObject() failed (Status %lx)\n", Status);
|
||||
return(Status);
|
||||
}
|
||||
SymbolicLink->TargetName.Length = 0;
|
||||
SymbolicLink->TargetName.MaximumLength =
|
||||
((wcslen(DeviceName->Buffer) + 1) * sizeof(WCHAR));
|
||||
SymbolicLink->TargetName.Buffer =
|
||||
ExAllocatePoolWithTag(NonPagedPool,
|
||||
SymbolicLink->TargetName.MaximumLength,
|
||||
TAG_SYMLINK_TARGET);
|
||||
RtlCopyUnicodeString(
|
||||
& (SymbolicLink->TargetName),
|
||||
DeviceName
|
||||
);
|
||||
|
||||
DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer);
|
||||
NtClose(Handle);
|
||||
|
||||
InitializeObjectAttributes(
|
||||
& (SymbolicLink->Target),
|
||||
& (SymbolicLink->TargetName),
|
||||
0,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__);
|
||||
ObDereferenceObject( SymbolicLink );
|
||||
return STATUS_SUCCESS;
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
@ -386,68 +180,4 @@ IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName)
|
|||
return(Status);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME (EXPORTED as Zw)
|
||||
* NtCreateSymbolicLinkObject
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* RETURN VALUE
|
||||
*
|
||||
* REVISIONS
|
||||
*
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
IN PUNICODE_STRING DeviceName)
|
||||
{
|
||||
PSYMLNK_OBJECT SymbolicLink;
|
||||
NTSTATUS Status;
|
||||
|
||||
assert_irql(PASSIVE_LEVEL);
|
||||
|
||||
DPRINT("NtCreateSymbolicLinkObject(SymbolicLinkHandle %p, DesiredAccess %ul, ObjectAttributes %p, DeviceName %S)\n",
|
||||
SymbolicLinkHandle,
|
||||
DesiredAccess,
|
||||
ObjectAttributes,
|
||||
DeviceName->Buffer);
|
||||
|
||||
Status = ObCreateObject(SymbolicLinkHandle,
|
||||
DesiredAccess,
|
||||
ObjectAttributes,
|
||||
IoSymbolicLinkType,
|
||||
(PVOID*)&SymbolicLink);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
SymbolicLink->TargetName.Length = 0;
|
||||
SymbolicLink->TargetName.MaximumLength =
|
||||
((wcslen(DeviceName->Buffer) + 1) * sizeof(WCHAR));
|
||||
SymbolicLink->TargetName.Buffer =
|
||||
ExAllocatePoolWithTag(NonPagedPool,
|
||||
SymbolicLink->TargetName.MaximumLength,
|
||||
TAG_SYMLINK_TARGET);
|
||||
RtlCopyUnicodeString(&SymbolicLink->TargetName,
|
||||
DeviceName);
|
||||
|
||||
DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer);
|
||||
|
||||
InitializeObjectAttributes(&SymbolicLink->Target,
|
||||
&SymbolicLink->TargetName,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__);
|
||||
ObDereferenceObject(SymbolicLink);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: namespc.c,v 1.35 2002/11/10 13:36:15 robd Exp $
|
||||
/* $Id: namespc.c,v 1.36 2003/02/25 16:49:08 ekohl Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -411,6 +411,9 @@ ObInit(VOID)
|
|||
|
||||
ObpCreateTypeObject(ObDirectoryType);
|
||||
ObpCreateTypeObject(ObTypeObjectType);
|
||||
|
||||
/* Create 'symbolic link' object type */
|
||||
ObInitSymbolicLinkImplementation();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: object.c,v 1.57 2002/11/05 20:51:23 hbirr Exp $
|
||||
/* $Id: object.c,v 1.58 2003/02/25 16:49:08 ekohl Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -17,7 +17,6 @@
|
|||
#include <internal/ps.h>
|
||||
#include <internal/id.h>
|
||||
#include <internal/ke.h>
|
||||
#include <internal/io.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
@ -170,7 +169,7 @@ NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
|
|||
|
||||
RootObject = CurrentObject;
|
||||
Attributes = ObjectAttributes->Attributes;
|
||||
if (ObjectType == IoSymbolicLinkType)
|
||||
if (ObjectType == ObSymbolicLinkType)
|
||||
Attributes |= OBJ_OPENLINK;
|
||||
|
||||
while (TRUE)
|
||||
|
|
339
reactos/ntoskrnl/ob/symlink.c
Normal file
339
reactos/ntoskrnl/ob/symlink.c
Normal file
|
@ -0,0 +1,339 @@
|
|||
/* $Id: symlink.c,v 1.1 2003/02/25 16:49:08 ekohl Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ob/symlink.c
|
||||
* PURPOSE: Implements symbolic links
|
||||
* PROGRAMMER: David Welch (welch@mcmail.com)
|
||||
* UPDATE HISTORY:
|
||||
* Created 22/05/98
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <limits.h>
|
||||
#include <ddk/ntddk.h>
|
||||
#include <internal/ob.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CSHORT Type;
|
||||
CSHORT Size;
|
||||
UNICODE_STRING TargetName;
|
||||
OBJECT_ATTRIBUTES Target;
|
||||
} SYMLNK_OBJECT, *PSYMLNK_OBJECT;
|
||||
|
||||
POBJECT_TYPE ObSymbolicLinkType = NULL;
|
||||
|
||||
static GENERIC_MAPPING ObpSymbolicLinkMapping = {
|
||||
STANDARD_RIGHTS_READ|SYMBOLIC_LINK_QUERY,
|
||||
STANDARD_RIGHTS_WRITE,
|
||||
STANDARD_RIGHTS_EXECUTE|SYMBOLIC_LINK_QUERY,
|
||||
SYMBOLIC_LINK_ALL_ACCESS};
|
||||
|
||||
#define TAG_SYMLINK_TTARGET TAG('S', 'Y', 'T', 'T')
|
||||
#define TAG_SYMLINK_TARGET TAG('S', 'Y', 'M', 'T')
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME INTERNAL
|
||||
* ObpCreateSymbolicLink
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* RETURNN VALUE
|
||||
* Status.
|
||||
*
|
||||
* REVISIONS
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
ObpCreateSymbolicLink(PVOID Object,
|
||||
PVOID Parent,
|
||||
PWSTR RemainingPath,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
{
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME INTERNAL
|
||||
* ObpDeleteSymbolicLink
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* RETURNN VALUE
|
||||
* Status.
|
||||
*
|
||||
* REVISIONS
|
||||
*/
|
||||
VOID STDCALL
|
||||
ObpDeleteSymbolicLink(PVOID ObjectBody)
|
||||
{
|
||||
PSYMLNK_OBJECT SymlinkObject = (PSYMLNK_OBJECT)ObjectBody;
|
||||
|
||||
RtlFreeUnicodeString(&SymlinkObject->TargetName);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME INTERNAL
|
||||
* ObpParseSymbolicLink
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* RETURN VALUE
|
||||
*
|
||||
* REVISIONS
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
ObpParseSymbolicLink(PVOID Object,
|
||||
PVOID * NextObject,
|
||||
PUNICODE_STRING FullPath,
|
||||
PWSTR * RemainingPath,
|
||||
ULONG Attributes)
|
||||
{
|
||||
PSYMLNK_OBJECT SymlinkObject = (PSYMLNK_OBJECT) Object;
|
||||
UNICODE_STRING TargetPath;
|
||||
|
||||
DPRINT("ObpParseSymbolicLink (RemainingPath %S)\n", *RemainingPath);
|
||||
|
||||
/*
|
||||
* Stop parsing if the entire path has been parsed and
|
||||
* the desired object is a symbolic link object.
|
||||
*/
|
||||
if (((*RemainingPath == NULL) || (**RemainingPath == 0)) &&
|
||||
(Attributes & OBJ_OPENLINK))
|
||||
{
|
||||
DPRINT("Parsing stopped!\n");
|
||||
*NextObject = NULL;
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
/* build the expanded path */
|
||||
TargetPath.MaximumLength = SymlinkObject->TargetName.Length + sizeof(WCHAR);
|
||||
if (RemainingPath && *RemainingPath)
|
||||
{
|
||||
TargetPath.MaximumLength += (wcslen(*RemainingPath) * sizeof(WCHAR));
|
||||
}
|
||||
TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR);
|
||||
TargetPath.Buffer = ExAllocatePoolWithTag(NonPagedPool,
|
||||
TargetPath.MaximumLength,
|
||||
TAG_SYMLINK_TTARGET);
|
||||
wcscpy(TargetPath.Buffer, SymlinkObject->TargetName.Buffer);
|
||||
if (RemainingPath && *RemainingPath)
|
||||
{
|
||||
wcscat(TargetPath.Buffer, *RemainingPath);
|
||||
}
|
||||
|
||||
/* transfer target path buffer into FullPath */
|
||||
RtlFreeUnicodeString(FullPath);
|
||||
FullPath->Length = TargetPath.Length;
|
||||
FullPath->MaximumLength = TargetPath.MaximumLength;
|
||||
FullPath->Buffer = TargetPath.Buffer;
|
||||
|
||||
/* reinitialize RemainingPath for reparsing */
|
||||
*RemainingPath = FullPath->Buffer;
|
||||
|
||||
*NextObject = NULL;
|
||||
return STATUS_REPARSE;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME INTERNAL
|
||||
* ObInitSymbolicLinkImplementation
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* ARGUMENTS
|
||||
* None.
|
||||
*
|
||||
* RETURNN VALUE
|
||||
* None.
|
||||
*
|
||||
* REVISIONS
|
||||
*/
|
||||
VOID ObInitSymbolicLinkImplementation (VOID)
|
||||
{
|
||||
ObSymbolicLinkType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
||||
|
||||
ObSymbolicLinkType->Tag = TAG('S', 'Y', 'M', 'T');
|
||||
ObSymbolicLinkType->TotalObjects = 0;
|
||||
ObSymbolicLinkType->TotalHandles = 0;
|
||||
ObSymbolicLinkType->MaxObjects = ULONG_MAX;
|
||||
ObSymbolicLinkType->MaxHandles = ULONG_MAX;
|
||||
ObSymbolicLinkType->PagedPoolCharge = 0;
|
||||
ObSymbolicLinkType->NonpagedPoolCharge = sizeof(SYMLNK_OBJECT);
|
||||
ObSymbolicLinkType->Mapping = &ObpSymbolicLinkMapping;
|
||||
ObSymbolicLinkType->Dump = NULL;
|
||||
ObSymbolicLinkType->Open = NULL;
|
||||
ObSymbolicLinkType->Close = NULL;
|
||||
ObSymbolicLinkType->Delete = ObpDeleteSymbolicLink;
|
||||
ObSymbolicLinkType->Parse = ObpParseSymbolicLink;
|
||||
ObSymbolicLinkType->Security = NULL;
|
||||
ObSymbolicLinkType->QueryName = NULL;
|
||||
ObSymbolicLinkType->OkayToClose = NULL;
|
||||
ObSymbolicLinkType->Create = ObpCreateSymbolicLink;
|
||||
ObSymbolicLinkType->DuplicationNotify = NULL;
|
||||
|
||||
RtlInitUnicodeStringFromLiteral(&ObSymbolicLinkType->TypeName,
|
||||
L"SymbolicLink");
|
||||
|
||||
ObpCreateTypeObject(ObSymbolicLinkType);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* NtCreateSymbolicLinkObject
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* RETURN VALUE
|
||||
*
|
||||
* REVISIONS
|
||||
*
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
IN PUNICODE_STRING DeviceName)
|
||||
{
|
||||
PSYMLNK_OBJECT SymbolicLink;
|
||||
NTSTATUS Status;
|
||||
|
||||
assert_irql(PASSIVE_LEVEL);
|
||||
|
||||
DPRINT("NtCreateSymbolicLinkObject(SymbolicLinkHandle %p, DesiredAccess %ul, ObjectAttributes %p, DeviceName %wZ)\n",
|
||||
SymbolicLinkHandle,
|
||||
DesiredAccess,
|
||||
ObjectAttributes,
|
||||
DeviceName);
|
||||
|
||||
Status = ObCreateObject(SymbolicLinkHandle,
|
||||
DesiredAccess,
|
||||
ObjectAttributes,
|
||||
ObSymbolicLinkType,
|
||||
(PVOID*)&SymbolicLink);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
SymbolicLink->TargetName.Length = 0;
|
||||
SymbolicLink->TargetName.MaximumLength =
|
||||
((wcslen(DeviceName->Buffer) + 1) * sizeof(WCHAR));
|
||||
SymbolicLink->TargetName.Buffer =
|
||||
ExAllocatePoolWithTag(NonPagedPool,
|
||||
SymbolicLink->TargetName.MaximumLength,
|
||||
TAG_SYMLINK_TARGET);
|
||||
RtlCopyUnicodeString(&SymbolicLink->TargetName,
|
||||
DeviceName);
|
||||
|
||||
DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer);
|
||||
|
||||
InitializeObjectAttributes(&SymbolicLink->Target,
|
||||
&SymbolicLink->TargetName,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__);
|
||||
ObDereferenceObject(SymbolicLink);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* NtOpenSymbolicLinkObject
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* RETURN VALUE
|
||||
*
|
||||
* REVISIONS
|
||||
*
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
{
|
||||
DPRINT("NtOpenSymbolicLinkObject (Name %wZ)\n",
|
||||
ObjectAttributes->ObjectName);
|
||||
|
||||
return(ObOpenObjectByName(ObjectAttributes,
|
||||
ObSymbolicLinkType,
|
||||
NULL,
|
||||
KeGetPreviousMode(),
|
||||
DesiredAccess,
|
||||
NULL,
|
||||
LinkHandle));
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* NtQuerySymbolicLinkObject
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* RETURN VALUE
|
||||
*
|
||||
* REVISIONS
|
||||
*
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtQuerySymbolicLinkObject(IN HANDLE LinkHandle,
|
||||
IN OUT PUNICODE_STRING LinkTarget,
|
||||
OUT PULONG ReturnedLength OPTIONAL)
|
||||
{
|
||||
PSYMLNK_OBJECT SymlinkObject;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = ObReferenceObjectByHandle(LinkHandle,
|
||||
SYMBOLIC_LINK_QUERY,
|
||||
ObSymbolicLinkType,
|
||||
KeGetPreviousMode(),
|
||||
(PVOID *)&SymlinkObject,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
RtlCopyUnicodeString(LinkTarget,
|
||||
SymlinkObject->Target.ObjectName);
|
||||
if (ReturnedLength != NULL)
|
||||
{
|
||||
*ReturnedLength = SymlinkObject->Target.Length;
|
||||
}
|
||||
ObDereferenceObject(SymlinkObject);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Reference in a new issue