diff --git a/dll/ntdll/ldr/ldrinit.c b/dll/ntdll/ldr/ldrinit.c index 14f0272dd3e..e40db1717ad 100644 --- a/dll/ntdll/ldr/ldrinit.c +++ b/dll/ntdll/ldr/ldrinit.c @@ -1207,8 +1207,29 @@ LdrShutdownThread(VOID) /* Check for FLS Data */ if (Teb->FlsData) { - /* FIXME */ - DPRINT1("We don't support FLS Data yet\n"); + /* Mimic BaseRundownFls */ + ULONG n, FlsHighIndex; + PRTL_FLS_DATA pFlsData; + PFLS_CALLBACK_FUNCTION lpCallback; + + pFlsData = Teb->FlsData; + + RtlAcquirePebLock(); + FlsHighIndex = NtCurrentPeb()->FlsHighIndex; + RemoveEntryList(&pFlsData->ListEntry); + RtlReleasePebLock(); + + for (n = 1; n <= FlsHighIndex; ++n) + { + lpCallback = NtCurrentPeb()->FlsCallback[n]; + if (lpCallback && pFlsData->Data[n]) + { + lpCallback(pFlsData->Data[n]); + } + } + + RtlFreeHeap(RtlGetProcessHeap(), 0, pFlsData); + Teb->FlsData = NULL; } /* Check for Fiber data */ @@ -1786,6 +1807,7 @@ LdrpInitializeProcess(IN PCONTEXT Context, Peb->FlsBitmapBits, FLS_MAXIMUM_AVAILABLE); RtlSetBit(&FlsBitMap, 0); + InitializeListHead(&Peb->FlsListHead); /* Initialize TLS Bitmap */ RtlInitializeBitMap(&TlsBitMap, diff --git a/dll/win32/kernel32/client/fiber.c b/dll/win32/kernel32/client/fiber.c index a3a38ecd7fb..47d2616e666 100644 --- a/dll/win32/kernel32/client/fiber.c +++ b/dll/win32/kernel32/client/fiber.c @@ -8,6 +8,7 @@ * KJK::Hyperion */ #include +#include #define NDEBUG #include @@ -21,6 +22,7 @@ C_ASSERT(FIELD_OFFSET(FIBER, FiberContext) == 0x14); C_ASSERT(FIELD_OFFSET(FIBER, GuaranteedStackBytes) == 0x2E0); C_ASSERT(FIELD_OFFSET(FIBER, FlsData) == 0x2E4); C_ASSERT(FIELD_OFFSET(FIBER, ActivationContextStackPointer) == 0x2E8); +C_ASSERT(RTL_FLS_MAXIMUM_AVAILABLE == FLS_MAXIMUM_AVAILABLE); #endif // _M_IX86 /* PRIVATE FUNCTIONS **********************************************************/ @@ -29,7 +31,27 @@ VOID WINAPI BaseRundownFls(_In_ PVOID FlsData) { - /* No FLS support yet */ + ULONG n, FlsHighIndex; + PRTL_FLS_DATA pFlsData; + PFLS_CALLBACK_FUNCTION lpCallback; + + pFlsData = FlsData; + + RtlAcquirePebLock(); + FlsHighIndex = NtCurrentPeb()->FlsHighIndex; + RemoveEntryList(&pFlsData->ListEntry); + RtlReleasePebLock(); + + for (n = 1; n <= FlsHighIndex; ++n) + { + lpCallback = NtCurrentPeb()->FlsCallback[n]; + if (lpCallback && pFlsData->Data[n]) + { + lpCallback(pFlsData->Data[n]); + } + } + + RtlFreeHeap(RtlGetProcessHeap(), 0, FlsData); } /* PUBLIC FUNCTIONS ***********************************************************/ @@ -61,7 +83,7 @@ ConvertFiberToThread(VOID) /* Free the fiber */ ASSERT(FiberData != NULL); - RtlFreeHeap(GetProcessHeap(), + RtlFreeHeap(RtlGetProcessHeap(), 0, FiberData); @@ -295,7 +317,7 @@ DeleteFiber(_In_ LPVOID lpFiber) RtlFreeActivationContextStack(Fiber->ActivationContextStackPointer); /* Free the fiber data */ - RtlFreeHeap(GetProcessHeap(), + RtlFreeHeap(RtlGetProcessHeap(), 0, lpFiber); } @@ -320,11 +342,11 @@ FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback) { DWORD dwFlsIndex; PPEB Peb = NtCurrentPeb(); - PVOID *ppFlsSlots; + PRTL_FLS_DATA pFlsData; RtlAcquirePebLock(); - ppFlsSlots = NtCurrentTeb()->FlsData; + pFlsData = NtCurrentTeb()->FlsData; if (!Peb->FlsCallback && !(Peb->FlsCallback = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, @@ -338,9 +360,8 @@ FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback) dwFlsIndex = RtlFindClearBitsAndSet(Peb->FlsBitmap, 1, 1); if (dwFlsIndex != FLS_OUT_OF_INDEXES) { - if (!ppFlsSlots && - !(ppFlsSlots = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, - (FLS_MAXIMUM_AVAILABLE + 2) * sizeof(PVOID)))) + if (!pFlsData && + !(pFlsData = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RTL_FLS_DATA)))) { RtlClearBits(Peb->FlsBitmap, dwFlsIndex, 1); dwFlsIndex = FLS_OUT_OF_INDEXES; @@ -349,13 +370,16 @@ FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback) else { if (!NtCurrentTeb()->FlsData) - NtCurrentTeb()->FlsData = ppFlsSlots; + { + NtCurrentTeb()->FlsData = pFlsData; + InsertTailList(&Peb->FlsListHead, &pFlsData->ListEntry); + } - if (lpCallback) - DPRINT1("FlsAlloc: Got lpCallback 0x%p, UNIMPLEMENTED!\n", lpCallback); - - ppFlsSlots[dwFlsIndex + 2] = NULL; /* clear the value */ + pFlsData->Data[dwFlsIndex] = NULL; /* clear the value */ Peb->FlsCallback[dwFlsIndex] = lpCallback; + + if (dwFlsIndex > Peb->FlsHighIndex) + Peb->FlsHighIndex = dwFlsIndex; } } else @@ -377,7 +401,6 @@ FlsFree(DWORD dwFlsIndex) { BOOL ret; PPEB Peb = NtCurrentPeb(); - PVOID *ppFlsSlots; if (dwFlsIndex >= FLS_MAXIMUM_AVAILABLE) { @@ -387,15 +410,30 @@ FlsFree(DWORD dwFlsIndex) RtlAcquirePebLock(); - ppFlsSlots = NtCurrentTeb()->FlsData; ret = RtlAreBitsSet(Peb->FlsBitmap, dwFlsIndex, 1); if (ret) { + PLIST_ENTRY Entry; + PFLS_CALLBACK_FUNCTION lpCallback; + RtlClearBits(Peb->FlsBitmap, dwFlsIndex, 1); - /* FIXME: call Fls callback */ - /* FIXME: add equivalent of ThreadZeroTlsCell here */ - if (ppFlsSlots) - ppFlsSlots[dwFlsIndex + 2] = NULL; + lpCallback = Peb->FlsCallback[dwFlsIndex]; + Peb->FlsCallback[dwFlsIndex] = NULL; + + for (Entry = Peb->FlsListHead.Flink; Entry != &Peb->FlsListHead; Entry = Entry->Flink) + { + PRTL_FLS_DATA pFlsData; + + pFlsData = CONTAINING_RECORD(Entry, RTL_FLS_DATA, ListEntry); + if (pFlsData->Data[dwFlsIndex]) + { + if (lpCallback) + { + lpCallback(pFlsData->Data[dwFlsIndex]); + } + pFlsData->Data[dwFlsIndex] = NULL; + } + } } else { @@ -413,17 +451,17 @@ PVOID WINAPI FlsGetValue(DWORD dwFlsIndex) { - PVOID *ppFlsSlots; + PRTL_FLS_DATA pFlsData; - ppFlsSlots = NtCurrentTeb()->FlsData; - if (!dwFlsIndex || dwFlsIndex >= FLS_MAXIMUM_AVAILABLE || !ppFlsSlots) + pFlsData = NtCurrentTeb()->FlsData; + if (!dwFlsIndex || dwFlsIndex >= FLS_MAXIMUM_AVAILABLE || !pFlsData) { SetLastError(ERROR_INVALID_PARAMETER); return NULL; } SetLastError(ERROR_SUCCESS); - return ppFlsSlots[dwFlsIndex + 2]; + return pFlsData->Data[dwFlsIndex]; } @@ -435,22 +473,31 @@ WINAPI FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData) { - PVOID *ppFlsSlots; + PRTL_FLS_DATA pFlsData; if (!dwFlsIndex || dwFlsIndex >= FLS_MAXIMUM_AVAILABLE) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } + + pFlsData = NtCurrentTeb()->FlsData; + if (!NtCurrentTeb()->FlsData && !(NtCurrentTeb()->FlsData = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, - (FLS_MAXIMUM_AVAILABLE + 2) * sizeof(PVOID)))) + sizeof(RTL_FLS_DATA)))) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } - ppFlsSlots = NtCurrentTeb()->FlsData; - ppFlsSlots[dwFlsIndex + 2] = lpFlsData; + if (!pFlsData) + { + pFlsData = NtCurrentTeb()->FlsData; + RtlAcquirePebLock(); + InsertTailList(&NtCurrentPeb()->FlsListHead, &pFlsData->ListEntry); + RtlReleasePebLock(); + } + pFlsData->Data[dwFlsIndex] = lpFlsData; return TRUE; } diff --git a/sdk/include/ndk/rtltypes.h b/sdk/include/ndk/rtltypes.h index 7070564389b..02d65a29719 100644 --- a/sdk/include/ndk/rtltypes.h +++ b/sdk/include/ndk/rtltypes.h @@ -1210,6 +1210,17 @@ typedef struct _RTL_DEBUG_INFORMATION PVOID Reserved[4]; } RTL_DEBUG_INFORMATION, *PRTL_DEBUG_INFORMATION; +// +// Fiber local storage data +// +#define RTL_FLS_MAXIMUM_AVAILABLE 128 +typedef struct _RTL_FLS_DATA +{ + LIST_ENTRY ListEntry; + PVOID Data[RTL_FLS_MAXIMUM_AVAILABLE]; +} RTL_FLS_DATA, *PRTL_FLS_DATA; + + // // Unload Event Trace Structure for RtlGetUnloadEventTrace //