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=25…
==============================================================================
--- 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=…
==============================================================================
--- 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…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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.…
==============================================================================
--- 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=2…
==============================================================================
--- 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;
+ }
}
}
}