Author: fireball Date: Thu Jul 10 04:46:25 2008 New Revision: 34404
URL: http://svn.reactos.org/svn/reactos?rev=34404&view=rev Log: Yuriy Sidorov jura@cp-lab.com - Implement RtlSetUserValueHeap, RtlSetUserFlagsHeap, RtlGetUserInfoHeap functions. It is quick implementation and it works. - It fixes "Out of memory" error in all InnoSetup based installations. A lot of software can be at least installed in ReactOS now. - Also it fixes Delphi applications which use TMemoryStream class. See issue #3464 for more details.
Modified: trunk/reactos/dll/ntdll/def/ntdll.def trunk/reactos/dll/win32/kernel32/mem/global.c trunk/reactos/include/ndk/rtlfuncs.h trunk/reactos/lib/rtl/heap.c
Modified: trunk/reactos/dll/ntdll/def/ntdll.def URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/def/ntdll.def?rev... ============================================================================== --- trunk/reactos/dll/ntdll/def/ntdll.def [iso-8859-1] (original) +++ trunk/reactos/dll/ntdll/def/ntdll.def [iso-8859-1] Thu Jul 10 04:46:25 2008 @@ -660,7 +660,7 @@ RtlSetSecurityObject@20 RtlSetTimeZoneInformation@4 ;RtlSetUnicodeCallouts -;RtlSetUserFlagsHeap +RtlSetUserFlagsHeap@16 RtlSetUserValueHeap@16 RtlSizeHeap@12 RtlSleepConditionVariableCS@12
Modified: trunk/reactos/dll/win32/kernel32/mem/global.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/mem/glob... ============================================================================== --- trunk/reactos/dll/win32/kernel32/mem/global.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/mem/global.c [iso-8859-1] Thu Jul 10 04:46:25 2008 @@ -101,6 +101,7 @@ { /* All worked well, save our heap entry */ RtlSetUserValueHeap(hProcessHeap, HEAP_NO_SERIALIZE, Ptr, hMemory); + RtlSetUserFlagsHeap(hProcessHeap, HEAP_NO_SERIALIZE, Ptr, Flags); } }
@@ -521,6 +522,10 @@ HEAP_NO_SERIALIZE, Ptr, hMem); + RtlSetUserFlagsHeap(hProcessHeap, + HEAP_NO_SERIALIZE, + Ptr, + Flags); } } else @@ -642,6 +647,10 @@ HEAP_NO_SERIALIZE, HandleEntry->Object, hMem); + RtlSetUserFlagsHeap(hProcessHeap, + HEAP_NO_SERIALIZE, + HandleEntry->Object, + HandleEntry->Flags); } } }
Modified: trunk/reactos/include/ndk/rtlfuncs.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/rtlfuncs.h?rev=... ============================================================================== --- trunk/reactos/include/ndk/rtlfuncs.h [iso-8859-1] (original) +++ trunk/reactos/include/ndk/rtlfuncs.h [iso-8859-1] Thu Jul 10 04:46:25 2008 @@ -620,6 +620,15 @@ IN PVOID UserValue );
+BOOLEAN +NTAPI +RtlSetUserFlagsHeap( + IN PVOID HeapHandle, + IN ULONG Flags, + IN PVOID BaseAddress, + IN ULONG UserFlags +); + NTSYSAPI ULONG NTAPI
Modified: trunk/reactos/lib/rtl/heap.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/heap.c?rev=34404&am... ============================================================================== --- trunk/reactos/lib/rtl/heap.c [iso-8859-1] (original) +++ trunk/reactos/lib/rtl/heap.c [iso-8859-1] Thu Jul 10 04:46:25 2008 @@ -69,7 +69,8 @@ typedef struct tagARENA_INUSE { DWORD size; /* Block size; must be the first field */ - DWORD magic : 24; /* Magic number */ + DWORD magic : 23; /* Magic number */ + DWORD has_user_data : 1; /* There is user data associated with this block */ DWORD unused_bytes : 8; /* Number of bytes in the block not used by user data (max value is HEAP_MIN_DATA_SIZE+HEAP_MIN_SHRINK_SIZE) */ } ARENA_INUSE;
@@ -123,11 +124,17 @@ struct tagSUBHEAP *next; /* Next sub-heap */ struct tagHEAP *heap; /* Main heap structure */ DWORD magic; /* Magic number */ - ULONG UserFlags; - PVOID UserValue; } SUBHEAP;
#define SUBHEAP_MAGIC ((DWORD)('S' | ('U'<<8) | ('B'<<16) | ('H'<<24))) + +typedef struct tagHEAP_USER_DATA +{ + LIST_ENTRY ListEntry; + PVOID BaseAddress; + ULONG UserFlags; + PVOID UserValue; +} HEAP_USER_DATA, *PHEAP_USER_DATA;
typedef struct tagHEAP { @@ -138,6 +145,7 @@ DWORD flags; /* Heap flags */ DWORD magic; /* Magic number */ PRTL_HEAP_COMMIT_ROUTINE commitRoutine; + LIST_ENTRY UserDataHead; } HEAP;
#define HEAP_MAGIC ((DWORD)('H' | ('E'<<8) | ('A'<<16) | ('P'<<24))) @@ -323,6 +331,35 @@ } #endif
+static PHEAP_USER_DATA HEAP_GetUserData(HEAP *heapPtr, PVOID BaseAddress) +{ + PLIST_ENTRY CurrentEntry; + PHEAP_USER_DATA udata; + + CurrentEntry = heapPtr->UserDataHead.Flink; + while (CurrentEntry != &heapPtr->UserDataHead) + { + udata = CONTAINING_RECORD(CurrentEntry, HEAP_USER_DATA, ListEntry); + if (udata->BaseAddress == BaseAddress) + return udata; + CurrentEntry = CurrentEntry->Flink; + } + return NULL; +} + +static PHEAP_USER_DATA HEAP_AllocUserData(HEAP *heapPtr, PVOID BaseAddress) +{ + /* Allocate user data entry */ + ARENA_INUSE *pInUse; + PHEAP_USER_DATA udata = RtlAllocateHeap(heapPtr, 0, sizeof(HEAP_USER_DATA)); + if (!udata) return NULL; + udata->BaseAddress = BaseAddress; + InsertTailList(&heapPtr->UserDataHead, &udata->ListEntry); + pInUse = (ARENA_INUSE *)BaseAddress - 1; + pInUse->has_user_data = 1; + return udata; +} + /*********************************************************************** * HEAP_GetPtr * RETURNS @@ -524,6 +561,18 @@ { ARENA_FREE *pFree; SIZE_T size = (pArena->size & ARENA_SIZE_MASK) + sizeof(*pArena); + PHEAP_USER_DATA udata; + + /* Find and free user data */ + if (pArena->has_user_data) + { + udata = HEAP_GetUserData(subheap->heap, pArena + 1); + if (udata) + { + RemoveEntryList(&udata->ListEntry); + RtlFreeHeap(subheap->heap, 0, udata); + } + }
/* Check if we can merge with previous block */
@@ -634,6 +683,7 @@ heap->commitRoutine = Parameters->CommitRoutine; else heap->commitRoutine = NULL; + InitializeListHead(&heap->UserDataHead);
/* Build the free lists */
@@ -1230,9 +1280,7 @@ * so we have to add the difference to the size */ pInUse->size = (pInUse->size & ~ARENA_FLAG_FREE) + sizeof(ARENA_FREE) - sizeof(ARENA_INUSE); pInUse->magic = ARENA_INUSE_MAGIC; - - /* Save user flags */ - subheap->UserFlags = flags & HEAP_SETTABLE_USER_FLAGS; + pInUse->has_user_data = 0;
/* Shrink the block */
@@ -1682,7 +1730,7 @@ }
/* - * @unimplemented + * @implemented */ BOOLEAN NTAPI @@ -1691,21 +1739,56 @@ IN PVOID BaseAddress, IN PVOID UserValue) { - HEAP *heapPtr = HEAP_GetPtr(HeapHandle); - ARENA_INUSE *pInUse; - SUBHEAP *subheap; - - /* Get the subheap */ - pInUse = (ARENA_INUSE *)BaseAddress - 1; - subheap = HEAP_FindSubHeap( heapPtr, pInUse ); - - /* Hack */ - subheap->UserValue = UserValue; + HEAP *heapPtr; + PHEAP_USER_DATA udata; + + heapPtr = HEAP_GetPtr(HeapHandle); + if (!heapPtr) + { + RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_HANDLE ); + return FALSE; + } + udata = HEAP_GetUserData(heapPtr, BaseAddress); + if (!udata) + { + udata = HEAP_AllocUserData(heapPtr, BaseAddress); + if (!udata) return FALSE; + } + udata->UserValue = UserValue; return TRUE; }
/* - * @unimplemented + * @implemented + */ +BOOLEAN +NTAPI +RtlSetUserFlagsHeap(IN PVOID HeapHandle, + IN ULONG Flags, + IN PVOID BaseAddress, + IN ULONG UserFlags) +{ + HEAP *heapPtr; + PHEAP_USER_DATA udata; + + heapPtr = HEAP_GetPtr(HeapHandle); + if (!heapPtr) + { + RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_HANDLE ); + return FALSE; + } + udata = HEAP_GetUserData(heapPtr, BaseAddress); + if (!udata) + { + udata = HEAP_AllocUserData(heapPtr, BaseAddress); + if (!udata) return FALSE; + } + udata->UserFlags = UserFlags & HEAP_SETTABLE_USER_FLAGS; + return TRUE; +} + +/* + * @implemented */ BOOLEAN NTAPI @@ -1715,18 +1798,23 @@ OUT PVOID *UserValue, OUT PULONG UserFlags) { - HEAP *heapPtr = HEAP_GetPtr(HeapHandle); - ARENA_INUSE *pInUse; - SUBHEAP *subheap; - - /* Get the subheap */ - pInUse = (ARENA_INUSE *)BaseAddress - 1; - subheap = HEAP_FindSubHeap( heapPtr, pInUse ); - - /* Hack */ - DPRINT1("V/F: %lx %p\n", subheap->UserValue, subheap->UserFlags); - if (UserValue) *UserValue = subheap->UserValue; - if (UserFlags) *UserFlags = subheap->UserFlags; + HEAP *heapPtr; + PHEAP_USER_DATA udata; + + heapPtr = HEAP_GetPtr(HeapHandle); + if (!heapPtr) + { + RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_HANDLE ); + return FALSE; + } + udata = HEAP_GetUserData(heapPtr, BaseAddress); + if (!udata) + { + RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER ); + return FALSE; + } + if (UserValue) *UserValue = udata->UserValue; + if (UserFlags) *UserFlags = udata->UserFlags; return TRUE; }