reactos/ntoskrnl/ob/obname.c

1418 lines
52 KiB
C
Raw Normal View History

/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/ob/obname.c
* PURPOSE: Manages all functions related to the Object Manager name-
* space, such as finding objects or querying their names.
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Eric Kohl
* Thomas Weidenmueller (w3seek@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
- Fix ObReferenceObjectByName to do proper name validation checks. - Fix ObReferenceObjectByName to call ObpCheckObjectReference before allowing the caller to obtain the reference. - Rename ObFindObject to ObpLookupObjectName and shuffle parameters around and add some placeholder code that resets the object pointer of the lookup context. - Modify ObpChargeQuotaForObject to also return if this is a new object. - Modify ObpDecrementHandleCount to detect when objects with a handle database are being used. Also protect close callout with checks. Protect ObpCloseHAndleTableEntry's callouts with checks as well. - Update logic of ObpIncrementHandleCount and ObpIncrementUnnamedHandleCount to handle currently exclusive objects as well as new handles with OBJ_EXCLUSIVE. Also detect objects that require handle databases and protect callouts. - Support CreatorInfo and the TypeList in ObpIncrementHandleCount. Also update the TotalNumberOfHandles in the object type properly. - Fixup object type lock usage in these routines. - Do proper invalid attributes check in ObOpenObjectByName, and also use a buffer from the pool instead of the stack. - Make ObInsertObject detect invalid object insertions and change some parameter names and checks. - Add stub code to validate the access mask in ObInsertObject. Proper initailize some lookup variables before starting lookup. - Add detection for symbolic link inserts which require some handling code later on. - Free the create information at the right moment isntead of too late. - Add some missing Ob functions, flags and types to the NDK. Fix OBJECT_DIRECTORY structure to use EX_PUSH_LOCK for locks, not ERESOURCE. svn path=/trunk/; revision=25372
2007-01-08 08:03:47 +00:00
#include <debug.h>
- Fix ObReferenceObjectByName to do proper name validation checks. - Fix ObReferenceObjectByName to call ObpCheckObjectReference before allowing the caller to obtain the reference. - Rename ObFindObject to ObpLookupObjectName and shuffle parameters around and add some placeholder code that resets the object pointer of the lookup context. - Modify ObpChargeQuotaForObject to also return if this is a new object. - Modify ObpDecrementHandleCount to detect when objects with a handle database are being used. Also protect close callout with checks. Protect ObpCloseHAndleTableEntry's callouts with checks as well. - Update logic of ObpIncrementHandleCount and ObpIncrementUnnamedHandleCount to handle currently exclusive objects as well as new handles with OBJ_EXCLUSIVE. Also detect objects that require handle databases and protect callouts. - Support CreatorInfo and the TypeList in ObpIncrementHandleCount. Also update the TotalNumberOfHandles in the object type properly. - Fixup object type lock usage in these routines. - Do proper invalid attributes check in ObOpenObjectByName, and also use a buffer from the pool instead of the stack. - Make ObInsertObject detect invalid object insertions and change some parameter names and checks. - Add stub code to validate the access mask in ObInsertObject. Proper initailize some lookup variables before starting lookup. - Add detection for symbolic link inserts which require some handling code later on. - Free the create information at the right moment isntead of too late. - Add some missing Ob functions, flags and types to the NDK. Fix OBJECT_DIRECTORY structure to use EX_PUSH_LOCK for locks, not ERESOURCE. svn path=/trunk/; revision=25372
2007-01-08 08:03:47 +00:00
BOOLEAN ObpCaseInsensitive = TRUE;
POBJECT_DIRECTORY ObpRootDirectoryObject;
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
};
WCHAR ObpUnsecureGlobalNamesBuffer[128] = {0};
ULONG ObpUnsecureGlobalNamesLength = sizeof(ObpUnsecureGlobalNamesBuffer);
/* PRIVATE FUNCTIONS *********************************************************/
CODE_SEG("INIT")
NTSTATUS
NTAPI
ObpGetDosDevicesProtection(OUT PSECURITY_DESCRIPTOR SecurityDescriptor)
{
PACL Dacl;
ULONG AclSize;
NTSTATUS Status;
/* Initialize the SD */
Status = RtlCreateSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
ASSERT(NT_SUCCESS(Status));
if (ObpProtectionMode & 1)
{
AclSize = sizeof(ACL) +
sizeof(ACE) + RtlLengthSid(SeWorldSid) +
sizeof(ACE) + RtlLengthSid(SeLocalSystemSid) +
sizeof(ACE) + RtlLengthSid(SeWorldSid) +
sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid) +
sizeof(ACE) + RtlLengthSid(SeLocalSystemSid) +
sizeof(ACE) + RtlLengthSid(SeCreatorOwnerSid);
/* Allocate the ACL */
Dacl = ExAllocatePoolWithTag(PagedPool, AclSize, TAG_DACL);
if (Dacl == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Initialize the DACL */
Status = RtlCreateAcl(Dacl, AclSize, ACL_REVISION);
ASSERT(NT_SUCCESS(Status));
/* Add the ACEs */
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
GENERIC_READ | GENERIC_EXECUTE,
SeWorldSid);
ASSERT(NT_SUCCESS(Status));
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
GENERIC_ALL,
SeLocalSystemSid);
ASSERT(NT_SUCCESS(Status));
Status = RtlAddAccessAllowedAceEx(Dacl,
ACL_REVISION,
INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
GENERIC_EXECUTE,
SeWorldSid);
ASSERT(NT_SUCCESS(Status));
Status = RtlAddAccessAllowedAceEx(Dacl,
ACL_REVISION,
INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
GENERIC_ALL,
SeAliasAdminsSid);
ASSERT(NT_SUCCESS(Status));
Status = RtlAddAccessAllowedAceEx(Dacl,
ACL_REVISION,
INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
GENERIC_ALL,
SeLocalSystemSid);
ASSERT(NT_SUCCESS(Status));
Status = RtlAddAccessAllowedAceEx(Dacl,
ACL_REVISION,
INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
GENERIC_ALL,
SeCreatorOwnerSid);
ASSERT(NT_SUCCESS(Status));
}
else
{
AclSize = sizeof(ACL) +
sizeof(ACE) + RtlLengthSid(SeLocalSystemSid) +
sizeof(ACE) + RtlLengthSid(SeWorldSid) +
sizeof(ACE) + RtlLengthSid(SeLocalSystemSid);
/* Allocate the ACL */
Dacl = ExAllocatePoolWithTag(PagedPool, AclSize, TAG_DACL);
if (Dacl == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Initialize the DACL */
Status = RtlCreateAcl(Dacl, AclSize, ACL_REVISION);
ASSERT(NT_SUCCESS(Status));
/* Add the ACEs */
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
GENERIC_READ | GENERIC_EXECUTE | GENERIC_WRITE,
SeWorldSid);
ASSERT(NT_SUCCESS(Status));
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
GENERIC_ALL,
SeLocalSystemSid);
ASSERT(NT_SUCCESS(Status));
Status = RtlAddAccessAllowedAceEx(Dacl,
ACL_REVISION,
INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
GENERIC_ALL,
SeWorldSid);
ASSERT(NT_SUCCESS(Status));
}
/* Attach the DACL to the SD */
Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor, TRUE, Dacl, FALSE);
ASSERT(NT_SUCCESS(Status));
return STATUS_SUCCESS;
}
CODE_SEG("INIT")
VOID
NTAPI
ObpFreeDosDevicesProtection(OUT PSECURITY_DESCRIPTOR SecurityDescriptor)
{
PACL Dacl;
NTSTATUS Status;
BOOLEAN DaclPresent, DaclDefaulted;
Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, &DaclPresent, &Dacl, &DaclDefaulted);
ASSERT(NT_SUCCESS(Status));
ASSERT(DaclPresent);
ASSERT(Dacl != NULL);
ExFreePoolWithTag(Dacl, TAG_DACL);
}
CODE_SEG("INIT")
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
NTSTATUS
NTAPI
ObpCreateDosDevicesDirectory(VOID)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING RootName, TargetName, LinkName;
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
HANDLE Handle, SymHandle;
SECURITY_DESCRIPTOR DosDevicesSD;
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
NTSTATUS Status;
/*
* Enable LUID mappings only if not explicitely disabled
* and if protection mode is set
*/
if (ObpProtectionMode == 0 || ObpLUIDDeviceMapsDisabled != 0)
ObpLUIDDeviceMapsEnabled = 0;
else
ObpLUIDDeviceMapsEnabled = 1;
/* Create a custom security descriptor for the global DosDevices directory */
Status = ObpGetDosDevicesProtection(&DosDevicesSD);
if (!NT_SUCCESS(Status))
return Status;
/* Create the global DosDevices directory \?? */
RtlInitUnicodeString(&RootName, L"\\GLOBAL??");
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
InitializeObjectAttributes(&ObjectAttributes,
&RootName,
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
OBJ_PERMANENT,
NULL,
&DosDevicesSD);
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
Status = NtCreateDirectoryObject(&Handle,
DIRECTORY_ALL_ACCESS,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
goto done;
/* Create the system device map */
Status = ObSetDeviceMap(NULL, Handle);
if (!NT_SUCCESS(Status))
goto done;
/*
* Initialize the \??\GLOBALROOT symbolic link
* pointing to the root directory \ .
*/
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
RtlInitUnicodeString(&LinkName, L"GLOBALROOT");
RtlInitUnicodeString(&TargetName, L"");
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
InitializeObjectAttributes(&ObjectAttributes,
&LinkName,
OBJ_PERMANENT,
Handle,
&DosDevicesSD);
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
Status = NtCreateSymbolicLinkObject(&SymHandle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes,
&TargetName);
if (NT_SUCCESS(Status)) NtClose(SymHandle);
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
/*
* Initialize the \??\Global symbolic link pointing to the global
* DosDevices directory \?? . It is used to access the global \??
* by user-mode components which, by default, use a per-session
* DosDevices directory.
*/
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
RtlInitUnicodeString(&LinkName, L"Global");
InitializeObjectAttributes(&ObjectAttributes,
&LinkName,
OBJ_PERMANENT,
Handle,
&DosDevicesSD);
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
Status = NtCreateSymbolicLinkObject(&SymHandle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes,
&RootName);
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
if (NT_SUCCESS(Status)) NtClose(SymHandle);
/* Close the directory handle */
NtClose(Handle);
if (!NT_SUCCESS(Status))
goto done;
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
/*
* Initialize the \DosDevices symbolic link pointing to the global
* DosDevices directory \?? , for backward compatibility with
* Windows NT-2000 systems.
*/
RtlInitUnicodeString(&LinkName, L"\\DosDevices");
RtlInitUnicodeString(&RootName, (PCWSTR)&ObpDosDevicesShortNameRoot);
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
InitializeObjectAttributes(&ObjectAttributes,
&LinkName,
OBJ_PERMANENT,
NULL,
&DosDevicesSD);
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
Status = NtCreateSymbolicLinkObject(&SymHandle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes,
&RootName);
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
if (NT_SUCCESS(Status)) NtClose(SymHandle);
done:
ObpFreeDosDevicesProtection(&DosDevicesSD);
- Set OBJ_OPENLINK invalid for core object types. - Initialize symbolic link in-line with other core object types. - Use the SePublicDefaultUnrestrictedSd directly instead of building another SD. - Create core directory objects with Nt* functions instead of Ob*, to insure full accounting and error-handling. - Create core objects with OBJ_CASE_INSENSITIVE. - Fix the huge ObInit hack which was manually inserting Directory and Type object types in the type directory, and now loop the type list. Now we don't skip the Process, Token, Thread, Job, Section types anymore. - Support Quota Information during object allocation and deallocation isntead of ignoring it. - Use interlocked decrement when touching the object type (since it's a shared structure. We don't use the lock yet, but we won't for this anyways, since it's a simple lockable operation). - Use the right object key when freeing the object. - Modify the allocation function for a more optimized way of allocating objects instead of having to keep track of two sets of variables. - Add various accounting variables. - Make sure to properly handle allocations without object create info (ie, for object types). Now they get creator info and name info (which allowed us to cleanp the hack in ObInit). - Add checks to see if Quota informatio is needed. - Clear CreatorBackTraceIndex during allocation. - Remove CreatorUniqueProcess hack from back when the idle thread was NULL. - Do not zero out the header during allocation anymore, since this slows down the routine (instead, simply zero out the 2 fields that are NULL). - Locate and clearly display that the fact we zero objects on creation is a HACK that needs to be fixed. (The Token code makes this assumption). - Update HighWaterNumberOfObjects when needed. - If caller didn't give pool charges, use the one from the object type. - Clear the Total/HighWater* values for newly created object types instead of using random values. - Properly typecast the WCHAR tag as CHAR. - Insert each new object type in the ObTypeObjectType Type List. - Set the Index member of each new object type and insert each new object type in the ObpObjectTypes array. This is crucial for object type enumeration when implemented. - Fixup the way we insert new object types into the tree. Allow failure and don't return a type if we couldn't insert it, and only reference the type directory object if it actually exists. - Move DOS Devices\"??" initialization in its own routine and fix it: - Use Nt APIs for all operations instead of raw I/O. - Create GLOBALROOT link to \ - Create \??\Global link to \?? svn path=/trunk/; revision=24568
2006-10-19 02:20:32 +00:00
/* Return status */
return Status;
}
/*++
* @name ObpDeleteNameCheck
*
* The ObpDeleteNameCheck routine checks if a named object should be
* removed from the object directory namespace.
*
* @param Object
* Pointer to the object to check for possible removal.
*
* @return None.
*
* @remarks An object is removed if the following 4 criteria are met:
* 1) The object has 0 handles open
* 2) The object is in the directory namespace and has a name
* 3) The object is not permanent
*
*--*/
VOID
NTAPI
ObpDeleteNameCheck(IN PVOID Object)
{
POBJECT_HEADER ObjectHeader;
OBP_LOOKUP_CONTEXT Context;
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
POBJECT_TYPE ObjectType;
PVOID Directory = NULL;
/* Get object structures */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader);
ObjectType = ObjectHeader->Type;
/*
* Check if the handle count is 0, if the object is named,
* and if the object isn't a permanent object.
*/
if (!(ObjectHeader->HandleCount) &&
(ObjectNameInfo) &&
(ObjectNameInfo->Name.Length) &&
(ObjectNameInfo->Directory) &&
!(ObjectHeader->Flags & OB_FLAG_PERMANENT))
{
/* Setup a lookup context and lock it */
ObpInitializeLookupContext(&Context);
ObpAcquireLookupContextLock(&Context, ObjectNameInfo->Directory);
/* Do the lookup */
Object = ObpLookupEntryDirectory(ObjectNameInfo->Directory,
&ObjectNameInfo->Name,
0,
FALSE,
&Context);
if (Object)
{
/* Lock the object */
ObpAcquireObjectLock(ObjectHeader);
/* 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 == ObpSymbolicLinkObjectType)
{
/* Remove internal name */
ObpDeleteSymbolicLinkName(Object);
}
/* Check if the kernel exclusive flag is set */
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
if ((ObjectNameInfo) &&
(ObjectNameInfo->QueryReferences & OB_FLAG_KERNEL_EXCLUSIVE))
{
/* Remove protection flag */
InterlockedExchangeAdd((PLONG)&ObjectNameInfo->QueryReferences,
-OB_FLAG_KERNEL_EXCLUSIVE);
}
/* Get the directory */
Directory = ObjectNameInfo->Directory;
}
/* Release the lock */
ObpReleaseObjectLock(ObjectHeader);
}
/* Cleanup after lookup */
ObpReleaseLookupContext(&Context);
/* Remove another query reference since we added one on top */
ObpDereferenceNameInfo(ObjectNameInfo);
/* Check if we were inserted in a directory */
if (Directory)
{
/* We were, so first remove the extra reference we had added */
ObpDereferenceNameInfo(ObjectNameInfo);
/* Now dereference the object as well */
ObDereferenceObject(Object);
}
}
else
{
/* Remove the reference we added */
ObpDereferenceNameInfo(ObjectNameInfo);
}
}
BOOLEAN
NTAPI
ObpIsUnsecureName(IN PUNICODE_STRING ObjectName,
IN BOOLEAN CaseInSensitive)
{
BOOLEAN Unsecure;
PWSTR UnsecureBuffer;
UNICODE_STRING UnsecureName;
/* No unsecure names known, quit */
if (ObpUnsecureGlobalNamesBuffer[0] == UNICODE_NULL)
{
return FALSE;
}
/* By default, we have a secure name */
Unsecure = FALSE;
/* We will browse the whole string */
UnsecureBuffer = &ObpUnsecureGlobalNamesBuffer[0];
while (TRUE)
{
/* Initialize the unicode string */
RtlInitUnicodeString(&UnsecureName, UnsecureBuffer);
/* We're at the end of the multisz string! */
if (UnsecureName.Length == 0)
{
break;
}
/*
* Does the unsecure name prefix the object name?
* If so, that's an unsecure name, and return so
*/
if (RtlPrefixUnicodeString(&UnsecureName, ObjectName, CaseInSensitive))
{
Unsecure = TRUE;
break;
}
/*
* Move to the next string. As a reminder, ObpUnsecureGlobalNamesBuffer is
* a multisz, so we move the string next to the current UNICODE_NULL char
*/
UnsecureBuffer = (PWSTR)((ULONG_PTR)UnsecureBuffer + UnsecureName.Length + sizeof(UNICODE_NULL));
}
/* Return our findings */
return Unsecure;
}
NTSTATUS
NTAPI
ObpLookupObjectName(IN HANDLE RootHandle OPTIONAL,
IN OUT PUNICODE_STRING ObjectName,
- Fix ObReferenceObjectByName to do proper name validation checks. - Fix ObReferenceObjectByName to call ObpCheckObjectReference before allowing the caller to obtain the reference. - Rename ObFindObject to ObpLookupObjectName and shuffle parameters around and add some placeholder code that resets the object pointer of the lookup context. - Modify ObpChargeQuotaForObject to also return if this is a new object. - Modify ObpDecrementHandleCount to detect when objects with a handle database are being used. Also protect close callout with checks. Protect ObpCloseHAndleTableEntry's callouts with checks as well. - Update logic of ObpIncrementHandleCount and ObpIncrementUnnamedHandleCount to handle currently exclusive objects as well as new handles with OBJ_EXCLUSIVE. Also detect objects that require handle databases and protect callouts. - Support CreatorInfo and the TypeList in ObpIncrementHandleCount. Also update the TotalNumberOfHandles in the object type properly. - Fixup object type lock usage in these routines. - Do proper invalid attributes check in ObOpenObjectByName, and also use a buffer from the pool instead of the stack. - Make ObInsertObject detect invalid object insertions and change some parameter names and checks. - Add stub code to validate the access mask in ObInsertObject. Proper initailize some lookup variables before starting lookup. - Add detection for symbolic link inserts which require some handling code later on. - Free the create information at the right moment isntead of too late. - Add some missing Ob functions, flags and types to the NDK. Fix OBJECT_DIRECTORY structure to use EX_PUSH_LOCK for locks, not ERESOURCE. svn path=/trunk/; revision=25372
2007-01-08 08:03:47 +00:00
IN ULONG Attributes,
IN POBJECT_TYPE ObjectType,
IN KPROCESSOR_MODE AccessMode,
IN OUT PVOID ParseContext,
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 Reparse = FALSE, SymLink = FALSE;
POBJECT_DIRECTORY Directory = NULL, ParentDirectory = NULL, RootDirectory;
POBJECT_DIRECTORY ReferencedDirectory = NULL, ReferencedParentDirectory = NULL;
KIRQL CalloutIrql;
OB_PARSE_METHOD ParseRoutine;
NTSTATUS Status;
KPROCESSOR_MODE AccessCheckMode;
PWCHAR NewName;
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
ULONG MaxReparse = 30;
PDEVICE_MAP DeviceMap = NULL;
UNICODE_STRING LocalName;
PAGED_CODE();
OBTRACE(OB_NAMESPACE_DEBUG,
"%s - Finding Object: %wZ. Expecting: %p\n",
__FUNCTION__,
ObjectName,
InsertObject);
/* Initialize starting state */
ObpInitializeLookupContext(LookupContext);
*FoundObject = NULL;
Status = STATUS_SUCCESS;
Object = NULL;
/* Check if case-insensitivity is checked */
if (ObpCaseInsensitive)
{
/* Check if the object type requests this */
if (!(ObjectType) || (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)
{
/* We did. Reference it */
Status = ObReferenceObjectByHandle(RootHandle,
0,
NULL,
AccessMode,
(PVOID*)&RootDirectory,
NULL);
if (!NT_SUCCESS(Status)) return Status;
/* Get the header */
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) &&
(ObjectHeader->Type != IoFileObjectType))
{
/* The syntax is bad, so fail this request */
ObDereferenceObject(RootDirectory);
return STATUS_OBJECT_PATH_SYNTAX_BAD;
}
/* Don't parse a Directory */
if (ObjectHeader->Type != ObpDirectoryObjectType)
{
/* Make sure the Object Type has a parse routine */
ParseRoutine = ObjectHeader->Type->TypeInfo.ParseProcedure;
if (!ParseRoutine)
{
/* We can't parse a name if we don't have a parse routine */
ObDereferenceObject(RootDirectory);
return STATUS_INVALID_HANDLE;
}
/* Set default parse count */
MaxReparse = 30;
/* Now parse */
while (TRUE)
{
/* Start with the full name */
RemainingName = *ObjectName;
/* Call the Parse Procedure */
ObpCalloutStart(&CalloutIrql);
Status = ParseRoutine(RootDirectory,
ObjectType,
AccessState,
AccessCheckMode,
Attributes,
ObjectName,
&RemainingName,
ParseContext,
SecurityQos,
&Object);
ObpCalloutEnd(CalloutIrql, "Parse", ObjectHeader->Type, Object);
/* Check for success or failure, so not reparse */
if ((Status != STATUS_REPARSE) &&
(Status != STATUS_REPARSE_OBJECT))
{
/* Check for failure */
if (!NT_SUCCESS(Status))
{
/* Parse routine might not have cleared this, do it */
Object = NULL;
}
else if (!Object)
{
/* Modify status to reflect failure inside Ob */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
/* We're done, return the status and object */
*FoundObject = Object;
ObDereferenceObject(RootDirectory);
return Status;
}
else if ((!ObjectName->Length) ||
(!ObjectName->Buffer) ||
(ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
{
/* Reparsed to the root directory, so start over */
ObDereferenceObject(RootDirectory);
RootDirectory = ObpRootDirectoryObject;
/* Don't use this anymore, since we're starting at root */
RootHandle = NULL;
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;
}
}
}
else if (!(ObjectName->Length) || !(ObjectName->Buffer))
{
/* Just return the Root Directory if we didn't get a name */
Status = ObReferenceObjectByPointer(RootDirectory,
0,
ObjectType,
AccessMode);
if (NT_SUCCESS(Status)) Object = RootDirectory;
/* Remove the first reference we added and return the object */
ObDereferenceObject(RootDirectory);
*FoundObject = Object;
return Status;
}
LocalName = *ObjectName;
}
else
{
/* We did not get a Root Directory, so use the root */
RootDirectory = ObpRootDirectoryObject;
/* It must start with a path separator */
if (!(ObjectName->Length) ||
!(ObjectName->Buffer) ||
(ObjectName->Buffer[0] != OBJ_NAME_PATH_SEPARATOR))
{
/* This name is invalid, so fail */
return STATUS_OBJECT_PATH_SYNTAX_BAD;
}
/* Check if the name is only the path separator */
if (ObjectName->Length == sizeof(OBJ_NAME_PATH_SEPARATOR))
{
/* So the caller only wants the root directory; do we have one? */
if (!RootDirectory)
{
/* This must be the first time we're creating it... right? */
if (InsertObject)
{
/* Yes, so return it to ObInsert so that it can create it */
Status = ObReferenceObjectByPointer(InsertObject,
0,
ObjectType,
AccessMode);
if (NT_SUCCESS(Status)) *FoundObject = InsertObject;
return Status;
}
else
{
/* This should never really happen */
ASSERT(FALSE);
return STATUS_INVALID_PARAMETER;
}
}
else
{
/* We do have the root directory, so just return it */
Status = ObReferenceObjectByPointer(RootDirectory,
0,
ObjectType,
AccessMode);
if (NT_SUCCESS(Status)) *FoundObject = RootDirectory;
return Status;
}
}
else
{
ParseFromRoot:
LocalName = *ObjectName;
/* Deference the device map if we already have one */
if (DeviceMap != NULL)
{
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))
{
DeviceMap = ObpReferenceDeviceMap();
/* We have a local mapping, drop the ?? prefix */
if (DeviceMap != NULL && DeviceMap->DosDevicesDirectory != NULL)
{
LocalName.Length -= ObpDosDevicesShortName.Length;
LocalName.MaximumLength -= ObpDosDevicesShortName.Length;
LocalName.Buffer += (ObpDosDevicesShortName.Length / sizeof(WCHAR));
/* We'll browse that local directory */
Directory = DeviceMap->DosDevicesDirectory;
}
}
else if ((ObjectName->Length == ObpDosDevicesShortName.Length -
sizeof(WCHAR)) &&
(*(PULONG)(ObjectName->Buffer) ==
ObpDosDevicesShortNameRoot.Alignment.LowPart) &&
(*((PWCHAR)(ObjectName->Buffer) + 2) ==
(WCHAR)(ObpDosDevicesShortNameRoot.Alignment.HighPart)))
{
DeviceMap = ObpReferenceDeviceMap();
/* Caller is looking for the directory itself */
if (DeviceMap != NULL && DeviceMap->DosDevicesDirectory != NULL)
{
Status = ObReferenceObjectByPointer(DeviceMap->DosDevicesDirectory,
0,
ObjectType,
AccessMode);
if (NT_SUCCESS(Status))
{
*FoundObject = DeviceMap->DosDevicesDirectory;
}
ObfDereferenceDeviceMap(DeviceMap);
return Status;
}
}
}
}
}
/* Check if we were reparsing a symbolic link */
if (!SymLink)
{
/* Allow reparse */
Reparse = TRUE;
MaxReparse = 30;
}
/* Reparse */
while (Reparse && MaxReparse)
{
/* Get the name */
RemainingName = LocalName;
/* 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 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 lookup context */
ObpAcquireLookupContextLock(LookupContext, Directory);
}
}
/* 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 == ObpDirectoryObjectType ?
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);
/*
* Deny object creation if:
* That's a section object or a symbolic link
* Which isn't in the same section that root directory
* That doesn't have the SeCreateGlobalPrivilege
* And that is not a known unsecure name
*/
if (RootDirectory->SessionId != -1)
{
if (ObjectHeader->Type == MmSectionObjectType ||
ObjectHeader->Type == ObpSymbolicLinkObjectType)
{
if (RootDirectory->SessionId != PsGetCurrentProcessSessionId() &&
!SeSinglePrivilegeCheck(SeCreateGlobalPrivilege, AccessCheckMode) &&
!ObpIsUnsecureName(&ComponentName, BooleanFlagOn(Attributes, OBJ_CASE_INSENSITIVE)))
{
Status = STATUS_ACCESS_DENIED;
break;
}
}
}
/* 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) ExFreePoolWithTag(NewName, OB_NAME_TAG);
/* 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 */
ExFreePoolWithTag(ObjectNameInfo->Name.Buffer, OB_NAME_TAG);
}
/* 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;
}
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 */
2018-01-29 19:31:07 +00:00
InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount, 1);
/* Cleanup from the first lookup */
ObpReleaseLookupContext(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;
--MaxReparse;
if (MaxReparse == 0)
{
Object = NULL;
break;
}
/* 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)
{
/* Stop using it, because we have a new directory now */
ObDereferenceObject(RootDirectory);
RootHandle = NULL;
}
/* Start at Root */
ParentDirectory = NULL;
RootDirectory = ObpRootDirectoryObject;
/* 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
{
/* This is a symbolic link */
SymLink = TRUE;
goto ParseFromRoot;
}
}
else if (RootDirectory == ObpRootDirectoryObject)
{
/* 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;
}
/* 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))
{
/* 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;
}
/* And get out of the reparse loop */
break;
}
else
{
/* We still have a name; check if this is a directory object */
if (ObjectHeader->Type == ObpDirectoryObjectType)
{
/* 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;
}
else
{
/* We still have a name, but no parse routine for it */
Status = STATUS_OBJECT_TYPE_MISMATCH;
Object = NULL;
break;
}
}
}
}
}
/* Check if we failed */
if (!NT_SUCCESS(Status))
{
/* Cleanup after lookup */
ObpReleaseLookupContext(LookupContext);
}
/* Check if we have a device map and dereference it if so */
if (DeviceMap) ObfDereferenceDeviceMap(DeviceMap);
/* Check if we have a referenced directory and dereference it if so */
if (ReferencedDirectory) ObDereferenceObject(ReferencedDirectory);
/* Check if we have a referenced parent directory */
if (ReferencedParentDirectory)
{
/* We do, dereference it */
ObDereferenceObject(ReferencedParentDirectory);
}
/* 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) ObDereferenceObject(RootDirectory);
/* Return status to caller */
OBTRACE(OB_NAMESPACE_DEBUG,
"%s - Found Object: %p. Expected: %p\n",
__FUNCTION__,
*FoundObject,
InsertObject);
return Status;
}
/* PUBLIC FUNCTIONS *********************************************************/
NTSTATUS
NTAPI
- Fix ObReferenceObjectByName to do proper name validation checks. - Fix ObReferenceObjectByName to call ObpCheckObjectReference before allowing the caller to obtain the reference. - Rename ObFindObject to ObpLookupObjectName and shuffle parameters around and add some placeholder code that resets the object pointer of the lookup context. - Modify ObpChargeQuotaForObject to also return if this is a new object. - Modify ObpDecrementHandleCount to detect when objects with a handle database are being used. Also protect close callout with checks. Protect ObpCloseHAndleTableEntry's callouts with checks as well. - Update logic of ObpIncrementHandleCount and ObpIncrementUnnamedHandleCount to handle currently exclusive objects as well as new handles with OBJ_EXCLUSIVE. Also detect objects that require handle databases and protect callouts. - Support CreatorInfo and the TypeList in ObpIncrementHandleCount. Also update the TotalNumberOfHandles in the object type properly. - Fixup object type lock usage in these routines. - Do proper invalid attributes check in ObOpenObjectByName, and also use a buffer from the pool instead of the stack. - Make ObInsertObject detect invalid object insertions and change some parameter names and checks. - Add stub code to validate the access mask in ObInsertObject. Proper initailize some lookup variables before starting lookup. - Add detection for symbolic link inserts which require some handling code later on. - Free the create information at the right moment isntead of too late. - Add some missing Ob functions, flags and types to the NDK. Fix OBJECT_DIRECTORY structure to use EX_PUSH_LOCK for locks, not ERESOURCE. svn path=/trunk/; revision=25372
2007-01-08 08:03:47 +00:00
ObQueryNameString(IN PVOID Object,
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
- Fix ObReferenceObjectByName to do proper name validation checks. - Fix ObReferenceObjectByName to call ObpCheckObjectReference before allowing the caller to obtain the reference. - Rename ObFindObject to ObpLookupObjectName and shuffle parameters around and add some placeholder code that resets the object pointer of the lookup context. - Modify ObpChargeQuotaForObject to also return if this is a new object. - Modify ObpDecrementHandleCount to detect when objects with a handle database are being used. Also protect close callout with checks. Protect ObpCloseHAndleTableEntry's callouts with checks as well. - Update logic of ObpIncrementHandleCount and ObpIncrementUnnamedHandleCount to handle currently exclusive objects as well as new handles with OBJ_EXCLUSIVE. Also detect objects that require handle databases and protect callouts. - Support CreatorInfo and the TypeList in ObpIncrementHandleCount. Also update the TotalNumberOfHandles in the object type properly. - Fixup object type lock usage in these routines. - Do proper invalid attributes check in ObOpenObjectByName, and also use a buffer from the pool instead of the stack. - Make ObInsertObject detect invalid object insertions and change some parameter names and checks. - Add stub code to validate the access mask in ObInsertObject. Proper initailize some lookup variables before starting lookup. - Add detection for symbolic link inserts which require some handling code later on. - Free the create information at the right moment isntead of too late. - Add some missing Ob functions, flags and types to the NDK. Fix OBJECT_DIRECTORY structure to use EX_PUSH_LOCK for locks, not ERESOURCE. svn path=/trunk/; revision=25372
2007-01-08 08:03:47 +00:00
IN ULONG Length,
OUT PULONG ReturnLength)
{
POBJECT_HEADER_NAME_INFO LocalInfo;
POBJECT_HEADER ObjectHeader;
POBJECT_DIRECTORY ParentDirectory;
ULONG NameSize;
PWCH ObjectName;
BOOLEAN ObjectIsNamed;
NTSTATUS Status = STATUS_SUCCESS;
/* Get the Kernel Meta-Structures */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
LocalInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
/* Check if a Query Name Procedure is available */
if (ObjectHeader->Type->TypeInfo.QueryNameProcedure)
{
/* Call the procedure inside SEH */
ObjectIsNamed = ((LocalInfo) && (LocalInfo->Name.Length > 0));
_SEH2_TRY
{
Status = ObjectHeader->Type->TypeInfo.QueryNameProcedure(Object,
ObjectIsNamed,
ObjectNameInfo,
Length,
ReturnLength,
KernelMode);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Return the exception code */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
return Status;
}
/* Check if the object doesn't even have a name */
if (!(LocalInfo) || !(LocalInfo->Name.Buffer))
{
Status = STATUS_SUCCESS;
_SEH2_TRY
{
/* We're returning the name structure */
*ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
/* Check if we were given enough space */
if (*ReturnLength > Length)
{
Status = STATUS_INFO_LENGTH_MISMATCH;
}
else
{
/* Return an empty buffer */
RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, NULL, 0);
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Return the exception code */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
return Status;
}
/*
* Find the size needed for the name. We won't do
* this during the Name Creation loop because we want
* to let the caller know that the buffer isn't big
* enough right at the beginning, not work our way through
* and find out at the end
*/
_SEH2_TRY
{
if (Object == ObpRootDirectoryObject)
{
/* Size of the '\' string */
NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR);
}
else
{
/* Get the Object Directory and add name of Object */
ParentDirectory = LocalInfo->Directory;
NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR) + LocalInfo->Name.Length;
/* Loop inside the directory to get the top-most one (meaning root) */
while ((ParentDirectory != ObpRootDirectoryObject) && (ParentDirectory))
{
/* Get the Name Information */
LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
OBJECT_TO_OBJECT_HEADER(ParentDirectory));
/* Add the size of the Directory Name */
if (LocalInfo && LocalInfo->Directory)
{
/* Size of the '\' string + Directory Name */
NameSize += sizeof(OBJ_NAME_PATH_SEPARATOR) +
LocalInfo->Name.Length;
/* Move to next parent Directory */
ParentDirectory = LocalInfo->Directory;
}
else
{
/* Directory with no name. We append "...\" */
NameSize += sizeof(L"...") + sizeof(OBJ_NAME_PATH_SEPARATOR);
break;
}
}
}
/* Finally, add the name of the structure and the null char */
*ReturnLength = NameSize +
sizeof(OBJECT_NAME_INFORMATION) +
sizeof(UNICODE_NULL);
/* Check if we were given enough space */
if (*ReturnLength > Length) _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH);
/*
* Now we will actually create the name. We work backwards because
* it's easier to start off from the Name we have and walk up the
* parent directories. We use the same logic as Name Length calculation.
*/
LocalInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
ObjectName = (PWCH)((ULONG_PTR)ObjectNameInfo + *ReturnLength);
*--ObjectName = UNICODE_NULL;
/* Check if the object is actually the Root directory */
if (Object == ObpRootDirectoryObject)
{
/* This is already the Root Directory, return "\\" */
*--ObjectName = OBJ_NAME_PATH_SEPARATOR;
ObjectNameInfo->Name.Length = (USHORT)NameSize;
ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize +
sizeof(UNICODE_NULL));
ObjectNameInfo->Name.Buffer = ObjectName;
Status = STATUS_SUCCESS;
}
else
{
/* Start by adding the Object's Name */
ObjectName = (PWCH)((ULONG_PTR)ObjectName -
LocalInfo->Name.Length);
RtlCopyMemory(ObjectName,
LocalInfo->Name.Buffer,
LocalInfo->Name.Length);
/* Now parse the Parent directories until we reach the top */
ParentDirectory = LocalInfo->Directory;
while ((ParentDirectory != ObpRootDirectoryObject) && (ParentDirectory))
{
/* Get the name information */
LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
OBJECT_TO_OBJECT_HEADER(ParentDirectory));
/* Add the "\" */
*(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
/* Add the Parent Directory's Name */
if (LocalInfo && LocalInfo->Name.Buffer)
{
/* Add the name */
ObjectName = (PWCH)((ULONG_PTR)ObjectName -
LocalInfo->Name.Length);
RtlCopyMemory(ObjectName,
LocalInfo->Name.Buffer,
LocalInfo->Name.Length);
/* Move to next parent */
ParentDirectory = LocalInfo->Directory;
}
else
{
/* Directory without a name, we add "..." */
ObjectName = (PWCH)((ULONG_PTR)ObjectName -
sizeof(L"...") +
sizeof(UNICODE_NULL));
RtlCopyMemory(ObjectName, L"...", sizeof(L"..."));
break;
}
}
/* Add Root Directory Name */
*(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
ObjectNameInfo->Name.Length = (USHORT)NameSize;
ObjectNameInfo->Name.MaximumLength =
(USHORT)(NameSize + sizeof(UNICODE_NULL));
ObjectNameInfo->Name.Buffer = ObjectName;
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Return the exception code */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
/* Return success */
return Status;
}
/* EOF */