- Fix compile issues caused by previous patch.
[reactos.git] / reactos / ntoskrnl / ob / symlink.c
index 5d657fd..371cc9b 100644 (file)
@@ -4,9 +4,8 @@
  * 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 *****************************************************************/
@@ -26,35 +25,8 @@ static GENERIC_MAPPING ObpSymbolicLinkMapping = {
        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
@@ -73,7 +45,7 @@ ObpDeleteSymbolicLink(PVOID ObjectBody)
 {
   PSYMLINK_OBJECT SymlinkObject = (PSYMLINK_OBJECT)ObjectBody;
 
-  RtlFreeUnicodeString(&SymlinkObject->TargetName);
+  ExFreePool(SymlinkObject->TargetName.Buffer);
 }
 
 
@@ -130,7 +102,7 @@ ObpParseSymbolicLink(PVOID Object,
      }
 
    /* transfer target path buffer into FullPath */
-   RtlFreeUnicodeString(FullPath);
+   ExFreePool(FullPath->Buffer);
    FullPath->Length = TargetPath.Length;
    FullPath->MaximumLength = TargetPath.MaximumLength;
    FullPath->Buffer = TargetPath.Buffer;
@@ -157,34 +129,28 @@ ObpParseSymbolicLink(PVOID Object,
  *
  * 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->PeakObjects = 0;
-  ObSymbolicLinkType->PeakHandles = 0;
-  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);
 }
 
 
@@ -207,61 +173,99 @@ NtCreateSymbolicLinkObject(OUT PHANDLE LinkHandle,
                           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 =
+      ((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,
+                            &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);
-
-  ZwQuerySystemTime (&SymbolicLink->CreateTime);
-
-  DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__);
-  ObDereferenceObject(SymbolicLink);
+  ReleaseCapturedUnicodeString(&CapturedLinkTarget,
+                               PreviousMode);
 
-  return(STATUS_SUCCESS);
+  return Status;
 }
 
 
@@ -283,16 +287,56 @@ NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle,
                         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;
 }
 
 
@@ -314,37 +358,90 @@ NtQuerySymbolicLinkObject(IN HANDLE LinkHandle,
                          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;
 }