diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index 3fc3b0d01f3..c61ef4022eb 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -163,25 +163,6 @@ NTSTATUS WINAPI NtSetInformationProcess( return 0; } -/* - * 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 3be2fef16e0..f28e2ed71e1 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 67868a49a0d..87ceaeb9906 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -107,7 +107,13 @@ NTSTATUS WINAPI NtTerminateThread( HANDLE handle, LONG exit_code ) 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 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class, 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 f9d83797c53..dd7d0db3571 100644 --- a/include/thread.h +++ b/include/thread.h @@ -128,7 +128,8 @@ typedef struct _TEB 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 f471b853003..1ef12d87518 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -171,7 +171,7 @@ typedef struct _TEB 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 NtSetEvent(HANDLE,PULONG); 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 bec3d7158ec..266e285a107 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -1502,8 +1502,7 @@ BOOL WINAPI TlsFree( 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 0738f6476a8..436f0240984 100644 --- a/scheduler/thread.c +++ b/scheduler/thread.c @@ -70,6 +70,7 @@ static BOOL THREAD_InitTEB( TEB *teb ) 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 @@ HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, SIZE_T stack, 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 @@ void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */ else { LdrShutdownThread(); + RtlAcquirePebLock(); + RemoveEntryList( &NtCurrentTeb()->TlsLinks ); + RtlReleasePebLock(); SYSDEPS_ExitThread( code ); } }