/* We know this is a pool-allocation if the size doesn't match */
if (Name->MaximumLength != OBP_NAME_LOOKASIDE_MAX_SIZE)
{
- /* Free it from the pool */
+ /*
+ * Free it from the pool.
+ *
+ * We cannot use here ExFreePoolWithTag(..., OB_NAME_TAG); , because
+ * the object name may have been massaged during operation by different
+ * object parse routines. If the latter ones have to resolve a symbolic
+ * link (e.g. as is done by CmpParseKey() and CmpGetSymbolicLink()),
+ * the original object name is freed and re-allocated from the pool,
+ * possibly with a different pool tag. At the end of the day, the new
+ * object name can be reallocated and completely different, but we
+ * should still be able to free it!
+ */
ExFreePool(Buffer);
}
else
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG StringLength;
- PWCHAR StringBuffer = NULL;
+ PWCHAR _SEH2_VOLATILE StringBuffer = NULL;
UNICODE_STRING LocalName;
PAGED_CODE();
}
/* Make sure there really is a string */
- if ((StringLength = LocalName.Length))
+ StringLength = LocalName.Length;
+ if (StringLength)
{
/* Check that the size is a valid WCHAR multiple */
if ((StringLength & (sizeof(WCHAR) - 1)) ||
/* Validate the Size and Attributes */
if ((ObjectAttributes->Length != sizeof(OBJECT_ATTRIBUTES)) ||
- (ObjectAttributes->Attributes & ~OBJ_VALID_ATTRIBUTES))
+ (ObjectAttributes->Attributes & ~OBJ_VALID_KERNEL_ATTRIBUTES))
{
/* Invalid combination, fail */
_SEH2_YIELD(return STATUS_INVALID_PARAMETER);
/* Set some Create Info and do not allow user-mode kernel handles */
ObjectCreateInfo->RootDirectory = ObjectAttributes->RootDirectory;
- ObjectCreateInfo->Attributes = ObjectAttributes->Attributes & OBJ_VALID_ATTRIBUTES;
+ ObjectCreateInfo->Attributes = ObjectAttributes->Attributes & OBJ_VALID_KERNEL_ATTRIBUTES;
if (CreatorMode != KernelMode) ObjectCreateInfo->Attributes &= ~OBJ_KERNEL_HANDLE;
LocalObjectName = ObjectAttributes->ObjectName;
SecurityDescriptor = ObjectAttributes->SecurityDescriptor;
/* Check if we have a security descriptor */
if (SecurityDescriptor)
{
- /* Capture it */
+ /* Capture it. Note: This has an implicit memory barrier due
+ to the function call, so cleanup is safe here.) */
Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
AccessMode,
NonPagedPool,
/* Clear the string */
RtlInitEmptyUnicodeString(ObjectName, NULL, 0);
- /* He can't have specified a Root Directory */
+ /* It cannot have specified a Root Directory */
if (ObjectCreateInfo->RootDirectory)
{
Status = STATUS_OBJECT_NAME_INVALID;
/* Check if this is a call with the special protection flag */
if ((PreviousMode == KernelMode) &&
(ObjectCreateInfo) &&
- (ObjectCreateInfo->Attributes & 0x10000))
+ (ObjectCreateInfo->Attributes & OBJ_KERNEL_EXCLUSIVE))
{
/* Set flag which will make the object protected from user-mode */
- NameInfo->QueryReferences |= 0x40000000;
+ NameInfo->QueryReferences |= OB_FLAG_KERNEL_EXCLUSIVE;
}
/* Set the header pointer */
(TypeName->Length % sizeof(WCHAR)) ||
!(ObjectTypeInitializer) ||
(ObjectTypeInitializer->Length != sizeof(*ObjectTypeInitializer)) ||
- (ObjectTypeInitializer->InvalidAttributes & ~OBJ_VALID_ATTRIBUTES) ||
+ (ObjectTypeInitializer->InvalidAttributes & ~OBJ_VALID_KERNEL_ATTRIBUTES) ||
(ObjectTypeInitializer->MaintainHandleCount &&
(!(ObjectTypeInitializer->OpenProcedure) &&
!ObjectTypeInitializer->CloseProcedure)) ||
/* Set the key and free the converted name */
LocalObjectType->Key = *(PULONG)AnsiName.Buffer;
- ExFreePool(AnsiName.Buffer);
+ RtlFreeAnsiString(&AnsiName);
}
else
{
InitializeListHead(&LocalObjectType->TypeList);
/* Lock the object type */
- ObpEnterObjectTypeMutex(LocalObjectType);
+ ObpEnterObjectTypeMutex(ObpTypeObjectType);
/* Get creator info and insert it into the type list */
CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(Header);
- if (CreatorInfo) InsertTailList(&ObpTypeObjectType->TypeList,
- &CreatorInfo->TypeList);
+ if (CreatorInfo)
+ {
+ InsertTailList(&ObpTypeObjectType->TypeList,
+ &CreatorInfo->TypeList);
+
+ /* CORE-8423: Avoid inserting this a second time if someone creates a
+ * handle to the object type (bug in Windows 2003) */
+ Header->Flags &= ~OB_FLAG_CREATE_INFO;
+ }
/* Set the index and the entry into the object type array */
LocalObjectType->Index = ObpTypeObjectType->TotalNumberOfObjects;
- NT_ASSERT(LocalObjectType->Index != 0);
+ ASSERT(LocalObjectType->Index != 0);
- if (LocalObjectType->Index < 32)
+ if (LocalObjectType->Index < RTL_NUMBER_OF(ObpObjectTypes))
{
/* It fits, insert it */
ObpObjectTypes[LocalObjectType->Index - 1] = LocalObjectType;
}
/* Release the object type */
- ObpLeaveObjectTypeMutex(LocalObjectType);
+ ObpLeaveObjectTypeMutex(ObpTypeObjectType);
/* Check if we're actually creating the directory object itself */
if (!(ObpTypeDirectoryObject) ||