On TlsFree, clear the released TLS index in all threads.
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
index 3fc3b0d..c61ef40 100644
--- a/dlls/ntdll/nt.c
+++ b/dlls/ntdll/nt.c
@@ -164,25 +164,6 @@
}
/*
- * Thread
- */
-
-/******************************************************************************
- * NtSetInformationThread [NTDLL.@]
- * ZwSetInformationThread [NTDLL.@]
- */
-NTSTATUS WINAPI NtSetInformationThread(
- HANDLE ThreadHandle,
- THREADINFOCLASS ThreadInformationClass,
- PVOID ThreadInformation,
- ULONG ThreadInformationLength)
-{
- FIXME("(%p,0x%08x,%p,0x%08lx),stub!\n",
- ThreadHandle, ThreadInformationClass, ThreadInformation, ThreadInformationLength);
- return 0;
-}
-
-/*
* Token
*/
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 3be2fef..f28e2ed 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -217,7 +217,7 @@
@ stdcall NtSetInformationKey(long long ptr long)
@ stdcall NtSetInformationObject(long long ptr long)
@ stdcall NtSetInformationProcess(long long long long)
-@ stdcall NtSetInformationThread(long long long long)
+@ stdcall NtSetInformationThread(long long ptr long)
@ stub NtSetInformationToken
@ stdcall NtSetIntervalProfile(long long)
@ stub NtSetIoCompletion
@@ -746,7 +746,7 @@
@ stdcall ZwSetInformationKey(long long ptr long) NtSetInformationKey
@ stdcall ZwSetInformationObject(long long ptr long) NtSetInformationObject
@ stdcall ZwSetInformationProcess(long long long long) NtSetInformationProcess
-@ stdcall ZwSetInformationThread(long long long long) NtSetInformationThread
+@ stdcall ZwSetInformationThread(long long ptr long) NtSetInformationThread
@ stub ZwSetInformationToken
@ stdcall ZwSetIntervalProfile(long long) NtSetIntervalProfile
@ stub ZwSetIoCompletion
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 67868a4..87ceaeb 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -107,7 +107,13 @@
if (self)
{
if (last) exit( exit_code );
- else SYSDEPS_ExitThread( exit_code );
+ else
+ {
+ RtlAcquirePebLock();
+ RemoveEntryList( &NtCurrentTeb()->TlsLinks );
+ RtlReleasePebLock();
+ SYSDEPS_ExitThread( exit_code );
+ }
}
return ret;
}
@@ -235,3 +241,57 @@
return STATUS_NOT_IMPLEMENTED;
}
}
+
+
+/******************************************************************************
+ * NtSetInformationThread (NTDLL.@)
+ * ZwSetInformationThread (NTDLL.@)
+ */
+NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class,
+ LPCVOID data, ULONG length )
+{
+ switch(class)
+ {
+ case ThreadZeroTlsCell:
+ if (handle == GetCurrentThread())
+ {
+ LIST_ENTRY *entry = &NtCurrentTeb()->TlsLinks;
+ DWORD index;
+
+ if (length != sizeof(DWORD)) return STATUS_INVALID_PARAMETER;
+ index = *(DWORD *)data;
+ if (index >= 64) return STATUS_INVALID_PARAMETER;
+ RtlAcquirePebLock();
+ do
+ {
+ TEB *teb = CONTAINING_RECORD(entry, TEB, TlsLinks);
+ teb->TlsSlots[index] = 0;
+ entry = entry->Flink;
+ } while (entry != &NtCurrentTeb()->TlsLinks);
+ RtlReleasePebLock();
+ return STATUS_SUCCESS;
+ }
+ FIXME( "ZeroTlsCell not supported on other threads\n" );
+ return STATUS_NOT_IMPLEMENTED;
+
+ case ThreadBasicInformation:
+ case ThreadTimes:
+ case ThreadPriority:
+ case ThreadBasePriority:
+ case ThreadAffinityMask:
+ case ThreadImpersonationToken:
+ case ThreadDescriptorTableEntry:
+ case ThreadEnableAlignmentFaultFixup:
+ case ThreadEventPair_Reusable:
+ case ThreadQuerySetWin32StartAddress:
+ case ThreadPerformanceCount:
+ case ThreadAmILastThread:
+ case ThreadIdealProcessor:
+ case ThreadPriorityBoost:
+ case ThreadSetTlsArrayAddress:
+ case ThreadIsIoPending:
+ default:
+ FIXME( "info class %d not supported yet\n", class );
+ return STATUS_NOT_IMPLEMENTED;
+ }
+}
diff --git a/include/thread.h b/include/thread.h
index f9d8379..dd7d0db 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -128,7 +128,8 @@
USHORT StaticUnicodeBuffer[261]; /* -2- c00 used by advapi32 */
PVOID DeallocationStack; /* -2- e0c Base of the stack */
LPVOID TlsSlots[64]; /* -2- e10 Thread local storage */
- DWORD pad8[3]; /* --n f10 */
+ LIST_ENTRY TlsLinks; /* -2- f10 */
+ DWORD pad8[1]; /* --n f18 */
PVOID ReservedForNtRpc; /* -2- f1c used by rpcrt4 */
DWORD pad9[24]; /* --n f20 */
PVOID ReservedForOle; /* -2- f80 used by ole32 (IErrorInfo*) */
diff --git a/include/winternl.h b/include/winternl.h
index f471b85..1ef12d8 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -171,7 +171,7 @@
WCHAR StaticUnicodeBuffer[261]; /* c00 used by advapi32 */
PVOID DeallocationStack; /* e0c */
PVOID TlsSlots[64]; /* e10 */
- BYTE Reserved3[8]; /* f10 */
+ LIST_ENTRY TlsLinks; /* f10 */
PVOID Reserved4[26]; /* f18 */
PVOID ReservedForOle; /* f80 Windows 2000 only */
PVOID Reserved5[4]; /* f84 */
@@ -1019,6 +1019,7 @@
NTSTATUS WINAPI NtSetInformationFile(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,FILE_INFORMATION_CLASS);
NTSTATUS WINAPI NtSetInformationKey(HKEY,const int,PVOID,ULONG);
NTSTATUS WINAPI NtSetInformationObject(HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG);
+NTSTATUS WINAPI NtSetInformationThread(HANDLE,THREADINFOCLASS,LPCVOID,ULONG);
NTSTATUS WINAPI NtSetSecurityObject(HANDLE,SECURITY_INFORMATION,PSECURITY_DESCRIPTOR);
NTSTATUS WINAPI NtSetSystemTime(const LARGE_INTEGER*,LARGE_INTEGER*);
NTSTATUS WINAPI NtSetTimer(HANDLE, const LARGE_INTEGER*, PTIMERAPCROUTINE, PVOID, BOOLEAN, ULONG, BOOLEAN*);
diff --git a/scheduler/process.c b/scheduler/process.c
index bec3d71..266e285 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -1502,8 +1502,7 @@
return FALSE;
}
*bits &= ~mask;
- NtCurrentTeb()->TlsSlots[index] = 0;
- /* FIXME: should zero all other thread values */
+ NtSetInformationThread( GetCurrentThread(), ThreadZeroTlsCell, &index, sizeof(index) );
RtlReleasePebLock();
return TRUE;
}
diff --git a/scheduler/thread.c b/scheduler/thread.c
index 0738f64..436f024 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -70,6 +70,7 @@
teb->wait_fd[1] = -1;
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
teb->StaticUnicodeString.Buffer = (PWSTR)teb->StaticUnicodeBuffer;
+ InitializeListHead(&teb->TlsLinks);
teb->teb_sel = wine_ldt_alloc_fs();
return (teb->teb_sel != 0);
}
@@ -268,12 +269,18 @@
teb->entry_point = start;
teb->entry_arg = param;
teb->htask16 = GetCurrentTask();
+ RtlAcquirePebLock();
+ InsertHeadList( &NtCurrentTeb()->TlsLinks, &teb->TlsLinks );
+ RtlReleasePebLock();
if (id) *id = tid;
if (SYSDEPS_SpawnThread( THREAD_Start, teb ) == -1)
{
CloseHandle( handle );
close( request_pipe[1] );
+ RtlAcquirePebLock();
+ RemoveEntryList( &teb->TlsLinks );
+ RtlReleasePebLock();
THREAD_FreeTEB( teb );
return 0;
}
@@ -307,6 +314,9 @@
else
{
LdrShutdownThread();
+ RtlAcquirePebLock();
+ RemoveEntryList( &NtCurrentTeb()->TlsLinks );
+ RtlReleasePebLock();
SYSDEPS_ExitThread( code );
}
}