Michael Ost <[EMAIL PROTECTED]> writes:
> With the emulation mode set to "winxp" I can only TlsAlloc 64 indexes,
> even though the MSDN docs say there should be at least 20 million.
>
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/thread_local_storage.asp
>
> Has anyone done any work on this? Any workaround/hackarounds? ... mo
It's not 20 million, it's 1088 (64 + 1024). You need to use the TLS
expansion slots for the extra 1024, something like this (completely
untested):
Index: dlls/kernel/process.c
===
RCS file: /opt/cvs-commit/wine/dlls/kernel/process.c,v
retrieving revision 1.85
diff -u -p -r1.85 process.c
--- dlls/kernel/process.c 7 Mar 2005 19:24:44 - 1.85
+++ dlls/kernel/process.c 18 Mar 2005 11:24:53 -
@@ -2192,11 +2192,32 @@ UINT WINAPI SetErrorMode( UINT mode )
DWORD WINAPI TlsAlloc( void )
{
DWORD index;
+PEB * const peb = NtCurrentTeb()->Peb;
RtlAcquirePebLock();
-index = RtlFindClearBitsAndSet( NtCurrentTeb()->Peb->TlsBitmap, 1, 0 );
+index = RtlFindClearBitsAndSet( peb->TlsBitmap, 1, 0 );
if (index != ~0UL) NtCurrentTeb()->TlsSlots[index] = 0; /* clear the value
*/
-else SetLastError( ERROR_NO_MORE_ITEMS );
+else
+{
+index = RtlFindClearBitsAndSet( peb->TlsExpansionBitmap, 1, 0 );
+if (index != ~0UL)
+{
+if (!NtCurrentTeb()->TlsExpansionSlots &&
+!(NtCurrentTeb()->TlsExpansionSlots = HeapAlloc(
GetProcessHeap(), HEAP_ZERO_MEMORY,
+
peb->TlsExpansionBitmap->SizeOfBitMap*sizeof(void*) )))
+{
+RtlClearBits( peb->TlsExpansionBitmap, index, 1 );
+index = ~0UL;
+SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+}
+else
+{
+NtCurrentTeb()->TlsExpansionSlots[index] = 0; /* clear the
value */
+index += peb->TlsBitmap->SizeOfBitMap;
+}
+}
+else SetLastError( ERROR_NO_MORE_ITEMS );
+}
RtlReleasePebLock();
return index;
}
@@ -2215,14 +2236,21 @@ BOOL WINAPI TlsFree(
DWORD index) /* [in] TLS Index to free */
{
BOOL ret;
+PEB * const peb = NtCurrentTeb()->Peb;
RtlAcquirePebLock();
-ret = RtlAreBitsSet( NtCurrentTeb()->Peb->TlsBitmap, index, 1 );
-if (ret)
+if (index >= peb->TlsBitmap->SizeOfBitMap)
{
-RtlClearBits( NtCurrentTeb()->Peb->TlsBitmap, index, 1 );
-NtSetInformationThread( GetCurrentThread(), ThreadZeroTlsCell, &index,
sizeof(index) );
+DWORD exp_index = index - peb->TlsBitmap->SizeOfBitMap;
+ret = RtlAreBitsSet( peb->TlsExpansionBitmap, exp_index, 1 );
+if (ret) RtlClearBits( peb->TlsExpansionBitmap, exp_index, 1 );
}
+else
+{
+ret = RtlAreBitsSet( peb->TlsBitmap, index, 1 );
+if (ret) RtlClearBits( peb->TlsBitmap, index, 1 );
+}
+if (ret) NtSetInformationThread( GetCurrentThread(), ThreadZeroTlsCell,
&index, sizeof(index) );
else SetLastError( ERROR_INVALID_PARAMETER );
RtlReleasePebLock();
return TRUE;
@@ -2239,13 +2267,25 @@ BOOL WINAPI TlsFree(
LPVOID WINAPI TlsGetValue(
DWORD index) /* [in] TLS index to retrieve value for */
{
-if (index >= NtCurrentTeb()->Peb->TlsBitmap->SizeOfBitMap)
+LPVOID ret;
+
+if (index < NtCurrentTeb()->Peb->TlsBitmap->SizeOfBitMap)
{
-SetLastError( ERROR_INVALID_PARAMETER );
-return NULL;
+ret = NtCurrentTeb()->TlsSlots[index];
+}
+else
+{
+index -= NtCurrentTeb()->Peb->TlsBitmap->SizeOfBitMap;
+if (index >= NtCurrentTeb()->Peb->TlsExpansionBitmap->SizeOfBitMap)
+{
+SetLastError( ERROR_INVALID_PARAMETER );
+return NULL;
+}
+if (!NtCurrentTeb()->TlsExpansionSlots) ret = NULL;
+else ret = NtCurrentTeb()->TlsExpansionSlots[index];
}
SetLastError( ERROR_SUCCESS );
-return NtCurrentTeb()->TlsSlots[index];
+return ret;
}
@@ -2260,12 +2300,29 @@ BOOL WINAPI TlsSetValue(
DWORD index, /* [in] TLS index to set value for */
LPVOID value) /* [in] Value to be stored */
{
-if (index >= NtCurrentTeb()->Peb->TlsBitmap->SizeOfBitMap)
+PEB * const peb = NtCurrentTeb()->Peb;
+
+if (index < peb->TlsBitmap->SizeOfBitMap)
+{
+NtCurrentTeb()->TlsSlots[index] = value;
+}
+else
{
-SetLastError( ERROR_INVALID_PARAMETER );
-return FALSE;
+index -= peb->TlsBitmap->SizeOfBitMap;
+if (index >= peb->TlsExpansionBitmap->SizeOfBitMap)
+{
+SetLastError( ERROR_INVALID_PARAMETER );
+return FALSE;
+}
+if (!NtCurrentTeb()->TlsExpansionSlots &&
+!(NtCurrentTeb()->TlsExpansionSlots = HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
+