From 31f87c95aee39720e5010b887e3c1c81d02b6eb9 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Tue, 25 Feb 2003 16:50:46 +0000 Subject: [PATCH] * 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 --- reactos/ntoskrnl/Makefile | 5 +- reactos/ntoskrnl/include/internal/io.h | 4 +- reactos/ntoskrnl/io/iomgr.c | 3 +- reactos/ntoskrnl/io/symlink.c | 414 +++++-------------------- reactos/ntoskrnl/ob/namespc.c | 5 +- reactos/ntoskrnl/ob/object.c | 5 +- reactos/ntoskrnl/ob/symlink.c | 339 ++++++++++++++++++++ 7 files changed, 422 insertions(+), 353 deletions(-) create mode 100644 reactos/ntoskrnl/ob/symlink.c diff --git a/reactos/ntoskrnl/Makefile b/reactos/ntoskrnl/Makefile index 01377f7795c..3e020d37be9 100644 --- a/reactos/ntoskrnl/Makefile +++ b/reactos/ntoskrnl/Makefile @@ -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 = \ diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index 9675baa3b13..0644cc06d29 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -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); diff --git a/reactos/ntoskrnl/io/iomgr.c b/reactos/ntoskrnl/io/iomgr.c index 7e2597f7ff6..4c217e78531 100644 --- a/reactos/ntoskrnl/io/iomgr.c +++ b/reactos/ntoskrnl/io/iomgr.c @@ -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(); diff --git a/reactos/ntoskrnl/io/symlink.c b/reactos/ntoskrnl/io/symlink.c index 9b45e14080b..e88eab8da0b 100644 --- a/reactos/ntoskrnl/io/symlink.c +++ b/reactos/ntoskrnl/io/symlink.c @@ -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 #include -#include +#include #define NDEBUG #include -/* 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,63 +34,37 @@ 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)); -} + SECURITY_DESCRIPTOR SecurityDescriptor; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE Handle; + NTSTATUS Status; + assert_irql(PASSIVE_LEVEL); -/********************************************************************** - * NAME EXPORTED - * IoCreateSymbolicLink - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - * - */ -NTSTATUS STDCALL -IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName, - PUNICODE_STRING DeviceName) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - PSYMLNK_OBJECT SymbolicLink; - NTSTATUS Status; + DPRINT("IoCreateUnprotectedSymbolicLink(SymbolicLinkName %wZ, DeviceName %wZ)\n", + SymbolicLinkName, + DeviceName); - assert_irql(PASSIVE_LEVEL); + Status = RtlCreateSecurityDescriptor(&SecurityDescriptor, + SECURITY_DESCRIPTOR_REVISION); + if (!NT_SUCCESS(Status)) + { + DPRINT1("RtlCreateSecurityDescriptor() failed (Status %lx)\n", Status); + return(Status); + } - DPRINT( - "IoCreateSymbolicLink(SymbolicLinkName %S, DeviceName %S)\n", - SymbolicLinkName->Buffer, - DeviceName->Buffer - ); + 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, - SYMBOLIC_LINK_ALL_ACCESS, - & 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; + InitializeObjectAttributes(&ObjectAttributes, + SymbolicLinkName, + OBJ_PERMANENT, + NULL, + &SecurityDescriptor); + + Status = NtCreateSymbolicLinkObject(&Handle, + SYMBOLIC_LINK_ALL_ACCESS, + &ObjectAttributes, + DeviceName); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtCreateSymbolicLinkObject() failed (Status %lx)\n", Status); + return(Status); + } + + NtClose(Handle); + + 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 */ diff --git a/reactos/ntoskrnl/ob/namespc.c b/reactos/ntoskrnl/ob/namespc.c index 5e8525f040b..bb38c111c16 100644 --- a/reactos/ntoskrnl/ob/namespc.c +++ b/reactos/ntoskrnl/ob/namespc.c @@ -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(); } diff --git a/reactos/ntoskrnl/ob/object.c b/reactos/ntoskrnl/ob/object.c index 66e80344fb3..30334a9a6f9 100644 --- a/reactos/ntoskrnl/ob/object.c +++ b/reactos/ntoskrnl/ob/object.c @@ -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 #include #include -#include #define NDEBUG #include @@ -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) diff --git a/reactos/ntoskrnl/ob/symlink.c b/reactos/ntoskrnl/ob/symlink.c new file mode 100644 index 00000000000..efba99b4883 --- /dev/null +++ b/reactos/ntoskrnl/ob/symlink.c @@ -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 +#include +#include + +#define NDEBUG +#include + +/* 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 */