Rob, as the HandleTable was your suggestion, could you provide a comment
on whether these patches are a practical way forward?
Jeff Latimer
Jeff Latimer wrote:
These 2 patches implement HandleTables for tracking memory usage for
the SCRIPT_STRING_ANALYSIS pointer. The problem is that the ssa can
be copied to another pointer and NULL'ing the pointer is not a
reliable means of de-allocating the pointer. The use of HandleTables
looks like a solution to the problem but it depends on whether storing
a handle in the ssa pointer is acceptable. The table is of fixed size
which is another potential problem but tests indicate that the number
of handles in use will remain relatively small by comparison to the
table size.
Advice is welcome.
Jeff Latimer
Changelog:
Create HandleTables to keep track of memory allocation
---
dlls/usp10/Makefile.in | 2 +
dlls/usp10/usp10.c | 71
+++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 70 insertions(+), 3 deletions(-)
------------------------------------------------------------------------
diff --git a/dlls/usp10/Makefile.in b/dlls/usp10/Makefile.in
index 9d716d5..edef33a 100644
--- a/dlls/usp10/Makefile.in
+++ b/dlls/usp10/Makefile.in
@@ -4,7 +4,7 @@ SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = usp10.dll
IMPORTLIB = libusp10.$(IMPLIBEXT)
-IMPORTS = gdi32 kernel32
+IMPORTS = gdi32 ntdll kernel32
C_SRCS = \
usp10.c
diff --git a/dlls/usp10/usp10.c b/dlls/usp10/usp10.c
index 9fd6c1e..4b15047 100644
--- a/dlls/usp10/usp10.c
+++ b/dlls/usp10/usp10.c
@@ -30,6 +30,7 @@ #include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
#include "usp10.h"
+#include "winternl.h"
#include "wine/debug.h"
@@ -73,17 +74,83 @@ typedef struct scriptcache {
HDC hdc;
} Scriptcache;
+typedef struct _CACHE_HANDLE
+{
+ RTL_HANDLE RtlHandle;
+ void * Cache_Address;
+} CACHE_HANDLE;
+
+DWORD TlsIndex; /* Adress of shared memory */
+
/***********************************************************************
* DllMain
*
+ * In this DllMain storage is allocated to each thread so that a HandleTable
can
+ * be created and maintained thread safe.
+ *
+ * NOTES
+ * The Tls functions (TlsAlloc, TlsSetValue, TlsGetValue and TlsFree) provide
+ * access to the local thread storage.
+ *
+ * LocalAlloc and LocalFree are used as in the Microsoft examples to access
+ * local thread storage.
+ *
+ * RtlInitializeHandleTable initialises the handle table to a fixed size of
+ * entries to contain the addresses of the cache pointers used in the
+ * ScriptString... functions. This function is fairly light weight as the
+ * space for the handle table entries is not allocated at this time but waits
+ * until the first RtlAllocateHandle call. Hence only the functions that need
+ * the handles incur the additional expense.
*/
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
{
+ RTL_HANDLE_TABLE *Cache_HandleTable;
+ BOOL Return_flag;
+
switch(fdwReason) {
+ /*
+ * When the dll is loaded obtain a TlsIndex so that the HandleTable
+ * pointer can be stored there uniquely for each thread.
+ */
case DLL_PROCESS_ATTACH:
- DisableThreadLibraryCalls(hInstDLL);
- break;
+ if ((TlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+ return FALSE;
+ /* Fall though to THREAD_ATTACH as loading a DLL only drives
+ * DLL_PROCESS_ATTACHand not DLL_THREAD_ATTACH. Here we allocate space
+ * for the HandleTable from the thread local storage, save the pointer
in
+ * the Tls and intialise the table.
+ */
+ case DLL_THREAD_ATTACH:
+ Cache_HandleTable = LocalAlloc(LPTR, sizeof(RTL_HANDLE_TABLE));
+ if (Cache_HandleTable)
+ {
+ Return_flag = TlsSetValue(TlsIndex, Cache_HandleTable);
+ RtlInitializeHandleTable(0x3FFF, sizeof(CACHE_HANDLE),
Cache_HandleTable);
+ }
+ break;
+ /*
+ * At exit from a thread, clean up HandleTable which includes freeing
the
+ * associated memory for handles and the HandleTable.
+ */
+ case DLL_THREAD_DETACH:
+ Cache_HandleTable = TlsGetValue(TlsIndex);
+ if (Cache_HandleTable)
+ {
+ RtlDestroyHandleTable(Cache_HandleTable);
+ LocalFree(Cache_HandleTable);
+ }
+ break;
+ /*
+ * As for DLL_THREAD_DETACH but includes freeing the TlsIndex.
+ */
case DLL_PROCESS_DETACH:
+ Cache_HandleTable = TlsGetValue(TlsIndex);
+ if (Cache_HandleTable)
+ {
+ RtlDestroyHandleTable(Cache_HandleTable);
+ LocalFree(Cache_HandleTable);
+ }
+ TlsFree(TlsIndex);
break;
}
return TRUE;
------------------------------------------------------------------------