Author: ion Date: Sat Jul 23 11:55:41 2011 New Revision: 52805
URL: http://svn.reactos.org/svn/reactos?rev=52805&view=rev Log: [KERNEL32]: Bug #47: CreateFiberEx should return ERROR_INVALID_PARAMETER for invalid flags. Bug #48: DeleteFiber should also check if HasFiberData is TRUE in TEB before calling ExitThread. Bug #49: DeleteFiber should only delete the FIBER data structure after cleanup is complete, not before. Also, enable the calls to RtlAllocateActivationContextStack since SxS kind-of exists now. However, we leak the context since RtlFreeActivationContextStack is not implemented. Also, add a call to BaseRundownFls so we don't forget to cleanup FLS data once FLS is implemented.
Modified: trunk/reactos/dll/win32/kernel32/client/fiber.c
Modified: trunk/reactos/dll/win32/kernel32/client/fiber.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/f... ============================================================================== --- trunk/reactos/dll/win32/kernel32/client/fiber.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/client/fiber.c [iso-8859-1] Sat Jul 23 11:55:41 2011 @@ -26,6 +26,16 @@ PVOID ActivationContextStack; /* 0x2E8 */ } FIBER, *PFIBER;
+/* PRIVATE FUNCTIONS **********************************************************/ + +VOID +WINAPI +BaseRundownFls(IN PVOID FlsData) +{ + /* No FLS support yet */ + +} + __declspec(noreturn) VOID WINAPI @@ -52,6 +62,8 @@ #endif }
+/* PUBLIC FUNCTIONS ***********************************************************/ + /* * @implemented */ @@ -93,58 +105,48 @@ ConvertThreadToFiberEx(LPVOID lpParameter, DWORD dwFlags) { - PTEB Teb; - PFIBER Fiber; + PTEB pTeb = NtCurrentTeb(); + PFIBER pfCurFiber; DPRINT1("Converting Thread to Fiber\n");
- /* Check for invalid flags */ - if (dwFlags &~ FIBER_FLAG_FLOAT_SWITCH) - { - /* Fail */ - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - /* Are we already a fiber? */ - Teb = NtCurrentTeb(); - if (Teb->HasFiberData) - { - /* Fail */ - SetLastError(ERROR_ALREADY_FIBER); - return NULL; - } - - /* Allocate the fiber */ - Fiber = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(FIBER)); - if (!Fiber) + /* the current thread is already a fiber */ + if(pTeb->HasFiberData && pTeb->NtTib.FiberData) return pTeb->NtTib.FiberData; + + /* allocate the fiber */ + pfCurFiber = (PFIBER)RtlAllocateHeap(GetProcessHeap(), + 0, + sizeof(FIBER)); + + /* failure */ + if (pfCurFiber == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; }
- /* Copy some contextual data from the thread to the fiber */ - Fiber->Parameter = lpParameter; - Fiber->ExceptionList = Teb->NtTib.ExceptionList; - Fiber->StackBase = Teb->NtTib.StackBase; - Fiber->StackLimit = Teb->NtTib.StackLimit; - Fiber->DeallocationStack = Teb->DeallocationStack; - Fiber->FlsData = Teb->FlsData; - Fiber->GuaranteedStackBytes = Teb->GuaranteedStackBytes; - Fiber->ActivationContextStack = Teb->ActivationContextStackPointer; - Fiber->Context.ContextFlags = CONTEXT_FULL; - - /* Save FPU State if requested */ + /* copy some contextual data from the thread to the fiber */ + pfCurFiber->Parameter = lpParameter; + pfCurFiber->ExceptionList = pTeb->NtTib.ExceptionList; + pfCurFiber->StackBase = pTeb->NtTib.StackBase; + pfCurFiber->StackLimit = pTeb->NtTib.StackLimit; + pfCurFiber->DeallocationStack = pTeb->DeallocationStack; + pfCurFiber->FlsData = pTeb->FlsData; + pfCurFiber->GuaranteedStackBytes = pTeb->GuaranteedStackBytes; + pfCurFiber->ActivationContextStack = pTeb->ActivationContextStackPointer; + pfCurFiber->Context.ContextFlags = CONTEXT_FULL; + + /* Save FPU State if requsted */ if (dwFlags & FIBER_FLAG_FLOAT_SWITCH) { - Fiber->Context.ContextFlags |= CONTEXT_FLOATING_POINT; - } - - /* Associate the fiber to the current thread */ - Teb->NtTib.FiberData = Fiber; - Teb->HasFiberData = TRUE; - - /* Return opaque fiber data */ - return (LPVOID)Fiber; + pfCurFiber->Context.ContextFlags |= CONTEXT_FLOATING_POINT; + } + + /* associate the fiber to the current thread */ + pTeb->NtTib.FiberData = pfCurFiber; + pTeb->HasFiberData = TRUE; + + /* success */ + return (LPVOID)pfCurFiber; }
/* @@ -182,73 +184,86 @@ LPFIBER_START_ROUTINE lpStartAddress, LPVOID lpParameter) { - PFIBER pfCurFiber; - NTSTATUS nErrCode; - INITIAL_TEB usFiberInitialTeb; + PFIBER Fiber; + NTSTATUS Status; + INITIAL_TEB InitialTeb; PVOID ActivationContextStack = NULL; DPRINT("Creating Fiber\n");
-#ifdef SXS_SUPPORT_ENABLED + /* Check for invalid flags */ + if (dwFlags &~ FIBER_FLAG_FLOAT_SWITCH) + { + /* Fail */ + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + /* Allocate the Activation Context Stack */ - nErrCode = RtlAllocateActivationContextStack(&ActivationContextStack); -#endif + Status = RtlAllocateActivationContextStack(&ActivationContextStack); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + SetLastErrorByStatus(Status); + return NULL; + }
/* Allocate the fiber */ - pfCurFiber = (PFIBER)RtlAllocateHeap(GetProcessHeap(), - 0, - sizeof(FIBER)); - /* Failure */ - if (pfCurFiber == NULL) - { + Fiber = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(FIBER)); + if (!Fiber) + { + /* Fail */ SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; }
/* Create the stack for the fiber */ - nErrCode = BasepCreateStack(NtCurrentProcess(), - dwStackCommitSize, - dwStackReserveSize, - &usFiberInitialTeb); - /* Failure */ - if(!NT_SUCCESS(nErrCode)) + Status = BasepCreateStack(NtCurrentProcess(), + dwStackCommitSize, + dwStackReserveSize, + &InitialTeb); + if (!NT_SUCCESS(Status)) { /* Free the fiber */ - RtlFreeHeap(GetProcessHeap(), 0, pfCurFiber); + RtlFreeHeap(GetProcessHeap(), 0, Fiber); + + /* Free the activation context */ + DPRINT1("Leaking activation stack because nobody implemented free"); + //RtlFreeActivationContextStack(&ActivationContextStack);
/* Failure */ - SetLastErrorByStatus(nErrCode); + SetLastErrorByStatus(Status); return NULL; }
/* Clear the context */ - RtlZeroMemory(&pfCurFiber->Context, sizeof(CONTEXT)); - - /* copy the data into the fiber */ - pfCurFiber->StackBase = usFiberInitialTeb.StackBase; - pfCurFiber->StackLimit = usFiberInitialTeb.StackLimit; - pfCurFiber->DeallocationStack = usFiberInitialTeb.AllocatedStackBase; - pfCurFiber->Parameter = lpParameter; - pfCurFiber->ExceptionList = (struct _EXCEPTION_REGISTRATION_RECORD *)-1; - pfCurFiber->GuaranteedStackBytes = 0; - pfCurFiber->FlsData = NULL; - pfCurFiber->ActivationContextStack = ActivationContextStack; - pfCurFiber->Context.ContextFlags = CONTEXT_FULL; + RtlZeroMemory(&Fiber->Context, sizeof(CONTEXT)); + + /* Copy the data into the fiber */ + Fiber->StackBase = InitialTeb.StackBase; + Fiber->StackLimit = InitialTeb.StackLimit; + Fiber->DeallocationStack = InitialTeb.AllocatedStackBase; + Fiber->Parameter = lpParameter; + Fiber->ExceptionList = EXCEPTION_CHAIN_END; + Fiber->GuaranteedStackBytes = 0; + Fiber->FlsData = NULL; + Fiber->ActivationContextStack = ActivationContextStack; + Fiber->Context.ContextFlags = CONTEXT_FULL;
/* Save FPU State if requsted */ if (dwFlags & FIBER_FLAG_FLOAT_SWITCH) { - pfCurFiber->Context.ContextFlags |= CONTEXT_FLOATING_POINT; + Fiber->Context.ContextFlags |= CONTEXT_FLOATING_POINT; }
/* initialize the context for the fiber */ - BasepInitializeContext(&pfCurFiber->Context, + BasepInitializeContext(&Fiber->Context, lpParameter, lpStartAddress, - usFiberInitialTeb.StackBase, + InitialTeb.StackBase, 2);
- /* Return the Fiber */ - return pfCurFiber; + /* Return the Fiber */ + return Fiber; }
/* @@ -258,20 +273,29 @@ WINAPI DeleteFiber(LPVOID lpFiber) { - SIZE_T nSize = 0; - PVOID pStackAllocBase = ((PFIBER)lpFiber)->DeallocationStack; - - /* free the fiber */ + SIZE_T Size = 0; + PFIBER Fiber = (PFIBER)lpFiber; + PTEB Teb; + + /* First, exit the thread */ + Teb = NtCurrentTeb(); + if ((Teb->HasFiberData) && (Teb->NtTib.FiberData == Fiber)) ExitThread(1); + + /* Now de-allocate the stack */ + NtFreeVirtualMemory(NtCurrentProcess(), + &Fiber->DeallocationStack, + &Size, + MEM_RELEASE); + + /* Get rid of FLS */ + if (Fiber->FlsData) BaseRundownFls(Fiber->FlsData); + + /* Get rid of the activation stack */ + DPRINT1("Leaking activation stack because nobody implemented free"); + //RtlFreeActivationContextStack(Fiber->ActivationContextStack); + + /* Free the fiber data */ RtlFreeHeap(GetProcessHeap(), 0, lpFiber); - - /* the fiber is deleting itself: let the system deallocate the stack */ - if(NtCurrentTeb()->NtTib.FiberData == lpFiber) ExitThread(1); - - /* deallocate the stack */ - NtFreeVirtualMemory(NtCurrentProcess(), - &pStackAllocBase, - &nSize, - MEM_RELEASE); }
/*