-/* $Id: symlink.c,v 1.5 2003/10/12 17:05:49 hbirr Exp $
+/* $Id$
*
* 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
+ *
+ * PROGRAMMERS: David Welch (welch@mcmail.com)
*/
/* INCLUDES *****************************************************************/
-#include <limits.h>
-#define NTOS_MODE_KERNEL
-#include <ntos.h>
-#include <internal/ob.h>
-
+#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
-/* GLOBALS ******************************************************************/
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, ObInitSymbolicLinkImplementation)
+#endif
-typedef struct
-{
- CSHORT Type;
- CSHORT Size;
- UNICODE_STRING TargetName;
- OBJECT_ATTRIBUTES Target;
-} SYMLNK_OBJECT, *PSYMLNK_OBJECT;
+
+/* GLOBALS ******************************************************************/
POBJECT_TYPE ObSymbolicLinkType = NULL;
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
VOID STDCALL
ObpDeleteSymbolicLink(PVOID ObjectBody)
{
- PSYMLNK_OBJECT SymlinkObject = (PSYMLNK_OBJECT)ObjectBody;
+ PSYMLINK_OBJECT SymlinkObject = (PSYMLINK_OBJECT)ObjectBody;
- RtlFreeUnicodeString(&SymlinkObject->TargetName);
+ ExFreePool(SymlinkObject->TargetName.Buffer);
}
PWSTR * RemainingPath,
ULONG Attributes)
{
- PSYMLNK_OBJECT SymlinkObject = (PSYMLNK_OBJECT) Object;
+ PSYMLINK_OBJECT SymlinkObject = (PSYMLINK_OBJECT) Object;
UNICODE_STRING TargetPath;
DPRINT("ObpParseSymbolicLink (RemainingPath %S)\n", *RemainingPath);
}
/* transfer target path buffer into FullPath */
- RtlFreeUnicodeString(FullPath);
+ ExFreePool(FullPath->Buffer);
FullPath->Length = TargetPath.Length;
FullPath->MaximumLength = TargetPath.MaximumLength;
FullPath->Buffer = TargetPath.Buffer;
*
* REVISIONS
*/
-VOID INIT_FUNCTION
+VOID
+INIT_FUNCTION
+NTAPI
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);
+ UNICODE_STRING Name;
+ OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
+
+ DPRINT("Creating SymLink Object Type\n");
+
+ /* Initialize the Directory type */
+ RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
+ RtlInitUnicodeString(&Name, L"SymbolicLink");
+ ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
+ ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(SYMLINK_OBJECT);
+ ObjectTypeInitializer.GenericMapping = ObpSymbolicLinkMapping;
+ ObjectTypeInitializer.PoolType = NonPagedPool;
+ ObjectTypeInitializer.ValidAccessMask = SYMBOLIC_LINK_ALL_ACCESS;
+ ObjectTypeInitializer.UseDefaultObject = TRUE;
+ ObjectTypeInitializer.ParseProcedure = ObpParseSymbolicLink;
+ ObjectTypeInitializer.DeleteProcedure = ObpDeleteSymbolicLink;
+ ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ObSymbolicLinkType);
}
*
*/
NTSTATUS STDCALL
-NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle,
+NtCreateSymbolicLinkObject(OUT PHANDLE LinkHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
- IN PUNICODE_STRING DeviceName)
+ IN PUNICODE_STRING LinkTarget)
{
- PSYMLNK_OBJECT SymbolicLink;
- NTSTATUS Status;
+ HANDLE hLink;
+ PSYMLINK_OBJECT SymbolicLink;
+ UNICODE_STRING CapturedLinkTarget;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
- assert_irql(PASSIVE_LEVEL);
+ PreviousMode = ExGetPreviousMode();
- DPRINT("NtCreateSymbolicLinkObject(SymbolicLinkHandle %p, DesiredAccess %ul, ObjectAttributes %p, DeviceName %wZ)\n",
- SymbolicLinkHandle,
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWriteHandle(LinkHandle);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
+ Status = ProbeAndCaptureUnicodeString(&CapturedLinkTarget,
+ PreviousMode,
+ LinkTarget);
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtCreateSymbolicLinkObject: Capturing the target link failed!\n");
+ return Status;
+ }
+
+ DPRINT("NtCreateSymbolicLinkObject(LinkHandle %p, DesiredAccess %ul, ObjectAttributes %p, LinkTarget %wZ)\n",
+ LinkHandle,
DesiredAccess,
ObjectAttributes,
- DeviceName);
+ &CapturedLinkTarget);
Status = ObCreateObject(ExGetPreviousMode(),
ObSymbolicLinkType,
ObjectAttributes,
- ExGetPreviousMode(),
+ PreviousMode,
NULL,
- sizeof(SYMLNK_OBJECT),
+ sizeof(SYMLINK_OBJECT),
0,
0,
(PVOID*)&SymbolicLink);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- Status = ObInsertObject ((PVOID)SymbolicLink,
- NULL,
- DesiredAccess,
- 0,
- NULL,
- SymbolicLinkHandle);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject (SymbolicLink);
- 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,
+ if (NT_SUCCESS(Status))
+ {
+ SymbolicLink->TargetName.Length = 0;
+ SymbolicLink->TargetName.MaximumLength =
+ ((wcslen(LinkTarget->Buffer) + 1) * sizeof(WCHAR));
+ SymbolicLink->TargetName.Buffer =
+ ExAllocatePoolWithTag(NonPagedPool,
+ SymbolicLink->TargetName.MaximumLength,
+ TAG_SYMLINK_TARGET);
+ RtlCopyUnicodeString(&SymbolicLink->TargetName,
+ &CapturedLinkTarget);
+
+ DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer);
+
+ ZwQuerySystemTime (&SymbolicLink->CreateTime);
+
+ Status = ObInsertObject ((PVOID)SymbolicLink,
+ NULL,
+ DesiredAccess,
0,
NULL,
- NULL);
+ &hLink);
+ if (NT_SUCCESS(Status))
+ {
+ _SEH_TRY
+ {
+ *LinkHandle = hLink;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+ ObDereferenceObject(SymbolicLink);
+ }
- DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__);
- ObDereferenceObject(SymbolicLink);
+ ReleaseCapturedUnicodeString(&CapturedLinkTarget,
+ PreviousMode);
- return(STATUS_SUCCESS);
+ return Status;
}
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
+ HANDLE hLink;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ PreviousMode = ExGetPreviousMode();
+
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWriteHandle(LinkHandle);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
DPRINT("NtOpenSymbolicLinkObject (Name %wZ)\n",
ObjectAttributes->ObjectName);
- return(ObOpenObjectByName(ObjectAttributes,
- ObSymbolicLinkType,
- NULL,
- KeGetPreviousMode(),
- DesiredAccess,
- NULL,
- LinkHandle));
+ Status = ObOpenObjectByName(ObjectAttributes,
+ ObSymbolicLinkType,
+ NULL,
+ PreviousMode,
+ DesiredAccess,
+ NULL,
+ &hLink);
+ if(NT_SUCCESS(Status))
+ {
+ _SEH_TRY
+ {
+ *LinkHandle = hLink;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+
+ return Status;
}
*/
NTSTATUS STDCALL
NtQuerySymbolicLinkObject(IN HANDLE LinkHandle,
- IN OUT PUNICODE_STRING LinkTarget,
- OUT PULONG ReturnedLength OPTIONAL)
+ OUT PUNICODE_STRING LinkTarget,
+ OUT PULONG ResultLength OPTIONAL)
{
- PSYMLNK_OBJECT SymlinkObject;
- NTSTATUS Status;
+ UNICODE_STRING SafeLinkTarget;
+ PSYMLINK_OBJECT SymlinkObject;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
- Status = ObReferenceObjectByHandle(LinkHandle,
- SYMBOLIC_LINK_QUERY,
- ObSymbolicLinkType,
- KeGetPreviousMode(),
- (PVOID *)&SymlinkObject,
- NULL);
- if (!NT_SUCCESS(Status))
+ PAGED_CODE();
+
+ PreviousMode = ExGetPreviousMode();
+
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
{
- return Status;
+ /* probe the unicode string and buffers supplied */
+ ProbeForWrite(LinkTarget,
+ sizeof(UNICODE_STRING),
+ sizeof(ULONG));
+ SafeLinkTarget = *LinkTarget;
+ ProbeForWrite(SafeLinkTarget.Buffer,
+ SafeLinkTarget.MaximumLength,
+ sizeof(WCHAR));
+
+ if(ResultLength != NULL)
+ {
+ ProbeForWriteUlong(ResultLength);
+ }
}
-
- if (ReturnedLength != NULL)
+ _SEH_HANDLE
{
- *ReturnedLength = (ULONG)SymlinkObject->TargetName.Length + sizeof(WCHAR);
+ Status = _SEH_GetExceptionCode();
}
+ _SEH_END;
- if (LinkTarget->MaximumLength >= SymlinkObject->TargetName.Length + sizeof(WCHAR))
+ if(!NT_SUCCESS(Status))
{
- RtlCopyUnicodeString(LinkTarget,
- &SymlinkObject->TargetName);
- Status = STATUS_SUCCESS;
+ return Status;
}
+ }
else
+ {
+ SafeLinkTarget = *LinkTarget;
+ }
+
+ Status = ObReferenceObjectByHandle(LinkHandle,
+ SYMBOLIC_LINK_QUERY,
+ ObSymbolicLinkType,
+ PreviousMode,
+ (PVOID *)&SymlinkObject,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ ULONG LengthRequired = SymlinkObject->TargetName.Length + sizeof(WCHAR);
+
+ _SEH_TRY
+ {
+ if(SafeLinkTarget.MaximumLength >= LengthRequired)
+ {
+ /* don't pass TargetLink to RtlCopyUnicodeString here because the caller
+ might have modified the structure which could lead to a copy into
+ kernel memory! */
+ RtlCopyUnicodeString(&SafeLinkTarget,
+ &SymlinkObject->TargetName);
+ SafeLinkTarget.Buffer[SafeLinkTarget.Length / sizeof(WCHAR)] = L'\0';
+ /* copy back the new UNICODE_STRING structure */
+ *LinkTarget = SafeLinkTarget;
+ }
+ else
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ if(ResultLength != NULL)
+ {
+ *ResultLength = LengthRequired;
+ }
+ }
+ _SEH_HANDLE
{
- Status = STATUS_BUFFER_TOO_SMALL;
+ Status = _SEH_GetExceptionCode();
}
+ _SEH_END;
- ObDereferenceObject(SymlinkObject);
+ ObDereferenceObject(SymlinkObject);
+ }
return Status;
}