Author: ion
Date: Tue Jan 9 11:38:07 2007
New Revision: 25394
URL: http://svn.reactos.org/svn/reactos?rev=25394&view=rev
Log:
- Enable sanity check in ObInsertObject to catch assholes that were calling it incorrectly (without a Handle output parameter, which is only allowed in a specific scenario). Changes:
- Registry code which was calling ObInsertObject for no reason at all. Now an ugly hack has been added to Cm code to perform the only operation the insert did -> to free the create info.
- SeSubProcessToken was broken and calling it incorrectly, fixed.
- \Device\PhysicalMemory was being inserted incorrectly, fixed.
- Boot-time driver objects were being inserted for no reason, call removed.
- Support the only case of ObInsertObject where it is OK to call it without an output handle. This codepath will only charge quota instead of creating the full-blown handle.
Modified:
trunk/reactos/ntoskrnl/cm/registry.c
trunk/reactos/ntoskrnl/cm/regobj.c
trunk/reactos/ntoskrnl/io/iomgr/driver.c
trunk/reactos/ntoskrnl/mm/section.c
trunk/reactos/ntoskrnl/ob/obhandle.c
trunk/reactos/ntoskrnl/se/token.c
Modified: trunk/reactos/ntoskrnl/cm/registry.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/registry.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/cm/registry.c (original)
+++ trunk/reactos/ntoskrnl/cm/registry.c Tue Jan 9 11:38:07 2007
@@ -597,6 +597,7 @@
RtlFreeUnicodeString(&RemainingPath);
return Status;
}
+#if 0
DPRINT("Inserting Key into Object Tree\n");
Status = ObInsertObject((PVOID)NewKey,
NULL,
@@ -605,6 +606,11 @@
NULL,
NULL);
DPRINT("Status %x\n", Status);
+#else
+ /* Free the create information */
+ ObpFreeAndReleaseCapturedAttributes(OBJECT_TO_OBJECT_HEADER(NewKey)->ObjectCreateInfo);
+ OBJECT_TO_OBJECT_HEADER(NewKey)->ObjectCreateInfo = NULL;
+#endif
NewKey->Flags = 0;
NewKey->SubKeyCounts = 0;
NewKey->SubKeys = NULL;
Modified: trunk/reactos/ntoskrnl/cm/regobj.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/regobj.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/cm/regobj.c (original)
+++ trunk/reactos/ntoskrnl/cm/regobj.c Tue Jan 9 11:38:07 2007
@@ -382,6 +382,7 @@
RtlFreeUnicodeString(&KeyName);
return(Status);
}
+#if 0
DPRINT("Inserting Key into Object Tree\n");
Status = ObInsertObject((PVOID)FoundObject,
NULL,
@@ -390,6 +391,11 @@
NULL,
NULL);
DPRINT("Status %x\n", Status);
+#else
+/* Free the create information */
+ObpFreeAndReleaseCapturedAttributes(OBJECT_TO_OBJECT_HEADER(FoundObject)->ObjectCreateInfo);
+OBJECT_TO_OBJECT_HEADER(FoundObject)->ObjectCreateInfo = NULL;
+#endif
/* Add the keep-alive reference */
ObReferenceObject(FoundObject);
Modified: trunk/reactos/ntoskrnl/io/iomgr/driver.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/driver.c…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/driver.c (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/driver.c Tue Jan 9 11:38:07 2007
@@ -262,18 +262,6 @@
else
ExFreePool(Buffer);
}
-
-
- Status = ObInsertObject(Object,
- NULL,
- FILE_ALL_ACCESS,
- 0,
- NULL,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
*DriverObject = Object;
Modified: trunk/reactos/ntoskrnl/mm/section.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/section.c (original)
+++ trunk/reactos/ntoskrnl/mm/section.c Tue Jan 9 11:38:07 2007
@@ -2216,6 +2216,7 @@
OBJECT_ATTRIBUTES Obj;
UNICODE_STRING Name = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
LARGE_INTEGER SectionSize;
+ HANDLE Handle;
/*
* Create the section mapping physical memory
@@ -2244,11 +2245,12 @@
SECTION_ALL_ACCESS,
0,
NULL,
- NULL);
+ &Handle);
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(PhysSection);
}
+ ObCloseHandle(Handle, KernelMode);
PhysSection->AllocationAttributes |= SEC_PHYSICALMEMORY;
PhysSection->Segment->Flags &= ~MM_PAGEFILE_SEGMENT;
Modified: trunk/reactos/ntoskrnl/ob/obhandle.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obhandle.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obhandle.c (original)
+++ trunk/reactos/ntoskrnl/ob/obhandle.c Tue Jan 9 11:38:07 2007
@@ -2329,6 +2329,7 @@
OB_OPEN_REASON OpenReason;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS, RealStatus;
+ BOOLEAN IsNewObject;
PAGED_CODE();
/* Get the Header */
@@ -2371,34 +2372,28 @@
ObjectName = &ObjectNameInfo->Name;
}
- /* Sanity check, but broken on ROS due to Cm */
-#if 0
+ /* Sanity check */
ASSERT((Handle) ||
((ObjectPointerBias == 0) &&
(ObjectName == NULL) &&
(ObjectType->TypeInfo.SecurityRequired) &&
(NewObject == NULL)));
-#endif
/* Check if the object is unnamed and also doesn't have security */
PreviousMode = KeGetPreviousMode();
if (!(ObjectType->TypeInfo.SecurityRequired) && !(ObjectName))
{
- /* ReactOS HACK */
- if (Handle)
- {
- /* Assume failure */
- *Handle = NULL;
-
- /* Create the handle */
- Status = ObpCreateUnnamedHandle(Object,
- DesiredAccess,
- ObjectPointerBias + 1,
- ObjectCreateInfo->Attributes,
- PreviousMode,
- NewObject,
- Handle);
- }
+ /* Assume failure */
+ *Handle = NULL;
+
+ /* Create the handle */
+ Status = ObpCreateUnnamedHandle(Object,
+ DesiredAccess,
+ ObjectPointerBias + 1,
+ ObjectCreateInfo->Attributes,
+ PreviousMode,
+ NewObject,
+ Handle);
/* Free the create information */
ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo);
@@ -2408,7 +2403,7 @@
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
/* Remove the extra keep-alive reference */
- if (Handle) ObDereferenceObject(Object);
+ ObDereferenceObject(Object);
/* Return */
OBTRACE(OB_HANDLE_DEBUG,
@@ -2590,12 +2585,7 @@
/* Save the actual status until here */
RealStatus = Status;
- /* HACKHACK: Because of ROS's incorrect startup, this can be called
- * without a valid Process until I finalize the startup patch,
- * so don't create a handle if this is the case. We also don't create
- * a handle if Handle is NULL when the Registry Code calls it, because
- * the registry code totally bastardizes the Ob and needs to be fixed
- */
+ /* Check if caller wants us to create a handle */
ObjectHeader->ObjectCreateInfo = NULL;
if (Handle)
{
@@ -2610,28 +2600,38 @@
PreviousMode,
NewObject,
Handle);
- }
-
- /* Check if creating the handle failed */
- if (!NT_SUCCESS(Status))
- {
- /* If the object had a name, backout everything */
- if (ObjectName) ObpDeleteNameCheck(Object);
- }
-
- /* Check our final status */
- if (!NT_SUCCESS(Status))
- {
- /* Return the status of the failure */
- *Handle = NULL;
- RealStatus = Status;
- }
-
- /* Remove a query reference */
- if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
-
- /* Remove the extra keep-alive reference */
- if (Handle) ObDereferenceObject(Object);
+ if (!NT_SUCCESS(Status))
+ {
+ /* If the object had a name, backout everything */
+ if (ObjectName) ObpDeleteNameCheck(Object);
+
+ /* Return the status of the failure */
+ *Handle = NULL;
+ RealStatus = Status;
+ }
+
+ /* Remove a query reference */
+ if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
+
+ /* Remove the extra keep-alive reference */
+ ObDereferenceObject(Object);
+ }
+ else
+ {
+ /* Otherwise, lock the object type */
+ ObpEnterObjectTypeMutex(ObjectType);
+
+ /* And charge quota for the process to make it appear as used */
+ RealStatus = ObpChargeQuotaForObject(ObjectHeader,
+ ObjectType,
+ &IsNewObject);
+
+ /* Release the lock */
+ ObpLeaveObjectTypeMutex(ObjectType);
+
+ /* Check if we failed and dereference the object if so */
+ if (!NT_SUCCESS(RealStatus)) ObDereferenceObject(Object);
+ }
/* We can delete the Create Info now */
ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo);
Modified: trunk/reactos/ntoskrnl/se/token.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/token.c?rev=25…
==============================================================================
--- trunk/reactos/ntoskrnl/se/token.c (original)
+++ trunk/reactos/ntoskrnl/se/token.c Tue Jan 9 11:38:07 2007
@@ -350,7 +350,7 @@
Status = ObInsertObject(NewToken,
NULL,
0,
- 1,
+ 0,
NULL,
NULL);
if (NT_SUCCESS(Status))
@@ -658,6 +658,8 @@
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
RtlInitUnicodeString(&Name, L"Token");
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
+ ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
+ ObjectTypeInitializer.SecurityRequired = TRUE;
ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(TOKEN);
ObjectTypeInitializer.GenericMapping = SepTokenMapping;
ObjectTypeInitializer.PoolType = PagedPool;
Author: ion
Date: Tue Jan 9 10:54:19 2007
New Revision: 25393
URL: http://svn.reactos.org/svn/reactos?rev=25393&view=rev
Log:
- Merge some local changes from my version of ObpLookupObjectName:
- Fixup the way we allocate object names: use paged pool instead of non-paged pool, detect insufficient memory case, detect failure to insert entry into the object directory, use name length, not maximum length when copying, use RtlCopy, not RtlMove.
- Support forcing of case-insensitivity and OBJ_FORCE_ACCESS_CHECK.
- Call ObCheckCreateObjectAccess and fail if access isn't granted.
- Call ObpCheckTraverseAccess if traversing a directory fomr user-mode and fail lookup if access wasn't granted.
- Fixup return of proper error code if we reparsed.
- Add FIXME note for SeCreateGlobalPrivilege check which is missing.
- Add callout IRQL checks around parse callouts.
- Rename some variables for clearer meaning.
- Add an extra reference when calling the parse routine in the reparse case.
Modified:
trunk/reactos/ntoskrnl/ob/obname.c
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 9 10:54:19 2007
@@ -287,30 +287,46 @@
IN KPROCESSOR_MODE AccessMode,
IN OUT PVOID ParseContext,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
- IN PVOID ExpectedObject,
+ IN PVOID InsertObject,
IN PACCESS_STATE AccessState,
- IN POBP_LOOKUP_CONTEXT Context,
- OUT PVOID *ReturnedObject)
+ IN POBP_LOOKUP_CONTEXT LookupContext,
+ OUT PVOID *FoundObject)
{
PVOID RootDirectory;
- PVOID CurrentDirectory = NULL;
- PVOID CurrentObject = NULL;
- POBJECT_HEADER CurrentHeader;
- NTSTATUS Status = STATUS_SUCCESS;
- PVOID NewName;
+ PVOID Directory = NULL;
+ PVOID Object;
+ POBJECT_HEADER ObjectHeader;
+ NTSTATUS Status;
+ PWCHAR NewName;
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
- UNICODE_STRING RemainingPath, PartName;
+ UNICODE_STRING RemainingName, ComponentName;
BOOLEAN InsideRoot = FALSE;
+ KPROCESSOR_MODE AccessCheckMode;
OB_PARSE_METHOD ParseRoutine;
+ KIRQL CalloutIrql;
PAGED_CODE();
-
- /* Assume failure */
OBTRACE(OB_NAMESPACE_DEBUG,
"%s - Finding Object: %wZ. Expecting: %p\n",
__FUNCTION__,
ObjectName,
- ExpectedObject);
- *ReturnedObject = NULL;
+ InsertObject);
+
+ /* Initialize starting state */
+ LookupContext->Object = NULL;
+ *FoundObject = NULL;
+ Status = STATUS_SUCCESS;
+ Object = NULL;
+
+ /* Check if case-insensitivity is forced */
+ if ((ObpCaseInsensitive) || (ObjectType->TypeInfo.CaseInsensitive))
+ {
+ /* Add the flag to disable case sensitivity */
+ Attributes |= OBJ_CASE_INSENSITIVE;
+ }
+
+ /* Check if this is a access checks are being forced */
+ AccessCheckMode = (Attributes & OBJ_FORCE_ACCESS_CHECK) ?
+ UserMode : AccessMode;
/* Check if we got a Root Directory */
if (RootHandle)
@@ -325,12 +341,12 @@
if (!NT_SUCCESS(Status)) return Status;
/* Get the header */
- CurrentHeader = OBJECT_TO_OBJECT_HEADER(RootDirectory);
+ ObjectHeader = OBJECT_TO_OBJECT_HEADER(RootDirectory);
/* The name cannot start with a separator, unless this is a file */
if ((ObjectName->Buffer) &&
(ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR) &&
- (CurrentHeader->Type != IoFileObjectType))
+ (ObjectHeader->Type != IoFileObjectType))
{
/* The syntax is bad, so fail this request */
ObDereferenceObject(RootDirectory);
@@ -338,10 +354,10 @@
}
/* Don't parse a Directory */
- if (CurrentHeader->Type != ObDirectoryType)
+ if (ObjectHeader->Type != ObDirectoryType)
{
/* Make sure the Object Type has a parse routine */
- ParseRoutine = CurrentHeader->Type->TypeInfo.ParseProcedure;
+ ParseRoutine = ObjectHeader->Type->TypeInfo.ParseProcedure;
if (!ParseRoutine)
{
/* We can't parse a name if we don't have a parse routine */
@@ -353,19 +369,21 @@
while (TRUE)
{
/* Start with the full name */
- RemainingPath = *ObjectName;
+ RemainingName = *ObjectName;
/* Call the Parse Procedure */
+ ObpCalloutStart(&CalloutIrql);
Status = ParseRoutine(RootDirectory,
ObjectType,
AccessState,
AccessMode,
Attributes,
ObjectName,
- &RemainingPath,
+ &RemainingName,
ParseContext,
SecurityQos,
- &CurrentObject);
+ &Object);
+ ObpCalloutEnd(CalloutIrql, "Parse", ObjectHeader->Type, Object);
/* Check for success or failure, so not reparse */
if ((Status != STATUS_REPARSE) &&
@@ -375,16 +393,16 @@
if (!NT_SUCCESS(Status))
{
/* Parse routine might not have cleared this, do it */
- CurrentObject = NULL;
+ Object = NULL;
}
- else if (!CurrentObject)
+ else if (!Object)
{
/* Modify status to reflect failure inside Ob */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
/* We're done, return the status and object */
- *ReturnedObject = CurrentObject;
+ *FoundObject = Object;
ObDereferenceObject(RootDirectory);
return Status;
}
@@ -409,8 +427,11 @@
0,
ObjectType,
AccessMode);
- if (NT_SUCCESS(Status)) *ReturnedObject = RootDirectory;
+ if (NT_SUCCESS(Status)) Object = RootDirectory;
+
+ /* Remove the first reference we added and return the object */
ObDereferenceObject(RootDirectory);
+ *FoundObject = Object;
return Status;
}
}
@@ -435,14 +456,14 @@
if (!RootDirectory)
{
/* This must be the first time we're creating it... right? */
- if (ExpectedObject)
+ if (InsertObject)
{
/* Yes, so return it to ObInsert so that it can create it */
- Status = ObReferenceObjectByPointer(ExpectedObject,
+ Status = ObReferenceObjectByPointer(InsertObject,
0,
ObjectType,
AccessMode);
- if (NT_SUCCESS(Status)) *ReturnedObject = ExpectedObject;
+ if (NT_SUCCESS(Status)) *FoundObject = InsertObject;
return Status;
}
else
@@ -459,7 +480,7 @@
0,
ObjectType,
AccessMode);
- if (NT_SUCCESS(Status)) *ReturnedObject = RootDirectory;
+ if (NT_SUCCESS(Status)) *FoundObject = RootDirectory;
return Status;
}
}
@@ -467,7 +488,7 @@
/* Save the name */
ReparseNewDir:
- RemainingPath = *ObjectName;
+ RemainingName = *ObjectName;
/* Reparse */
while (TRUE)
@@ -476,121 +497,171 @@
if (!InsideRoot)
{
/* Yes, use the root directory and remember that */
- CurrentDirectory = RootDirectory;
+ Directory = RootDirectory;
InsideRoot = TRUE;
}
/* Check if the name starts with a path separator */
- if ((RemainingPath.Length) &&
- (RemainingPath.Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
+ if ((RemainingName.Length) &&
+ (RemainingName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
{
/* Skip the path separator */
- RemainingPath.Buffer++;
- RemainingPath.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
+ RemainingName.Buffer++;
+ RemainingName.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
}
/* Find the next Part Name */
- PartName = RemainingPath;
- while (RemainingPath.Length)
+ ComponentName = RemainingName;
+ while (RemainingName.Length)
{
/* Break if we found the \ ending */
- if (RemainingPath.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) break;
+ if (RemainingName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) break;
/* Move on */
- RemainingPath.Buffer++;
- RemainingPath.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
+ RemainingName.Buffer++;
+ RemainingName.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
}
/* Get its size and make sure it's valid */
- if (!(PartName.Length -= RemainingPath.Length))
+ if (!(ComponentName.Length -= RemainingName.Length))
{
Status = STATUS_OBJECT_NAME_INVALID;
break;
}
/* Do the look up */
- Context->DirectoryLocked = TRUE;
- Context->Directory = CurrentDirectory;
- CurrentObject = ObpLookupEntryDirectory(CurrentDirectory,
- &PartName,
+ LookupContext->DirectoryLocked = TRUE;
+ LookupContext->Directory = Directory;
+ Object = ObpLookupEntryDirectory(Directory,
+ &ComponentName,
Attributes,
- FALSE,
- Context);
- if (!CurrentObject)
+ InsertObject ? FALSE : TRUE,
+ LookupContext);
+ if (!Object)
{
/* We didn't find it... do we still have a path? */
- if (RemainingPath.Length)
+ if (RemainingName.Length)
{
/* Then tell the caller the path wasn't found */
Status = STATUS_OBJECT_PATH_NOT_FOUND;
break;
}
- else if (!ExpectedObject)
+ else if (!InsertObject)
{
/* Otherwise, we have a path, but the name isn't valid */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
break;
}
- /* Reference newly to be inserted object */
- ObReferenceObject(ExpectedObject);
- CurrentHeader = OBJECT_TO_OBJECT_HEADER(ExpectedObject);
-
- /* Create Object Name */
- NewName = ExAllocatePoolWithTag(NonPagedPool,
- PartName.MaximumLength,
- OB_NAME_TAG);
- ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(CurrentHeader);
-
- /* Copy the Name */
- RtlMoveMemory(NewName, PartName.Buffer, PartName.MaximumLength);
-
- /* Free old name */
- if (ObjectNameInfo->Name.Buffer) ExFreePool(ObjectNameInfo->Name.Buffer);
-
- /* Write new one */
- ObjectNameInfo->Name.Buffer = NewName;
- ObjectNameInfo->Name.Length = PartName.Length;
- ObjectNameInfo->Name.MaximumLength = PartName.MaximumLength;
-
- /* Rereference the Directory and insert */
- ObReferenceObject(CurrentDirectory);
- ObpInsertEntryDirectory(CurrentDirectory, Context, CurrentHeader);
-
- /* Return Status and the Expected Object */
- Status = STATUS_SUCCESS;
- CurrentObject = ExpectedObject;
-
- /* Get out of here */
- 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 */
- CurrentHeader = OBJECT_TO_OBJECT_HEADER(CurrentObject);
+ 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 = CurrentHeader->Type->TypeInfo.ParseProcedure;
- if (ParseRoutine &&
- (!ExpectedObject || ParseRoutine == ObpParseSymbolicLink))
+ 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);
+
/* Call the Parse Procedure */
- Status = ParseRoutine(CurrentObject,
+ ObpCalloutStart(&CalloutIrql);
+ Status = ParseRoutine(Object,
ObjectType,
AccessState,
AccessMode,
Attributes,
ObjectName,
- &RemainingPath,
+ &RemainingName,
ParseContext,
SecurityQos,
- &CurrentObject);
+ &Object);
+ ObpCalloutEnd(CalloutIrql, "Parse", ObjectHeader->Type, Object);
+
+ /* Remove our extra reference */
+ ObDereferenceObject(&ObjectHeader->Body);
/* Check if we have to reparse */
if ((Status == STATUS_REPARSE) ||
@@ -615,7 +686,7 @@
if (Status == STATUS_REPARSE_OBJECT)
{
/* Did we actually get an object to which to reparse? */
- if (!CurrentObject)
+ if (!Object)
{
/* We didn't, so set a failure status */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
@@ -634,16 +705,16 @@
else if (RootDirectory == NameSpaceRoot)
{
/* We got STATUS_REPARSE but are at the Root Directory */
- CurrentObject = NULL;
+ Object = NULL;
Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
}
else if (!NT_SUCCESS(Status))
{
/* Total failure */
- CurrentObject = NULL;
- }
- else if (!CurrentObject)
+ Object = NULL;
+ }
+ else if (!Object)
{
/* We didn't reparse but we didn't find the Object Either */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
@@ -655,17 +726,35 @@
else
{
/* No parse routine...do we still have a remaining name? */
- if (!RemainingPath.Length)
+ if (!RemainingName.Length)
{
/* Are we creating an object? */
- if (!ExpectedObject)
- {
- /* We don't... reference the Object */
- Status = ObReferenceObjectByPointer(CurrentObject,
+ if (!InsertObject)
+ {
+ /* Check if this is a user-mode call that needs to traverse */
+ if ((AccessCheckMode != KernelMode) &&
+ !(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE))
+ {
+ /* 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)) CurrentObject = NULL;
+ if (!NT_SUCCESS(Status)) Object = NULL;
}
/* And get out of the reparse loop */
@@ -674,42 +763,51 @@
else
{
/* We still have a name; check if this is a directory object */
- if (CurrentHeader->Type == ObDirectoryType)
+ if (ObjectHeader->Type == ObDirectoryType)
{
/* Restart from this directory */
- CurrentDirectory = CurrentObject;
+ Directory = Object;
}
else
{
/* We still have a name, but no parse routine for it */
Status = STATUS_OBJECT_TYPE_MISMATCH;
- CurrentObject = NULL;
+ Object = NULL;
break;
}
}
}
}
- /* Write what we found, and if it's null, check if we got success */
- if (!(*ReturnedObject = CurrentObject) && (NT_SUCCESS(Status)))
- {
- /* Nothing found... but we have success. Correct the status code */
- Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ /* Check if we failed */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Cleanup after lookup */
+ //ObpCleanupDirectoryLookup(LookupContext, TRUE);
+ LookupContext->Object = NULL;
+ }
+
+ /* Set the found object and check if we got one */
+ *FoundObject = Object;
+ if (!Object)
+ {
+ /* Nothing was found. Did we reparse or get success? */
+ if ((Status == STATUS_REPARSE) || (NT_SUCCESS(Status)))
+ {
+ /* Set correct failure */
+ Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ }
}
/* Check if we had a root directory */
- if (RootHandle)
- {
- /* Dereference it */
- ObDereferenceObject(RootDirectory);
- }
+ if (RootHandle) ObDereferenceObject(RootDirectory);
/* Return status to caller */
OBTRACE(OB_NAMESPACE_DEBUG,
"%s - Found Object: %p. Expected: %p\n",
__FUNCTION__,
- *ReturnedObject,
- ExpectedObject);
+ *FoundObject,
+ InsertObject);
return Status;
}
Author: ion
Date: Tue Jan 9 10:28:40 2007
New Revision: 25392
URL: http://svn.reactos.org/svn/reactos?rev=25392&view=rev
Log:
- Add internal macros for acquiring the object directory pushlock during lookup (not yet used).
- Add internal macros for incrementing/decrementing query references, and use them where appropriate. Do not yet support the path for an object which is currently being defer deleted.
- Add internal macros for cleaning up a directory lookup (not yet used and needs renaming/cleanup), initializing a directory lookup (not yet used).
- Don't call security callback in ObpDeleteNameCheck. Make sure permanent flag is still cleared after acquiring type lock. Add special call for symboilc links. Add commented out calls to lock the object directory.
Modified:
trunk/reactos/ntoskrnl/include/internal/ob_x.h
trunk/reactos/ntoskrnl/ob/obhandle.c
trunk/reactos/ntoskrnl/ob/obname.c
Modified: trunk/reactos/ntoskrnl/include/internal/ob_x.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ob_x.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ob_x.h Tue Jan 9 10:28:40 2007
@@ -6,6 +6,8 @@
* PROGRAMMERS: Alex Ionescu (alex.ionescu(a)reactos.org)
*/
+#include "ex.h"
+
#if DBG
VOID
FORCEINLINE
@@ -55,6 +57,193 @@
VOID
FORCEINLINE
+_ObpAcquireDirectoryLockShared(IN POBJECT_DIRECTORY Directory,
+ IN POBP_LOOKUP_CONTEXT Context)
+{
+ /* It's not, set lock flag */
+ Context->LockStateSignature = 0xBBBB1234;
+
+ /* Lock it */
+ KeEnterCriticalRegion();
+ ExAcquirePushLockShared(&Directory->Lock);
+
+ /* Update lock flag */
+ Context->LockStateSignature = 0xDDDD1234;
+}
+
+VOID
+FORCEINLINE
+_ObpAcquireDirectoryLockExclusive(IN POBJECT_DIRECTORY Directory,
+ IN POBP_LOOKUP_CONTEXT Context)
+{
+ /* Update lock flag */
+ Context->LockStateSignature = 0xAAAA1234;
+
+ /* Lock it */
+ KeEnterCriticalRegion();
+ ExAcquirePushLockExclusive(&Directory->Lock);
+}
+
+VOID
+FORCEINLINE
+_ObpReleaseDirectoryLock(IN POBJECT_DIRECTORY Directory,
+ IN POBP_LOOKUP_CONTEXT Context)
+{
+ /* Release the lock */
+ ExReleasePushLock(&Directory->Lock);
+ Context->LockStateSignature = 0xEEEE1234;
+ KeLeaveCriticalRegion();
+}
+
+ULONG
+FORCEINLINE
+ObpIncrementQueryReference(IN POBJECT_HEADER ObjectHeader,
+ IN POBJECT_HEADER_NAME_INFO ObjectNameInfo)
+{
+ ULONG NewValue, References;
+
+ /* Get the number of references */
+ NewValue = ObjectNameInfo->QueryReferences;
+ while ((NewValue != 0) && (References = NewValue))
+ {
+ /* Increment the number of references */
+ if (InterlockedCompareExchange(&ObjectNameInfo->QueryReferences,
+ NewValue + 1,
+ NewValue) == References)
+ {
+ /* Check if the object is to be deferred deleted */
+ if (ObjectHeader->Flags & OB_FLAG_DEFER_DELETE)
+ {
+ /* FIXME: Unhandled*/
+ DbgPrint("OB: Unhandled path\n");
+ KEBUGCHECK(0);
+ }
+
+ /* Done looping */
+ NewValue = ObjectNameInfo->QueryReferences;
+ break;
+ }
+ }
+
+ /* Return the number of references */
+ return NewValue;
+}
+
+VOID
+FORCEINLINE
+_ObpDecrementQueryReference(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo)
+{
+ POBJECT_DIRECTORY Directory;
+
+ /* Remove a query reference and check if it was the last one */
+ if (!InterlockedExchangeAdd(&HeaderNameInfo->QueryReferences, -1))
+ {
+ /* Check if we have a name */
+ if (HeaderNameInfo->Name.Buffer)
+ {
+ /* We can get rid of the object name now */
+ ExFreePool(HeaderNameInfo->Name.Buffer);
+ RtlInitEmptyUnicodeString(&HeaderNameInfo->Name, NULL, 0);
+ }
+
+ /* Check if the object has a directory associated to it */
+ Directory = HeaderNameInfo->Directory;
+ if (Directory)
+ {
+ /* Delete the directory */
+ HeaderNameInfo->Directory = NULL;
+ ObDereferenceObjectDeferDelete(Directory);
+ }
+ }
+}
+
+VOID
+FORCEINLINE
+_ObpCleanupDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context,
+ IN BOOLEAN DereferenceObject)
+{
+ POBJECT_HEADER ObjectHeader;
+ POBJECT_HEADER_NAME_INFO HeaderNameInfo;
+
+ /* Check if we came back with the directory locked */
+ if (Context->DirectoryLocked)
+ {
+ /* Release the lock */
+ _ObpReleaseDirectoryLock(Context->Directory, Context);
+ }
+
+ /* Clear the context */
+ Context->Directory = NULL;
+ Context->DirectoryLocked = FALSE;
+
+ /* Check if we had found an object */
+ if (Context->Object)
+ {
+ /* Get the object name information */
+ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Context->Object);
+ HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
+
+ /* Check if we do have name information */
+ if (HeaderNameInfo) _ObpDecrementQueryReference(HeaderNameInfo);
+
+ /* Check if we need to dereference it */
+ if (DereferenceObject) ObDereferenceObject(Context->Object);
+ }
+}
+
+VOID
+FORCEINLINE
+_ObpInitializeDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context)
+{
+ /* Initialize a null context */
+ Context->Object = NULL;
+ Context->Directory = NULL;
+ Context->DirectoryLocked = FALSE;
+ Context->LockStateSignature = 0xFFFF1234;
+}
+
+#if _OB_DEBUG_
+#define ObpAcquireDirectoryLockShared(a, b) \
+{ \
+ DbgPrint("OB QUERY: Acquiring lock at %s %d\n", __FUNCTION__, __LINE__);\
+ _ObpAcquireDirectoryLockShared(a, b); \
+}
+#define ObpAcquireDirectoryLockExclusive(a, b) \
+{ \
+ DbgPrint("OB QUERY: Acquiring lock at %s %d\n", __FUNCTION__, __LINE__);\
+ _ObpAcquireDirectoryLockExclusive(a, b); \
+}
+#define ObpReleaseDirectoryLock(a, b) \
+{ \
+ DbgPrint("OB QUERY: Releasing lock at %s %d\n", __FUNCTION__, __LINE__);\
+ _ObpReleaseDirectoryLock(a, b); \
+}
+#define ObpInitializeDirectoryLookup(a) \
+{ \
+ DbgPrint("OB QUERY: Initialization at %s %d\n", __FUNCTION__, __LINE__);\
+ _ObpInitializeDirectoryLookup(a); \
+}
+#define ObpCleanupDirectoryLookup(a, b) \
+{ \
+ DbgPrint("OB QUERY: Cleanup at %s %d\n", __FUNCTION__, __LINE__); \
+ _ObpCleanupDirectoryLookup(a, b); \
+}
+#define ObpDecrementQueryReference(a) \
+{ \
+ DbgPrint("OB QUERY: Decrement at %s %d\n", __FUNCTION__, __LINE__); \
+ _ObpDecrementQueryReference(a); \
+}
+#else
+#define ObpDecrementQueryReference _ObpDecrementQueryReference
+#define ObpAcquireDirectoryLockExclusive _ObpAcquireDirectoryLockExclusive
+#define ObpAcquireDirectoryLockShared _ObpAcquireDirectoryLockShared
+#define ObpReleaseDirectoryLock _ObpReleaseDirectoryLock
+#define ObpInitializeDirectoryLookup _ObpInitializeDirectoryLookup
+#define ObpCleanupDirectoryLookup _ObpCleanupDirectoryLookup
+#endif
+
+VOID
+FORCEINLINE
ObpEnterObjectTypeMutex(IN POBJECT_TYPE ObjectType)
{
/* Sanity check */
@@ -176,3 +365,5 @@
ObpFreeCapturedAttributes(ObjectCreateInfo, LookasideCreateInfoList);
}
+
+
Modified: trunk/reactos/ntoskrnl/ob/obhandle.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obhandle.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obhandle.c (original)
+++ trunk/reactos/ntoskrnl/ob/obhandle.c Tue Jan 9 10:28:40 2007
@@ -2352,6 +2352,16 @@
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
ObjectType = ObjectHeader->Type;
+ /* Check if we have name information */
+ if (ObjectNameInfo)
+ {
+ /* Add a query reference */
+ if (!ObpIncrementQueryReference(ObjectHeader, ObjectNameInfo))
+ {
+ /* There are no query references, so the name info is invalid */
+ ObjectNameInfo = NULL;
+ }
+ }
/* Check if this is an named object */
ObjectName = NULL;
@@ -2394,6 +2404,8 @@
ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo);
ObjectHeader->ObjectCreateInfo = NULL;
+ /* Remove a query reference if we added one */
+ if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
/* Remove the extra keep-alive reference */
if (Handle) ObDereferenceObject(Object);
@@ -2419,6 +2431,7 @@
if (!NT_SUCCESS(Status))
{
/* Fail */
+ if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
ObDereferenceObject(Object);
return Status;
}
@@ -2489,7 +2502,10 @@
/* Check if anything until now failed */
if (!NT_SUCCESS(Status))
{
- /* We failed, dereference the object and delete the access state */
+ /* Remove query reference that we added */
+ if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
+
+ /* Dereference the object and delete the access state */
ObDereferenceObject(Object);
if (AccessState == &LocalAccessState)
{
@@ -2554,8 +2570,10 @@
/* Check if anything until now failed */
if (!NT_SUCCESS(Status))
{
- /* We failed, dereference the object and delete the access state */
- KEBUGCHECK(0);
+ /* Remove query reference that we added */
+ if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
+
+ /* Dereference the object and delete the access state */
ObDereferenceObject(Object);
if (AccessState == &LocalAccessState)
{
@@ -2564,6 +2582,7 @@
}
/* Return failure code */
+ KEBUGCHECK(0);
return Status;
}
}
@@ -2608,8 +2627,8 @@
RealStatus = Status;
}
-
-
+ /* Remove a query reference */
+ if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
/* Remove the extra keep-alive reference */
if (Handle) ObDereferenceObject(Object);
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 9 10:28:40 2007
@@ -173,6 +173,17 @@
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
ObjectType = ObjectHeader->Type;
+ /* Check if we have a name information structure */
+ if (ObjectNameInfo)
+ {
+ /* Add a query reference */
+ if (!ObpIncrementQueryReference(ObjectHeader, ObjectNameInfo))
+ {
+ /* No references, so the name info is invalid */
+ ObjectNameInfo = NULL;
+ }
+ }
+
/*
* Check if the handle count is 0, if the object is named,
* and if the object isn't a permanent object.
@@ -182,61 +193,88 @@
(ObjectNameInfo->Name.Length) &&
!(ObjectHeader->Flags & OB_FLAG_PERMANENT))
{
+ /* Setup a lookup context */
Context.Object = NULL;
- /* Make sure it's still inserted */
+ /* Lock the directory */
+ //ObpAcquireDirectoryLockExclusive(ObjectNameInfo->Directory, &Context);
+
+ /* Set the lookup parameters */
Context.Directory = ObjectNameInfo->Directory;
Context.DirectoryLocked = TRUE;
+ Context.LockStateSignature = 0xCCCC1234;
+
+ /* Do the lookup */
Object = ObpLookupEntryDirectory(ObjectNameInfo->Directory,
&ObjectNameInfo->Name,
0,
FALSE,
&Context);
- if ((Object) && !(ObjectHeader->HandleCount))
+ if (Object)
{
/* Lock the object type */
ObpEnterObjectTypeMutex(ObjectType);
- /* First delete it from the directory */
- ObpDeleteEntryDirectory(&Context);
-
- /* Now check if we have a security callback */
- if (ObjectType->TypeInfo.SecurityRequired)
- {
- /* Call it */
- ObjectType->TypeInfo.SecurityProcedure(Object,
- DeleteSecurityDescriptor,
- 0,
- NULL,
- NULL,
- &ObjectHeader->
- SecurityDescriptor,
- ObjectType->
- TypeInfo.PoolType,
- NULL);
+ /* Make sure we can still delete the object */
+ if (!(ObjectHeader->HandleCount) &&
+ !(ObjectHeader->Flags & OB_FLAG_PERMANENT))
+ {
+ /* First delete it from the directory */
+ ObpDeleteEntryDirectory(&Context);
+
+ /* Check if this is a symbolic link */
+ if (ObjectType == ObSymbolicLinkType)
+ {
+ /* Remove internal name */
+ ObpDeleteSymbolicLinkName(Object);
+ }
+
+ /* Add a query reference */
+ ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
+ if (!ObpIncrementQueryReference(ObjectHeader, ObjectNameInfo))
+ {
+ /* No references, so the name info is invalid */
+ ObjectNameInfo = NULL;
+ }
+
+ /* Check if the magic protection flag is set */
+ if ((ObjectNameInfo) &&
+ (ObjectNameInfo->QueryReferences & 0x40000000))
+ {
+ /* Add deletion flag */
+ InterlockedExchangeAdd(&ObjectNameInfo->QueryReferences,
+ 0xC0000000);
+ }
+
+ /* Get the directory */
+ Directory = ObjectNameInfo->Directory;
}
/* Release the lock */
ObpLeaveObjectTypeMutex(ObjectType);
-
- /* Free the name */
- ExFreePool(ObjectNameInfo->Name.Buffer);
- RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, NULL, 0);
-
- Context.Object = NULL;
-
- /* Clear the current directory and de-reference it */
- Directory = ObjectNameInfo->Directory;
- ObjectNameInfo->Directory = NULL;
- }
+ }
+
+ /* Cleanup after lookup */
+ //ObpCleanupDirectoryLookup(&Context, TRUE);
+ Context.Object = NULL;
+
+ /* Remove another query reference since we added one on top */
+ ObpDecrementQueryReference(ObjectNameInfo);
/* Check if we were inserted in a directory */
if (Directory)
{
- /* We were, so dereference the directory and the object as well */
- ObDereferenceObject(Directory);
+ /* We were, so first remove the extra reference we had added */
+ ObpDecrementQueryReference(ObjectNameInfo);
+
+ /* Now dereference the object as well */
ObDereferenceObject(Object);
}
+ }
+ else
+ {
+ /* Remove the reference we added */
+ if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
}
}
Author: ion
Date: Mon Jan 8 20:56:56 2007
New Revision: 25382
URL: http://svn.reactos.org/svn/reactos?rev=25382&view=rev
Log:
- Fix kmtest's inclusion of the NDK.
- Implement support for the Handle Count Database.
- Don't do anything in IopCloseFile if this isn't the last handle for the process.
- Fix definition of OBJECT_HANDLE_COUNT_DATABASE.
Modified:
trunk/reactos/drivers/test/kmtest/ntos_ob.c
trunk/reactos/include/ndk/obtypes.h
trunk/reactos/ntoskrnl/io/iomgr/file.c
trunk/reactos/ntoskrnl/ob/obhandle.c
Modified: trunk/reactos/drivers/test/kmtest/ntos_ob.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/test/kmtest/ntos_o…
==============================================================================
--- trunk/reactos/drivers/test/kmtest/ntos_ob.c (original)
+++ trunk/reactos/drivers/test/kmtest/ntos_ob.c Mon Jan 8 20:56:56 2007
@@ -28,12 +28,7 @@
//#define NDEBUG
#include "debug.h"
-#include "ndk/obtypes.h"
-#include "ndk/obfuncs.h"
-
-#include "ndk/ifssupp.h"
-#include "ndk/setypes.h"
-#include "ndk/sefuncs.h"
+#include "ntndk.h"
// I ment to make this test scalable, but for now
// we work with two object types only
Modified: trunk/reactos/include/ndk/obtypes.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/obtypes.h?rev=…
==============================================================================
--- trunk/reactos/include/ndk/obtypes.h (original)
+++ trunk/reactos/include/ndk/obtypes.h Mon Jan 8 20:56:56 2007
@@ -399,7 +399,7 @@
typedef struct _OBJECT_HANDLE_COUNT_DATABASE
{
ULONG CountEntries;
- POBJECT_HANDLE_COUNT_ENTRY HandleCountEntries[1];
+ OBJECT_HANDLE_COUNT_ENTRY HandleCountEntries[1];
} OBJECT_HANDLE_COUNT_DATABASE, *POBJECT_HANDLE_COUNT_DATABASE;
typedef struct _OBJECT_HEADER_HANDLE_INFO
Modified: trunk/reactos/ntoskrnl/io/iomgr/file.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/file.c?r…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/file.c (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/file.c Mon Jan 8 20:56:56 2007
@@ -1396,6 +1396,9 @@
KIRQL OldIrql;
IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);
+ /* If this isn't the last handle for the current process, quit */
+ if (HandleCount != 1) return;
+
/* Check if the file is locked and has more then one handle opened */
if ((FileObject->LockOperation) && (SystemHandleCount != 1))
{
Modified: trunk/reactos/ntoskrnl/ob/obhandle.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obhandle.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obhandle.c (original)
+++ trunk/reactos/ntoskrnl/ob/obhandle.c Mon Jan 8 20:56:56 2007
@@ -19,7 +19,177 @@
PHANDLE_TABLE ObpKernelHandleTable = NULL;
+#define TAG_OB_HANDLE TAG('O', 'b', 'H', 'd')
+
/* PRIVATE FUNCTIONS *********************************************************/
+
+POBJECT_HANDLE_COUNT_ENTRY
+NTAPI
+ObpInsertHandleCount(IN POBJECT_HEADER ObjectHeader)
+{
+ POBJECT_HEADER_HANDLE_INFO HandleInfo;
+ POBJECT_HANDLE_COUNT_ENTRY FreeEntry;
+ POBJECT_HANDLE_COUNT_DATABASE HandleDatabase, OldHandleDatabase;
+ ULONG i;
+ ULONG Size, OldSize;
+ OBJECT_HANDLE_COUNT_DATABASE SingleDatabase;
+ PAGED_CODE();
+
+ /* Get the handle info */
+ HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader);
+ if (!HandleInfo) return NULL;
+
+ /* Check if we only have one entry */
+ if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS)
+ {
+ /* Fill out the single entry */
+ SingleDatabase.CountEntries = 1;
+ SingleDatabase.HandleCountEntries[0] = HandleInfo->SingleEntry;
+
+ /* Use this as the old size */
+ OldHandleDatabase = &SingleDatabase;
+ OldSize = sizeof(SingleDatabase);
+
+ /* Now we'll have two entries, and an entire DB */
+ i = 2;
+ Size = sizeof(OBJECT_HANDLE_COUNT_DATABASE) +
+ sizeof(OBJECT_HANDLE_COUNT_ENTRY);
+ }
+ else
+ {
+ /* We already have a DB, get the information from it */
+ OldHandleDatabase = HandleInfo->HandleCountDatabase;
+ i = OldHandleDatabase->CountEntries;
+ OldSize = sizeof(OBJECT_HANDLE_COUNT_DATABASE) +
+ ((i - 1) * sizeof(OBJECT_HANDLE_COUNT_ENTRY));
+
+ /* Add 4 more entries */
+ i += 4;
+ Size = OldSize += (4 * sizeof(OBJECT_HANDLE_COUNT_ENTRY));
+ }
+
+ /* Allocate the DB */
+ HandleDatabase = ExAllocatePoolWithTag(PagedPool, Size, TAG_OB_HANDLE);
+ if (!HandleDatabase) return NULL;
+
+ /* Copy the old database */
+ RtlMoveMemory(HandleDatabase, OldHandleDatabase, OldSize);
+
+ /* Check if we he had a single entry before */
+ if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS)
+ {
+ /* Now we have more */
+ ObjectHeader->Flags &= ~OB_FLAG_SINGLE_PROCESS;
+ }
+ else
+ {
+ /* Otherwise we had a DB, free it */
+ ExFreePool(OldHandleDatabase);
+ }
+
+ /* Find the end of the copy and zero out the new data */
+ FreeEntry = (PVOID)((ULONG_PTR)HandleDatabase + OldSize);
+ RtlZeroMemory(FreeEntry, Size - OldSize);
+
+ /* Set the new information and return the free entry */
+ HandleDatabase->CountEntries = i;
+ HandleInfo->HandleCountDatabase = HandleDatabase;
+ return FreeEntry;
+}
+
+NTSTATUS
+NTAPI
+ObpIncrementHandleDataBase(IN POBJECT_HEADER ObjectHeader,
+ IN PEPROCESS Process,
+ IN OUT PULONG NewProcessHandleCount)
+{
+ POBJECT_HEADER_HANDLE_INFO HandleInfo;
+ POBJECT_HANDLE_COUNT_ENTRY HandleEntry, FreeEntry = NULL;
+ POBJECT_HANDLE_COUNT_DATABASE HandleDatabase;
+ ULONG i;
+ PAGED_CODE();
+
+ /* Get the handle info and check if we only have one entry */
+ HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader);
+ if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS)
+ {
+ /* Check if the entry is free */
+ if (!HandleInfo->SingleEntry.HandleCount)
+ {
+ /* Add ours */
+ HandleInfo->SingleEntry.HandleCount = 1;
+ HandleInfo->SingleEntry.Process = Process;
+
+ /* Return success and 1 handle */
+ *NewProcessHandleCount = 1;
+ return STATUS_SUCCESS;
+ }
+ else if (HandleInfo->SingleEntry.Process == Process)
+ {
+ /* Busy entry, but same process */
+ *NewProcessHandleCount = ++HandleInfo->SingleEntry.HandleCount;
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ /* Insert a new entry */
+ FreeEntry = ObpInsertHandleCount(ObjectHeader);
+ if (!FreeEntry) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Fill it out */
+ FreeEntry->Process = Process;
+ FreeEntry->HandleCount = 1;
+
+ /* Return success and 1 handle */
+ *NewProcessHandleCount = 1;
+ return STATUS_SUCCESS;
+ }
+ }
+
+ /* We have a database instead */
+ HandleDatabase = HandleInfo->HandleCountDatabase;
+ if (HandleDatabase)
+ {
+ /* Get the entries and loop them */
+ i = HandleDatabase->CountEntries;
+ HandleEntry = &HandleDatabase->HandleCountEntries[0];
+ while (i)
+ {
+ /* Check if this is a match */
+ if (HandleEntry->Process == Process)
+ {
+ /* Found it, get the process handle count */
+ *NewProcessHandleCount = ++HandleEntry->HandleCount;
+ return STATUS_SUCCESS;
+ }
+ else if (!HandleEntry->HandleCount)
+ {
+ /* Found a free entry */
+ FreeEntry = HandleEntry;
+ }
+
+ /* Keep looping */
+ HandleEntry++;
+ i--;
+ }
+
+ /* Check if we couldn't find a free entry */
+ if (!FreeEntry)
+ {
+ /* Allocate one */
+ FreeEntry = ObpInsertHandleCount(ObjectHeader);
+ if (!FreeEntry) return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Fill out the entry */
+ FreeEntry->Process = Process;
+ FreeEntry->HandleCount = 1;
+ *NewProcessHandleCount = 1;
+ }
+
+ /* Return success if we got here */
+ return STATUS_SUCCESS;
+}
NTSTATUS
NTAPI
@@ -101,6 +271,10 @@
LONG NewCount;
POBJECT_HEADER_CREATOR_INFO CreatorInfo;
KIRQL CalloutIrql;
+ POBJECT_HEADER_HANDLE_INFO HandleInfo;
+ POBJECT_HANDLE_COUNT_ENTRY HandleEntry;
+ POBJECT_HANDLE_COUNT_DATABASE HandleDatabase;
+ ULONG i;
/* Get the object type and header */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
@@ -138,8 +312,53 @@
/* Is the object type keeping track of handles? */
if (ObjectType->TypeInfo.MaintainHandleCount)
{
- /* FIXME */
- DPRINT("Handle Database not yet implemented\n");
+ /* Get handle information */
+ HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader);
+
+ /* Check if there's only a single entry */
+ if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS)
+ {
+ /* It should be us */
+ ASSERT(HandleInfo->SingleEntry.Process == Process);
+ ASSERT(HandleInfo->SingleEntry.HandleCount > 0);
+
+ /* Get the handle counts */
+ ProcessHandleCount = HandleInfo->SingleEntry.HandleCount--;
+ HandleEntry = &HandleInfo->SingleEntry;
+ }
+ else
+ {
+ /* Otherwise, get the database */
+ HandleDatabase = HandleInfo->HandleCountDatabase;
+ if (HandleDatabase)
+ {
+ /* Get the entries and loop them */
+ i = HandleDatabase->CountEntries;
+ HandleEntry = &HandleDatabase->HandleCountEntries[0];
+ while (i)
+ {
+ /* Check if this is a match */
+ if ((HandleEntry->HandleCount) &&
+ (HandleEntry->Process == Process))
+ {
+ /* Found it, get the process handle count */
+ ProcessHandleCount = HandleEntry->HandleCount--;
+ }
+
+ /* Keep looping */
+ HandleEntry++;
+ i--;
+ }
+ }
+ }
+
+ /* Check if this is the last handle */
+ if (ProcessHandleCount == 1)
+ {
+ /* Then clear the entry */
+ HandleEntry->Process = NULL;
+ HandleEntry->HandleCount = 0;
+ }
}
/* Release the lock */
@@ -461,8 +680,17 @@
/* Check if we have a handle database */
if (ObjectType->TypeInfo.MaintainHandleCount)
{
- /* FIXME: TODO */
- DPRINT("Handle DB not yet supported\n");
+ /* Increment the handle database */
+ Status = ObpIncrementHandleDataBase(ObjectHeader,
+ Process,
+ &ProcessHandleCount);
+ if (!NT_SUCCESS(Status))
+ {
+ /* FIXME: This should never happen for now */
+ DPRINT1("Unhandled case\n");
+ KEBUGCHECK(0);
+ goto Quickie;
+ }
}
/* Release the lock */
@@ -672,8 +900,17 @@
/* Check if we have a handle database */
if (ObjectType->TypeInfo.MaintainHandleCount)
{
- /* FIXME: TODO */
- DPRINT("Handle DB not yet supported\n");
+ /* Increment the handle database */
+ Status = ObpIncrementHandleDataBase(ObjectHeader,
+ Process,
+ &ProcessHandleCount);
+ if (!NT_SUCCESS(Status))
+ {
+ /* FIXME: This should never happen for now */
+ DPRINT1("Unhandled case\n");
+ KEBUGCHECK(0);
+ goto Quickie;
+ }
}
/* Release the lock */
Author: ion
Date: Mon Jan 8 20:49:44 2007
New Revision: 25381
URL: http://svn.reactos.org/svn/reactos?rev=25381&view=rev
Log:
- Fix build. Sorry, forgot that the last commit also included changes to FsrtlAreNamesEqual to raise an exception if upcasing the strings failed.
Modified:
trunk/reactos/ntoskrnl/fsrtl/name.c
Modified: trunk/reactos/ntoskrnl/fsrtl/name.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/name.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/fsrtl/name.c (original)
+++ trunk/reactos/ntoskrnl/fsrtl/name.c Mon Jan 8 20:49:44 2007
@@ -49,6 +49,7 @@
UNICODE_STRING UpcaseName2;
BOOLEAN StringsAreEqual, MemoryAllocated = FALSE;
ULONG i;
+ NTSTATUS Status;
/* Well, first check their size */
if (Name1->Length != Name2->Length) return FALSE;