[ros-diffs] [dchapyshev] 42122: - Revert my previous changes in QueueUserWorkItem

dchapyshev at svn.reactos.org dchapyshev at svn.reactos.org
Tue Jul 21 18:38:50 CEST 2009


Author: dchapyshev
Date: Tue Jul 21 18:38:50 2009
New Revision: 42122

URL: http://svn.reactos.org/svn/reactos?rev=42122&view=rev
Log:
- Revert my previous changes in QueueUserWorkItem

Modified:
    trunk/reactos/dll/win32/kernel32/thread/thread.c

Modified: trunk/reactos/dll/win32/kernel32/thread/thread.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/thread/thread.c?rev=42122&r1=42121&r2=42122&view=diff
==============================================================================
--- trunk/reactos/dll/win32/kernel32/thread/thread.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/thread/thread.c [iso-8859-1] Tue Jul 21 18:38:50 2009
@@ -854,6 +854,34 @@
 }
 
 
+typedef struct _QUEUE_USER_WORKITEM_CONTEXT
+{
+    LPTHREAD_START_ROUTINE Function;
+    PVOID Context;
+} QUEUE_USER_WORKITEM_CONTEXT, *PQUEUE_USER_WORKITEM_CONTEXT;
+
+static VOID
+NTAPI
+InternalWorkItemTrampoline(PVOID Context)
+{
+    QUEUE_USER_WORKITEM_CONTEXT Info;
+
+    ASSERT(Context);
+
+    /* Save the context to the stack */
+    Info = *(volatile QUEUE_USER_WORKITEM_CONTEXT *)Context;
+
+    /* Free the context before calling the callback. This avoids
+       a memory leak in case the thread dies... */
+    RtlFreeHeap(RtlGetProcessHeap(),
+                0,
+                Context);
+
+    /* Call the real callback */
+    Info.Function(Info.Context);
+}
+
+
 /*
  * @implemented
  */
@@ -865,13 +893,34 @@
     ULONG Flags
     )
 {
-    NTSTATUS Status;
-
-    Status = RtlQueueWorkItem((WORKERCALLBACKFUNC)Function,
-                              Context,
+    PQUEUE_USER_WORKITEM_CONTEXT WorkItemContext;
+    NTSTATUS Status;
+
+    /* Save the context for the trampoline function */
+    WorkItemContext = RtlAllocateHeap(RtlGetProcessHeap(),
+                                      0,
+                                      sizeof(*WorkItemContext));
+    if (WorkItemContext == NULL)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
+
+    WorkItemContext->Function = Function;
+    WorkItemContext->Context = Context;
+
+    /* NOTE: Don't use Function directly since the callback signature
+             differs. This might cause problems on certain platforms... */
+    Status = RtlQueueWorkItem(InternalWorkItemTrampoline,
+                              WorkItemContext,
                               Flags);
     if (!NT_SUCCESS(Status))
     {
+        /* Free the allocated context in case of failure */
+        RtlFreeHeap(RtlGetProcessHeap(),
+                    0,
+                    WorkItemContext);
+
         SetLastErrorByStatus(Status);
         return FALSE;
     }



More information about the Ros-diffs mailing list