#define UNICODE_PATH_SEP L'\\'
#define UNICODE_NO_PATH L"..."
+#define OB_NAME_TAG TAG('O','b','N','m')
typedef struct _RETENTION_CHECK_PARAMS
{
IN KPROCESSOR_MODE AccessMode)
{
NTSTATUS Status = STATUS_SUCCESS;
+ ULONG StringLength;
+ PWCHAR StringBuffer = NULL;
UNICODE_STRING LocalName = {}; /* <= GCC 4.0 + Optimizer */
- /* First Probe the String */
- DPRINT("ObpCaptureObjectName: %wZ\n", ObjectName);
- if (AccessMode != KernelMode)
+ /* Initialize the Input String */
+ RtlInitUnicodeString(CapturedName, NULL);
+
+ /* Protect everything */
+ _SEH_TRY
{
- DPRINT("Probing Struct\n");
- _SEH_TRY
+ /* First Probe the String */
+ DPRINT("ObpCaptureObjectName: %wZ\n", ObjectName);
+ if (AccessMode != KernelMode)
{
- /* FIXME: Explorer or win32 broken I think */
- #if 0
ProbeForRead(ObjectName,
sizeof(UNICODE_STRING),
sizeof(USHORT));
- #endif
LocalName = *ObjectName;
+
+ ProbeForRead(LocalName.Buffer,
+ LocalName.Length,
+ sizeof(WCHAR));
}
- _SEH_HANDLE
+ else
{
- Status = _SEH_GetExceptionCode();
+ /* No probing needed */
+ LocalName = *ObjectName;
}
- _SEH_END;
-
- if (NT_SUCCESS(Status))
+
+ /* Make sure there really is a string */
+ DPRINT("Probing OK\n");
+ if ((StringLength = LocalName.Length))
{
- DPRINT("Probing OK\n");
- _SEH_TRY
+ /* Check that the size is a valid WCHAR multiple */
+ if ((StringLength & (sizeof(WCHAR) - 1)) ||
+ /* Check that the NULL-termination below will work */
+ (StringLength == (MAXUSHORT - sizeof(WCHAR) + 1)))
{
- #if 0
- DPRINT("Probing buffer\n");
- ProbeForRead(LocalName.Buffer,
- LocalName.Length,
- sizeof(USHORT));
- #endif
+ /* PS: Please keep the checks above expanded for clarity */
+ DPRINT1("Invalid String Length\n");
+ Status = STATUS_OBJECT_NAME_INVALID;
}
- _SEH_HANDLE
+ else
{
- Status = _SEH_GetExceptionCode();
+ /* Allocate a non-paged buffer for this string */
+ DPRINT("Capturing String\n");
+ CapturedName->Length = StringLength;
+ CapturedName->MaximumLength = StringLength + sizeof(WCHAR);
+ if ((StringBuffer = ExAllocatePoolWithTag(NonPagedPool,
+ StringLength + sizeof(WCHAR),
+ OB_NAME_TAG)))
+ {
+ /* Copy the string and null-terminate it */
+ RtlMoveMemory(StringBuffer, LocalName.Buffer, StringLength);
+ StringBuffer[StringLength / sizeof(WCHAR)] = UNICODE_NULL;
+ CapturedName->Buffer = StringBuffer;
+ DPRINT("String Captured: %wZ\n", CapturedName);
+ }
+ else
+ {
+ /* Fail */
+ DPRINT1("Out of Memory!\n");
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
}
- _SEH_END;
- }
-
- /* Fail if anything up to here died */
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Probing failed\n");
- return Status;
}
}
- else
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{
- LocalName = *ObjectName;
- }
-
- /* Make sure there really is a string */
- DPRINT("Probing OK\n");
- if (LocalName.Length)
- {
- /* Allocate a non-paged buffer for this string */
- DPRINT("Capturing String\n");
- CapturedName->Length = LocalName.Length;
- CapturedName->MaximumLength = LocalName.Length + sizeof(WCHAR);
- CapturedName->Buffer = ExAllocatePoolWithTag(NonPagedPool,
- CapturedName->MaximumLength,
- TAG('O','b','N','m'));
-
- /* Copy the string and null-terminate it */
- RtlMoveMemory(CapturedName->Buffer, LocalName.Buffer, LocalName.Length);
- CapturedName->Buffer[LocalName.Length / sizeof(WCHAR)] = UNICODE_NULL;
- DPRINT("String Captured: %p, %wZ\n", CapturedName, CapturedName);
+ Status = _SEH_GetExceptionCode();
+
+ /* Remember to free the buffer in case of failure */
+ DPRINT1("Failed\n");
+ if (StringBuffer) ExFreePool(StringBuffer);
}
+ _SEH_END;
+ /* Return */
+ DPRINT("Returning: %lx\n", Status);
return Status;
}
NTSTATUS
STDCALL
-ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes,
IN KPROCESSOR_MODE AccessMode,
- IN POOL_TYPE PoolType,
- IN BOOLEAN CaptureIfKernel,
- OUT POBJECT_CREATE_INFORMATION CapturedObjectAttributes OPTIONAL,
- OUT PUNICODE_STRING ObjectName OPTIONAL)
+ IN POBJECT_TYPE ObjectType,
+ IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
+ OUT PUNICODE_STRING ObjectName)
{
- OBJECT_ATTRIBUTES AttributesCopy;
NTSTATUS Status = STATUS_SUCCESS;
+ PSECURITY_DESCRIPTOR SecurityDescriptor;
+ PSECURITY_QUALITY_OF_SERVICE SecurityQos;
+ PUNICODE_STRING LocalObjectName = NULL;
- /* 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);
- goto failbasiccleanup;
- }
- }
- else if (!CaptureIfKernel)
+ /* Zero out the Capture Data */
+ DPRINT("ObpCaptureObjectAttributes\n");
+ RtlZeroMemory(ObjectCreateInfo, sizeof(OBJECT_CREATE_INFORMATION));
+
+ /* SEH everything here for protection */
+ _SEH_TRY
{
- if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
+ /* Check if we got Oba */
+ if (ObjectAttributes)
{
- if (ObjectName != NULL)
+ if (AccessMode != KernelMode)
{
- /* we don't have to capture any memory, the caller considers the passed data
- as valid */
- if (ObjectAttributes->ObjectName != NULL)
- {
- *ObjectName = *ObjectAttributes->ObjectName;
- }
- else
+ DPRINT("Probing OBA\n");
+ ProbeForRead(ObjectAttributes,
+ sizeof(OBJECT_ATTRIBUTES),
+ sizeof(ULONG));
+ }
+
+ /* Validate the Size and Attributes */
+ DPRINT("Validating OBA\n");
+ if ((ObjectAttributes->Length != sizeof(OBJECT_ATTRIBUTES)) ||
+ (ObjectAttributes->Attributes & ~OBJ_VALID_ATTRIBUTES))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ DPRINT1("Invalid Size: %lx or Attributes: %lx\n",
+ ObjectAttributes->Length, ObjectAttributes->Attributes);
+ _SEH_LEAVE;
+ }
+
+ /* 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)
+ {
+ DPRINT("Probing SD: %x\n", SecurityDescriptor);
+ Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
+ AccessMode,
+ NonPagedPool,
+ TRUE,
+ &ObjectCreateInfo->SecurityDescriptor);
+ if(!NT_SUCCESS(Status))
{
- ObjectName->Length = ObjectName->MaximumLength = 0;
- ObjectName->Buffer = NULL;
+ DPRINT1("Unable to capture the security descriptor!!!\n");
+ ObjectCreateInfo->SecurityDescriptor = NULL;
+ _SEH_LEAVE;
}
+
+ DPRINT("Probe done\n");
+ ObjectCreateInfo->SecurityDescriptorCharge = 2048; /* FIXME */
+ ObjectCreateInfo->ProbeMode = AccessMode;
}
- if (CapturedObjectAttributes != NULL)
+
+ /* Validate the QoS */
+ if (SecurityQos)
{
- CapturedObjectAttributes->RootDirectory = ObjectAttributes->RootDirectory;
- CapturedObjectAttributes->Attributes = ObjectAttributes->Attributes;
- CapturedObjectAttributes->SecurityDescriptor = ObjectAttributes->SecurityDescriptor;
- CapturedObjectAttributes->SecurityDescriptorCharge = 0; /* FIXME */
- CapturedObjectAttributes->ProbeMode = AccessMode;
+ if (AccessMode != KernelMode)
+ {
+ DPRINT("Probing QoS\n");
+ ProbeForRead(SecurityQos,
+ sizeof(SECURITY_QUALITY_OF_SERVICE),
+ sizeof(ULONG));
+ }
+
+ /* Save Info */
+ ObjectCreateInfo->SecurityQualityOfService = *SecurityQos;
+ ObjectCreateInfo->SecurityQos = &ObjectCreateInfo->SecurityQualityOfService;
}
-
- return STATUS_SUCCESS;
}
else
{
- Status = STATUS_INVALID_PARAMETER;
- goto failbasiccleanup;
+ LocalObjectName = NULL;
}
}
- 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))
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{
- Status = STATUS_INVALID_PARAMETER;
- goto failbasiccleanup;
+ Status = _SEH_GetExceptionCode();
+ DPRINT1("Failed\n");
}
+ _SEH_END;
- if (CapturedObjectAttributes != NULL)
+ if (NT_SUCCESS(Status))
{
- CapturedObjectAttributes->RootDirectory = AttributesCopy.RootDirectory;
- CapturedObjectAttributes->Attributes = AttributesCopy.Attributes;
-
- if (AttributesCopy.SecurityDescriptor != NULL)
+ /* Now check if the Object Attributes had an Object Name */
+ if (LocalObjectName)
{
- Status = SeCaptureSecurityDescriptor(AttributesCopy.SecurityDescriptor,
- AccessMode,
- PoolType,
- TRUE,
- &CapturedObjectAttributes->SecurityDescriptor);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to capture the security descriptor!!!\n");
- goto failbasiccleanup;
- }
- CapturedObjectAttributes->SecurityDescriptorCharge = 0; /* FIXME */
+ DPRINT("Name Buffer: %wZ\n", LocalObjectName);
+ Status = ObpCaptureObjectName(ObjectName,
+ LocalObjectName,
+ AccessMode);
}
else
{
- CapturedObjectAttributes->SecurityDescriptor = NULL;
- CapturedObjectAttributes->SecurityDescriptorCharge = 0;
- }
- }
-
- if (ObjectName != NULL)
- {
- ObjectName->Buffer = NULL;
-
- if (AttributesCopy.ObjectName != NULL)
- {
- UNICODE_STRING OriginalCopy = {0};
-
- if (AccessMode != KernelMode)
- {
- _SEH_TRY
- {
- /* 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;
+ /* Clear the string */
+ RtlInitUnicodeString(ObjectName, NULL);
- 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 */
+ /* He can't have specified a Root Directory */
+ if (ObjectCreateInfo->RootDirectory)
{
- 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;
- }
+ DPRINT1("Invalid name\n");
+ Status = STATUS_OBJECT_NAME_INVALID;
}
}
- else
- {
- ObjectName->Length = ObjectName->MaximumLength = 0;
- }
}
-
- CapturedObjectAttributes->ProbeMode = AccessMode;
-
- if (!NT_SUCCESS(Status))
+ else
{
- if (ObjectName != NULL && 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));
- }
+ DPRINT1("Failed to capture, cleaning up\n");
+ ObpReleaseCapturedAttributes(ObjectCreateInfo);
}
-
+
+ DPRINT("Return to caller %x\n", Status);
return Status;
}
VOID
STDCALL
-ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION CapturedObjectAttributes OPTIONAL,
- IN PUNICODE_STRING ObjectName OPTIONAL,
- IN KPROCESSOR_MODE AccessMode,
- IN BOOLEAN CaptureIfKernel)
+ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo)
{
- /* 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)
+ /* Release the SD, it's the only thing we allocated */
+ if (ObjectCreateInfo->SecurityDescriptor)
{
- ExFreePool(CapturedObjectAttributes->SecurityDescriptor);
-
-#ifdef DBG
- RtlZeroMemory(CapturedObjectAttributes, sizeof(OBJECT_CREATE_INFORMATION));
-#endif
+ SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor,
+ ObjectCreateInfo->ProbeMode,
+ TRUE);
+ ObjectCreateInfo->SecurityDescriptor = NULL;
}
- if(ObjectName != NULL &&
- ObjectName->Length > 0)
- {
- ExFreePool(ObjectName->Buffer);
- }
- }
}
* RETURN VALUE
*/
NTSTATUS
+NTAPI
ObFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
PUNICODE_STRING ObjectName,
PVOID* ReturnedObject,
ObjectName->Buffer[0] != L'\\')
{
ObDereferenceObject (CurrentObject);
- DPRINT1("failed: \"%wZ\"\n", ObjectName);
+ DPRINT1("failed\n");
return STATUS_UNSUCCESSFUL;
}
DPRINT("Capturing Create Info\n");
Status = ObpCaptureObjectAttributes(ObjectAttributes,
ObjectAttributesAccessMode,
- NonPagedPool,
- TRUE,
+ Type,
ObjectCreateInfo,
&ObjectName);
/* Release the Capture Info, we don't need it */
DPRINT1("Allocation failed\n");
- ObpReleaseCapturedAttributes(ObjectCreateInfo,
- &ObjectName,
- ObjectAttributesAccessMode,
- TRUE);
+ ObpReleaseCapturedAttributes(ObjectCreateInfo);
+ if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
}
/* We failed, so release the Buffer */
}
if (Header->ObjectCreateInfo)
{
- ObpReleaseCapturedAttributes(Header->ObjectCreateInfo,
- NULL,
- Header->ObjectCreateInfo->ProbeMode,
- FALSE);
+ ObpReleaseCapturedAttributes(Header->ObjectCreateInfo);
ExFreePool(Header->ObjectCreateInfo);
}
* Reference count.
*/
ULONG
+NTAPI
ObGetObjectHandleCount(PVOID Object)
{
POBJECT_HEADER Header;