DriveType = DOSDEVICE_DRIVE_REMOTE;
break;
default:
- DPRINT1("Device Type %ld for %wZ is not known or unhandled\n",
+ DPRINT1("Device Type %lu for %wZ is not known or unhandled\n",
((PDEVICE_OBJECT)Object)->DeviceType,
&SymbolicLink->LinkTarget);
DriveType = DOSDEVICE_DRIVE_UNKNOWN;
POBJECT_SYMBOLIC_LINK SymlinkObject = (POBJECT_SYMBOLIC_LINK)ParsedObject;
PUNICODE_STRING TargetPath;
PWSTR NewTargetPath;
- ULONG LengthUsed, MaximumLength;
+ ULONG LengthUsed, MaximumLength, TempLength;
NTSTATUS Status;
PAGED_CODE();
return STATUS_OBJECT_TYPE_MISMATCH;
}
+ /* Check if this symlink is bound to a specific object */
+ if (SymlinkObject->LinkTargetObject)
+ {
+ UNIMPLEMENTED;
+ }
+
/* Set the target path and length */
TargetPath = &SymlinkObject->LinkTarget;
- LengthUsed = TargetPath->Length + RemainingName->Length;
+ TempLength = TargetPath->Length;
+
+ /*
+ * Strip off the extra trailing '\', if we don't do this we will end up
+ * adding a extra '\' between TargetPath and RemainingName
+ * causing caller's like ObpLookupObjectName() to fail.
+ */
+ if (TempLength && RemainingName->Length)
+ {
+ /* The target and remaining names aren't empty, so check for slashes */
+ if ((TargetPath->Buffer[TempLength / sizeof(WCHAR) - 1] ==
+ OBJ_NAME_PATH_SEPARATOR) &&
+ (RemainingName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
+ {
+ /* Reduce the length by one to cut off the extra '\' */
+ TempLength -= sizeof(OBJ_NAME_PATH_SEPARATOR);
+ }
+ }
+
+ /* Calculate the new length */
+ LengthUsed = TempLength + RemainingName->Length;
+
+ /* Check if it's not too much */
+ if (LengthUsed > 0xFFF0)
+ return STATUS_NAME_TOO_LONG;
/* Optimization: check if the new name is shorter */
if (FullPath->MaximumLength <= LengthUsed)
if (RemainingName->Length)
{
/* Copy the new path */
- RtlMoveMemory((PVOID)((ULONG_PTR)NewTargetPath + TargetPath->Length),
+ RtlMoveMemory((PVOID)((ULONG_PTR)NewTargetPath + TempLength),
RemainingName->Buffer,
RemainingName->Length);
}
/* Copy the target path and null-terminate it */
- RtlCopyMemory(NewTargetPath, TargetPath->Buffer, TargetPath->Length);
+ RtlCopyMemory(NewTargetPath, TargetPath->Buffer, TempLength);
NewTargetPath[LengthUsed / sizeof(WCHAR)] = UNICODE_NULL;
/* If the optimization didn't work, free the old buffer */
ExAllocatePoolWithTag(PagedPool,
CapturedLinkTarget.MaximumLength,
TAG_SYMLINK_TARGET);
- if (!SymbolicLink->LinkTarget.Buffer) return STATUS_NO_MEMORY;
+ if (!SymbolicLink->LinkTarget.Buffer)
+ {
+ /* Dereference the symbolic link object and fail */
+ ObDereferenceObject(SymbolicLink);
+ return STATUS_NO_MEMORY;
+ }
/* Copy it */
RtlCopyMemory(SymbolicLink->LinkTarget.Buffer,