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(a)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?re…
==============================================================================
--- 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/glo…
==============================================================================
--- 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&a…
==============================================================================
--- 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;
}