ReactOS 0.4.16-dev-2528-g7139e57
implicit_tls.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS API Tests
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Tests for Implicit Thread Local Storage (TLS) support
5 * COPYRIGHT: Copyright 2025 Shane Fournier <shanefournier@yandex.com>
6 */
7
8#include "precomp.h"
9
10#include <pseh/pseh2.h>
11
12#define TLS_VECTOR_MAX_SIZE 512
13
15
17
19
22 _In_ LPVOID pParameter
23)
24{
25 PVOID* TlsVector;
26 PTEB Teb = NtCurrentTeb();
27 int i = 0;
29 TlsVector = Teb->ThreadLocalStoragePointer;
30 while (TlsVector[i] && !((ULONG_PTR)TlsVector[i] % 4))
31 {
32 ++i;
33 }
35 ok(i == TLS_VECTOR_MAX_SIZE + ExtantTlsEntryCount, "ThreadLocalStoragePointer length is %d, expected length %lu\n", i, TLS_VECTOR_MAX_SIZE + ExtantTlsEntryCount);
36 return 0;
37}
38
41 _In_ LPVOID pParameter
42)
43{
44 PVOID* TlsVector;
45 PTEB Teb = NtCurrentTeb();
46 TlsVector = Teb->ThreadLocalStoragePointer;
47 ok(TlsVector[1] != NULL, "ThreadLocalStoragePointer index 1 is NULL; failed to initialize other thread with TLS entries present\n");
48 return 0;
49}
50
51START_TEST(implicit_tls)
52{
53 PVOID* TlsVector;
55 WCHAR duplicatepath[MAX_PATH];
56 WCHAR basedllname[MAX_PATH];
58 BOOL IsSuccess;
60 HANDLE AuxThread0, AuxThread1;
61 int i;
62 PTEB Teb = NtCurrentTeb();
63 ULONG TlsIdx0Value;
64 ULONG TlsIdx0ValueAfter;
65
66 IsSuccess = GetTempPathW(_countof(workdir), workdir);
67 ok(IsSuccess, "GetTempPathW error: %lu\n", GetLastError());
68
70 ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError());
71
72 IsSuccess = CopyFileW(L"implicit_tls.dll", dllpath_implicit_tls, FALSE);
73 ok(IsSuccess, "CopyFileW failed with %lu\n", GetLastError());
74
76 ok(ThreadEvent != INVALID_HANDLE_VALUE, "CreateEventA failed with %lu\n", GetLastError());
77
78 AuxThread0 = CreateThread(NULL, 0, AuxThread0Proc, NULL, 0, NULL);
79 ok(AuxThread0 != NULL, "CreateThread failed with %lu\n", GetLastError());
80
81 TlsVector = Teb->ThreadLocalStoragePointer;
82 PULONG_PTR ModuleHandle = TlsVector[0];
83 #if defined(_MSC_VER)
84 #pragma warning( disable : 4311)
85 #endif
86 *ModuleHandle = (ULONG)GetModuleHandleA(NULL) + 3;
87
88 TlsIdx0Value = *(PULONG)TlsVector[0];
89 while (TlsVector[ExtantTlsEntryCount] && !((ULONG_PTR)TlsVector[ExtantTlsEntryCount] % 4))
90 {
92 }
93 for (i = 0; i < TLS_VECTOR_MAX_SIZE; i++)
94 {
95 StringCchPrintfW(basedllname, MAX_PATH, L"basedllname_%d", i);
96 Length = GetTempFileNameW(workdir, basedllname, 0, duplicatepath);
97 ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError());
98 IsSuccess = CopyFileW(dllpath_implicit_tls, duplicatepath, FALSE);
99 ok(IsSuccess, "CopyFileW failed with %lu\n", GetLastError());
100 DllAddr[i] = LoadLibraryW(duplicatepath);
101 ok(DllAddr[i] != NULL, "LoadLibraryW failed with %lu\n", GetLastError());
102
103 if (i == TLS_VECTOR_MAX_SIZE / 2)
104 {
105 AuxThread1 = CreateThread(NULL, 0, AuxThread1Proc, NULL, 0, NULL);
106 ok(AuxThread1 != NULL, "CreateThread failed with %lu\n", GetLastError());
107 }
108 }
109
110 TlsVector = Teb->ThreadLocalStoragePointer;
111 ok(TlsVector[1] != NULL, "ThreadLocalStoragePointer index 1 is NULL; Implicit TLS unavailable\n");
112
114
115 TlsIdx0ValueAfter = *(PULONG)TlsVector[0];
116
117 ok(TlsIdx0Value == TlsIdx0ValueAfter, "Value in TLS index 0 corrupted by DLL loads; expected %lu and got %lu\n", TlsIdx0Value, TlsIdx0ValueAfter);
118
119 i = 0;
120 while (TlsVector[i] && !((ULONG_PTR)TlsVector[i] % 4))
121 {
122 ++i;
123 }
124 ok(i == TLS_VECTOR_MAX_SIZE + ExtantTlsEntryCount, "ThreadLocalStoragePointer length is %d, expected length %lu\n", i, TLS_VECTOR_MAX_SIZE + ExtantTlsEntryCount);
125
127
128 for (i = 0; i < TLS_VECTOR_MAX_SIZE; i++)
129 {
130 StringCchPrintfW(basedllname, MAX_PATH, L"basedllname_%d", i);
131 Length = GetTempFileNameW(workdir, basedllname, 0, duplicatepath);
132 ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError());
133 IsSuccess = DeleteFileW(duplicatepath);
134 ok(IsSuccess, "DeleteFileW failed with %lu\n", GetLastError());
135 FreeLibrary(DllAddr[i]);
136 }
137
139}
#define ok(value,...)
Definition: atltest.h:57
#define START_TEST(x)
Definition: atltest.h:75
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define FreeLibrary(x)
Definition: compat.h:748
#define MAX_PATH
Definition: compat.h:34
#define LoadLibraryW(x)
Definition: compat.h:747
BOOL WINAPI CopyFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:365
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
DWORD WINAPI GetTempPathW(IN DWORD count, OUT LPWSTR path)
Definition: path.c:1999
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
#define L(x)
Definition: resources.c:13
#define INFINITE
Definition: serial.h:102
UINT WINAPI GetTempFileNameW(IN LPCWSTR lpPathName, IN LPCWSTR lpPrefixString, IN UINT uUnique, OUT LPWSTR lpTempFileName)
Definition: filename.c:84
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
WCHAR dllpath_implicit_tls[MAX_PATH]
Definition: implicit_tls.c:14
ULONG ExtantTlsEntryCount
Definition: implicit_tls.c:18
HANDLE ThreadEvent
Definition: implicit_tls.c:16
#define TLS_VECTOR_MAX_SIZE
Definition: implicit_tls.c:12
DWORD WINAPI AuxThread0Proc(_In_ LPVOID pParameter)
Definition: implicit_tls.c:21
DWORD WINAPI AuxThread1Proc(_In_ LPVOID pParameter)
Definition: implicit_tls.c:40
#define NtCurrentTeb
static char workdir[MAX_PATH]
Definition: batch.c:26
#define _In_
Definition: no_sal2.h:158
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define _countof(array)
Definition: sndvol32.h:70
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
Definition: compat.h:836
PVOID ThreadLocalStoragePointer
Definition: compat.h:841
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:573
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:669
uint32_t * PULONG_PTR
Definition: typedefs.h:65
uint32_t * PULONG
Definition: typedefs.h:59
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define WINAPI
Definition: msvc.h:6
__wchar_t WCHAR
Definition: xmlstorage.h:180