* 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:
Eric Kohl 2003-02-25 16:50:46 +00:00
parent 97049b595e
commit 31f87c95ae
7 changed files with 422 additions and 353 deletions

View file

@ -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 = \

View file

@ -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);

View file

@ -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();

View file

@ -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,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 */

View file

@ -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();
}

View file

@ -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)

View 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 */