[ros-diffs] [ion] 25602: - Fix MSVC breakage caused by recent modifications of cctypes.h. - Remove structures from ntifs.h that shouldn't be there. - Add support for optimized detection of a DOS device path \?? or \??\ and implement it into ObpLookupObjectName. - Add support for proper re-parsing up to a maximum of 30 times to avoid reparse DOS attacks on the kernel. - Set WIN32_WINNT version to Windows 2003 SP1.

ion at svn.reactos.org ion at svn.reactos.org
Mon Jan 22 23:16:14 CET 2007


Author: ion
Date: Tue Jan 23 01:16:13 2007
New Revision: 25602

URL: http://svn.reactos.org/svn/reactos?rev=25602&view=rev
Log:
- Fix MSVC breakage caused by recent modifications of cctypes.h.
- Remove structures from ntifs.h that shouldn't be there.
- Add support for optimized detection of a DOS device path \?? or \??\ and implement it into ObpLookupObjectName.
- Add support for proper re-parsing up to a maximum of 30 times to avoid reparse DOS attacks on the kernel.
- Set WIN32_WINNT version to Windows 2003 SP1.

Modified:
    trunk/reactos/include/ddk/ntifs.h
    trunk/reactos/include/ndk/cctypes.h
    trunk/reactos/ntoskrnl/ex/pushlock.c
    trunk/reactos/ntoskrnl/include/internal/ex.h
    trunk/reactos/ntoskrnl/include/internal/ob.h
    trunk/reactos/ntoskrnl/include/ntoskrnl.h
    trunk/reactos/ntoskrnl/ob/obname.c

Modified: trunk/reactos/include/ddk/ntifs.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ddk/ntifs.h?rev=25602&r1=25601&r2=25602&view=diff
==============================================================================
--- trunk/reactos/include/ddk/ntifs.h (original)
+++ trunk/reactos/include/ddk/ntifs.h Tue Jan 23 01:16:13 2007
@@ -49,6 +49,9 @@
 #ifndef NTSYSAPI
 #define NTSYSAPI
 #endif
+
+#define EX_PUSH_LOCK ULONG_PTR
+#define PEX_PUSH_LOCK PULONG_PTR
 
 #include "csq.h"
 
@@ -1402,35 +1405,6 @@
     WCHAR Name[1];
 } PATHNAME_BUFFER, *PPATHNAME_BUFFER;
 
-#if (VER_PRODUCTBUILD >= 2600)
-
-typedef struct _PRIVATE_CACHE_MAP_FLAGS {
-    ULONG DontUse           : 16;
-    ULONG ReadAheadActive   : 1;
-    ULONG ReadAheadEnabled  : 1;
-    ULONG Available         : 14;
-} PRIVATE_CACHE_MAP_FLAGS, *PPRIVATE_CACHE_MAP_FLAGS;
-
-typedef struct _PRIVATE_CACHE_MAP {
-    _ANONYMOUS_UNION union {
-        CSHORT                  NodeTypeCode;
-        PRIVATE_CACHE_MAP_FLAGS Flags;
-        ULONG                   UlongFlags;
-    } DUMMYUNIONNAME;
-    ULONG                       ReadAheadMask;
-    PFILE_OBJECT                FileObject;
-    LARGE_INTEGER               FileOffset1;
-    LARGE_INTEGER               BeyondLastByte1;
-    LARGE_INTEGER               FileOffset2;
-    LARGE_INTEGER               BeyondLastByte2;
-    LARGE_INTEGER               ReadAheadOffset[2];
-    ULONG                       ReadAheadLength[2];
-    KSPIN_LOCK                  ReadAheadSpinLock;
-    LIST_ENTRY                  PrivateLinks;
-} PRIVATE_CACHE_MAP, *PPRIVATE_CACHE_MAP;
-
-#endif
-
 typedef enum _RTL_GENERIC_COMPARE_RESULTS
 {
     GenericLessThan,
@@ -1715,16 +1689,6 @@
     USHORT              NumEntries;
 } TUNNEL, *PTUNNEL;
 
-typedef struct _VACB {
-    PVOID               BaseAddress;
-    PSHARED_CACHE_MAP   SharedCacheMap;
-    union {
-        LARGE_INTEGER   FileOffset;
-        USHORT          ActiveCount;
-    } Overlay;
-    LIST_ENTRY          LruList;
-} VACB, *PVACB;
-
 typedef struct _VAD_HEADER {
     PVOID       StartVPN;
     PVOID       EndVPN;

Modified: trunk/reactos/include/ndk/cctypes.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/cctypes.h?rev=25602&r1=25601&r2=25602&view=diff
==============================================================================
--- trunk/reactos/include/ndk/cctypes.h (original)
+++ trunk/reactos/include/ndk/cctypes.h Tue Jan 23 01:16:13 2007
@@ -35,54 +35,101 @@
 extern ULONG NTSYSAPI CcFastReadNoWait;
 extern ULONG NTSYSAPI CcFastMdlReadNotPossible;
 
+//
+// Virtual Address Control BLock
+//
+typedef struct _VACB
+{
+    PVOID BaseAddress;
+    struct _SHARED_CACHE_MAP *SharedCacheMap;
+    union
+    {
+        LARGE_INTEGER FileOffset;
+        USHORT ActiveCount;
+    } Overlay;
+    LIST_ENTRY LruList;
+} VACB, *PVACB;
+
+//
+// Private Cache Map Structure and Flags
+//
+typedef struct _PRIVATE_CACHE_MAP_FLAGS
+{
+    ULONG DontUse:16;
+    ULONG ReadAheadActive:1;
+    ULONG ReadAheadEnabled:1;
+    ULONG Available:14;
+} PRIVATE_CACHE_MAP_FLAGS;
+
+typedef struct _PRIVATE_CACHE_MAP
+{
+    union
+    {
+        CSHORT NodeTypeCode;
+        PRIVATE_CACHE_MAP_FLAGS Flags;
+        ULONG UlongFlags;
+    };
+    ULONG ReadAheadMask;
+    PFILE_OBJECT FileObject;
+    LARGE_INTEGER FileOffset1;
+    LARGE_INTEGER BeyondLastByte1;
+    LARGE_INTEGER FileOffset2;
+    LARGE_INTEGER BeyondLastByte2;
+    LARGE_INTEGER ReadAheadOffset[2];
+    ULONG ReadAheadLength[2];
+    KSPIN_LOCK ReadAheadSpinLock;
+    LIST_ENTRY PrivateLinks;
+} PRIVATE_CACHE_MAP, *PPRIVATE_CACHE_MAP;
 
 #ifdef _NTIFS_INCLUDED_
 
-typedef struct _SHARED_CACHE_MAP {
-        SHORT  NodeTypeCode;
-        SHORT NodeByteSize;
-        ULONG OpenCount;
-        LARGE_INTEGER FileSize;
-        LIST_ENTRY BcbList;
-        LARGE_INTEGER SectionSize;
-        LARGE_INTEGER ValidDataLength;
-        LARGE_INTEGER ValidDataGoal;
-        PVACB InitialVacbs[4];
-        PVACB Vacbs;
-        PFILE_OBJECT FileObject;
-        PVACB ActiveVacb;
-        PVOID NeedToZero;
-        ULONG ActivePage;
-        ULONG NeedToZeroPage;
-        ULONG ActiveVacbSpinLock;
-        ULONG VacbActiveCount;
-        ULONG DirtyPages;
-        LIST_ENTRY SharedCacheMapLinks;
-        ULONG Flags;
-        ULONG Status;
-        PMCB Mbcb;
-        PVOID Section;
-        PKEVENT CreateEvent;
-        PKEVENT WaitOnActiveCount;
-        ULONG PagesToWrite;
-        LONGLONG BeyondLastFlush;
-        PCACHE_MANAGER_CALLBACKS Callbacks;
-        PVOID LazyWriteContext;
-        PLIST_ENTRY PrivateList;
-        PVOID LogHandle;
-        PVOID FlushToLsnRoutine;
-        ULONG DirtyPageThreshold;
-        ULONG LazyWritePassCount;
-        PCACHE_UNINITIALIZE_EVENT UninitializeEvent;
-        PVACB NeedToZeroVacb;
-        ULONG BcbSpinLock;
-        PVOID Reserved;
-        KEVENT Event;
-        /* FIX ME: This should be PEX_PUSH_LOCK */
-        PVOID VacbPushLock;
-        PPRIVATE_CACHE_MAP PrivateCacheMap;
-   } SHARED_CACHE_MAP;
-
+//
+// Shared Cache Map
+//
+typedef struct _SHARED_CACHE_MAP
+{
+    SHORT NodeTypeCode;
+    SHORT NodeByteSize;
+    ULONG OpenCount;
+    LARGE_INTEGER FileSize;
+    LIST_ENTRY BcbList;
+    LARGE_INTEGER SectionSize;
+    LARGE_INTEGER ValidDataLength;
+    LARGE_INTEGER ValidDataGoal;
+    PVACB InitialVacbs[4];
+    PVACB Vacbs;
+    PFILE_OBJECT FileObject;
+    PVACB ActiveVacb;
+    PVOID NeedToZero;
+    ULONG ActivePage;
+    ULONG NeedToZeroPage;
+    ULONG ActiveVacbSpinLock;
+    ULONG VacbActiveCount;
+    ULONG DirtyPages;
+    LIST_ENTRY SharedCacheMapLinks;
+    ULONG Flags;
+    ULONG Status;
+    PMCB Mbcb;
+    PVOID Section;
+    PKEVENT CreateEvent;
+    PKEVENT WaitOnActiveCount;
+    ULONG PagesToWrite;
+    LONGLONG BeyondLastFlush;
+    PCACHE_MANAGER_CALLBACKS Callbacks;
+    PVOID LazyWriteContext;
+    PLIST_ENTRY PrivateList;
+    PVOID LogHandle;
+    PVOID FlushToLsnRoutine;
+    ULONG DirtyPageThreshold;
+    ULONG LazyWritePassCount;
+    PCACHE_UNINITIALIZE_EVENT UninitializeEvent;
+    PVACB NeedToZeroVacb;
+    ULONG BcbSpinLock;
+    PVOID Reserved;
+    KEVENT Event;
+    PEX_PUSH_LOCK VacbPushLock;
+    PPRIVATE_CACHE_MAP PrivateCacheMap;
+} SHARED_CACHE_MAP;
 
 #endif /* _NTIFS_INCLUDED_  */
 #endif /* NTOS_MODE_USER    */

Modified: trunk/reactos/ntoskrnl/ex/pushlock.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/pushlock.c?rev=25602&r1=25601&r2=25602&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ex/pushlock.c (original)
+++ trunk/reactos/ntoskrnl/ex/pushlock.c Tue Jan 23 01:16:13 2007
@@ -362,7 +362,7 @@
 VOID
 FASTCALL
 ExWaitForUnblockPushLock(IN PEX_PUSH_LOCK PushLock,
-                         IN PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock)
+                         IN PVOID WaitBlock)
 {
     /* Call the timed function with no timeout */
     ExTimedWaitForUnblockPushLock(PushLock, WaitBlock, NULL);

Modified: trunk/reactos/ntoskrnl/include/internal/ex.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/ex.h?rev=25602&r1=25601&r2=25602&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ex.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ex.h Tue Jan 23 01:16:13 2007
@@ -652,18 +652,24 @@
 
 VOID
 FASTCALL
-ExBlockPushLock(PEX_PUSH_LOCK PushLock,
-                PVOID WaitBlock);
-
-VOID
-FASTCALL
-ExfUnblockPushLock(PEX_PUSH_LOCK PushLock,
-                   PVOID CurrentWaitBlock);
-
-VOID
-FASTCALL
-ExWaitForUnblockPushLock(IN PEX_PUSH_LOCK PushLock,
-                         IN PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock);
+ExBlockPushLock(
+    IN PEX_PUSH_LOCK PushLock,
+    IN PVOID WaitBlock
+);
+
+VOID
+FASTCALL
+ExfUnblockPushLock(
+    IN PEX_PUSH_LOCK PushLock,
+    IN PVOID CurrentWaitBlock
+);
+
+VOID
+FASTCALL
+ExWaitForUnblockPushLock(
+    IN PEX_PUSH_LOCK PushLock,
+    IN PVOID WaitBlock
+);
 
 /*++
  * @name ExInitializePushLock

Modified: trunk/reactos/ntoskrnl/include/internal/ob.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/ob.h?rev=25602&r1=25601&r2=25602&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ob.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ob.h Tue Jan 23 01:16:13 2007
@@ -103,6 +103,15 @@
 } OBP_FIND_HANDLE_DATA, *POBP_FIND_HANDLE_DATA;
 
 //
+// Structure for quick-compare of a DOS Device path
+//
+typedef union
+{
+    WCHAR Name[sizeof(ULARGE_INTEGER) / sizeof(WCHAR)];
+    ULARGE_INTEGER Alignment;
+} ALIGNEDNAME;
+
+//
 // Private Temporary Buffer for Lookup Routines
 //
 #define TAG_OB_TEMP_STORAGE TAG('O', 'b', 'S', 't')
@@ -502,6 +511,9 @@
 extern volatile PVOID ObpReaperList;
 extern NPAGED_LOOKASIDE_LIST ObpNmLookasideList, ObpCiLookasideList;
 extern BOOLEAN IoCountOperations;
+extern ALIGNEDNAME ObpDosDevicesShortNamePrefix;
+extern ALIGNEDNAME ObpDosDevicesShortNameRoot;
+extern UNICODE_STRING ObpDosDevicesShortName;
 
 //
 // Inlined Functions

Modified: trunk/reactos/ntoskrnl/include/ntoskrnl.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/ntoskrnl.h?rev=25602&r1=25601&r2=25602&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/ntoskrnl.h (original)
+++ trunk/reactos/ntoskrnl/include/ntoskrnl.h Tue Jan 23 01:16:13 2007
@@ -9,7 +9,7 @@
 /* INCLUDES ******************************************************************/
 
 /* Always target Windows 2003 Service Pack 1 */
-#undef NTDDI_VERSION
+#define _WIN32_WINNT _WIN32_WINNT_WS03
 #define NTDDI_VERSION NTDDI_WS03SP1
 #define NTKERNELAPI
 

Modified: trunk/reactos/ntoskrnl/ob/obname.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obname.c?rev=25602&r1=25601&r2=25602&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obname.c (original)
+++ trunk/reactos/ntoskrnl/ob/obname.c Tue Jan 23 01:16:13 2007
@@ -16,8 +16,18 @@
 #include <debug.h>
 
 BOOLEAN ObpCaseInsensitive = TRUE;
-POBJECT_DIRECTORY NameSpaceRoot = NULL;
-POBJECT_DIRECTORY ObpTypeDirectoryObject = NULL;
+POBJECT_DIRECTORY NameSpaceRoot;
+POBJECT_DIRECTORY ObpTypeDirectoryObject;
+
+/* DOS Device Prefix \??\ and \?? */
+ALIGNEDNAME ObpDosDevicesShortNamePrefix = {{L'\\',L'?',L'?',L'\\'}};
+ALIGNEDNAME ObpDosDevicesShortNameRoot = {{L'\\',L'?',L'?',L'\0'}};
+UNICODE_STRING ObpDosDevicesShortName =
+{
+    sizeof(ObpDosDevicesShortNamePrefix),
+    sizeof(ObpDosDevicesShortNamePrefix),
+    (PWSTR)&ObpDosDevicesShortNamePrefix
+};
 
 /* PRIVATE FUNCTIONS *********************************************************/
 
@@ -256,22 +266,22 @@
 
 NTSTATUS
 NTAPI
-ObpLookupObjectName(IN HANDLE RootHandle,
+ObpLookupObjectName(IN HANDLE RootHandle OPTIONAL,
                     IN PUNICODE_STRING ObjectName,
                     IN ULONG Attributes,
                     IN POBJECT_TYPE ObjectType,
                     IN KPROCESSOR_MODE AccessMode,
                     IN OUT PVOID ParseContext,
-                    IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
-                    IN PVOID InsertObject,
-                    IN PACCESS_STATE AccessState,
-                    IN POBP_LOOKUP_CONTEXT LookupContext,
+                    IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
+                    IN PVOID InsertObject OPTIONAL,
+                    IN OUT PACCESS_STATE AccessState,
+                    OUT POBP_LOOKUP_CONTEXT LookupContext,
                     OUT PVOID *FoundObject)
 {
     PVOID Object;
     POBJECT_HEADER ObjectHeader;
     UNICODE_STRING ComponentName, RemainingName;
-    BOOLEAN InsideRoot = FALSE;
+    BOOLEAN Reparse = FALSE, SymLink = FALSE;
     PDEVICE_MAP DeviceMap = NULL;
     POBJECT_DIRECTORY Directory = NULL, ParentDirectory = NULL, RootDirectory;
     POBJECT_DIRECTORY ReferencedDirectory = NULL, ReferencedParentDirectory = NULL;
@@ -281,6 +291,7 @@
     KPROCESSOR_MODE AccessCheckMode;
     PWCHAR NewName;
     POBJECT_HEADER_NAME_INFO ObjectNameInfo;
+    ULONG MaxReparse = 30;
     PAGED_CODE();
     OBTRACE(OB_NAMESPACE_DEBUG,
             "%s - Finding Object: %wZ. Expecting: %p\n",
@@ -345,6 +356,9 @@
                 ObDereferenceObject(RootDirectory);
                 return STATUS_INVALID_HANDLE;
             }
+
+            /* Set default parse count */
+            MaxReparse = 30;
 
             /* Now parse */
             while (TRUE)
@@ -397,7 +411,22 @@
 
                     /* Don't use this anymore, since we're starting at root */
                     RootHandle = NULL;
-                    break;
+                    goto ParseFromRoot;
+                }
+                else if (--MaxReparse)
+                {
+                    /* Try reparsing again */
+                    continue;
+                }
+                else
+                {
+                    /* Reparsed too many times */
+                    ObDereferenceObject(RootDirectory);
+
+                    /* Return the object and normalized status */
+                    *FoundObject = Object;
+                    if (!Object) Status = STATUS_OBJECT_NAME_NOT_FOUND;
+                    return Status;
                 }
             }
         }
@@ -465,373 +494,434 @@
                 return Status;
             }
         }
-    }
-
-    /* Save the name */
-ReparseNewDir:
-    RemainingName = *ObjectName;
+        else
+        {
+ParseFromRoot:
+            /* Check if we have a device map */
+            if (DeviceMap)
+            {
+                /* Dereference it */
+                ObfDereferenceDeviceMap(DeviceMap);
+                DeviceMap = NULL;
+            }
+
+            /* Check if this is a possible DOS name */
+            if (!((ULONG_PTR)(ObjectName->Buffer) & 7))
+            {
+                /*
+                 * This could be one. Does it match the prefix?
+                 * Note that as an optimization, the match is done as 64-bit
+                 * compare since the prefix is "\??\" which is exactly 8 bytes.
+                 *
+                 * In the second branch, we test for "\??" which is also valid.
+                 * This time, we use a 32-bit compare followed by a Unicode
+                 * character compare (16-bit), since the sum is 6 bytes.
+                 */
+                if ((ObjectName->Length >= ObpDosDevicesShortName.Length) &&
+                    (*(PULONGLONG)(ObjectName->Buffer) ==
+                     ObpDosDevicesShortNamePrefix.Alignment.QuadPart))
+                {
+                    /* FIXME! */
+                }
+                else if ((ObjectName->Length == ObpDosDevicesShortName.Length -
+                                                sizeof(WCHAR)) &&
+                         (*(PULONG)(ObjectName->Buffer) ==
+                          ObpDosDevicesShortNameRoot.Alignment.LowPart) &&
+                         (*((PWCHAR)(ObjectName->Buffer) + 2) ==
+                          (WCHAR)(ObpDosDevicesShortNameRoot.Alignment.HighPart)))
+                {
+                    /* FIXME! */
+                }
+            }
+        }
+    }
+
+    /* Check if we were reparsing a symbolic link */
+    if (!SymLink)
+    {
+        /* Allow reparse */
+        Reparse = TRUE;
+        MaxReparse = 30;
+    }
 
     /* Reparse */
-    while (TRUE)
-    {
-        /* Check if we should use the Root Directory */
-        if (!InsideRoot)
-        {
-            /* Yes, use the root directory and remember that */
-            Directory = RootDirectory;
-            InsideRoot = TRUE;
-        }
-
-        /* Check if the name starts with a path separator */
-        if ((RemainingName.Length) &&
-            (RemainingName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
-        {
-            /* Skip the path separator */
-            RemainingName.Buffer++;
-            RemainingName.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
-        }
-
-        /* Find the next Part Name */
-        ComponentName = RemainingName;
-        while (RemainingName.Length)
-        {
-            /* Break if we found the \ ending */
-            if (RemainingName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) break;
-
-            /* Move on */
-            RemainingName.Buffer++;
-            RemainingName.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
-        }
-
-        /* Get its size and make sure it's valid */
-        ComponentName.Length -= RemainingName.Length;
-        if (!ComponentName.Length)
-        {
-            /* Invalid size, fail */
-            Status = STATUS_OBJECT_NAME_INVALID;
-            break;
-        }
-
-        /* Check if this is a user-mode call that needs to traverse */
-        if ((AccessCheckMode != KernelMode) &&
-            !(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE))
-        {
-            /* We shouldn't have referenced a directory yet */
-            ASSERT(ReferencedDirectory == NULL);
-
-            /* Reference the directory */
-            ObReferenceObject(Directory);
-            ReferencedDirectory = Directory;
-
-            /* Check if we have a parent directory */
-            if (ParentDirectory)
-            {
-                /* Check for traverse access */
-                if (!ObpCheckTraverseAccess(ParentDirectory,
-                                            DIRECTORY_TRAVERSE,
-                                            AccessState,
-                                            FALSE,
-                                            AccessCheckMode,
-                                            &Status))
-                {
-                    /* We don't have it, fail */
-                    break;
-                }
-            }
-        }
-
-        /* Check if we don't have a remaining name yet */
-        if (!RemainingName.Length)
-        {
-            /* Check if we don't have a referenced directory yet */
-            if (!ReferencedDirectory)
-            {
-                /* Reference it */
+    while (Reparse)
+    {
+        /* Get the name */
+        RemainingName = *ObjectName;
+
+        /* Disable reparsing again */
+        Reparse = FALSE;
+
+        /* Start parse loop */
+        while (TRUE)
+        {
+            /* Clear object */
+            Object = NULL;
+
+            /* Check if the name starts with a path separator */
+            if ((RemainingName.Length) &&
+                (RemainingName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
+            {
+                /* Skip the path separator */
+                RemainingName.Buffer++;
+                RemainingName.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
+            }
+
+            /* Find the next Part Name */
+            ComponentName = RemainingName;
+            while (RemainingName.Length)
+            {
+                /* Break if we found the \ ending */
+                if (RemainingName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) break;
+
+                /* Move on */
+                RemainingName.Buffer++;
+                RemainingName.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
+            }
+
+            /* Get its size and make sure it's valid */
+            ComponentName.Length -= RemainingName.Length;
+            if (!ComponentName.Length)
+            {
+                /* Invalid size, fail */
+                Status = STATUS_OBJECT_NAME_INVALID;
+                break;
+            }
+
+            /* Check if we're in the root */
+            if (!Directory) Directory = RootDirectory;
+
+            /* Check if this is a user-mode call that needs to traverse */
+            if ((AccessCheckMode != KernelMode) &&
+                !(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE))
+            {
+                /* We shouldn't have referenced a directory yet */
+                ASSERT(ReferencedDirectory == NULL);
+
+                /* Reference the directory */
                 ObReferenceObject(Directory);
                 ReferencedDirectory = Directory;
-            }
-
-            /* Check if we are inserting an object */
-            if (InsertObject)
-            {
-                /* Lock the directory */
-                ObpAcquireDirectoryLockExclusive(Directory, LookupContext);
-            }
-        }
-
-        /* Do the lookup */
-        Object = ObpLookupEntryDirectory(Directory,
-                                         &ComponentName,
-                                         Attributes,
-                                         InsertObject ? FALSE : TRUE,
-                                         LookupContext);
-        if (!Object)
-        {
-            /* We didn't find it... do we still have a path? */
-            if (RemainingName.Length)
-            {
-                /* Then tell the caller the path wasn't found */
-                Status = STATUS_OBJECT_PATH_NOT_FOUND;
+
+                /* Check if we have a parent directory */
+                if (ParentDirectory)
+                {
+                    /* Check for traverse access */
+                    if (!ObpCheckTraverseAccess(ParentDirectory,
+                                                DIRECTORY_TRAVERSE,
+                                                AccessState,
+                                                FALSE,
+                                                AccessCheckMode,
+                                                &Status))
+                    {
+                        /* We don't have it, fail */
+                        break;
+                    }
+                }
+            }
+
+            /* Check if we don't have a remaining name yet */
+            if (!RemainingName.Length)
+            {
+                /* Check if we don't have a referenced directory yet */
+                if (!ReferencedDirectory)
+                {
+                    /* Reference it */
+                    ObReferenceObject(Directory);
+                    ReferencedDirectory = Directory;
+                }
+
+                /* Check if we are inserting an object */
+                if (InsertObject)
+                {
+                    /* Lock the directory */
+                    ObpAcquireDirectoryLockExclusive(Directory, LookupContext);
+                }
+            }
+
+            /* Do the lookup */
+            Object = ObpLookupEntryDirectory(Directory,
+                                             &ComponentName,
+                                             Attributes,
+                                             InsertObject ? FALSE : TRUE,
+                                             LookupContext);
+            if (!Object)
+            {
+                /* We didn't find it... do we still have a path? */
+                if (RemainingName.Length)
+                {
+                    /* Then tell the caller the path wasn't found */
+                    Status = STATUS_OBJECT_PATH_NOT_FOUND;
+                    break;
+                }
+                else if (!InsertObject)
+                {
+                    /* Otherwise, we have a path, but the name isn't valid */
+                    Status = STATUS_OBJECT_NAME_NOT_FOUND;
+                    break;
+                }
+
+                /* Check create access for the object */
+                if (!ObCheckCreateObjectAccess(Directory,
+                                               ObjectType == ObDirectoryType ?
+                                               DIRECTORY_CREATE_SUBDIRECTORY :
+                                               DIRECTORY_CREATE_OBJECT,
+                                               AccessState,
+                                               &ComponentName,
+                                               FALSE,
+                                               AccessCheckMode,
+                                               &Status))
+                {
+                    /* We don't have create access, fail */
+                    break;
+                }
+
+                /* Get the object header */
+                ObjectHeader = OBJECT_TO_OBJECT_HEADER(InsertObject);
+
+                /* FIXME: Check if this is a Section Object or Sym Link */
+                /* FIXME: If it is, then check if this isn't session 0 */
+                /* FIXME: If it isn't, check for SeCreateGlobalPrivilege */
+                /* FIXME: If privilege isn't there, check for unsecure name */
+                /* FIXME: If it isn't a known unsecure name, then fail */
+
+                /* Create Object Name */
+                NewName = ExAllocatePoolWithTag(PagedPool,
+                                                ComponentName.Length,
+                                                OB_NAME_TAG);
+                if (!(NewName) ||
+                    !(ObpInsertEntryDirectory(Directory,
+                                              LookupContext,
+                                              ObjectHeader)))
+                {
+                    /* Either couldn't allocate the name, or insert failed */
+                    if (NewName) ExFreePool(NewName);
+
+                    /* Fail due to memory reasons */
+                    Status = STATUS_INSUFFICIENT_RESOURCES;
+                    break;
+                }
+
+                /* Reference newly to be inserted object */
+                ObReferenceObject(InsertObject);
+
+                /* Get the name information */
+                ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
+
+                /* Reference the directory */
+                ObReferenceObject(Directory);
+
+                /* Copy the Name */
+                RtlCopyMemory(NewName,
+                              ComponentName.Buffer,
+                              ComponentName.Length);
+
+                /* Check if we had an old name */
+                if (ObjectNameInfo->Name.Buffer)
+                {
+                    /* Free it */
+                    ExFreePool(ObjectNameInfo->Name.Buffer);
+                }
+
+                /* Write new one */
+                ObjectNameInfo->Name.Buffer = NewName;
+                ObjectNameInfo->Name.Length = ComponentName.Length;
+                ObjectNameInfo->Name.MaximumLength = ComponentName.Length;
+
+                /* Return Status and the Expected Object */
+                Status = STATUS_SUCCESS;
+                Object = InsertObject;
+
+                /* Get out of here */
                 break;
             }
-            else if (!InsertObject)
-            {
-                /* Otherwise, we have a path, but the name isn't valid */
-                Status = STATUS_OBJECT_NAME_NOT_FOUND;
-                break;
-            }
-
-            /* Check create access for the object */
-            if (!ObCheckCreateObjectAccess(Directory,
-                                           ObjectType == ObDirectoryType ?
-                                           DIRECTORY_CREATE_SUBDIRECTORY :
-                                           DIRECTORY_CREATE_OBJECT,
-                                           AccessState,
-                                           &ComponentName,
-                                           FALSE,
-                                           AccessCheckMode,
-                                           &Status))
-            {
-                /* We don't have create access, fail */
-                break;
-            }
-
-            /* Get the object header */
-            ObjectHeader = OBJECT_TO_OBJECT_HEADER(InsertObject);
-
-            /* FIXME: Check if this is a Section Object or Sym Link */
-            /* FIXME: If it is, then check if this isn't session 0 */
-            /* FIXME: If it isn't, check for SeCreateGlobalPrivilege */
-            /* FIXME: If privilege isn't there, check for unsecure name */
-            /* FIXME: If it isn't a known unsecure name, then fail */
-
-            /* Create Object Name */
-            NewName = ExAllocatePoolWithTag(PagedPool,
-                                            ComponentName.Length,
-                                            OB_NAME_TAG);
-            if (!(NewName) ||
-                !(ObpInsertEntryDirectory(Directory,
-                                          LookupContext,
-                                          ObjectHeader)))
-            {
-                /* Either couldn't allocate the name, or insert failed */
-                if (NewName) ExFreePool(NewName);
-
-                /* Fail due to memory reasons */
-                Status = STATUS_INSUFFICIENT_RESOURCES;
-                break;
-            }
-
-            /* Reference newly to be inserted object */
-            ObReferenceObject(InsertObject);
-
-            /* Get the name information */
-            ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
-
-            /* Reference the directory */
-            ObReferenceObject(Directory);
-
-            /* Copy the Name */
-            RtlCopyMemory(NewName,
-                          ComponentName.Buffer,
-                          ComponentName.Length);
-
-            /* Check if we had an old name */
-            if (ObjectNameInfo->Name.Buffer)
-            {
-                /* Free it */
-                ExFreePool(ObjectNameInfo->Name.Buffer);
-            }
-
-            /* Write new one */
-            ObjectNameInfo->Name.Buffer = NewName;
-            ObjectNameInfo->Name.Length = ComponentName.Length;
-            ObjectNameInfo->Name.MaximumLength = ComponentName.Length;
-
-            /* Return Status and the Expected Object */
-            Status = STATUS_SUCCESS;
-            Object = InsertObject;
-
-            /* Get out of here */
-            break;
-        }
-
-Reparse:
-        /* We found it, so now get its header */
-        ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
-
-        /*
-         * Check for a parse Procedure, but don't bother to parse for an insert
-         * unless it's a Symbolic Link, in which case we MUST parse
-         */
-        ParseRoutine = ObjectHeader->Type->TypeInfo.ParseProcedure;
-        if ((ParseRoutine) &&
-            (!(InsertObject) || (ParseRoutine == ObpParseSymbolicLink)))
-        {
-            /* Use the Root Directory next time */
-            InsideRoot = FALSE;
-
-            /* Increment the pointer count */
-            InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1);
-
-            /* Cleanup from the first lookup */
-            ObpCleanupDirectoryLookup(LookupContext);
-
-            /* Check if we have a referenced directory */
-            if (ReferencedDirectory)
-            {
-                /* We do, dereference it */
-                ObDereferenceObject(ReferencedDirectory);
-                ReferencedDirectory = NULL;
-            }
-
-            /* Check if we have a referenced parent directory */
-            if (ReferencedParentDirectory)
-            {
-                /* We do, dereference it */
-                ObDereferenceObject(ReferencedParentDirectory);
-                ReferencedParentDirectory = NULL;
-            }
-
-            /* Call the Parse Procedure */
-            ObpCalloutStart(&CalloutIrql);
-            Status = ParseRoutine(Object,
-                                  ObjectType,
-                                  AccessState,
-                                  AccessCheckMode,
-                                  Attributes,
-                                  ObjectName,
-                                  &RemainingName,
-                                  ParseContext,
-                                  SecurityQos,
-                                  &Object);
-            ObpCalloutEnd(CalloutIrql, "Parse", ObjectHeader->Type, Object);
-
-            /* Remove our extra reference */
-            ObDereferenceObject(&ObjectHeader->Body);
-
-            /* Check if we have to reparse */
-            if ((Status == STATUS_REPARSE) ||
-                (Status == STATUS_REPARSE_OBJECT))
-            {
-                /* Start over from root if we got sent back there */
-                if ((Status == STATUS_REPARSE_OBJECT) ||
-                    (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
-                {
-                    /* Check if we got a root directory */
-                    if (RootHandle)
+
+ReparseObject:
+            /* We found it, so now get its header */
+            ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
+
+            /*
+             * Check for a parse Procedure, but don't bother to parse for an insert
+             * unless it's a Symbolic Link, in which case we MUST parse
+             */
+            ParseRoutine = ObjectHeader->Type->TypeInfo.ParseProcedure;
+            if ((ParseRoutine) &&
+                (!(InsertObject) || (ParseRoutine == ObpParseSymbolicLink)))
+            {
+                /* Use the Root Directory next time */
+                Directory = NULL;
+
+                /* Increment the pointer count */
+                InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1);
+
+                /* Cleanup from the first lookup */
+                ObpCleanupDirectoryLookup(LookupContext);
+
+                /* Check if we have a referenced directory */
+                if (ReferencedDirectory)
+                {
+                    /* We do, dereference it */
+                    ObDereferenceObject(ReferencedDirectory);
+                    ReferencedDirectory = NULL;
+                }
+
+                /* Check if we have a referenced parent directory */
+                if (ReferencedParentDirectory)
+                {
+                    /* We do, dereference it */
+                    ObDereferenceObject(ReferencedParentDirectory);
+                    ReferencedParentDirectory = NULL;
+                }
+
+                /* Call the Parse Procedure */
+                ObpCalloutStart(&CalloutIrql);
+                Status = ParseRoutine(Object,
+                                      ObjectType,
+                                      AccessState,
+                                      AccessCheckMode,
+                                      Attributes,
+                                      ObjectName,
+                                      &RemainingName,
+                                      ParseContext,
+                                      SecurityQos,
+                                      &Object);
+                ObpCalloutEnd(CalloutIrql, "Parse", ObjectHeader->Type, Object);
+
+                /* Remove our extra reference */
+                ObDereferenceObject(&ObjectHeader->Body);
+
+                /* Check if we have to reparse */
+                if ((Status == STATUS_REPARSE) ||
+                    (Status == STATUS_REPARSE_OBJECT))
+                {
+                    /* Reparse again */
+                    Reparse = TRUE;
+
+                    /* Start over from root if we got sent back there */
+                    if ((Status == STATUS_REPARSE_OBJECT) ||
+                        (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
                     {
-                        /* Stop using it, because we have a new directory now */
-                        ObDereferenceObject(RootDirectory);
-                        RootHandle = NULL;
-                    }
-
-                    /* Start at Root */
-                    ParentDirectory = NULL;
-                    RootDirectory = NameSpaceRoot;
-
-                    /* Check for reparse status */
-                    if (Status == STATUS_REPARSE_OBJECT)
-                    {
-                        /* Did we actually get an object to which to reparse? */
-                        if (!Object)
+                        /* Check if we got a root directory */
+                        if (RootHandle)
                         {
-                            /* We didn't, so set a failure status */
-                            Status = STATUS_OBJECT_NAME_NOT_FOUND;
+                            /* Stop using it, because we have a new directory now */
+                            ObDereferenceObject(RootDirectory);
+                            RootHandle = NULL;
+                        }
+
+                        /* Start at Root */
+                        ParentDirectory = NULL;
+                        RootDirectory = NameSpaceRoot;
+
+                        /* Check for reparse status */
+                        if (Status == STATUS_REPARSE_OBJECT)
+                        {
+                            /* Don't reparse again */
+                            Reparse = FALSE;
+
+                            /* Did we actually get an object to which to reparse? */
+                            if (!Object)
+                            {
+                                /* We didn't, so set a failure status */
+                                Status = STATUS_OBJECT_NAME_NOT_FOUND;
+                            }
+                            else
+                            {
+                                /* We did, so we're free to parse the new object */
+                                goto ReparseObject;
+                            }
                         }
                         else
                         {
-                            /* We did, so we're free to parse the new object */
-                            InsideRoot = TRUE;
-                            goto Reparse;
+                            /* This is a symbolic link */
+                            SymLink = TRUE;
+                            goto ParseFromRoot;
                         }
                     }
-
-                    /* Restart the search */
-                    goto ReparseNewDir;
-                }
-                else if (RootDirectory == NameSpaceRoot)
-                {
-                    /* We got STATUS_REPARSE but are at the Root Directory */
+                    else if (RootDirectory == NameSpaceRoot)
+                    {
+                        /* We got STATUS_REPARSE but are at the Root Directory */
+                        Object = NULL;
+                        Status = STATUS_OBJECT_NAME_NOT_FOUND;
+                        Reparse = FALSE;
+                    }
+                }
+                else if (!NT_SUCCESS(Status))
+                {
+                    /* Total failure */
                     Object = NULL;
+                }
+                else if (!Object)
+                {
+                    /* We didn't reparse but we didn't find the Object Either */
                     Status = STATUS_OBJECT_NAME_NOT_FOUND;
                 }
-            }
-            else if (!NT_SUCCESS(Status))
-            {
-                /* Total failure */
-                Object = NULL;
-            }
-            else if (!Object)
-            {
-                /* We didn't reparse but we didn't find the Object Either */
-                Status = STATUS_OBJECT_NAME_NOT_FOUND;
-            }
-
-            /* Break out of the loop */
-            break;
-        }
-        else
-        {
-            /* No parse routine...do we still have a remaining name? */
-            if (!RemainingName.Length)
-            {
-                /* Are we creating an object? */
-                if (!InsertObject)
-                {
-                    /* Check if this is a user-mode call that needs to traverse */
-                    if ((AccessCheckMode != KernelMode) &&
-                        !(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE))
+
+                /* Break out of the loop */
+                break;
+            }
+            else
+            {
+                /* No parse routine...do we still have a remaining name? */
+                if (!RemainingName.Length)
+                {
+                    /* Are we creating an object? */
+                    if (!InsertObject)
                     {
-                        /* Check if we can get it */
-                        if (!ObpCheckTraverseAccess(Directory,
-                                                    DIRECTORY_TRAVERSE,
-                                                    AccessState,
-                                                    FALSE,
-                                                    AccessCheckMode,
-                                                    &Status))
+                        /* Check if this is a user-mode call that needs to traverse */
+                        if ((AccessCheckMode != KernelMode) &&
+                            !(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE))
                         {
-                            /* We don't have access, fail */
-                            Object = NULL;
-                            break;
+                            /* Check if we can get it */
+                            if (!ObpCheckTraverseAccess(Directory,
+                                                        DIRECTORY_TRAVERSE,
+                                                        AccessState,
+                                                        FALSE,
+                                                        AccessCheckMode,
+                                                        &Status))
+                            {
+                                /* We don't have access, fail */
+                                Object = NULL;
+                                break;
+                            }
                         }
+
+                        /* Reference the Object */
+                        Status = ObReferenceObjectByPointer(Object,
+                                                            0,
+                                                            ObjectType,
+                                                            AccessMode);
+                        if (!NT_SUCCESS(Status)) Object = NULL;
                     }
 
-                    /* Reference the Object */
-                    Status = ObReferenceObjectByPointer(Object,
-                                                        0,
-                                                        ObjectType,
-                                                        AccessMode);
-                    if (!NT_SUCCESS(Status)) Object = NULL;
-                }
-
-                /* And get out of the reparse loop */
-                break;
-            }
-            else
-            {
-                /* We still have a name; check if this is a directory object */
-                if (ObjectHeader->Type == ObDirectoryType)
-                {
-                    /* Check if we have a referenced parent directory */
-                    if (ReferencedParentDirectory)
+                    /* And get out of the reparse loop */
+                    break;
+                }
+                else
+                {
+                    /* We still have a name; check if this is a directory object */
+                    if (ObjectHeader->Type == ObDirectoryType)
                     {
-                        /* Dereference it */
-                        ObDereferenceObject(ReferencedParentDirectory);
+                        /* Check if we have a referenced parent directory */
+                        if (ReferencedParentDirectory)
+                        {
+                            /* Dereference it */
+                            ObDereferenceObject(ReferencedParentDirectory);
+                        }
+
+                        /* Restart the lookup from this directory */
+                        ReferencedParentDirectory = ReferencedDirectory;
+                        ParentDirectory = Directory;
+                        Directory = Object;
+                        ReferencedDirectory = NULL;
                     }
-
-                    /* Restart the lookup from this directory */
-                    ReferencedParentDirectory = ReferencedDirectory;
-                    ParentDirectory = Directory;
-                    Directory = Object;
-                    ReferencedDirectory = NULL;
-                }
-                else
-                {
-                    /* We still have a name, but no parse routine for it */
-                    Status = STATUS_OBJECT_TYPE_MISMATCH;
-                    Object = NULL;
-                    break;
+                    else
+                    {
+                        /* We still have a name, but no parse routine for it */
+                        Status = STATUS_OBJECT_TYPE_MISMATCH;
+                        Object = NULL;
+                        break;
+                    }
                 }
             }
         }




More information about the Ros-diffs mailing list