@@ -51,6 +51,7 @@ RTL_BITMAP TlsExpansionBitMap;
5151RTL_BITMAP FlsBitMap ;
5252BOOLEAN LdrpImageHasTls ;
5353LIST_ENTRY LdrpTlsList ;
54+ LIST_ENTRY LdrpActiveTebList ;
5455ULONG LdrpNumberOfTlsEntries ;
5556ULONG LdrpNumberOfProcessors ;
5657PVOID NtDllBase ;
@@ -509,6 +510,8 @@ NTAPI
509510LdrpInitializeThread (IN PCONTEXT Context )
510511{
511512 PPEB Peb = NtCurrentPeb ();
513+ PTEB Teb = NtCurrentTeb ();
514+ PLDRP_TEB_LIST_ENTRY TebEntry ;
512515 PLDR_DATA_TABLE_ENTRY LdrEntry ;
513516 PLIST_ENTRY NextEntry , ListHead ;
514517 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx ;
@@ -535,7 +538,13 @@ LdrpInitializeThread(IN PCONTEXT Context)
535538 if (LdrpShutdownInProgress ) goto Exit ;
536539
537540 /* Allocate TLS */
538- LdrpAllocateTls ();
541+ LdrpAllocateTls (Teb );
542+
543+ /* Add thread to active TEB list */
544+ ListHead = & LdrpActiveTebList ;
545+ TebEntry = RtlAllocateHeap (RtlGetProcessHeap (), HEAP_ZERO_MEMORY , sizeof (* TebEntry ));
546+ TebEntry -> Teb = NtCurrentTeb ();
547+ InsertTailList (& LdrpActiveTebList , & TebEntry -> TebLinks );
539548
540549 /* Start at the beginning */
541550 ListHead = & Peb -> Ldr -> InMemoryOrderModuleList ;
@@ -1094,6 +1103,7 @@ LdrShutdownThread(VOID)
10941103{
10951104 PPEB Peb = NtCurrentPeb ();
10961105 PTEB Teb = NtCurrentTeb ();
1106+ PLDRP_TEB_LIST_ENTRY TebEntry ;
10971107 PLDR_DATA_TABLE_ENTRY LdrEntry ;
10981108 PLIST_ENTRY NextEntry , ListHead ;
10991109 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx ;
@@ -1112,6 +1122,20 @@ LdrShutdownThread(VOID)
11121122 /* Get the Ldr Lock */
11131123 RtlEnterCriticalSection (& LdrpLoaderLock );
11141124
1125+ /* Remove the thread from the active TEB list */
1126+ ListHead = & LdrpActiveTebList ;
1127+ for (NextEntry = ListHead -> Blink ;
1128+ NextEntry != ListHead ;
1129+ NextEntry = NextEntry -> Blink )
1130+ {
1131+ TebEntry = CONTAINING_RECORD (NextEntry , LDRP_TEB_LIST_ENTRY , TebLinks );
1132+ if (TebEntry -> Teb == Teb )
1133+ {
1134+ RemoveEntryList (NextEntry );
1135+ break ;
1136+ }
1137+ }
1138+
11151139 /* Start at the end */
11161140 ListHead = & Peb -> Ldr -> InInitializationOrderModuleList ;
11171141 NextEntry = ListHead -> Blink ;
@@ -1270,12 +1294,16 @@ LdrpInitializeTls(VOID)
12701294{
12711295 PLIST_ENTRY NextEntry , ListHead ;
12721296 PLDR_DATA_TABLE_ENTRY LdrEntry ;
1297+ PLDRP_TEB_LIST_ENTRY TebEntry ;
12731298 PIMAGE_TLS_DIRECTORY TlsDirectory ;
12741299 PLDRP_TLS_DATA TlsData ;
12751300 ULONG Size ;
1301+ NTSTATUS Status ;
1302+ BOOLEAN AllocateTls = FALSE;
12761303
12771304 /* Initialize the TLS List */
1278- InitializeListHead (& LdrpTlsList );
1305+ if (!LdrpImageHasTls )
1306+ InitializeListHead (& LdrpTlsList );
12791307
12801308 /* Loop all the modules */
12811309 ListHead = & NtCurrentPeb ()-> Ldr -> InLoadOrderModuleList ;
@@ -1295,8 +1323,12 @@ LdrpInitializeTls(VOID)
12951323 /* Check if we have a directory */
12961324 if (!TlsDirectory ) continue ;
12971325
1326+ if (LdrEntry -> Flags & LDRP_TLS_LOADED )
1327+ continue ;
1328+
12981329 /* Check if the image has TLS */
12991330 if (!LdrpImageHasTls ) LdrpImageHasTls = TRUE;
1331+ AllocateTls = TRUE;
13001332
13011333 /* Show debug message */
13021334 if (ShowSnaps )
@@ -1313,6 +1345,7 @@ LdrpInitializeTls(VOID)
13131345 /* Lock the DLL and mark it for TLS Usage */
13141346 LdrEntry -> LoadCount = -1 ;
13151347 LdrEntry -> TlsIndex = -1 ;
1348+ LdrEntry -> Flags |= LDRP_TLS_LOADED ;
13161349
13171350 /* Save the cached TLS data */
13181351 TlsData -> TlsDirectory = * TlsDirectory ;
@@ -1324,29 +1357,57 @@ LdrpInitializeTls(VOID)
13241357 }
13251358
13261359 /* Done setting up TLS, allocate entries */
1327- return LdrpAllocateTls ();
1360+ if (AllocateTls )
1361+ {
1362+ Status = LdrpAllocateTls (NtCurrentTeb ());
1363+ if (Status != STATUS_SUCCESS )
1364+ return Status ;
1365+
1366+ ListHead = & LdrpActiveTebList ;
1367+ NextEntry = ListHead -> Blink ;
1368+
1369+ for (NextEntry = ListHead -> Blink ;
1370+ NextEntry != ListHead ;
1371+ NextEntry = NextEntry -> Blink )
1372+ {
1373+ TebEntry = CONTAINING_RECORD (NextEntry , LDRP_TEB_LIST_ENTRY , TebLinks );
1374+ if (TebEntry -> Teb != NtCurrentTeb ())
1375+ {
1376+ Status = LdrpAllocateTls (TebEntry -> Teb );
1377+ if (Status != STATUS_SUCCESS )
1378+ return Status ;
1379+ }
1380+ }
1381+ }
1382+
1383+ return STATUS_SUCCESS ;
13281384}
13291385
13301386NTSTATUS
13311387NTAPI
1332- LdrpAllocateTls (VOID )
1388+ LdrpAllocateTls (_In_ PTEB Teb )
13331389{
1334- PTEB Teb = NtCurrentTeb ();
13351390 PLIST_ENTRY NextEntry , ListHead ;
13361391 PLDRP_TLS_DATA TlsData ;
13371392 SIZE_T TlsDataSize ;
13381393 PVOID * TlsVector ;
1394+ PVOID * OldTlsVector ;
1395+ PLDRP_OLD_TLS_VECTOR_ENTRY OldTlsVectorEntry ;
13391396
13401397 /* Check if we have any entries */
13411398 if (!LdrpNumberOfTlsEntries )
13421399 return STATUS_SUCCESS ;
1400+ /* Check if there are new entries to add to the vector */
1401+ if (LdrpNumberOfTlsEntries == Teb -> UserReserved .ThreadNumberOfTlsEntries )
1402+ return STATUS_SUCCESS ;
13431403
13441404 /* Allocate the vector array */
13451405 TlsVector = RtlAllocateHeap (RtlGetProcessHeap (),
1346- 0 ,
1347- LdrpNumberOfTlsEntries * sizeof (PVOID ));
1406+ 0 ,
1407+ LdrpNumberOfTlsEntries * sizeof (PVOID ));
13481408 if (!TlsVector ) return STATUS_NO_MEMORY ;
1349- Teb -> ThreadLocalStoragePointer = TlsVector ;
1409+ /* Grab old TLS vector to retrieve existing values */
1410+ OldTlsVector = Teb -> ThreadLocalStoragePointer ;
13501411
13511412 /* Loop the TLS Array */
13521413 ListHead = & LdrpTlsList ;
@@ -1360,32 +1421,74 @@ LdrpAllocateTls(VOID)
13601421 /* Allocate this vector */
13611422 TlsDataSize = TlsData -> TlsDirectory .EndAddressOfRawData -
13621423 TlsData -> TlsDirectory .StartAddressOfRawData ;
1363- TlsVector [TlsData -> TlsDirectory .Characteristics ] = RtlAllocateHeap (RtlGetProcessHeap (),
1364- 0 ,
1365- TlsDataSize );
1366- if (!TlsVector [TlsData -> TlsDirectory .Characteristics ])
1424+
1425+ if (!OldTlsVector || ((TlsData -> TlsDirectory .Characteristics + 1 ) > Teb -> UserReserved .ThreadNumberOfTlsEntries ))
13671426 {
1368- /* Out of memory */
1369- return STATUS_NO_MEMORY ;
1370- }
1427+ TlsVector [TlsData -> TlsDirectory .Characteristics ] = RtlAllocateHeap (RtlGetProcessHeap (),
1428+ 0 ,
1429+ TlsDataSize );
1430+ if (!TlsVector [TlsData -> TlsDirectory .Characteristics ])
1431+ {
1432+ /* Out of memory */
1433+ return STATUS_NO_MEMORY ;
1434+ }
13711435
1372- /* Show debug message */
1373- if (ShowSnaps )
1436+ /* Show debug message */
1437+ if (ShowSnaps )
1438+ {
1439+ DPRINT1 ("LDR: TlsVector %p Index %lu = %p copied from %x to %p\n" ,
1440+ TlsVector ,
1441+ TlsData -> TlsDirectory .Characteristics ,
1442+ & TlsVector [TlsData -> TlsDirectory .Characteristics ],
1443+ TlsData -> TlsDirectory .StartAddressOfRawData ,
1444+ TlsVector [TlsData -> TlsDirectory .Characteristics ]);
1445+ }
1446+
1447+ /* Copy the data */
1448+ RtlCopyMemory (TlsVector [TlsData -> TlsDirectory .Characteristics ],
1449+ (PVOID )TlsData -> TlsDirectory .StartAddressOfRawData ,
1450+ TlsDataSize );
1451+ }
1452+ else
13741453 {
1375- DPRINT1 ("LDR: TlsVector %p Index %lu = %p copied from %x to %p\n" ,
1376- TlsVector ,
1377- TlsData -> TlsDirectory .Characteristics ,
1378- & TlsVector [TlsData -> TlsDirectory .Characteristics ],
1379- TlsData -> TlsDirectory .StartAddressOfRawData ,
1380- TlsVector [TlsData -> TlsDirectory .Characteristics ]);
1454+ /* Reuse the previous thread-local copy of the TLS data in the new vector. */
1455+ TlsVector [TlsData -> TlsDirectory .Characteristics ] = OldTlsVector [TlsData -> TlsDirectory .Characteristics ];
1456+ /* Show debug message */
1457+ if (ShowSnaps )
1458+ {
1459+ DPRINT1 ("LDR: TlsVector %p Index %lu = %p recycled from %x to %p\n" ,
1460+ TlsVector ,
1461+ TlsData -> TlsDirectory .Characteristics ,
1462+ & OldTlsVector [TlsData -> TlsDirectory .Characteristics ],
1463+ OldTlsVector [TlsData -> TlsDirectory .Characteristics ],
1464+ TlsVector [TlsData -> TlsDirectory .Characteristics ]);
1465+ }
13811466 }
1382-
1383- /* Copy the data */
1384- RtlCopyMemory (TlsVector [TlsData -> TlsDirectory .Characteristics ],
1385- (PVOID )TlsData -> TlsDirectory .StartAddressOfRawData ,
1386- TlsDataSize );
13871467 }
13881468
1469+ if (OldTlsVector )
1470+ {
1471+ OldTlsVectorEntry = RtlAllocateHeap (RtlGetProcessHeap (), 0 ,
1472+ sizeof (* OldTlsVectorEntry ));
1473+ if (!OldTlsVectorEntry )
1474+ {
1475+ RtlFreeHeap (RtlGetProcessHeap (), 0 , TlsVector );
1476+ return STATUS_NO_MEMORY ;
1477+ }
1478+ OldTlsVectorEntry -> OldTlsVector = OldTlsVector ;
1479+ if (Teb -> SystemReserved1 .OldTlsVectorList )
1480+ {
1481+ InsertTailList ((PLIST_ENTRY )Teb -> SystemReserved1 .OldTlsVectorList ,
1482+ & OldTlsVectorEntry -> TlsVectorLinks );
1483+ }
1484+ else
1485+ {
1486+ InitializeListHead (& OldTlsVectorEntry -> TlsVectorLinks );
1487+ Teb -> SystemReserved1 .OldTlsVectorList = OldTlsVectorEntry ;
1488+ }
1489+ }
1490+ Teb -> ThreadLocalStoragePointer = TlsVector ;
1491+ Teb -> UserReserved .ThreadNumberOfTlsEntries = LdrpNumberOfTlsEntries ;
13891492 /* Done */
13901493 return STATUS_SUCCESS ;
13911494}
@@ -1396,6 +1499,7 @@ LdrpFreeTls(VOID)
13961499{
13971500 PLIST_ENTRY ListHead , NextEntry ;
13981501 PLDRP_TLS_DATA TlsData ;
1502+ PLDRP_OLD_TLS_VECTOR_ENTRY OldTlsVectorDataEntry ;
13991503 PVOID * TlsVector ;
14001504 PTEB Teb = NtCurrentTeb ();
14011505
@@ -1424,6 +1528,24 @@ LdrpFreeTls(VOID)
14241528 RtlFreeHeap (RtlGetProcessHeap (),
14251529 0 ,
14261530 TlsVector );
1531+
1532+ if (Teb -> SystemReserved1 .OldTlsVectorList )
1533+ {
1534+ /* Loop through it */
1535+ ListHead = (PLIST_ENTRY )Teb -> SystemReserved1 .OldTlsVectorList ;
1536+ NextEntry = ListHead -> Flink ;
1537+ while (NextEntry != ListHead )
1538+ {
1539+ OldTlsVectorDataEntry = CONTAINING_RECORD (NextEntry ,
1540+ LDRP_OLD_TLS_VECTOR_ENTRY ,
1541+ TlsVectorLinks );
1542+ NextEntry = NextEntry -> Flink ;
1543+
1544+ /* Free each old TLS vector and the entry itself */
1545+ RtlFreeHeap (RtlGetProcessHeap (), 0 , OldTlsVectorDataEntry -> OldTlsVector );
1546+ RtlFreeHeap (RtlGetProcessHeap (), 0 , OldTlsVectorDataEntry );
1547+ }
1548+ }
14271549}
14281550
14291551NTSTATUS
@@ -2436,6 +2558,9 @@ LdrpInitializeProcess(IN PCONTEXT Context,
24362558 RtlpInitializeKeyedEvent ();
24372559 RtlpInitializeThreadPooling ();
24382560
2561+ /* Initialize Active TEB List */
2562+ InitializeListHead (& LdrpActiveTebList );
2563+
24392564 /* Initialize TLS */
24402565 Status = LdrpInitializeTls ();
24412566 if (!NT_SUCCESS (Status ))
0 commit comments