- reverted ObpCaptureObjectAttributes back to my old implementation (slightly modified and extended) because that one at least does what it's supposed to correctly

svn path=/trunk/; revision=17205
This commit is contained in:
Thomas Bluemel 2005-08-08 15:39:35 +00:00
parent 910c9075f0
commit a3abeb83af
7 changed files with 333 additions and 158 deletions

View file

@ -192,20 +192,19 @@ NtCreateKey(OUT PHANDLE KeyHandle,
PWSTR Start;
UNICODE_STRING ObjectName;
OBJECT_CREATE_INFORMATION ObjectCreateInfo;
KPROCESSOR_MODE PreviousMode;
unsigned i;
PAGED_CODE();
DPRINT("NtCreateKey (Name %wZ KeyHandle 0x%p Root 0x%p)\n",
ObjectAttributes->ObjectName,
KeyHandle,
ObjectAttributes->RootDirectory);
PreviousMode = KeGetPreviousMode();
/* Capture all the info */
DPRINT("Capturing Create Info\n");
Status = ObpCaptureObjectAttributes(ObjectAttributes,
KeGetPreviousMode(),
CmiKeyType,
PreviousMode,
PagedPool,
FALSE,
&ObjectCreateInfo,
&ObjectName);
if (!NT_SUCCESS(Status))
@ -219,8 +218,10 @@ NtCreateKey(OUT PHANDLE KeyHandle,
(PVOID*)&Object,
&RemainingPath,
CmiKeyType);
ObpReleaseCapturedAttributes(&ObjectCreateInfo);
if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
ObpReleaseCapturedAttributes(&ObjectCreateInfo,
&ObjectName,
PreviousMode,
FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT("CmpFindObject failed, Status: 0x%x\n", Status);
@ -1169,7 +1170,8 @@ NtOpenKey(OUT PHANDLE KeyHandle,
DPRINT("Capturing Create Info\n");
Status = ObpCaptureObjectAttributes(ObjectAttributes,
PreviousMode,
CmiKeyType,
PagedPool,
FALSE,
&ObjectCreateInfo,
&ObjectName);
if (!NT_SUCCESS(Status))
@ -1185,8 +1187,10 @@ NtOpenKey(OUT PHANDLE KeyHandle,
(PVOID*)&Object,
&RemainingPath,
CmiKeyType);
ObpReleaseCapturedAttributes(&ObjectCreateInfo);
if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
ObpReleaseCapturedAttributes(&ObjectCreateInfo,
&ObjectName,
PreviousMode,
FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT("CmpFindObject() returned 0x%08lx\n", Status);

View file

@ -705,7 +705,8 @@ CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
DPRINT("Capturing Create Info\n");
Status = ObpCaptureObjectAttributes(KeyObjectAttributes,
KernelMode,
CmiKeyType,
PagedPool,
FALSE,
&ObjectCreateInfo,
&ObjectName);
if (!NT_SUCCESS(Status))
@ -719,8 +720,10 @@ CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
(PVOID*)&ParentKey,
&RemainingPath,
CmiKeyType);
ObpReleaseCapturedAttributes(&ObjectCreateInfo);
if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
ObpReleaseCapturedAttributes(&ObjectCreateInfo,
&ObjectName,
KernelMode,
FALSE);
if (!NT_SUCCESS(Status))
{
return Status;

View file

@ -173,14 +173,6 @@ ObFastDereferenceObject(IN PEX_FAST_REF FastRef,
/* Secure object information functions */
typedef struct _CAPTURED_OBJECT_ATTRIBUTES
{
HANDLE RootDirectory;
ULONG Attributes;
PSECURITY_DESCRIPTOR SecurityDescriptor;
PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
} CAPTURED_OBJECT_ATTRIBUTES, *PCAPTURED_OBJECT_ATTRIBUTES;
NTSTATUS
STDCALL
ObpCaptureObjectName(IN PUNICODE_STRING CapturedName,
@ -189,16 +181,19 @@ ObpCaptureObjectName(IN PUNICODE_STRING CapturedName,
NTSTATUS
STDCALL
ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes,
ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN KPROCESSOR_MODE AccessMode,
IN POBJECT_TYPE ObjectType,
IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
OUT PUNICODE_STRING ObjectName);
IN POOL_TYPE PoolType,
IN BOOLEAN CaptureIfKernel,
OUT POBJECT_CREATE_INFORMATION CapturedObjectAttributes OPTIONAL,
OUT PUNICODE_STRING ObjectName OPTIONAL);
VOID
STDCALL
ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo);
ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION CapturedObjectAttributes OPTIONAL,
IN PUNICODE_STRING ObjectName OPTIONAL,
IN KPROCESSOR_MODE AccessMode,
IN BOOLEAN CaptureIfKernel);
/* object information classes */
#define ICIF_QUERY 0x1

View file

@ -410,7 +410,7 @@ NtConnectPort (PHANDLE UnsafeConnectedPortHandle,
NULL,
PORT_ALL_ACCESS, /* DesiredAccess */
LpcPortObjectType,
UserMode,
PreviousMode,
NULL,
(PVOID*)&NamedPort);
if (!NT_SUCCESS(Status))
@ -430,7 +430,7 @@ NtConnectPort (PHANDLE UnsafeConnectedPortHandle,
Status = ObReferenceObjectByHandle(WriteMap.SectionHandle,
SECTION_MAP_READ | SECTION_MAP_WRITE,
MmSectionObjectType,
UserMode,
PreviousMode,
(PVOID*)&SectionObject,
NULL);
if (!NT_SUCCESS(Status))

View file

@ -955,7 +955,7 @@ ObInsertObject(IN PVOID Object,
/* First try to find the Object */
if (ObjectNameInfo && ObjectNameInfo->Name.Buffer)
{
DPRINT("Object has a name. Trying to find it: %wZ.\n", &ObjectNameInfo->Name);
DPRINT("Object has a name. Trying to find it: \"%wZ\".\n", &ObjectNameInfo->Name);
Status = ObFindObject(ObjectCreateInfo,
&ObjectNameInfo->Name,
&FoundObject,
@ -1132,7 +1132,10 @@ ObInsertObject(IN PVOID Object,
/* We can delete the Create Info now */
Header->ObjectCreateInfo = NULL;
ObpReleaseCapturedAttributes(ObjectCreateInfo);
ObpReleaseCapturedAttributes(ObjectCreateInfo,
NULL,
ObjectCreateInfo->ProbeMode,
FALSE);
ExFreePool(ObjectCreateInfo);
DPRINT("Status %x\n", Status);

View file

@ -70,20 +70,35 @@ ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
NTSTATUS Status;
PAGED_CODE();
/* capture the ObjectPath */
Status = RtlCaptureUnicodeString(&ObjectName,
AccessMode,
NonPagedPool, /* FIXME */
FALSE,
ObjectPath);
if (!NT_SUCCESS(Status))
{
DPRINT("RtlCaptureUnicodeString() failed (Status %lx)\n", Status);
return Status;
}
InitializeObjectAttributes(&ObjectAttributes,
ObjectPath,
&ObjectName,
Attributes | OBJ_OPENIF,
NULL,
NULL);
/* Capture all the info */
/* "Capture" all the info, it doesn't make sense to capture from the kernel
stack as the information should be safe anyway...just do a raw copy of the
data into the OBJECT_CREATE_INFORMATION structure */
DPRINT("Capturing Create Info\n");
Status = ObpCaptureObjectAttributes(&ObjectAttributes,
AccessMode,
ObjectType,
KernelMode, /* raw copy! */
NonPagedPool,
FALSE,
&ObjectCreateInfo,
&ObjectName);
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status);
@ -96,8 +111,18 @@ ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
&RemainingPath,
ObjectType);
ObpReleaseCapturedAttributes(&ObjectCreateInfo);
if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
/* we don't need to release the "captured" object attributes! Nothing was allocated! */
#if 0
ObpReleaseCapturedAttributes(&ObjectCreateInfo,
NULL,
AccessMode,
FALSE);
#endif
/* free the captured ObjectPath if needed */
RtlReleaseCapturedUnicodeString(&ObjectName,
AccessMode,
FALSE);
if (!NT_SUCCESS(Status))
{
@ -169,7 +194,8 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
DPRINT("Capturing Create Info\n");
Status = ObpCaptureObjectAttributes(ObjectAttributes,
AccessMode,
ObjectType,
PagedPool,
FALSE,
&ObjectCreateInfo,
&ObjectName);
if (!NT_SUCCESS(Status))
@ -183,8 +209,10 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
&Object,
&RemainingPath,
ObjectType);
ObpReleaseCapturedAttributes(&ObjectCreateInfo);
if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
ObpReleaseCapturedAttributes(&ObjectCreateInfo,
&ObjectName,
AccessMode,
FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT("ObFindObject() failed (Status %lx)\n", Status);

View file

@ -110,162 +110,298 @@ ObpCaptureObjectName(IN OUT PUNICODE_STRING CapturedName,
NTSTATUS
STDCALL
ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes,
ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN KPROCESSOR_MODE AccessMode,
IN POBJECT_TYPE ObjectType,
IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
OUT PUNICODE_STRING ObjectName)
IN POOL_TYPE PoolType,
IN BOOLEAN CaptureIfKernel,
OUT POBJECT_CREATE_INFORMATION CapturedObjectAttributes OPTIONAL,
OUT PUNICODE_STRING ObjectName OPTIONAL)
{
OBJECT_ATTRIBUTES AttributesCopy;
NTSTATUS Status = STATUS_SUCCESS;
PSECURITY_DESCRIPTOR SecurityDescriptor;
PSECURITY_QUALITY_OF_SERVICE SecurityQos;
PUNICODE_STRING LocalObjectName = NULL;
/* Zero out the Capture Data */
DPRINT("ObpCaptureObjectAttributes\n");
RtlZeroMemory(ObjectCreateInfo, sizeof(OBJECT_CREATE_INFORMATION));
/* Check if we got Oba */
if (ObjectAttributes)
/* at least one output parameter must be != NULL! */
ASSERT(CapturedObjectAttributes != NULL || ObjectName != NULL);
if (ObjectAttributes == NULL)
{
if (AccessMode != KernelMode)
{
DPRINT("Probing OBA\n");
_SEH_TRY
{
/* FIXME: SMSS SENDS BULLSHIT. */
#if 0
ProbeForRead(ObjectAttributes,
sizeof(ObjectAttributes),
sizeof(ULONG));
#endif
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
/* Validate the Size */
DPRINT("Validating OBA\n");
if (ObjectAttributes->Length != sizeof(OBJECT_ATTRIBUTES))
{
Status = STATUS_INVALID_PARAMETER;
}
/* we're going to return STATUS_SUCCESS! */
goto failbasiccleanup;
}
if (AccessMode != KernelMode)
{
_SEH_TRY
{
ProbeForRead(ObjectAttributes,
sizeof(ObjectAttributes),
sizeof(ULONG));
/* make a copy on the stack */
AttributesCopy = *ObjectAttributes;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
/* Fail if SEH or Size Validation failed */
if(!NT_SUCCESS(Status))
{
DPRINT1("ObpCaptureObjectAttributes failed to probe object attributes\n");
goto fail;
DPRINT1("ObpCaptureObjectAttributes failed to probe object attributes 0x%p\n", ObjectAttributes);
KEBUGCHECK(0);
goto failbasiccleanup;
}
/* Set some Create Info */
DPRINT("Creating OBCI\n");
ObjectCreateInfo->RootDirectory = ObjectAttributes->RootDirectory;
ObjectCreateInfo->Attributes = ObjectAttributes->Attributes;
LocalObjectName = ObjectAttributes->ObjectName;
SecurityDescriptor = ObjectAttributes->SecurityDescriptor;
SecurityQos = ObjectAttributes->SecurityQualityOfService;
/* Validate the SD */
if (SecurityDescriptor)
}
else if (!CaptureIfKernel)
{
if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
{
DPRINT("Probing SD: %x\n", SecurityDescriptor);
Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
if (ObjectName != NULL)
{
/* we don't have to capture any memory, the caller considers the passed data
as valid */
if (ObjectAttributes->ObjectName != NULL)
{
*ObjectName = *ObjectAttributes->ObjectName;
}
else
{
ObjectName->Length = ObjectName->MaximumLength = 0;
ObjectName->Buffer = NULL;
}
}
if (CapturedObjectAttributes != NULL)
{
CapturedObjectAttributes->RootDirectory = ObjectAttributes->RootDirectory;
CapturedObjectAttributes->Attributes = ObjectAttributes->Attributes;
CapturedObjectAttributes->SecurityDescriptor = ObjectAttributes->SecurityDescriptor;
CapturedObjectAttributes->SecurityDescriptorCharge = 0; /* FIXME */
CapturedObjectAttributes->ProbeMode = AccessMode;
}
return STATUS_SUCCESS;
}
else
{
Status = STATUS_INVALID_PARAMETER;
goto failbasiccleanup;
}
}
else
{
AttributesCopy = *ObjectAttributes;
}
/* if Length isn't as expected, bail with an invalid parameter status code so
the caller knows he passed garbage... */
if (AttributesCopy.Length != sizeof(OBJECT_ATTRIBUTES))
{
Status = STATUS_INVALID_PARAMETER;
goto failbasiccleanup;
}
if (CapturedObjectAttributes != NULL)
{
CapturedObjectAttributes->RootDirectory = AttributesCopy.RootDirectory;
CapturedObjectAttributes->Attributes = AttributesCopy.Attributes;
if (AttributesCopy.SecurityDescriptor != NULL)
{
Status = SeCaptureSecurityDescriptor(AttributesCopy.SecurityDescriptor,
AccessMode,
NonPagedPool,
PoolType,
TRUE,
&ObjectCreateInfo->SecurityDescriptor);
if(!NT_SUCCESS(Status))
&CapturedObjectAttributes->SecurityDescriptor);
if (!NT_SUCCESS(Status))
{
DPRINT1("Unable to capture the security descriptor!!!\n");
ObjectCreateInfo->SecurityDescriptor = NULL;
goto fail;
goto failbasiccleanup;
}
DPRINT("Probe done\n");
ObjectCreateInfo->SecurityDescriptorCharge = 0; /* FIXME */
ObjectCreateInfo->ProbeMode = AccessMode;
CapturedObjectAttributes->SecurityDescriptorCharge = 0; /* FIXME */
}
/* Validate the QoS */
if (SecurityQos)
else
{
CapturedObjectAttributes->SecurityDescriptor = NULL;
CapturedObjectAttributes->SecurityDescriptorCharge = 0;
}
}
if (ObjectName != NULL)
{
ObjectName->Buffer = NULL;
if (AttributesCopy.ObjectName != NULL)
{
UNICODE_STRING OriginalCopy = {0};
if (AccessMode != KernelMode)
{
DPRINT("Probing QoS\n");
_SEH_TRY
{
ProbeForRead(SecurityQos,
sizeof(SECURITY_QUALITY_OF_SERVICE),
/* probe the ObjectName structure and make a local stack copy of it */
ProbeForRead(AttributesCopy.ObjectName,
sizeof(UNICODE_STRING),
sizeof(ULONG));
OriginalCopy = *AttributesCopy.ObjectName;
if (OriginalCopy.Length > 0)
{
ProbeForRead(OriginalCopy.Buffer,
OriginalCopy.Length,
sizeof(WCHAR));
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
if(!NT_SUCCESS(Status))
{
DPRINT1("Unable to capture QoS!!!\n");
goto fail;
if (NT_SUCCESS(Status))
{
ObjectName->Length = OriginalCopy.Length;
if(OriginalCopy.Length > 0)
{
ObjectName->MaximumLength = OriginalCopy.Length + sizeof(WCHAR);
ObjectName->Buffer = ExAllocatePool(PoolType,
ObjectName->MaximumLength);
if (ObjectName->Buffer != NULL)
{
_SEH_TRY
{
/* no need to probe OriginalCopy.Buffer again, we already did that
when capturing the UNICODE_STRING structure itself */
RtlCopyMemory(ObjectName->Buffer, OriginalCopy.Buffer, OriginalCopy.Length);
ObjectName->Buffer[OriginalCopy.Length / sizeof(WCHAR)] = L'\0';
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if (!NT_SUCCESS(Status))
{
DPRINT1("ObpCaptureObjectAttributes failed to copy the unicode string!\n");
}
}
else
{
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
else if(AttributesCopy.RootDirectory != NULL /* && OriginalCopy.Length == 0 */)
{
/* if the caller specified a root directory, there must be an object name! */
Status = STATUS_OBJECT_NAME_INVALID;
}
else
{
ObjectName->Length = ObjectName->MaximumLength = 0;
}
}
#ifdef DBG
else
{
DPRINT1("ObpCaptureObjectAttributes failed to probe the object name UNICODE_STRING structure!\n");
}
#endif
}
else /* AccessMode == KernelMode */
{
OriginalCopy = *AttributesCopy.ObjectName;
ObjectName->Length = OriginalCopy.Length;
if (OriginalCopy.Length > 0)
{
ObjectName->MaximumLength = OriginalCopy.Length + sizeof(WCHAR);
ObjectName->Buffer = ExAllocatePool(PoolType,
ObjectName->MaximumLength);
if (ObjectName->Buffer != NULL)
{
RtlCopyMemory(ObjectName->Buffer, OriginalCopy.Buffer, OriginalCopy.Length);
ObjectName->Buffer[OriginalCopy.Length / sizeof(WCHAR)] = L'\0';
}
else
{
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
else if (AttributesCopy.RootDirectory != NULL /* && OriginalCopy.Length == 0 */)
{
/* if the caller specified a root directory, there must be an object name! */
Status = STATUS_OBJECT_NAME_INVALID;
}
else
{
ObjectName->Length = ObjectName->MaximumLength = 0;
}
}
ObjectCreateInfo->SecurityQualityOfService = *SecurityQos;
ObjectCreateInfo->SecurityQos = &ObjectCreateInfo->SecurityQualityOfService;
}
}
/* Clear Local Object Name */
DPRINT("Clearing name\n");
RtlZeroMemory(ObjectName, sizeof(UNICODE_STRING));
/* Now check if the Object Attributes had an Object Name */
if (LocalObjectName)
{
DPRINT("Name Buffer: %x\n", LocalObjectName->Buffer);
Status = ObpCaptureObjectName(ObjectName,
LocalObjectName,
AccessMode);
}
else
{
/* He can't have specified a Root Directory */
if (ObjectCreateInfo->RootDirectory)
else
{
DPRINT1("Invalid name\n");
Status = STATUS_OBJECT_NAME_INVALID;
ObjectName->Length = ObjectName->MaximumLength = 0;
}
}
fail:
CapturedObjectAttributes->ProbeMode = AccessMode;
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to capture, cleaning up\n");
ObpReleaseCapturedAttributes(ObjectCreateInfo);
if (ObjectName->Buffer)
{
ExFreePool(ObjectName->Buffer);
}
if (CapturedObjectAttributes != NULL)
{
/* cleanup allocated resources */
SeReleaseSecurityDescriptor(CapturedObjectAttributes->SecurityDescriptor,
AccessMode,
TRUE);
}
failbasiccleanup:
if (ObjectName != NULL)
{
ObjectName->Length = ObjectName->MaximumLength = 0;
ObjectName->Buffer = NULL;
}
if (CapturedObjectAttributes != NULL)
{
RtlZeroMemory(CapturedObjectAttributes, sizeof(OBJECT_CREATE_INFORMATION));
}
}
DPRINT("Return to caller\n");
return Status;
}
VOID
STDCALL
ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo)
ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION CapturedObjectAttributes OPTIONAL,
IN PUNICODE_STRING ObjectName OPTIONAL,
IN KPROCESSOR_MODE AccessMode,
IN BOOLEAN CaptureIfKernel)
{
/* Release the SD, it's the only thing we allocated */
if (ObjectCreateInfo->SecurityDescriptor)
/* WARNING - You need to pass the same parameters to this function as you passed
to ObpCaptureObjectAttributes() to avoid memory leaks */
if(AccessMode != KernelMode || CaptureIfKernel)
{
if(CapturedObjectAttributes != NULL &&
CapturedObjectAttributes->SecurityDescriptor != NULL)
{
SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor,
ObjectCreateInfo->ProbeMode,
TRUE);
ObjectCreateInfo->SecurityDescriptor = NULL;
ExFreePool(CapturedObjectAttributes->SecurityDescriptor);
#ifdef DBG
RtlZeroMemory(CapturedObjectAttributes, sizeof(OBJECT_CREATE_INFORMATION));
#endif
}
if(ObjectName != NULL &&
ObjectName->Length > 0)
{
ExFreePool(ObjectName->Buffer);
}
}
}
@ -348,7 +484,7 @@ ObFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
ObjectName->Buffer[0] != L'\\')
{
ObDereferenceObject (CurrentObject);
DPRINT1("failed\n");
DPRINT1("failed: \"%wZ\"\n", ObjectName);
return STATUS_UNSUCCESSFUL;
}
@ -795,8 +931,9 @@ ObCreateObject(IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL,
/* Capture all the info */
DPRINT("Capturing Create Info\n");
Status = ObpCaptureObjectAttributes(ObjectAttributes,
AccessMode,
Type,
ObjectAttributesAccessMode,
NonPagedPool,
TRUE,
ObjectCreateInfo,
&ObjectName);
@ -822,8 +959,10 @@ ObCreateObject(IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL,
/* Release the Capture Info, we don't need it */
DPRINT1("Allocation failed\n");
ObpReleaseCapturedAttributes(ObjectCreateInfo);
if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
ObpReleaseCapturedAttributes(ObjectCreateInfo,
&ObjectName,
ObjectAttributesAccessMode,
TRUE);
}
/* We failed, so release the Buffer */
@ -977,7 +1116,10 @@ ObpDeleteObject(POBJECT_HEADER Header)
}
if (Header->ObjectCreateInfo)
{
ObpReleaseCapturedAttributes(Header->ObjectCreateInfo);
ObpReleaseCapturedAttributes(Header->ObjectCreateInfo,
NULL,
Header->ObjectCreateInfo->ProbeMode,
FALSE);
ExFreePool(Header->ObjectCreateInfo);
}