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/fiber.c?rev=52805&r1=52804&r2=52805&view=diff
==============================================================================
--- 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);
 }
 
 /*


Reply via email to