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)
+ {
+ /* 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;
+
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("ObpCaptureObjectAttributes failed to probe object attributes 0x%p\n", ObjectAttributes);
+ KEBUGCHECK(0);
+ goto failbasiccleanup;
+ }
+ }
+ else if (!CaptureIfKernel)
{
- if (AccessMode != KernelMode)
+ if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
{
- DPRINT("Probing OBA\n");
- _SEH_TRY
+ if (ObjectName != NULL)
{
- /* FIXME: SMSS SENDS BULLSHIT. */
- #if 0
- ProbeForRead(ObjectAttributes,
- sizeof(ObjectAttributes),
- sizeof(ULONG));
- #endif
+ /* 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;
+ }
}
- _SEH_HANDLE
+ if (CapturedObjectAttributes != NULL)
{
- Status = _SEH_GetExceptionCode();
+ CapturedObjectAttributes->RootDirectory = ObjectAttributes->RootDirectory;
+ CapturedObjectAttributes->Attributes = ObjectAttributes->Attributes;
+ CapturedObjectAttributes->SecurityDescriptor = ObjectAttributes->SecurityDescriptor;
+ CapturedObjectAttributes->SecurityDescriptorCharge = 0; /* FIXME */
+ CapturedObjectAttributes->ProbeMode = AccessMode;
}
- _SEH_END;
+
+ return STATUS_SUCCESS;
}
-
- /* Validate the Size */
- DPRINT("Validating OBA\n");
- if (ObjectAttributes->Length != sizeof(OBJECT_ATTRIBUTES))
+ else
{
Status = STATUS_INVALID_PARAMETER;
+ goto failbasiccleanup;
}
+ }
+ else
+ {
+ AttributesCopy = *ObjectAttributes;
+ }
- /* Fail if SEH or Size Validation failed */
- if(!NT_SUCCESS(Status))
- {
- DPRINT1("ObpCaptureObjectAttributes failed to probe object attributes\n");
- goto fail;
- }
-
- /* 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)
+ /* 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)
{
- DPRINT("Probing SD: %x\n", SecurityDescriptor);
- Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
+ 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))
+ 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 */
{
- DPRINT1("Unable to capture QoS!!!\n");
- goto fail;
+ 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);
}
+ }
}
ObjectName->Buffer[0] != L'\\')
{
ObDereferenceObject (CurrentObject);
- DPRINT1("failed\n");
+ DPRINT1("failed: \"%wZ\"\n", ObjectName);
return STATUS_UNSUCCESSFUL;
}
/* Capture all the info */
DPRINT("Capturing Create Info\n");
Status = ObpCaptureObjectAttributes(ObjectAttributes,
- AccessMode,
- Type,
+ ObjectAttributesAccessMode,
+ NonPagedPool,
+ TRUE,
ObjectCreateInfo,
&ObjectName);
/* 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 */
}
if (Header->ObjectCreateInfo)
{
- ObpReleaseCapturedAttributes(Header->ObjectCreateInfo);
+ ObpReleaseCapturedAttributes(Header->ObjectCreateInfo,
+ NULL,
+ Header->ObjectCreateInfo->ProbeMode,
+ FALSE);
ExFreePool(Header->ObjectCreateInfo);
}