progwrp/fiber.c
2025-12-13 23:37:26 +01:00

198 lines
4.7 KiB
C

#include "progwrp.h"
#include "export.h"
#include "implementations.h"
BOOL WINAPI Implementation_IsThreadAFiber()
// Vista uses a TEB flag to determine whether a thread is a fiber.
// XP puts the flag in a different area, and 2000 has none.
// But there is the TIB's FiberData member, which also has a "version" number assigned to it.
// On XP and Vista it is assigned 0x1E00. Anything greather than that is assumed to be fiber data.
{
PTEB_CUSTOM Teb;
Teb = (PTEB_CUSTOM)NtCurrentTeb();
if((ULONG_PTR)Teb->FiberData <= 0x1E00)
return FALSE;
return TRUE;
}
DWORD WINAPI Implementation_FlsAlloc(
PFLS_CALLBACK_FUNCTION lpCallback
)
{
return TlsAlloc();
}
BOOL WINAPI Implementation_FlsFree(
DWORD dwFlsIndex
)
{
return TlsFree(dwFlsIndex);
}
typedef PVOID(WINAPI* pfnFlsGetValue)(DWORD);
BOOLEAN IsNt6Level = FALSE;
pfnFlsGetValue pFlsGetVal = NULL;
PVOID Test = NULL;
PVOID WINAPI Implementation_FlsGetValue(
DWORD dwFlsIndex
)
{
PTEB_CUSTOM Teb;
int i;
PLDR_DATA_TABLE_ENTRY DataTableEntry, DataTableEntryInit;
ANSI_STRING Fls;
if (!Test)
{
RtlInitAnsiString(&Fls, "FlsGetValue");
LdrGetProcedureAddress(GetModuleHandleA("kernel32.dll"), &Fls, 0, &pFlsGetVal);
RtlInitAnsiString(&Fls, "WerpInitiateRemoteRecovery");
LdrGetProcedureAddress(GetModuleHandleA("kernel32.dll"), &Fls, 0, &Test);
if (!Test) {
for (i = 0; i < TlsBasesCount; i++)
{
TLSInit_DllMain_ThreadAttach_Internal(TlsBases[i], NULL);
}
}
}
if (pFlsGetVal)
return pFlsGetVal(dwFlsIndex);
return TlsGetValue(dwFlsIndex);
}
BOOL WINAPI Implementation_FlsSetValue(
DWORD dwFlsIndex,
PVOID lpFlsData
)
{
return TlsSetValue(dwFlsIndex, lpFlsData);
}
typedef struct
{
LPVOID lpParameter;
PVOID Reserved [4];
CONTEXT Ctx;
}FIBER, *PFIBER;
LPVOID WINAPI Implementation_ConvertThreadToFiberEx(
LPVOID lpParameter,
DWORD dwFlags
)
{
PFIBER Result = (PFIBER) ConvertThreadToFiber(lpParameter);
if(Result && dwFlags & FIBER_FLAG_FLOAT_SWITCH)
{
Result->Ctx.ContextFlags |= CONTEXT_FLOATING_POINT | CONTEXT_CONTROL | CONTEXT_SEGMENTS | CONTEXT_INTEGER;
}
return (LPVOID) Result;
}
LPVOID WINAPI Implementation_CreateFiberEx(
SIZE_T dwStackCommitSize,
SIZE_T dwStackReserveSize,
DWORD dwFlags,
LPFIBER_START_ROUTINE lpStartAddress,
LPVOID lpParameter
)
{
PFIBER Result;
typedef LPVOID (WINAPI* pfnCreateFiberEx)(SIZE_T, SIZE_T, DWORD, LPFIBER_START_ROUTINE, LPVOID);
pfnCreateFiberEx pCreateFib = (pfnCreateFiberEx)Implementation_GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateFiberEx");
if(g_pfn_ConvertThreadToFiberEx == (pfnFunc_generic)Implementation_ConvertThreadToFiberEx)
{
Result = (PFIBER) pCreateFib(dwStackCommitSize, dwStackReserveSize, 0, lpStartAddress, lpParameter);
if(Result && dwFlags & FIBER_FLAG_FLOAT_SWITCH)
{
Result->Ctx.ContextFlags |= CONTEXT_FLOATING_POINT | CONTEXT_CONTROL | CONTEXT_SEGMENTS | CONTEXT_INTEGER;
}
}
else
Result = (PFIBER) pCreateFib(dwStackCommitSize, dwStackReserveSize, dwFlags, lpStartAddress, lpParameter);
return (LPVOID) Result;
}
void WINAPI Implementation_SwitchToFiber(LPVOID lpFiber)
{
/*
#ifdef _M_IX86
__asm
{
mov edx, fs:0x18 ; NtCurrentTeb()
mov eax, [edx+0x10] ; FiberData
mov [eax+0xB8], ebx
mov [eax+0xB0], edi
mov [eax+0xB4], esi
mov [eax+0xC8], ebp
cmp dword ptr [eax+0x14], 0x1000F ; Result->Ctx.ContextFlags & CONTEXT_FLOATING_POINT | CONTEXT_CONTROL | CONTEXT_SEGMENTS | CONTEXT_INTEGER
jnz SkipFloatingPoint
fstsw word ptr [eax+0x34]
fnstcw word ptr [eax+0x30]
cmp byte ptr ds:0x7FFE027A, 1 ; PF_XMMI_INSTRUCTIONS_AVAILABLE check, available since Windows 2000
jnz SkipFloatingPoint
nop ; stmxcsr dword ptr [eax+0x28]
SkipFloatingPoint:
mov [eax+0xD8], esp
mov ecx, [edx]
mov ebx, [edx+8]
mov [eax+4], ecx
mov [eax+0xC], ebx
mov ecx, [esp+4] ; lpFiber
mov [edx+0x10], ecx
mov esi, [ecx+4]
mov ebx, [ecx+8]
mov [edx], esi
mov [edx+4], ebx
mov esi, [ecx+0xC]
mov ebx, [ecx+0x10]
mov [edx+8], esi
mov [edx+0xE0C], ebx
cmp dword ptr [ecx+0x14], 1000Fh
jnz SkipFloatingPoint2
mov ebx, [eax+0x34]
cmp bx, [ecx+0x34]
jnz loc_7DD8105B
mov ebx, [eax+0x30]
cmp bx, [ecx+0x30]
jz loc_7DD81064
loc_7DD8105B:
mov word ptr [ecx+0x38], 0xFFFF
fldenv byte ptr [ecx+0x30]
loc_7DD81064:
cmp byte ptr ds:0x7FFE027A, 1
jnz SkipFloatingPoint2
nop ; ldmxcsr dword ptr [ecx+0x28]
SkipFloatingPoint2:
mov edi, [ecx+0xB0]
mov esi, [ecx+0xB4]
mov ebp, [ecx+0xC8]
mov ebx, [ecx+0xB8]
mov esp, [ecx+0xD8]
}
#endif
*/
}
BOOL WINAPI Implementation_ConvertFiberToThread()
{
PTEB_CUSTOM Teb = (PTEB_CUSTOM)NtCurrentTeb();
if((ULONG_PTR)Teb->FiberData <= 0x1E00)
return FALSE;
else
Teb->FiberData = 0x1E00;
return TRUE;
}