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);
}
} return TRUE;TlsFree(TlsIndex); break;