* 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 *****************************************************************/
#define NDEBUG
#include <internal/debug.h>
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, ObInitSymbolicLinkImplementation)
+#endif
+
/* GLOBALS ******************************************************************/
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
{
PSYMLINK_OBJECT SymlinkObject = (PSYMLINK_OBJECT)ObjectBody;
- RtlFreeUnicodeString(&SymlinkObject->TargetName);
+ ExFreePool(SymlinkObject->TargetName.Buffer);
}
}
/* 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(SYMLINK_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;
-
- RtlRosInitUnicodeStringFromLiteral(&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);
}
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PUNICODE_STRING LinkTarget)
{
+ HANDLE hLink;
PSYMLINK_OBJECT SymbolicLink;
- NTSTATUS Status;
+ UNICODE_STRING CapturedLinkTarget;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ PreviousMode = ExGetPreviousMode();
- ASSERT_IRQL(PASSIVE_LEVEL);
+ 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,
- LinkTarget);
+ &CapturedLinkTarget);
Status = ObCreateObject(ExGetPreviousMode(),
ObSymbolicLinkType,
ObjectAttributes,
- ExGetPreviousMode(),
+ PreviousMode,
NULL,
sizeof(SYMLINK_OBJECT),
0,
0,
(PVOID*)&SymbolicLink);
- if (!NT_SUCCESS(Status))
+ if (NT_SUCCESS(Status))
+ {
+ SymbolicLink->TargetName.Length = 0;
+ SymbolicLink->TargetName.MaximumLength =
+ CapturedLinkTarget.Length + 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,
+ &hLink);
+ if (NT_SUCCESS(Status))
{
- return(Status);
+ _SEH_TRY
+ {
+ *LinkHandle = hLink;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
}
+ ObDereferenceObject(SymbolicLink);
+ }
- Status = ObInsertObject ((PVOID)SymbolicLink,
- NULL,
- DesiredAccess,
- 0,
- NULL,
- LinkHandle);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject (SymbolicLink);
- return 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,
- LinkTarget);
-
- DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer);
-
- NtQuerySystemTime (&SymbolicLink->CreateTime);
-
- 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,
- (KPROCESSOR_MODE)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;
}
OUT PUNICODE_STRING LinkTarget,
OUT PULONG ResultLength OPTIONAL)
{
+ UNICODE_STRING SafeLinkTarget;
PSYMLINK_OBJECT SymlinkObject;
- NTSTATUS Status;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
- Status = ObReferenceObjectByHandle(LinkHandle,
- SYMBOLIC_LINK_QUERY,
- ObSymbolicLinkType,
- (KPROCESSOR_MODE)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 (ResultLength != NULL)
+ _SEH_HANDLE
{
- *ResultLength = (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;
}