diff --git a/reactos/include/ndk/obtypes.h b/reactos/include/ndk/obtypes.h index 1b5d9b231fd..152919070b9 100644 --- a/reactos/include/ndk/obtypes.h +++ b/reactos/include/ndk/obtypes.h @@ -98,6 +98,10 @@ Author: ((POBJECT_HEADER_HANDLE_INFO)(!(h)->HandleInfoOffset ? \ NULL: ((PCHAR)(h) - (h)->HandleInfoOffset))) +#define OBJECT_HEADER_TO_QUOTA_INFO(h) \ + ((POBJECT_HEADER_QUOTA_INFO)(!(h)->QuotaInfoOffset ? \ + NULL: ((PCHAR)(h) - (h)->QuotaInfoOffset))) + #define OBJECT_HEADER_TO_CREATOR_INFO(h) \ ((POBJECT_HEADER_CREATOR_INFO)(!((h)->Flags & \ OB_FLAG_CREATOR_INFO) ? NULL: ((PCHAR)(h) - \ @@ -409,6 +413,14 @@ typedef struct _OBJECT_HEADER_CREATOR_INFO USHORT Reserved; } OBJECT_HEADER_CREATOR_INFO, *POBJECT_HEADER_CREATOR_INFO; +typedef struct _OBJECT_HEADER_QUOTA_INFO +{ + ULONG PagedPoolCharge; + ULONG NonPagedPoolCharge; + ULONG SecurityDescriptorCharge; + PEPROCESS ExclusiveProcess; +} OBJECT_HEADER_QUOTA_INFO, *POBJECT_HEADER_QUOTA_INFO; + // // Object Header // diff --git a/reactos/ntoskrnl/io/file.c b/reactos/ntoskrnl/io/file.c index 0f78c4dbfa3..92738a87a82 100644 --- a/reactos/ntoskrnl/io/file.c +++ b/reactos/ntoskrnl/io/file.c @@ -26,6 +26,86 @@ SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation, /* INTERNAL FUNCTIONS ********************************************************/ +NTSTATUS +NTAPI +IopParseDevice(IN PVOID ParseObject, + IN POBJECT_TYPE ObjectType, + IN OUT PACCESS_STATE AccessState, + IN KPROCESSOR_MODE AccessMode, + IN ULONG Attributes, + IN OUT PUNICODE_STRING CompleteName, + IN OUT PUNICODE_STRING RemainingName, + IN OUT PVOID Context OPTIONAL, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, + OUT PVOID *Object) +{ + DPRINT("IopParseDevice:\n" + "DeviceObject : %p, Type : %p, TypeName : %wZ\n" + "FileObject : %p, Type : %p, TypeName : %wZ\n" + "CompleteName : %wZ, RemainingName : %wZ\n", + ParseObject, + ObjectType, + &ObjectType->Name, + Context, + Context ? OBJECT_TO_OBJECT_HEADER(Context)->Type : NULL, + Context ? &OBJECT_TO_OBJECT_HEADER(Context)->Type->Name: NULL, + CompleteName, + RemainingName); + + /* + * Just clear the object and return success, and ObFindObject will behave + * just as if we had no parse procedure, so we can debug in peace. + */ + *Object = NULL; + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +IopParseFile(IN PVOID ParseObject, + IN POBJECT_TYPE ObjectType, + IN OUT PACCESS_STATE AccessState, + IN KPROCESSOR_MODE AccessMode, + IN ULONG Attributes, + IN OUT PUNICODE_STRING CompleteName, + IN OUT PUNICODE_STRING RemainingName, + IN OUT PVOID Context OPTIONAL, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, + OUT PVOID *Object) +{ + PVOID DeviceObject; + + /* Get the device object */ + DeviceObject = IoGetRelatedDeviceObject(ParseObject); + Context = ParseObject; + + DPRINT("IopParseFile:\n" + "DeviceObject : %p, Type : %p, TypeName : %wZ\n" + "FileObject : %p, Type : %p, TypeName : %wZ\n" + "CompleteName : %wZ, RemainingName : %wZ\n", + DeviceObject, + OBJECT_TO_OBJECT_HEADER(DeviceObject)->Type, + &OBJECT_TO_OBJECT_HEADER(DeviceObject)->Type->Name, + ParseObject, + ObjectType, + &ObjectType->Name, + CompleteName, + RemainingName); + + /* Call the main routine */ + return IopParseDevice(DeviceObject, + ObjectType, + AccessState, + AccessMode, + Attributes, + CompleteName, + RemainingName, + Context, + SecurityQos, + Object); + +} + /* * NAME INTERNAL * IopCreateFile diff --git a/reactos/ntoskrnl/io/iomgr.c b/reactos/ntoskrnl/io/iomgr.c index 0fd2759ee3e..6d4dc1dd340 100644 --- a/reactos/ntoskrnl/io/iomgr.c +++ b/reactos/ntoskrnl/io/iomgr.c @@ -51,7 +51,31 @@ VOID INIT_FUNCTION IopInitLookasideLists(VOID); #pragma alloc_text(INIT, IoInit3) #endif +NTSTATUS +NTAPI +IopParseFile(IN PVOID ParseObject, + IN PVOID ObjectType, + IN OUT PACCESS_STATE AccessState, + IN KPROCESSOR_MODE AccessMode, + IN ULONG Attributes, + IN OUT PUNICODE_STRING CompleteName, + IN OUT PUNICODE_STRING RemainingName, + IN OUT PVOID Context OPTIONAL, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, + OUT PVOID *Object); +NTSTATUS +NTAPI +IopParseDevice(IN PVOID ParseObject, + IN PVOID ObjectType, + IN OUT PACCESS_STATE AccessState, + IN KPROCESSOR_MODE AccessMode, + IN ULONG Attributes, + IN OUT PUNICODE_STRING CompleteName, + IN OUT PUNICODE_STRING RemainingName, + IN OUT PVOID Context OPTIONAL, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, + OUT PVOID *Object); /* INIT FUNCTIONS ************************************************************/ VOID @@ -210,6 +234,7 @@ IoInit (VOID) ObjectTypeInitializer.ValidAccessMask = FILE_ALL_ACCESS; ObjectTypeInitializer.UseDefaultObject = TRUE; ObjectTypeInitializer.GenericMapping = IopFileMapping; + ObjectTypeInitializer.ParseProcedure = IopParseDevice; ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoDeviceObjectType); /* Do the Adapter Type */ @@ -229,6 +254,7 @@ IoInit (VOID) ObjectTypeInitializer.DeleteProcedure = IopDeleteFile; ObjectTypeInitializer.SecurityProcedure = IopSecurityFile; ObjectTypeInitializer.QueryNameProcedure = IopQueryNameFile; + ObjectTypeInitializer.ParseProcedure = IopParseFile; ObjectTypeInitializer.UseDefaultObject = FALSE; ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoFileObjectType); diff --git a/reactos/ntoskrnl/ob/obhandle.c b/reactos/ntoskrnl/ob/obhandle.c index 0a604ed366c..b2c59f2a1e4 100644 --- a/reactos/ntoskrnl/ob/obhandle.c +++ b/reactos/ntoskrnl/ob/obhandle.c @@ -27,6 +27,50 @@ PHANDLE_TABLE ObpKernelHandleTable = NULL; /* PRIVATE FUNCTIONS *********************************************************/ +NTSTATUS +NTAPI +ObpChargeQuotaForObject(IN POBJECT_HEADER ObjectHeader, + IN POBJECT_TYPE ObjectType) +{ + POBJECT_HEADER_QUOTA_INFO ObjectQuota; + ULONG PagedPoolCharge, NonPagedPoolCharge; + PEPROCESS Process; + + /* Get quota information */ + ObjectQuota = OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader); + + /* Check if this is a new object */ + if (ObjectHeader->Flags & OB_FLAG_CREATE_INFO) + { + /* Remove the flag */ + ObjectHeader->Flags &= ~ OB_FLAG_CREATE_INFO; + if (ObjectQuota) + { + /* We have a quota, get the charges */ + PagedPoolCharge = ObjectQuota->PagedPoolCharge; + NonPagedPoolCharge = ObjectQuota->NonPagedPoolCharge; + } + else + { + /* Get it from the object type */ + PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge; + NonPagedPoolCharge = ObjectType->TypeInfo.DefaultNonPagedPoolCharge; + } + + /* + * Charge the quota + * FIXME: This is a *COMPLETE* guess and probably defintely not the way to do this. + */ + Process = PsGetCurrentProcess(); + Process->QuotaBlock->QuotaEntry[PagedPool].Usage += PagedPoolCharge; + Process->QuotaBlock->QuotaEntry[NonPagedPool].Usage += NonPagedPoolCharge; + ObjectHeader->QuotaBlockCharged = Process->QuotaBlock; + } + + /* Return success */ + return STATUS_SUCCESS; +} + /*++ * @name ObpDecrementHandleCount * @@ -247,6 +291,7 @@ ObpIncrementHandleCount(IN PVOID Object, POBJECT_HEADER ObjectHeader; POBJECT_TYPE ObjectType; ULONG ProcessHandleCount; + NTSTATUS Status; /* Get the object header and type */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); @@ -258,6 +303,10 @@ ObpIncrementHandleCount(IN PVOID Object, ObjectHeader->HandleCount, ObjectHeader->PointerCount); + /* Charge quota and remove the creator info flag */ + Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType); + if (!NT_SUCCESS(Status)) return Status; + /* Check if we're opening an existing handle */ if (OpenReason == ObOpenHandle) { @@ -1151,6 +1200,14 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, { /* Then we are creating a new handle */ OpenReason = ObCreateHandle; + + /* Check if we still have create info */ + if (ObjectHeader->ObjectCreateInfo) + { + /* Free it */ + //ObpFreeAndReleaseCapturedAttributes(&ObjectCreateInfo); + //ObjectHeader->ObjectCreateInfo = NULL; + } } else {