[KERNEL32] Fix bug in CreateFiberEx that made it replace the CONTEXT_FULL bits rather...
authorStefan Ginsberg <stefanginsberg@gmail.com>
Thu, 8 Oct 2015 16:26:29 +0000 (16:26 +0000)
committerStefan Ginsberg <stefanginsberg@gmail.com>
Thu, 8 Oct 2015 16:26:29 +0000 (16:26 +0000)
svn path=/trunk/; revision=69466

reactos/dll/win32/kernel32/client/fiber.c
reactos/dll/win32/kernel32/client/i386/fiber.S
reactos/dll/win32/kernel32/client/utils.c
reactos/include/asm/ks386.template.h
reactos/include/ndk/i386/asm.h

index 8185e7a..2c2a786 100644 (file)
@@ -27,10 +27,9 @@ C_ASSERT(FIELD_OFFSET(FIBER, ActivationContextStackPointer) == 0x2E8);
 
 VOID
 WINAPI
-BaseRundownFls(IN PVOID FlsData)
+BaseRundownFls(_In_ PVOID FlsData)
 {
     /* No FLS support yet */
-
 }
 
 /* PUBLIC FUNCTIONS ***********************************************************/
@@ -55,16 +54,18 @@ ConvertFiberToThread(VOID)
         return FALSE;
     }
 
-    /* this thread won't run a fiber anymore */
+    /* This thread won't run a fiber anymore */
     Teb->HasFiberData = FALSE;
     FiberData = Teb->NtTib.FiberData;
     Teb->NtTib.FiberData = NULL;
 
     /* Free the fiber */
     ASSERT(FiberData != NULL);
-    RtlFreeHeap(GetProcessHeap(), 0, FiberData);
+    RtlFreeHeap(GetProcessHeap(),
+                0,
+                FiberData);
 
-    /* success */
+    /* Success */
     return TRUE;
 }
 
@@ -73,15 +74,15 @@ ConvertFiberToThread(VOID)
  */
 LPVOID
 WINAPI
-ConvertThreadToFiberEx(LPVOID lpParameter,
-                       DWORD dwFlags)
+ConvertThreadToFiberEx(_In_opt_ LPVOID lpParameter,
+                       _In_ DWORD dwFlags)
 {
     PTEB Teb;
     PFIBER Fiber;
     DPRINT1("Converting Thread to Fiber\n");
 
     /* Check for invalid flags */
-    if (dwFlags &FIBER_FLAG_FLOAT_SWITCH)
+    if (dwFlags & ~FIBER_FLAG_FLOAT_SWITCH)
     {
         /* Fail */
         SetLastError(ERROR_INVALID_PARAMETER);
@@ -98,9 +99,12 @@ ConvertThreadToFiberEx(LPVOID lpParameter,
     }
 
     /* Allocate the fiber */
-    Fiber = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(FIBER));
+    Fiber = RtlAllocateHeap(RtlGetProcessHeap(),
+                            0,
+                            sizeof(FIBER));
     if (!Fiber)
     {
+        /* Fail */
         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return NULL;
     }
@@ -114,13 +118,11 @@ ConvertThreadToFiberEx(LPVOID lpParameter,
     Fiber->FlsData = Teb->FlsData;
     Fiber->GuaranteedStackBytes = Teb->GuaranteedStackBytes;
     Fiber->ActivationContextStackPointer = Teb->ActivationContextStackPointer;
-    Fiber->FiberContext.ContextFlags = CONTEXT_FULL;
 
-    /* Save FPU State if requested */
-    if (dwFlags & FIBER_FLAG_FLOAT_SWITCH)
-    {
-        Fiber->FiberContext.ContextFlags |= CONTEXT_FLOATING_POINT;
-    }
+    /* Save FPU State if requested, otherwise just the basic registers */
+    Fiber->FiberContext.ContextFlags = (dwFlags & FIBER_FLAG_FLOAT_SWITCH) ?
+                                       (CONTEXT_FULL | CONTEXT_FLOATING_POINT) :
+                                       CONTEXT_FULL;
 
     /* Associate the fiber to the current thread */
     Teb->NtTib.FiberData = Fiber;
@@ -135,10 +137,11 @@ ConvertThreadToFiberEx(LPVOID lpParameter,
  */
 LPVOID
 WINAPI
-ConvertThreadToFiber(LPVOID lpParameter)
+ConvertThreadToFiber(_In_opt_ LPVOID lpParameter)
 {
     /* Call the newer function */
-    return ConvertThreadToFiberEx(lpParameter, 0);
+    return ConvertThreadToFiberEx(lpParameter,
+                                  0);
 }
 
 /*
@@ -146,12 +149,16 @@ ConvertThreadToFiber(LPVOID lpParameter)
  */
 LPVOID
 WINAPI
-CreateFiber(SIZE_T dwStackSize,
-            LPFIBER_START_ROUTINE lpStartAddress,
-            LPVOID lpParameter)
+CreateFiber(_In_ SIZE_T dwStackSize,
+            _In_ LPFIBER_START_ROUTINE lpStartAddress,
+            _In_opt_ LPVOID lpParameter)
 {
     /* Call the Newer Function */
-    return CreateFiberEx(dwStackSize, 0, 0, lpStartAddress, lpParameter);
+    return CreateFiberEx(dwStackSize,
+                         0,
+                         0,
+                         lpStartAddress,
+                         lpParameter);
 }
 
 /*
@@ -159,20 +166,20 @@ CreateFiber(SIZE_T dwStackSize,
  */
 LPVOID
 WINAPI
-CreateFiberEx(SIZE_T dwStackCommitSize,
-              SIZE_T dwStackReserveSize,
-              DWORD dwFlags,
-              LPFIBER_START_ROUTINE lpStartAddress,
-              LPVOID lpParameter)
+CreateFiberEx(_In_ SIZE_T dwStackCommitSize,
+              _In_ SIZE_T dwStackReserveSize,
+              _In_ DWORD dwFlags,
+              _In_ LPFIBER_START_ROUTINE lpStartAddress,
+              _In_opt_ LPVOID lpParameter)
 {
     PFIBER Fiber;
     NTSTATUS Status;
     INITIAL_TEB InitialTeb;
-    PACTIVATION_CONTEXT_STACK ActivationContextStackPointer = NULL;
+    PACTIVATION_CONTEXT_STACK ActivationContextStackPointer;
     DPRINT("Creating Fiber\n");
 
     /* Check for invalid flags */
-    if (dwFlags &FIBER_FLAG_FLOAT_SWITCH)
+    if (dwFlags & ~FIBER_FLAG_FLOAT_SWITCH)
     {
         /* Fail */
         SetLastError(ERROR_INVALID_PARAMETER);
@@ -180,6 +187,7 @@ CreateFiberEx(SIZE_T dwStackCommitSize,
     }
 
     /* Allocate the Activation Context Stack */
+    ActivationContextStackPointer = NULL;
     Status = RtlAllocateActivationContextStack(&ActivationContextStackPointer);
     if (!NT_SUCCESS(Status))
     {
@@ -189,7 +197,9 @@ CreateFiberEx(SIZE_T dwStackCommitSize,
     }
 
     /* Allocate the fiber */
-    Fiber = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(FIBER));
+    Fiber = RtlAllocateHeap(RtlGetProcessHeap(),
+                            0,
+                            sizeof(FIBER));
     if (!Fiber)
     {
         /* Free the activation context stack */
@@ -208,7 +218,9 @@ CreateFiberEx(SIZE_T dwStackCommitSize,
     if (!NT_SUCCESS(Status))
     {
         /* Free the fiber */
-        RtlFreeHeap(GetProcessHeap(), 0, Fiber);
+        RtlFreeHeap(GetProcessHeap(),
+                    0,
+                    Fiber);
 
         /* Free the activation context stack */
         RtlFreeActivationContextStack(ActivationContextStackPointer);
@@ -219,7 +231,8 @@ CreateFiberEx(SIZE_T dwStackCommitSize,
     }
 
     /* Clear the context */
-    RtlZeroMemory(&Fiber->FiberContext, sizeof(CONTEXT));
+    RtlZeroMemory(&Fiber->FiberContext,
+                  sizeof(CONTEXT));
 
     /* Copy the data into the fiber */
     Fiber->StackBase = InitialTeb.StackBase;
@@ -230,12 +243,13 @@ CreateFiberEx(SIZE_T dwStackCommitSize,
     Fiber->GuaranteedStackBytes = 0;
     Fiber->FlsData = NULL;
     Fiber->ActivationContextStackPointer = ActivationContextStackPointer;
-    Fiber->FiberContext.ContextFlags = CONTEXT_FULL;
 
-    /* Save FPU State if requested */
-    Fiber->FiberContext.ContextFlags = (dwFlags & FIBER_FLAG_FLOAT_SWITCH) ? CONTEXT_FLOATING_POINT : 0;
+    /* Save FPU State if requested, otherwise just the basic registers */
+    Fiber->FiberContext.ContextFlags = (dwFlags & FIBER_FLAG_FLOAT_SWITCH) ?
+                                       (CONTEXT_FULL | CONTEXT_FLOATING_POINT) :
+                                       CONTEXT_FULL;
 
-    /* initialize the context for the fiber */
+    /* Initialize the context for the fiber */
     BaseInitializeContext(&Fiber->FiberContext,
                           lpParameter,
                           lpStartAddress,
@@ -251,17 +265,24 @@ CreateFiberEx(SIZE_T dwStackCommitSize,
  */
 VOID
 WINAPI
-DeleteFiber(LPVOID lpFiber)
+DeleteFiber(_In_ LPVOID lpFiber)
 {
-    SIZE_T Size = 0;
-    PFIBER Fiber = (PFIBER)lpFiber;
+    SIZE_T Size;
+    PFIBER Fiber;
     PTEB Teb;
 
-    /* First, exit the thread */
+    /* Are we deleting ourselves? */
     Teb = NtCurrentTeb();
-    if ((Teb->HasFiberData) && (Teb->NtTib.FiberData == Fiber)) ExitThread(1);
+    Fiber = (PFIBER)lpFiber;
+    if ((Teb->HasFiberData) &&
+        (Teb->NtTib.FiberData == Fiber))
+    {
+        /* Just exit */
+        ExitThread(1);
+    }
 
-    /* Now de-allocate the stack */
+    /* Not ourselves, de-allocate the stack */
+    Size = 0 ;
     NtFreeVirtualMemory(NtCurrentProcess(),
                         &Fiber->DeallocationStack,
                         &Size,
@@ -274,7 +295,9 @@ DeleteFiber(LPVOID lpFiber)
     RtlFreeActivationContextStack(Fiber->ActivationContextStackPointer);
 
     /* Free the fiber data */
-    RtlFreeHeap(GetProcessHeap(), 0, lpFiber);
+    RtlFreeHeap(GetProcessHeap(),
+                0,
+                lpFiber);
 }
 
 /*
@@ -284,6 +307,7 @@ BOOL
 WINAPI
 IsThreadAFiber(VOID)
 {
+    /* Return flag in the TEB */
     return NtCurrentTeb()->HasFiberData;
 }
 
@@ -349,7 +373,8 @@ l_InvalidParam:
  */
 BOOL
 WINAPI
-FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
+FlsSetValue(DWORD dwFlsIndex,
+            PVOID lpFlsData)
 {
     PVOID *ppFlsSlots;
     TEB *pTeb = NtCurrentTeb();
index 6e2444a..9a34e79 100644 (file)
@@ -15,21 +15,26 @@ EXTERN _BaseThreadStartup@8:PROC
 .code
 
 PUBLIC _BaseFiberStartup@0
-.PROC _BaseFiberStartup@0
-    /* Frame pointer is zeroed */
+FUNC _BaseFiberStartup@0
     FPO 0, 0, 0, 0, 0, FRAME_FPO
 
+    /* Note that EBP is already zeroed for us during fiber creation */
+
     /* Get the fiber data */
     mov eax, fs:[TEB_FIBER_DATA]
 
-    push dword ptr [eax+FIBER_CONTEXT_EBX] /* Parameter */
-    push dword ptr [eax+FIBER_CONTEXT_EAX] /* Start Address */
-    call _BaseThreadStartup@8
-.ENDP
+    /* Start the thread with our parameters */
+    push dword ptr [eax+FIBER_CONTEXT_EBX]
+    push dword ptr [eax+FIBER_CONTEXT_EAX]
+    jmp _BaseThreadStartup@8
+
+ENDFUNC
 
 
 PUBLIC _SwitchToFiber@4
-_SwitchToFiber@4:
+FUNC _SwitchToFiber@4
+    FPO 0, 0, 0, 0, 0, FRAME_FPO
+
     /* Get the TEB */
     mov edx, fs:[TEB_SELF]
 
@@ -51,7 +56,7 @@ _SwitchToFiber@4:
     fnstcw [eax+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD]
 
     /* Check if the CPU supports SIMD MXCSR State Save */
-    cmp byte ptr ds:[PF_XMMI_INSTRUCTIONS_AVAILABLE], 1
+    cmp byte ptr ds:[USER_SHARED_DATA + USER_SHARED_DATA_PROCESSOR_FEATURES + PF_XMMI_INSTRUCTIONS_AVAILABLE], 1
     jnz NoFpuStateSave
     stmxcsr [eax+FIBER_CONTEXT_DR6]
 
@@ -109,13 +114,13 @@ NoFpuStateSave:
 StatusWordChanged:
 
     /* Load the new one */
-    mov word ptr [ecx+FIBER_CONTEXT_FLOAT_SAVE_TAG_WORD], HEX(0FFFF)
+    mov word ptr [ecx+FIBER_CONTEXT_FLOAT_SAVE_TAG_WORD], HEX(FFFF)
     fldenv [ecx+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD]
 
 ControlWordEqual:
 
     /* Load the new one */
-    cmp byte ptr ds:[PF_XMMI_INSTRUCTIONS_AVAILABLE], 1
+    cmp byte ptr ds:[USER_SHARED_DATA + USER_SHARED_DATA_PROCESSOR_FEATURES + PF_XMMI_INSTRUCTIONS_AVAILABLE], 1
     jnz NoFpuStateRestore
     ldmxcsr [ecx+FIBER_CONTEXT_DR6]
 
@@ -136,6 +141,7 @@ NoFpuStateRestore:
     mov esp, [ecx+FIBER_CONTEXT_ESP]
     ret 4
 
+ENDFUNC
 
 END
 /* EOF */
index 8b39f5d..8a0eb64 100644 (file)
@@ -548,7 +548,7 @@ BaseInitializeContext(IN PCONTEXT Context,
 
         /* Is FPU state required? */
         Context->ContextFlags |= ContextFlags;
-        if (ContextFlags == CONTEXT_FLOATING_POINT)
+        if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
         {
             /* Set an initial state */
             Context->FloatSave.ControlWord = 0x27F;
index 609eaf4..3582aed 100644 (file)
@@ -724,17 +724,20 @@ OFFSET(KPROCESS_IOPM_OFFSET, KPROCESS, IopmOffset),
 
 HEADER("TEB"),
 OFFSET(TEB_EXCEPTION_LIST, TEB, NtTib.ExceptionList),
-OFFSET(TEB_STACK_LIMIT, TEB, NtTib.StackLimit),
 OFFSET(TEB_STACK_BASE, TEB, NtTib.StackBase),
-OFFSET(TEB_SELF, TEB, NtTib.Self),
+OFFSET(TEB_STACK_LIMIT, TEB, NtTib.StackLimit),
 OFFSET(TEB_FIBER_DATA, TEB, NtTib.FiberData),
+OFFSET(TEB_SELF, TEB, NtTib.Self),
 OFFSET(TEB_PEB, TEB, ProcessEnvironmentBlock),
 OFFSET(TEB_EXCEPTION_CODE, TEB, ExceptionCode),
-OFFSET(PEB_KERNEL_CALLBACK_TABLE, PEB, KernelCallbackTable),
-OFFSET(TEB_FLS_DATA, TEB, FlsData),
 OFFSET(TEB_ACTIVATION_CONTEXT_STACK_POINTER, TEB, ActivationContextStackPointer),
-OFFSET(TEB_GUARANTEED_STACK_BYTES, TEB, GuaranteedStackBytes),
 OFFSET(TEB_DEALLOCATION_STACK, TEB, DeallocationStack),
+OFFSET(TEB_GDI_BATCH_COUNT, TEB, GdiBatchCount),
+OFFSET(TEB_GUARANTEED_STACK_BYTES, TEB, GuaranteedStackBytes),
+OFFSET(TEB_FLS_DATA, TEB, FlsData),
+
+HEADER("PEB"),
+OFFSET(PEB_KERNEL_CALLBACK_TABLE, PEB, KernelCallbackTable),
 
 HEADER("Misc"),
 CONSTANT(NPX_FRAME_LENGTH),
@@ -754,4 +757,6 @@ CONSTANT(STATUS_CALLBACK_POP_STACK),
 CONSTANT(CONTEXT_ALIGNED_SIZE),
 CONSTANT(PROCESSOR_FEATURE_FXSR),
 CONSTANT(KUSER_SHARED_SYSCALL_RET),
+CONSTANT(USER_SHARED_DATA),
+CONSTANT(USER_SHARED_DATA_PROCESSOR_FEATURES),
 
index 72d2b23..4c5318e 100644 (file)
@@ -315,13 +315,14 @@ Author:
 #define FRAME_EDITED                            0xFFF8
 
 //
-// KUSER_SHARED_DATA Offsets
+// USER_SHARED_DATA Offsets
 //
 #ifdef __ASM__
 #define USER_SHARED_DATA                        0xFFDF0000
 #endif
 #define USER_SHARED_DATA_INTERRUPT_TIME         0x8
 #define USER_SHARED_DATA_SYSTEM_TIME            0x14
+#define USER_SHARED_DATA_PROCESSOR_FEATURES     0x274
 #define USER_SHARED_DATA_TICK_COUNT             0x320
 
 //