}
/* Catch invalid access */
- Header->Type = (POBJECT_TYPE)0xBAADB0B0;
+ Header->Type = (POBJECT_TYPE)(ULONG_PTR)0xBAADB0B0BAADB0B0ULL;
/* Free the object using the same allocation tag */
ExFreePoolWithTag(HeaderLocation, ObjectType->Key);
/* 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 */
POBJECT_TYPE LocalObjectType;
ULONG HeaderSize;
NTSTATUS Status;
- CHAR Tag[4];
OBP_LOOKUP_CONTEXT Context;
PWCHAR p;
ULONG i;
UNICODE_STRING ObjectName;
+ ANSI_STRING AnsiName;
POBJECT_HEADER_CREATOR_INFO CreatorInfo;
/* Verify parameters */
(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)) ||
}
else
{
- /* Set Tag */
- Tag[0] = (CHAR)TypeName->Buffer[0];
- Tag[1] = (CHAR)TypeName->Buffer[1];
- Tag[2] = (CHAR)TypeName->Buffer[2];
- Tag[3] = (CHAR)TypeName->Buffer[3];
- LocalObjectType->Key = *(PULONG)Tag;
+ /* Convert the tag to ASCII */
+ Status = RtlUnicodeStringToAnsiString(&AnsiName, TypeName, TRUE);
+ if (NT_SUCCESS(Status))
+ {
+ /* For every missing character, use a space */
+ for (i = 3; i >= AnsiName.Length; i--) AnsiName.Buffer[i] = ' ';
+
+ /* Set the key and free the converted name */
+ LocalObjectType->Key = *(PULONG)AnsiName.Buffer;
+ RtlFreeAnsiString(&AnsiName);
+ }
+ else
+ {
+ /* Just copy the characters */
+ LocalObjectType->Key = *(PULONG)TypeName->Buffer;
+ }
}
/* Set up the type information */
else if ((TypeName->Length == 8) && !(wcscmp(TypeName->Buffer, L"File")))
{
/* Wait on the File Object's event directly */
- LocalObjectType->DefaultObject = (PVOID)FIELD_OFFSET(FILE_OBJECT,
- Event);
+ LocalObjectType->DefaultObject = UlongToPtr(FIELD_OFFSET(FILE_OBJECT,
+ Event));
}
else if ((TypeName->Length == 24) && !(wcscmp(TypeName->Buffer, L"WaitablePort")))
{
/* Wait on the LPC Port's object directly */
- LocalObjectType->DefaultObject = (PVOID)FIELD_OFFSET(LPCP_PORT_OBJECT,
- WaitEvent);
+ LocalObjectType->DefaultObject = UlongToPtr(FIELD_OFFSET(LPCP_PORT_OBJECT,
+ WaitEvent));
}
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;
- if (LocalObjectType->Index < 32)
+
+ ASSERT(LocalObjectType->Index != 0);
+
+ 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) ||
return STATUS_INSUFFICIENT_RESOURCES;
}
+VOID
+NTAPI
+ObDeleteCapturedInsertInfo(IN PVOID Object)
+{
+ POBJECT_HEADER ObjectHeader;
+ PAGED_CODE();
+
+ /* Check if there is anything to free */
+ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
+ if ((ObjectHeader->Flags & OB_FLAG_CREATE_INFO) &&
+ (ObjectHeader->ObjectCreateInfo != NULL))
+ {
+ /* Free the create info */
+ ObpFreeObjectCreateInformation(ObjectHeader->ObjectCreateInfo);
+ ObjectHeader->ObjectCreateInfo = NULL;
+ }
+}
+
VOID
NTAPI
ObpDeleteObjectType(IN PVOID Object)
POBJECT_HEADER ObjectHeader = NULL;
POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
POBJECT_BASIC_INFORMATION BasicInfo;
- ULONG InfoLength;
+ ULONG InfoLength = 0;
PVOID Object = NULL;
NTSTATUS Status;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
BasicInfo->SecurityDescriptorSize = 0; /* FIXME*/
/* Check if this is a symlink */
- if (ObjectHeader->Type == ObSymbolicLinkType)
+ if (ObjectHeader->Type == ObpSymbolicLinkObjectType)
{
/* Return the creation time */
BasicInfo->CreationTime.QuadPart =
_SEH2_END;
/* Dereference the object if we had referenced it */
- if (Object) ObDereferenceObject (Object);
+ if (Object) ObDereferenceObject(Object);
/* Return status */
return Status;
OBP_SET_HANDLE_ATTRIBUTES_CONTEXT Context;
PVOID ObjectTable;
KAPC_STATE ApcState;
+ POBJECT_DIRECTORY Directory;
+ KPROCESSOR_MODE PreviousMode;
BOOLEAN AttachedToProcess = FALSE;
PAGED_CODE();
/* Validate the information class */
- if (ObjectInformationClass != ObjectHandleFlagInformation)
+ switch (ObjectInformationClass)
{
- /* Invalid class */
- return STATUS_INVALID_INFO_CLASS;
- }
+ case ObjectHandleFlagInformation:
- /* Validate the length */
- if (Length != sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION))
- {
- /* Invalid length */
- return STATUS_INFO_LENGTH_MISMATCH;
- }
+ /* Validate the length */
+ if (Length != sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION))
+ {
+ /* Invalid length */
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
- /* Save the previous mode */
- Context.PreviousMode = ExGetPreviousMode();
+ /* Save the previous mode */
+ Context.PreviousMode = ExGetPreviousMode();
- /* Check if we were called from user mode */
- if (Context.PreviousMode != KernelMode)
- {
- /* Enter SEH */
- _SEH2_TRY
- {
- /* Probe and capture the attribute buffer */
- ProbeForRead(ObjectInformation,
- sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION),
- sizeof(BOOLEAN));
- Context.Information = *(POBJECT_HANDLE_ATTRIBUTE_INFORMATION)
- ObjectInformation;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
- }
- _SEH2_END;
- }
- else
- {
- /* Just copy the buffer directly */
- Context.Information = *(POBJECT_HANDLE_ATTRIBUTE_INFORMATION)
- ObjectInformation;
- }
+ /* Check if we were called from user mode */
+ if (Context.PreviousMode != KernelMode)
+ {
+ /* Enter SEH */
+ _SEH2_TRY
+ {
+ /* Probe and capture the attribute buffer */
+ ProbeForRead(ObjectInformation,
+ sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION),
+ sizeof(BOOLEAN));
+ Context.Information = *(POBJECT_HANDLE_ATTRIBUTE_INFORMATION)
+ ObjectInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ /* Just copy the buffer directly */
+ Context.Information = *(POBJECT_HANDLE_ATTRIBUTE_INFORMATION)
+ ObjectInformation;
+ }
- /* Check if this is a kernel handle */
- if (ObIsKernelHandle(ObjectHandle, Context.PreviousMode))
- {
- /* Get the actual handle */
- ObjectHandle = ObKernelHandleToHandle(ObjectHandle);
- ObjectTable = ObpKernelHandleTable;
+ /* Check if this is a kernel handle */
+ if (ObpIsKernelHandle(ObjectHandle, Context.PreviousMode))
+ {
+ /* Get the actual handle */
+ ObjectHandle = ObKernelHandleToHandle(ObjectHandle);
+ ObjectTable = ObpKernelHandleTable;
- /* Check if we're not in the system process */
- if (PsGetCurrentProcess() != PsInitialSystemProcess)
- {
- /* Attach to it */
- KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
- AttachedToProcess = TRUE;
- }
- }
- else
- {
- /* Use the current table */
- ObjectTable = PsGetCurrentProcess()->ObjectTable;
- }
+ /* Check if we're not in the system process */
+ if (PsGetCurrentProcess() != PsInitialSystemProcess)
+ {
+ /* Attach to it */
+ KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
+ AttachedToProcess = TRUE;
+ }
+ }
+ else
+ {
+ /* Use the current table */
+ ObjectTable = PsGetCurrentProcess()->ObjectTable;
+ }
- /* Change the handle attributes */
- if (!ExChangeHandle(ObjectTable,
- ObjectHandle,
- ObpSetHandleAttributes,
- (ULONG_PTR)&Context))
- {
- /* Some failure */
- Status = STATUS_ACCESS_DENIED;
- }
- else
- {
- /* We are done */
- Status = STATUS_SUCCESS;
+ /* Change the handle attributes */
+ if (!ExChangeHandle(ObjectTable,
+ ObjectHandle,
+ ObpSetHandleAttributes,
+ (ULONG_PTR)&Context))
+ {
+ /* Some failure */
+ Status = STATUS_ACCESS_DENIED;
+ }
+ else
+ {
+ /* We are done */
+ Status = STATUS_SUCCESS;
+ }
+
+ /* De-attach if we were attached, and return status */
+ if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
+ break;
+
+ case ObjectSessionInformation:
+
+ /* Only a system process can do this */
+ PreviousMode = ExGetPreviousMode();
+ if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
+ {
+ /* Fail */
+ DPRINT1("Privilege not held\n");
+ Status = STATUS_PRIVILEGE_NOT_HELD;
+ }
+ else
+ {
+ /* Get the object directory */
+ Status = ObReferenceObjectByHandle(ObjectHandle,
+ 0,
+ ObpDirectoryObjectType,
+ PreviousMode,
+ (PVOID*)&Directory,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ /* FIXME: Missng locks */
+ /* Set its session ID */
+ Directory->SessionId = PsGetCurrentProcessSessionId();
+ ObDereferenceObject(Directory);
+ }
+ }
+ break;
+
+ default:
+ /* Unsupported class */
+ Status = STATUS_INVALID_INFO_CLASS;
+ break;
}
- /* De-attach if we were attached, and return status */
- if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
return Status;
}