Author: ion Date: Wed May 24 08:28:57 2006 New Revision: 22003
URL: http://svn.reactos.ru/svn/reactos?rev=22003&view=rev Log: - Move all object directory stuff in dirobj.c and implement a simple profiler to measure the time spent in those functions until the desktop appears. Enable with #define OBP_PROFILE.
Modified: trunk/reactos/ntoskrnl/include/internal/ob.h trunk/reactos/ntoskrnl/ob/dirobj.c trunk/reactos/ntoskrnl/ob/namespc.c
Modified: trunk/reactos/ntoskrnl/include/internal/ob.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/include/internal/ob... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ob.h (original) +++ trunk/reactos/ntoskrnl/include/internal/ob.h Wed May 24 08:28:57 2006 @@ -105,6 +105,16 @@ PWSTR Name );
+NTSTATUS +NTAPI +ObpCreateDirectory( + OB_OPEN_REASON Reason, + PEPROCESS Process, + PVOID ObjectBody, + ACCESS_MASK GrantedAccess, + ULONG HandleCount +); + VOID NTAPI ObpRemoveEntryDirectory(PROS_OBJECT_HEADER Header); @@ -120,6 +130,16 @@ ACCESS_MASK GrantedAccess, ULONG HandleAttributes, PHANDLE Handle +); + +NTSTATUS +NTAPI +ObpParseDirectory( + PVOID Object, + PVOID * NextObject, + PUNICODE_STRING FullPath, + PWSTR * Path, + ULONG Attributes );
VOID
Modified: trunk/reactos/ntoskrnl/ob/dirobj.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/ob/dirobj.c?rev=220... ============================================================================== --- trunk/reactos/ntoskrnl/ob/dirobj.c (original) +++ trunk/reactos/ntoskrnl/ob/dirobj.c Wed May 24 08:28:57 2006 @@ -11,6 +11,226 @@ #include <ntoskrnl.h> #define NDEBUG #include <internal/debug.h> + +#ifdef OBP_PROFILE + +LARGE_INTEGER ObpProfileTime; +BOOLEAN ObpProfileComplete; + +#define ObpStartProfile() \ + LARGE_INTEGER StartTime; \ + LARGE_INTEGER EndTime; \ + StartTime = KeQueryPerformanceCounter(NULL); + +#define ObpEndProfile() \ + EndTime = KeQueryPerformanceCounter(NULL); \ + ObpProfileTime.QuadPart += (EndTime.QuadPart - \ + StartTime.QuadPart); + +#define ObpCompleteProfile() \ + if (!wcscmp(Name, L"NlsSectionCP1252") && \ + !ObpProfileComplete) \ + { \ + DPRINT1("******************************\n");\ + DPRINT1("Obp Profiling1 Complete: %I64d\n", \ + ObpProfileTime.QuadPart); \ + DPRINT1("******************************\n");\ + ObpProfileComplete = TRUE; \ + } + +#else + +#define ObpStartProfile() +#define ObpEndProfile() +#define ObpCompleteProfile() + +#endif + +/* PRIVATE FUNCTIONS ******************************************************/ + +VOID +NTAPI +ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent, + PROS_OBJECT_HEADER Header, + PWSTR Name) +{ + KIRQL oldlvl; + + ObpStartProfile(); + ASSERT(HEADER_TO_OBJECT_NAME(Header)); + HEADER_TO_OBJECT_NAME(Header)->Directory = Parent; + + KeAcquireSpinLock(&Parent->Lock, &oldlvl); + InsertTailList(&Parent->head, &Header->Entry); + KeReleaseSpinLock(&Parent->Lock, oldlvl); + ObpEndProfile(); +} + +VOID +NTAPI +ObpRemoveEntryDirectory(PROS_OBJECT_HEADER Header) +{ + KIRQL oldlvl; + + ObpStartProfile(); + DPRINT("ObpRemoveEntryDirectory(Header %x)\n",Header); + + KeAcquireSpinLock(&(HEADER_TO_OBJECT_NAME(Header)->Directory->Lock),&oldlvl); + if (Header->Entry.Flink && Header->Entry.Blink) + { + RemoveEntryList(&(Header->Entry)); + Header->Entry.Flink = Header->Entry.Blink = NULL; + } + KeReleaseSpinLock(&(HEADER_TO_OBJECT_NAME(Header)->Directory->Lock),oldlvl); + ObpEndProfile(); +} + +NTSTATUS +NTAPI +ObpCreateDirectory(OB_OPEN_REASON Reason, + PEPROCESS Process, + PVOID ObjectBody, + ACCESS_MASK GrantedAccess, + ULONG HandleCount) +{ + PDIRECTORY_OBJECT Directory = ObjectBody; + + ObpStartProfile(); + if (Reason == ObCreateHandle) + { + InitializeListHead(&Directory->head); + KeInitializeSpinLock(&Directory->Lock); + } + ObpEndProfile(); + + return STATUS_SUCCESS; +} + +PVOID +NTAPI +ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject, + PWSTR Name, + ULONG Attributes) +{ + PLIST_ENTRY current = DirectoryObject->head.Flink; + PROS_OBJECT_HEADER current_obj; + + ObpStartProfile(); + DPRINT("ObFindEntryDirectory(dir %x, name %S)\n",DirectoryObject, Name); + ObpCompleteProfile(); + + if (Name[0]==0) + { + ObpEndProfile(); + return(DirectoryObject); + } + if (Name[0]=='.' && Name[1]==0) + { + ObpEndProfile(); + return(DirectoryObject); + } + if (Name[0]=='.' && Name[1]=='.' && Name[2]==0) + { + ObpEndProfile(); + return(HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(DirectoryObject))->Directory); + } + while (current!=(&(DirectoryObject->head))) + { + current_obj = CONTAINING_RECORD(current,ROS_OBJECT_HEADER,Entry); + DPRINT(" Scanning: %S for: %S\n",HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name); + if (Attributes & OBJ_CASE_INSENSITIVE) + { + if (_wcsicmp(HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name)==0) + { + DPRINT("Found it %x\n",¤t_obj->Body); + ObpEndProfile(); + return(¤t_obj->Body); + } + } + else + { + if ( wcscmp(HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name)==0) + { + DPRINT("Found it %x\n",¤t_obj->Body); + ObpEndProfile(); + return(¤t_obj->Body); + } + } + current = current->Flink; + } + DPRINT(" Not Found: %s() = NULL\n",__FUNCTION__); + ObpEndProfile(); + return(NULL); +} + +NTSTATUS +NTAPI +ObpParseDirectory(PVOID Object, + PVOID * NextObject, + PUNICODE_STRING FullPath, + PWSTR * Path, + ULONG Attributes) +{ + PWSTR Start; + PWSTR End; + PVOID FoundObject; + KIRQL oldlvl; + + ObpStartProfile(); + DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n", + Object,Path,*Path); + + *NextObject = NULL; + + if ((*Path) == NULL) + { + ObpEndProfile(); + return STATUS_UNSUCCESSFUL; + } + + Start = *Path; + if (*Start == L'\') + Start++; + + End = wcschr(Start, L'\'); + if (End != NULL) + { + *End = 0; + } + + KeAcquireSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), &oldlvl); + FoundObject = ObpFindEntryDirectory(Object, Start, Attributes); + if (FoundObject == NULL) + { + KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl); + if (End != NULL) + { + *End = L'\'; + } + ObpEndProfile(); + return STATUS_UNSUCCESSFUL; + } + + ObReferenceObjectByPointer(FoundObject, + STANDARD_RIGHTS_REQUIRED, + NULL, + UserMode); + KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl); + if (End != NULL) + { + *End = L'\'; + *Path = End; + } + else + { + *Path = NULL; + } + + *NextObject = FoundObject; + + ObpEndProfile(); + return STATUS_SUCCESS; +}
/* FUNCTIONS **************************************************************/
@@ -143,8 +363,6 @@ PDIRECTORY_OBJECT Directory; KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); ULONG SkipEntries = 0; - ULONG NextEntry = 0; - ULONG CopyBytes = 0; NTSTATUS Status = STATUS_SUCCESS; PAGED_CODE();
@@ -191,201 +409,7 @@ NULL); if(NT_SUCCESS(Status)) { - PVOID TemporaryBuffer = ExAllocatePool(NonPagedPool, BufferLength); - if(TemporaryBuffer != NULL) - { - PROS_OBJECT_HEADER EntryHeader; - PLIST_ENTRY ListEntry; - KIRQL OldLevel; - ULONG RequiredSize = sizeof(OBJECT_DIRECTORY_INFORMATION); - ULONG nDirectories = 0; - POBJECT_DIRECTORY_INFORMATION DirInfo = - (POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer; - - Status = STATUS_NO_MORE_ENTRIES; - - KeAcquireSpinLock(&Directory->Lock, &OldLevel); - - for(ListEntry = Directory->head.Flink; - ListEntry != &Directory->head; - ListEntry = ListEntry->Flink) - { - NextEntry++; - if(SkipEntries == 0) - { - PUNICODE_STRING Name, Type; - ULONG EntrySize; - - EntryHeader = CONTAINING_RECORD(ListEntry, - ROS_OBJECT_HEADER, - Entry); - - /* calculate the size of the required buffer space for this entry */ - Name = (HEADER_TO_OBJECT_NAME(EntryHeader)->Name.Length != 0 ? - &HEADER_TO_OBJECT_NAME(EntryHeader)->Name : NULL); - Type = &EntryHeader->Type->Name; - EntrySize = sizeof(OBJECT_DIRECTORY_INFORMATION) + - ((Name != NULL) ? - ((ULONG)Name->Length + sizeof(WCHAR)) : 0) + - (ULONG)EntryHeader->Type->Name.Length + - sizeof(WCHAR); - - if(RequiredSize + EntrySize <= BufferLength) - { - /* the buffer is large enough to receive this entry. It would've - been much easier if the strings were directly appended to the - OBJECT_DIRECTORY_INFORMATION structured written into the buffer */ - if(Name != NULL) - DirInfo->ObjectName = *Name; - else - { - DirInfo->ObjectName.Length = - DirInfo->ObjectName.MaximumLength = 0; - DirInfo->ObjectName.Buffer = NULL; - } - DirInfo->ObjectTypeName = *Type; - - nDirectories++; - RequiredSize += EntrySize; - - Status = STATUS_SUCCESS; - - if(ReturnSingleEntry) - { - /* we're only supposed to query one entry, so bail and copy the - strings to the buffer */ - break; - } - DirInfo++; - } - else - { - if(ReturnSingleEntry) - { - /* the buffer is too small, so return the number of bytes that - would've been required for this query */ - RequiredSize += EntrySize; - Status = STATUS_BUFFER_TOO_SMALL; - } - - /* we couldn't query this entry, so leave the index that will be stored - in Context to this entry so the caller can query it the next time - he queries (hopefully with a buffer that is large enough then...) */ - NextEntry--; - - /* just copy the entries that fit into the buffer */ - break; - } - } - else - { - /* skip the entry */ - SkipEntries--; - } - } - - if(!ReturnSingleEntry && ListEntry != &Directory->head) - { - /* there are more entries to enumerate but the buffer is already full. - only tell this to the user if he queries multiple entries */ - Status = STATUS_MORE_ENTRIES; - } - - if(NT_SUCCESS(Status) && nDirectories > 0) - { - PWSTR strbuf = - (PWSTR)((POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer + - nDirectories + 1); - PWSTR deststrbuf = - (PWSTR)((POBJECT_DIRECTORY_INFORMATION)Buffer + - nDirectories + 1); - - memset((POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer + - nDirectories, - 0, - sizeof(OBJECT_DIRECTORY_INFORMATION)); - - CopyBytes = (nDirectories + 1) * - sizeof(OBJECT_DIRECTORY_INFORMATION); - - /* copy the names from the objects and append them to the list of the - objects. copy to the temporary buffer only because the directory - lock can't be released and the buffer might be pagable memory! */ - for(DirInfo = (POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer; - nDirectories > 0; - nDirectories--, DirInfo++) - { - ULONG NameLength; - - if(DirInfo->ObjectName.Length > 0) - { - RtlCopyMemory(strbuf, - DirInfo->ObjectName.Buffer, - DirInfo->ObjectName.Length); - - /* change the buffer pointer to the buffer */ - DirInfo->ObjectName.Buffer = deststrbuf; - NameLength = DirInfo->ObjectName.Length / - sizeof(WCHAR); - - /* NULL-terminate the string */ - strbuf[NameLength] = L'\0'; - strbuf += NameLength + 1; - deststrbuf += NameLength + 1; - - CopyBytes += (NameLength + 1) * sizeof(WCHAR); - } - - RtlCopyMemory(strbuf, - DirInfo->ObjectTypeName.Buffer, - DirInfo->ObjectTypeName.Length); - - /* change the buffer pointer to the buffer */ - DirInfo->ObjectTypeName.Buffer = deststrbuf; - NameLength = DirInfo->ObjectTypeName.Length / - sizeof(WCHAR); - - /* NULL-terminate the string */ - strbuf[NameLength] = L'\0'; - strbuf += NameLength + 1; - deststrbuf += NameLength + 1; - - CopyBytes += (NameLength + 1) * sizeof(WCHAR); - } - } - - KeReleaseSpinLock(&Directory->Lock, OldLevel); - ObDereferenceObject(Directory); - - if(NT_SUCCESS(Status) || ReturnSingleEntry) - { - _SEH_TRY - { - if(CopyBytes != 0) - { - RtlCopyMemory(Buffer, TemporaryBuffer, CopyBytes); - } - - *Context = NextEntry; - - if(ReturnLength != NULL) - { - *ReturnLength = RequiredSize; - } - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - - ExFreePool(TemporaryBuffer); - } - else - { - Status = STATUS_INSUFFICIENT_RESOURCES; - } + Status = STATUS_INSUFFICIENT_RESOURCES; }
return Status;
Modified: trunk/reactos/ntoskrnl/ob/namespc.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/ob/namespc.c?rev=22... ============================================================================== --- trunk/reactos/ntoskrnl/ob/namespc.c (original) +++ trunk/reactos/ntoskrnl/ob/namespc.c Wed May 24 08:28:57 2006 @@ -242,184 +242,6 @@
/* FIXME: Release the DeviceMap Spinlock */ // KeReleasepinLock(DeviceMap->Lock, OldIrql); -} - -VOID -NTAPI -ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent, - PROS_OBJECT_HEADER Header, - PWSTR Name) -/* - * FUNCTION: Add an entry to a namespace directory - * ARGUMENTS: - * Parent = directory to add in - * Header = Header of the object to add the entry for - * Name = Name to give the entry - */ -{ - KIRQL oldlvl; - - ASSERT(HEADER_TO_OBJECT_NAME(Header)); - HEADER_TO_OBJECT_NAME(Header)->Directory = Parent; - - KeAcquireSpinLock(&Parent->Lock, &oldlvl); - InsertTailList(&Parent->head, &Header->Entry); - KeReleaseSpinLock(&Parent->Lock, oldlvl); -} - - -VOID -NTAPI -ObpRemoveEntryDirectory(PROS_OBJECT_HEADER Header) -/* - * FUNCTION: Remove an entry from a namespace directory - * ARGUMENTS: - * Header = Header of the object to remove - */ -{ - KIRQL oldlvl; - - DPRINT("ObpRemoveEntryDirectory(Header %x)\n",Header); - - KeAcquireSpinLock(&(HEADER_TO_OBJECT_NAME(Header)->Directory->Lock),&oldlvl); - if (Header->Entry.Flink && Header->Entry.Blink) - { - RemoveEntryList(&(Header->Entry)); - Header->Entry.Flink = Header->Entry.Blink = NULL; - } - KeReleaseSpinLock(&(HEADER_TO_OBJECT_NAME(Header)->Directory->Lock),oldlvl); -} - -NTSTATUS -STDCALL -ObpCreateDirectory(OB_OPEN_REASON Reason, - PEPROCESS Process, - PVOID ObjectBody, - ACCESS_MASK GrantedAccess, - ULONG HandleCount) -{ - PDIRECTORY_OBJECT Directory = ObjectBody; - - if (Reason == ObCreateHandle) - { - InitializeListHead(&Directory->head); - KeInitializeSpinLock(&Directory->Lock); - } - - return STATUS_SUCCESS; -} - -PVOID -ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject, - PWSTR Name, - ULONG Attributes) -{ - PLIST_ENTRY current = DirectoryObject->head.Flink; - PROS_OBJECT_HEADER current_obj; - - DPRINT("ObFindEntryDirectory(dir %x, name %S)\n",DirectoryObject, Name); - - if (Name[0]==0) - { - return(DirectoryObject); - } - if (Name[0]=='.' && Name[1]==0) - { - return(DirectoryObject); - } - if (Name[0]=='.' && Name[1]=='.' && Name[2]==0) - { - return(HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(DirectoryObject))->Directory); - } - while (current!=(&(DirectoryObject->head))) - { - current_obj = CONTAINING_RECORD(current,ROS_OBJECT_HEADER,Entry); - DPRINT(" Scanning: %S for: %S\n",HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name); - if (Attributes & OBJ_CASE_INSENSITIVE) - { - if (_wcsicmp(HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name)==0) - { - DPRINT("Found it %x\n",¤t_obj->Body); - return(¤t_obj->Body); - } - } - else - { - if ( wcscmp(HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name)==0) - { - DPRINT("Found it %x\n",¤t_obj->Body); - return(¤t_obj->Body); - } - } - current = current->Flink; - } - DPRINT(" Not Found: %s() = NULL\n",__FUNCTION__); - return(NULL); -} - - -NTSTATUS STDCALL -ObpParseDirectory(PVOID Object, - PVOID * NextObject, - PUNICODE_STRING FullPath, - PWSTR * Path, - ULONG Attributes) -{ - PWSTR Start; - PWSTR End; - PVOID FoundObject; - KIRQL oldlvl; - - DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n", - Object,Path,*Path); - - *NextObject = NULL; - - if ((*Path) == NULL) - { - return STATUS_UNSUCCESSFUL; - } - - Start = *Path; - if (*Start == L'\') - Start++; - - End = wcschr(Start, L'\'); - if (End != NULL) - { - *End = 0; - } - - KeAcquireSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), &oldlvl); - FoundObject = ObpFindEntryDirectory(Object, Start, Attributes); - if (FoundObject == NULL) - { - KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl); - if (End != NULL) - { - *End = L'\'; - } - return STATUS_UNSUCCESSFUL; - } - - ObReferenceObjectByPointer(FoundObject, - STANDARD_RIGHTS_REQUIRED, - NULL, - UserMode); - KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl); - if (End != NULL) - { - *End = L'\'; - *Path = End; - } - else - { - *Path = NULL; - } - - *NextObject = FoundObject; - - return STATUS_SUCCESS; }
VOID