[NTOS:IO] Implement IopAcquireFileObjectLock and use it to fix IopLockFileObject
[reactos.git] / ntoskrnl / ob / oblife.c
index 0a5324d..56dbcae 100644 (file)
@@ -137,7 +137,7 @@ ObpDeallocateObject(IN PVOID Object)
     }
 
     /* 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);
@@ -351,7 +351,18 @@ ObpFreeObjectNameBuffer(IN PUNICODE_STRING Name)
     /* 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
@@ -370,7 +381,7 @@ ObpCaptureObjectName(IN OUT PUNICODE_STRING CapturedName,
 {
     NTSTATUS Status = STATUS_SUCCESS;
     ULONG StringLength;
-    PWCHAR StringBuffer = NULL;
+    PWCHAR _SEH2_VOLATILE StringBuffer = NULL;
     UNICODE_STRING LocalName;
     PAGED_CODE();
 
@@ -394,7 +405,8 @@ ObpCaptureObjectName(IN OUT PUNICODE_STRING CapturedName,
         }
 
         /* 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)) ||
@@ -474,7 +486,7 @@ ObpCaptureObjectCreateInformation(IN POBJECT_ATTRIBUTES ObjectAttributes,
 
             /* 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);
@@ -482,7 +494,7 @@ ObpCaptureObjectCreateInformation(IN POBJECT_ATTRIBUTES ObjectAttributes,
 
             /* 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;
@@ -491,7 +503,8 @@ ObpCaptureObjectCreateInformation(IN POBJECT_ATTRIBUTES ObjectAttributes,
             /* 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,
@@ -555,7 +568,7 @@ ObpCaptureObjectCreateInformation(IN POBJECT_ATTRIBUTES ObjectAttributes,
         /* 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;
@@ -730,10 +743,10 @@ ObpAllocateObject(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
         /* 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 */
@@ -1040,7 +1053,7 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName,
         (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)) ||
@@ -1145,7 +1158,7 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName,
 
             /* Set the key and free the converted name */
             LocalObjectType->Key = *(PULONG)AnsiName.Buffer;
-            ExFreePool(AnsiName.Buffer);
+            RtlFreeAnsiString(&AnsiName);
         }
         else
         {
@@ -1202,14 +1215,14 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName,
     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
     {
@@ -1227,26 +1240,33 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName,
     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) ||
@@ -1543,7 +1563,7 @@ NtQueryObject(IN HANDLE ObjectHandle,
                 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 =
@@ -1778,7 +1798,7 @@ NtSetInformationObject(IN HANDLE ObjectHandle,
                 /* Get the object directory */
                 Status = ObReferenceObjectByHandle(ObjectHandle,
                                                    0,
-                                                   ObDirectoryType,
+                                                   ObpDirectoryObjectType,
                                                    PreviousMode,
                                                    (PVOID*)&Directory,
                                                    NULL);