Author: ion
Date: Wed May 24 06:45:06 2006
New Revision: 22000
URL:
http://svn.reactos.ru/svn/reactos?rev=22000&view=rev
Log:
- Fix Symbolic Link implementation:
- Use OBJECT_SYMBOLIC_LINK structure as used by Windows NT (and added the structure to
the NDK)
- Changed code to use the new names in the structure
- Only free the symlink's name if it has one, to avoid a bugcheck.
- Optimize parsing: if the new name is actually shorter then the target name, then
don't allocate from pool, but re-use the buffer. This improves symlink parsing speed.
Also fix a bug which made it depend on the incorrect implementation of
NtCreateSymbolicLinkObject
- Re-align the link target maximum length in NtCreateSymbolicLinkObject if it's odd,
and fail if the length is odd, smaller then the maximum, or if the maximum is zero.
- Originally allocate the symlink name in Paged Pool.
- Initialize new members of the structure.
- Fail in no-memory case, instead of continuing.
- Properly probe the LinkTarget in NtQuerySymbolicLinkObject.
- Properly handle which length is chosen for the copy and for the return in
NtQuerySymbolicObject.
- Lock the symbolic link object type while querying it. Eventually many more parts of Ob
need to do this kind of locking.
- SymLinkTest now only gives 2 failures.
- Fix some NDK bugs
Modified:
trunk/reactos/include/ndk/exfuncs.h
trunk/reactos/include/ndk/obtypes.h
trunk/reactos/include/ndk/psfuncs.h
trunk/reactos/include/ndk/rtltypes.h
trunk/reactos/ntoskrnl/include/internal/ob.h
trunk/reactos/ntoskrnl/ob/ntobj.c
trunk/reactos/ntoskrnl/ob/symlink.c
Modified: trunk/reactos/include/ndk/exfuncs.h
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/include/ndk/exfuncs.h?rev=2…
==============================================================================
--- trunk/reactos/include/ndk/exfuncs.h (original)
+++ trunk/reactos/include/ndk/exfuncs.h Wed May 24 06:45:06 2006
@@ -859,7 +859,6 @@
);
NTSYSAPI
-NTSYSAPI
NTSTATUS
NTAPI
ZwSetEvent(
Modified: trunk/reactos/include/ndk/obtypes.h
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/include/ndk/obtypes.h?rev=2…
==============================================================================
--- trunk/reactos/include/ndk/obtypes.h (original)
+++ trunk/reactos/include/ndk/obtypes.h Wed May 24 06:45:06 2006
@@ -384,15 +384,29 @@
{
struct _OBJECT_DIRECTORY_ENTRY *ChainLink;
PVOID Object;
+#if (NTDDI_VERSION >= NTDDI_WS03)
ULONG HashValue;
+#endif
} OBJECT_DIRECTORY_ENTRY, *POBJECT_DIRECTORY_ENTRY;
typedef struct _OBJECT_DIRECTORY
{
struct _OBJECT_DIRECTORY_ENTRY *HashBuckets[NUMBER_HASH_BUCKETS];
- struct _EX_PUSH_LOCK *Lock;
+#if (NTDDI_VERSION < NTDDI_WINXP)
+ PERESOURCE Lock;
+#elif (NTDDI_VERSION >= NTDDI_WINXP)
+ EX_PUSH_LOCK Lock;
+#endif
+#if (NTDDI_VERSION < NTDDI_WINXP)
+ BOOLEAN CurrentEntryValid;
+#else
struct _DEVICE_MAP *DeviceMap;
+#endif
ULONG SessionId;
+#if (NTDDI_VERSION == NTDDI_WINXP)
+ USHORT Reserved;
+ USHORT SymbolicLinkUsageCount;
+#endif
} OBJECT_DIRECTORY, *POBJECT_DIRECTORY;
//
@@ -408,6 +422,18 @@
} DEVICE_MAP, *PDEVICE_MAP;
//
+// Symbolic Link Object
+//
+typedef struct _OBJECT_SYMBOLIC_LINK
+{
+ LARGE_INTEGER CreationTime;
+ UNICODE_STRING LinkTarget;
+ UNICODE_STRING LinkTargetRemaining;
+ PVOID LinkTargetObject;
+ ULONG DosDeviceDriveIndex;
+} OBJECT_SYMBOLIC_LINK, *POBJECT_SYMBOLIC_LINK;
+
+//
// Kernel Exports
//
extern POBJECT_TYPE NTSYSAPI ObDirectoryType;
Modified: trunk/reactos/include/ndk/psfuncs.h
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/include/ndk/psfuncs.h?rev=2…
==============================================================================
--- trunk/reactos/include/ndk/psfuncs.h (original)
+++ trunk/reactos/include/ndk/psfuncs.h Wed May 24 06:45:06 2006
@@ -298,7 +298,6 @@
);
NTSYSCALLAPI
-NTSYSCALLAPI
NTSTATUS
NTAPI
NtSetInformationThread(
Modified: trunk/reactos/include/ndk/rtltypes.h
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/include/ndk/rtltypes.h?rev=…
==============================================================================
--- trunk/reactos/include/ndk/rtltypes.h (original)
+++ trunk/reactos/include/ndk/rtltypes.h Wed May 24 06:45:06 2006
@@ -171,6 +171,42 @@
#define NLS_MB_CODE_PAGE_TAG NlsMbCodePageTag
#define NLS_MB_OEM_CODE_PAGE_TAG NlsMbOemCodePageTag
#define NLS_OEM_LEAD_BYTE_INFO NlsOemLeadByteInfo
+
+//
+// C++ CONST casting
+//
+#if defined(__cplusplus)
+#define RTL_CONST_CAST(type) const_cast<type>
+#else
+#define RTL_CONST_CAST(type) (type)
+#endif
+
+//
+// Constant String Macro
+//
+#define RTL_CONSTANT_STRING(__SOURCE_STRING__) \
+{ \
+ sizeof(__SOURCE_STRING__) - sizeof((__SOURCE_STRING__)[0]), \
+ sizeof(__SOURCE_STRING__), \
+ (__SOURCE_STRING__) \
+}
+
+//
+// Constant Object Attributes Macro
+//
+#define RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a) \
+{ \
+ sizeof(OBJECT_ATTRIBUTES), \
+ NULL, \
+ RTL_CONST_CAST(PUNICODE_STRING)(n), \
+ a, \
+ NULL, \
+ NULL \
+}
+
+#define RTL_INIT_OBJECT_ATTRIBUTES(n, a) \
+ RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a)
+
#else
//
// Message Resource Flag
Modified: trunk/reactos/ntoskrnl/include/internal/ob.h
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/include/internal/o…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ob.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ob.h Wed May 24 06:45:06 2006
@@ -22,14 +22,6 @@
LIST_ENTRY head;
KSPIN_LOCK Lock;
} DIRECTORY_OBJECT, *PDIRECTORY_OBJECT;
-
-typedef struct _SYMLINK_OBJECT
-{
- CSHORT Type;
- CSHORT Size;
- UNICODE_STRING TargetName;
- LARGE_INTEGER CreateTime;
-} SYMLINK_OBJECT, *PSYMLINK_OBJECT;
typedef struct _ROS_OBJECT_HEADER
{
Modified: trunk/reactos/ntoskrnl/ob/ntobj.c
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/ob/ntobj.c?rev=220…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/ntobj.c (original)
+++ trunk/reactos/ntoskrnl/ob/ntobj.c Wed May 24 06:45:06 2006
@@ -210,7 +210,7 @@
if (ObjectHeader->Type == ObSymbolicLinkType)
{
BasicInfo->CreateTime.QuadPart =
- ((PSYMLINK_OBJECT)Object)->CreateTime.QuadPart;
+ ((POBJECT_SYMBOLIC_LINK)Object)->CreationTime.QuadPart;
}
else
{
Modified: trunk/reactos/ntoskrnl/ob/symlink.c
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/ob/symlink.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/symlink.c (original)
+++ trunk/reactos/ntoskrnl/ob/symlink.c Wed May 24 06:45:06 2006
@@ -48,8 +48,15 @@
NTAPI
ObpDeleteSymbolicLink(PVOID ObjectBody)
{
- PSYMLINK_OBJECT SymlinkObject = (PSYMLINK_OBJECT)ObjectBody;
- ExFreePool(SymlinkObject->TargetName.Buffer);
+ POBJECT_SYMBOLIC_LINK SymlinkObject = (POBJECT_SYMBOLIC_LINK)ObjectBody;
+
+ /* Make sure that the symbolic link has a name */
+ if (SymlinkObject->LinkTarget.Buffer)
+ {
+ /* Free the name */
+ ExFreePool(SymlinkObject->LinkTarget.Buffer);
+ SymlinkObject->LinkTarget.Buffer = NULL;
+ }
}
/*++
@@ -85,10 +92,10 @@
PWSTR * RemainingPath,
ULONG Attributes)
{
- PSYMLINK_OBJECT SymlinkObject = (PSYMLINK_OBJECT) Object;
- UNICODE_STRING TargetPath;
-
- DPRINT("ObpParseSymbolicLink (RemainingPath %S)\n", *RemainingPath);
+ POBJECT_SYMBOLIC_LINK SymlinkObject = (POBJECT_SYMBOLIC_LINK)Object;
+ PUNICODE_STRING TargetPath;
+ PWSTR NewTargetPath;
+ ULONG LengthUsed, MaximumLength, RemainLength;
/*
* Stop parsing if the entire path has been parsed and
@@ -97,33 +104,51 @@
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,
+ /* Set the target path and length */
+ TargetPath = &SymlinkObject->LinkTarget;
+ RemainLength = *RemainingPath ? wcslen(*RemainingPath) * sizeof(WCHAR) : 0;
+ LengthUsed = TargetPath->Length + RemainLength;
+
+ /* Optimization: check if the new name is shorter */
+ if (FullPath->MaximumLength <= LengthUsed)
+ {
+ /* It's not, allocate a new one */
+ MaximumLength = LengthUsed + sizeof(WCHAR);
+ NewTargetPath = ExAllocatePoolWithTag(NonPagedPool,
+ MaximumLength,
TAG_SYMLINK_TTARGET);
- wcscpy(TargetPath.Buffer, SymlinkObject->TargetName.Buffer);
- if (RemainingPath && *RemainingPath)
- {
- wcscat(TargetPath.Buffer, *RemainingPath);
- }
-
- /* Transfer target path buffer into FullPath */
- ExFreePool(FullPath->Buffer);
- FullPath->Length = TargetPath.Length;
- FullPath->MaximumLength = TargetPath.MaximumLength;
- FullPath->Buffer = TargetPath.Buffer;
+ }
+ else
+ {
+ /* It is! Reuse the name... */
+ MaximumLength = FullPath->MaximumLength;
+ NewTargetPath = FullPath->Buffer;
+ }
+
+ /* Make sure we have a length */
+ if (RemainLength)
+ {
+ /* Copy the new path */
+ RtlMoveMemory((PVOID)((ULONG_PTR)NewTargetPath + TargetPath->Length),
+ *RemainingPath,
+ RemainLength);
+ }
+
+ /* Copy the target path and null-terminate it */
+ RtlMoveMemory(NewTargetPath, TargetPath->Buffer, TargetPath->Length);
+ NewTargetPath[LengthUsed / sizeof(WCHAR)] = UNICODE_NULL;
+
+ /* If the optimization didn't work, free the old buffer */
+ if (NewTargetPath != FullPath->Buffer) ExFreePool(FullPath->Buffer);
+
+ /* Update the path values */
+ FullPath->Length = LengthUsed;
+ FullPath->MaximumLength = MaximumLength;
+ FullPath->Buffer = NewTargetPath;
/* Reinitialize RemainingPath for reparsing */
*RemainingPath = FullPath->Buffer;
@@ -152,13 +177,11 @@
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.DefaultNonPagedPoolCharge = sizeof(OBJECT_SYMBOLIC_LINK);
ObjectTypeInitializer.GenericMapping = ObpSymbolicLinkMapping;
ObjectTypeInitializer.PoolType = NonPagedPool;
ObjectTypeInitializer.ValidAccessMask = SYMBOLIC_LINK_ALL_ACCESS;
@@ -201,72 +224,99 @@
IN PUNICODE_STRING LinkTarget)
{
HANDLE hLink;
- PSYMLINK_OBJECT SymbolicLink;
+ POBJECT_SYMBOLIC_LINK SymbolicLink;
UNICODE_STRING CapturedLinkTarget;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
- DPRINT("NtCreateSymbolicLinkObject(LinkHandle %p, DesiredAccess %ul"
- ", ObjectAttributes %p, LinkTarget %wZ)\n",
- LinkHandle,
- DesiredAccess,
- ObjectAttributes,
- LinkTarget);
-
+ /* Check if we need to probe parameters */
if(PreviousMode != KernelMode)
{
_SEH_TRY
{
+ /* Probe the target */
+ ProbeForRead(LinkTarget, sizeof(UNICODE_STRING), sizeof(WCHAR));
+ CapturedLinkTarget = *LinkTarget;
+ ProbeForRead(CapturedLinkTarget.Buffer,
+ CapturedLinkTarget.MaximumLength,
+ sizeof(WCHAR));
+
+ /* Probe the return handle */
ProbeForWriteHandle(LinkHandle);
}
_SEH_HANDLE
{
+ /* Exception, get the error code */
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;
- }
-
+ /* Probing failed, return the error code */
+ if(!NT_SUCCESS(Status)) return Status;
+ }
+ else
+ {
+ /* No need to capture */
+ CapturedLinkTarget = *LinkTarget;
+ }
+
+ /* Check if the maximum length is odd */
+ if (CapturedLinkTarget.MaximumLength % sizeof(WCHAR))
+ {
+ /* Round it down */
+ CapturedLinkTarget.MaximumLength =
+ ALIGN_DOWN(CapturedLinkTarget.MaximumLength, WCHAR);
+ }
+
+ /* Fail if the length is odd, or if the maximum is smaller or 0 */
+ if ((CapturedLinkTarget.Length % sizeof(WCHAR)) ||
+ (CapturedLinkTarget.MaximumLength < CapturedLinkTarget.Length) ||
+ !(CapturedLinkTarget.MaximumLength))
+ {
+ /* This message is displayed on the debugger in Windows */
+ DbgPrint("OB: Invalid symbolic link target - %wZ\n",
+ &CapturedLinkTarget);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Create the object */
Status = ObCreateObject(PreviousMode,
ObSymbolicLinkType,
ObjectAttributes,
PreviousMode,
NULL,
- sizeof(SYMLINK_OBJECT),
+ sizeof(OBJECT_SYMBOLIC_LINK),
0,
0,
(PVOID*)&SymbolicLink);
if (NT_SUCCESS(Status))
{
- SymbolicLink->TargetName.Length = 0;
- SymbolicLink->TargetName.MaximumLength = CapturedLinkTarget.Length +
+ /* Success! Fill in the creation time immediately */
+ KeQuerySystemTime(&SymbolicLink->CreationTime);
+
+ /* Setup the target name */
+ SymbolicLink->LinkTarget.Length = CapturedLinkTarget.Length;
+ SymbolicLink->LinkTarget.MaximumLength = CapturedLinkTarget.Length +
sizeof(WCHAR);
- SymbolicLink->TargetName.Buffer =
- ExAllocatePoolWithTag(NonPagedPool,
- SymbolicLink->TargetName.MaximumLength,
+ SymbolicLink->LinkTarget.Buffer =
+ ExAllocatePoolWithTag(PagedPool,
+ CapturedLinkTarget.MaximumLength,
TAG_SYMLINK_TARGET);
-
- RtlCopyUnicodeString(&SymbolicLink->TargetName, &CapturedLinkTarget);
-
- DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer);
-
- ZwQuerySystemTime (&SymbolicLink->CreateTime);
-
- Status = ObInsertObject((PVOID)SymbolicLink,
+ if (!SymbolicLink->LinkTarget.Buffer) return STATUS_NO_MEMORY;
+
+ /* Copy it */
+ RtlMoveMemory(SymbolicLink->LinkTarget.Buffer,
+ CapturedLinkTarget.Buffer,
+ CapturedLinkTarget.MaximumLength);
+
+ /* Initialize the remaining name, dos drive index and target object */
+ SymbolicLink->LinkTargetObject = NULL;
+ SymbolicLink->DosDeviceDriveIndex = 0;
+ RtlInitUnicodeString(&SymbolicLink->LinkTargetRemaining, NULL);
+
+ /* Insert it into the object tree */
+ Status = ObInsertObject(SymbolicLink,
NULL,
DesiredAccess,
0,
@@ -276,18 +326,22 @@
{
_SEH_TRY
{
+ /* Return the handle to caller */
*LinkHandle = hLink;
}
_SEH_HANDLE
{
+ /* Get exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
+
+ /* ReactOS Hack: Our ObInsertObject references an object twice */
ObDereferenceObject(SymbolicLink);
}
- ReleaseCapturedUnicodeString(&CapturedLinkTarget, PreviousMode);
+ /* Return status to caller */
return Status;
}
@@ -322,27 +376,26 @@
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
+ /* Check if we need to probe parameters */
if(PreviousMode != KernelMode)
{
_SEH_TRY
{
+ /* Probe the return handle */
ProbeForWriteHandle(LinkHandle);
}
_SEH_HANDLE
{
+ /* Exception, get the error code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
- if(!NT_SUCCESS(Status))
- {
- return Status;
- }
- }
-
- DPRINT("NtOpenSymbolicLinkObject (Name %wZ)\n",
- ObjectAttributes->ObjectName);
-
+ /* Probing failed, return the error code */
+ if(!NT_SUCCESS(Status)) return Status;
+ }
+
+ /* Open the object */
Status = ObOpenObjectByName(ObjectAttributes,
ObSymbolicLinkType,
NULL,
@@ -350,19 +403,22 @@
DesiredAccess,
NULL,
&hLink);
- if(NT_SUCCESS(Status))
+ if (NT_SUCCESS(Status))
{
_SEH_TRY
{
+ /* Return the handle to caller */
*LinkHandle = hLink;
}
_SEH_HANDLE
{
+ /* Get exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
+ /* Return status to caller */
return Status;
}
@@ -393,46 +449,47 @@
OUT PULONG ResultLength OPTIONAL)
{
UNICODE_STRING SafeLinkTarget;
- PSYMLINK_OBJECT SymlinkObject;
+ POBJECT_SYMBOLIC_LINK SymlinkObject;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
- ULONG LengthRequired;
+ ULONG LengthUsed;
PAGED_CODE();
if(PreviousMode != KernelMode)
{
_SEH_TRY
{
- /* probe the unicode string and buffers supplied */
- ProbeForWrite(LinkTarget, sizeof(UNICODE_STRING), sizeof(ULONG));
-
+ /* Probe the unicode string for read and write */
+ ProbeForRead(LinkTarget, sizeof(UNICODE_STRING), sizeof(WCHAR));
+ ProbeForWriteUshort(&LinkTarget->Length);
+ ProbeForWriteUshort(&LinkTarget->MaximumLength);
+
+ /* Probe the unicode string's buffer for write */
SafeLinkTarget = *LinkTarget;
-
ProbeForWrite(SafeLinkTarget.Buffer,
SafeLinkTarget.MaximumLength,
- sizeof(WCHAR));
-
- if(ResultLength != NULL)
- {
- ProbeForWriteUlong(ResultLength);
- }
+ sizeof(CHAR));
+
+ /* Probe the return length */
+ if(ResultLength) ProbeForWriteUlong(ResultLength);
}
_SEH_HANDLE
{
+ /* Probe failure: get exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
- if(!NT_SUCCESS(Status))
- {
- return Status;
- }
+ /* Probe failed, return status */
+ if(!NT_SUCCESS(Status)) return Status;
}
else
{
+ /* No need to probe */
SafeLinkTarget = *LinkTarget;
}
+ /* Reference the object */
Status = ObReferenceObjectByHandle(LinkHandle,
SYMBOLIC_LINK_QUERY,
ObSymbolicLinkType,
@@ -441,44 +498,59 @@
NULL);
if (NT_SUCCESS(Status))
{
- LengthRequired = SymlinkObject->TargetName.Length + sizeof(WCHAR);
-
+ /* Lock the object type */
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&ObSymbolicLinkType->Mutex, TRUE);
+
+ /*
+ * So here's the thing: If you specify a return length, then the
+ * implementation will use the maximum length. If you don't, then
+ * it will use the length.
+ */
+ LengthUsed = ResultLength ? SymlinkObject->LinkTarget.MaximumLength :
+ SymlinkObject->LinkTarget.Length;
+
+ /* Enter SEH so we can safely copy */
_SEH_TRY
{
- if(SafeLinkTarget.MaximumLength >= LengthRequired)
+ /* Make sure our buffer will fit */
+ if (LengthUsed <= SafeLinkTarget.MaximumLength)
{
- /*
- * 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)] = UNICODE_NULL;
-
- /* Copy back the new UNICODE_STRING structure */
- *LinkTarget = SafeLinkTarget;
+ /* Copy the buffer */
+ RtlMoveMemory(SafeLinkTarget.Buffer,
+ SymlinkObject->LinkTarget.Buffer,
+ LengthUsed);
+
+ /* Copy the new length */
+ LinkTarget->Length = SymlinkObject->LinkTarget.Length;
}
else
{
+ /* Otherwise set the failure status */
Status = STATUS_BUFFER_TOO_SMALL;
}
- if(ResultLength != NULL)
+ /* In both cases, check if the required length was requested */
+ if (ResultLength)
{
- *ResultLength = LengthRequired;
+ /* Then return it */
+ *ResultLength = SymlinkObject->LinkTarget.MaximumLength;
}
}
_SEH_HANDLE
{
+ /* Get the error code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
+ /* Unlock the object type and reference the object */
+ ExReleaseResourceLite(&ObSymbolicLinkType->Mutex);
+ KeLeaveCriticalRegion();
ObDereferenceObject(SymlinkObject);
}
+ /* Return query status */
return Status;
}