- Silence TCPIP.
[reactos.git] / reactos / ntoskrnl / ob / object.c
index 70adcc1..aaa6336 100644 (file)
@@ -17,6 +17,7 @@
 
 #define UNICODE_PATH_SEP L'\\'
 #define UNICODE_NO_PATH L"..."
+#define OB_NAME_TAG TAG('O','b','N','m')
 
 typedef struct _RETENTION_CHECK_PARAMS
 {
@@ -33,374 +34,233 @@ ObpCaptureObjectName(IN OUT PUNICODE_STRING CapturedName,
                      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);
-    }
-  }
 }
 
 
@@ -428,6 +288,7 @@ ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION CapturedObjectAttribu
  * RETURN VALUE
  */
 NTSTATUS
+NTAPI
 ObFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
             PUNICODE_STRING ObjectName,
             PVOID* ReturnedObject,
@@ -483,7 +344,7 @@ ObFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
       ObjectName->Buffer[0] != L'\\')
     {
       ObDereferenceObject (CurrentObject);
-      DPRINT1("failed: \"%wZ\"\n", ObjectName);
+      DPRINT1("failed\n");
       return STATUS_UNSUCCESSFUL;
     }
 
@@ -931,8 +792,7 @@ ObCreateObject(IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL,
     DPRINT("Capturing Create Info\n");
     Status = ObpCaptureObjectAttributes(ObjectAttributes,
                                         ObjectAttributesAccessMode,
-                                        NonPagedPool,
-                                        TRUE,
+                                        Type,
                                         ObjectCreateInfo,
                                         &ObjectName);
                                         
@@ -958,10 +818,8 @@ ObCreateObject(IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL,
         
         /* 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 */
@@ -1115,10 +973,7 @@ ObpDeleteObject(POBJECT_HEADER Header)
     }
   if (Header->ObjectCreateInfo)
     {
-      ObpReleaseCapturedAttributes(Header->ObjectCreateInfo,
-                                   NULL,
-                                   Header->ObjectCreateInfo->ProbeMode,
-                                   FALSE);
+      ObpReleaseCapturedAttributes(Header->ObjectCreateInfo);
       ExFreePool(Header->ObjectCreateInfo);
     }
     
@@ -1393,6 +1248,7 @@ ObGetObjectPointerCount(PVOID Object)
  *     Reference count.
  */
 ULONG
+NTAPI
 ObGetObjectHandleCount(PVOID Object)
 {
   POBJECT_HEADER Header;