Piotr Caban : msvcrt: Add ExternalContextBase class stub.

Alexandre Julliard julliard at winehq.org
Thu Mar 23 15:34:54 CDT 2017


Module: wine
Branch: master
Commit: 3dff8b8213e2f37992aedd2bafa69c1a68707fe8
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=3dff8b8213e2f37992aedd2bafa69c1a68707fe8

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Thu Mar 23 11:41:05 2017 +0100

msvcrt: Add ExternalContextBase class stub.

Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/msvcrt/cppexcept.h |   2 +-
 dlls/msvcrt/cxx.h       |  15 ++++
 dlls/msvcrt/main.c      |  10 +++
 dlls/msvcrt/msvcrt.h    |   6 ++
 dlls/msvcrt/scheduler.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 213 insertions(+), 7 deletions(-)

diff --git a/dlls/msvcrt/cppexcept.h b/dlls/msvcrt/cppexcept.h
index 16a6e16..6ea5818 100644
--- a/dlls/msvcrt/cppexcept.h
+++ b/dlls/msvcrt/cppexcept.h
@@ -33,7 +33,7 @@ typedef struct __type_info
 {
   const vtable_ptr *vtable;
   char              *name;        /* Unmangled name, allocated lazily */
-  char               mangled[32]; /* Variable length, but we declare it large enough for static RTTI */
+  char               mangled[64]; /* Variable length, but we declare it large enough for static RTTI */
 } type_info;
 
 /* exception object */
diff --git a/dlls/msvcrt/cxx.h b/dlls/msvcrt/cxx.h
index 8f31f24..baf519f 100644
--- a/dlls/msvcrt/cxx.h
+++ b/dlls/msvcrt/cxx.h
@@ -259,3 +259,18 @@ typedef struct
 } rtti_object_locator;
 
 #endif
+
+#ifdef __i386__
+
+#define CALL_VTBL_FUNC(this, off, ret, type, args) ((ret (WINAPI*)type)&vtbl_wrapper_##off)args
+
+extern void *vtbl_wrapper_0;
+extern void *vtbl_wrapper_4;
+extern void *vtbl_wrapper_8;
+extern void *vtbl_wrapper_20;
+
+#else
+
+#define CALL_VTBL_FUNC(this, off, ret, type, args) ((ret (__cdecl***)type)this)[0][off/4]args
+
+#endif
diff --git a/dlls/msvcrt/main.c b/dlls/msvcrt/main.c
index a930a32..0be8dd3 100644
--- a/dlls/msvcrt/main.c
+++ b/dlls/msvcrt/main.c
@@ -115,6 +115,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
     msvcrt_init_console();
     msvcrt_init_args();
     msvcrt_init_signals();
+#if _MSVCR_VER >= 100 && _MSVCR_VER <= 120
+    msvcrt_init_scheduler(hinstDLL);
+#endif
 #if _MSVCR_VER == 0
     /* don't allow unloading msvcrt, we can't setup file handles twice */
     LdrAddRefDll( LDR_ADDREF_DLL_PIN, hinstDLL );
@@ -137,11 +140,18 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
     if (!msvcrt_free_tls())
       return FALSE;
     MSVCRT__free_locale(MSVCRT_locale);
+#if _MSVCR_VER >= 100 && _MSVCR_VER <= 120
+    msvcrt_free_scheduler_thread();
+    msvcrt_free_scheduler();
+#endif
     msvcrt_destroy_heap();
     TRACE("finished process free\n");
     break;
   case DLL_THREAD_DETACH:
     msvcrt_free_tls_mem();
+#if _MSVCR_VER >= 100 && _MSVCR_VER <= 120
+    msvcrt_free_scheduler_thread();
+#endif
     TRACE("finished thread free\n");
     break;
   }
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index cee8113..659a3dc 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -329,6 +329,12 @@ extern void msvcrt_free_popen_data(void) DECLSPEC_HIDDEN;
 extern BOOL msvcrt_init_heap(void) DECLSPEC_HIDDEN;
 extern void msvcrt_destroy_heap(void) DECLSPEC_HIDDEN;
 
+#if _MSVCR_VER >= 100
+extern void msvcrt_init_scheduler(void*) DECLSPEC_HIDDEN;
+extern void msvcrt_free_scheduler(void) DECLSPEC_HIDDEN;
+extern void msvcrt_free_scheduler_thread(void) DECLSPEC_HIDDEN;
+#endif
+
 extern unsigned msvcrt_create_io_inherit_block(WORD*, BYTE**) DECLSPEC_HIDDEN;
 
 extern unsigned int __cdecl _control87(unsigned int, unsigned int);
diff --git a/dlls/msvcrt/scheduler.c b/dlls/msvcrt/scheduler.c
index 4c64859..257637e 100644
--- a/dlls/msvcrt/scheduler.c
+++ b/dlls/msvcrt/scheduler.c
@@ -18,6 +18,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "config.h"
+
 #include <stdarg.h>
 
 #include "windef.h"
@@ -31,23 +33,89 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
 
+#ifdef __i386__
+
+#define DEFINE_VTBL_WRAPPER(off)            \
+    __ASM_GLOBAL_FUNC(vtbl_wrapper_ ## off, \
+        "popl %eax\n\t"                     \
+        "popl %ecx\n\t"                     \
+        "pushl %eax\n\t"                    \
+        "movl 0(%ecx), %eax\n\t"            \
+        "jmp *" #off "(%eax)\n\t")
+
+DEFINE_VTBL_WRAPPER(0);
+DEFINE_VTBL_WRAPPER(4);
+DEFINE_VTBL_WRAPPER(8);
+DEFINE_VTBL_WRAPPER(20);
+
+#endif
+
 typedef struct {
     const vtable_ptr *vtable;
 } Context;
+#define call_Context_GetId(this) CALL_VTBL_FUNC(this, 0, \
+        unsigned int, (const Context*), (this))
+#define call_Context_GetVirtualProcessorId(this) CALL_VTBL_FUNC(this, 4, \
+        unsigned int, (const Context*), (this))
+#define call_Context_GetScheduleGroupId(this) CALL_VTBL_FUNC(this, 8, \
+        unsigned int, (const Context*), (this))
+#define call_Context_dtor(this, flags) CALL_VTBL_FUNC(this, 20, \
+        Context*, (Context*, unsigned int), (this, flags))
+
+typedef struct {
+    Context context;
+} ExternalContextBase;
+extern const vtable_ptr MSVCRT_ExternalContextBase_vtable;
+static void ExternalContextBase_ctor(ExternalContextBase*);
+
+static int context_tls_index = TLS_OUT_OF_INDEXES;
+
+static Context* try_get_current_context(void)
+{
+    if (context_tls_index == TLS_OUT_OF_INDEXES)
+        return NULL;
+    return TlsGetValue(context_tls_index);
+}
+
+static Context* get_current_context(void)
+{
+    Context *ret;
+
+    if (context_tls_index == TLS_OUT_OF_INDEXES) {
+        int tls_index = TlsAlloc();
+        if (tls_index == TLS_OUT_OF_INDEXES) {
+            /* throw scheduler_resource_allocation_error */
+            return NULL;
+        }
+
+        if(InterlockedCompareExchange(&context_tls_index, tls_index, TLS_OUT_OF_INDEXES) != TLS_OUT_OF_INDEXES)
+            TlsFree(tls_index);
+    }
+
+    ret = TlsGetValue(context_tls_index);
+    if (!ret) {
+        ExternalContextBase *context = MSVCRT_operator_new(sizeof(ExternalContextBase));
+        ExternalContextBase_ctor(context);
+        TlsSetValue(context_tls_index, context);
+        ret = &context->context;
+    }
+    return ret;
+}
 
 /* ?CurrentContext at Context@Concurrency@@SAPAV12 at XZ */
 /* ?CurrentContext at Context@Concurrency@@SAPEAV12 at XZ */
 Context* __cdecl Context_CurrentContext(void)
 {
-    FIXME("()\n");
-    return NULL;
+    TRACE("()\n");
+    return get_current_context();
 }
 
 /* ?Id at Context@Concurrency@@SAIXZ */
 unsigned int __cdecl Context_Id(void)
 {
-    FIXME("()\n");
-    return -1;
+    Context *ctx = try_get_current_context();
+    TRACE("()\n");
+    return ctx ? call_Context_GetId(ctx) : -1;
 }
 
 /* ?Block at Context@Concurrency@@SAXXZ */
@@ -84,15 +152,122 @@ void __cdecl Context_Oversubscribe(MSVCRT_bool begin)
 /* ?ScheduleGroupId at Context@Concurrency@@SAIXZ */
 unsigned int __cdecl Context_ScheduleGroupId(void)
 {
-    FIXME("()\n");
-    return -1;
+    Context *ctx = try_get_current_context();
+    TRACE("()\n");
+    return ctx ? call_Context_GetScheduleGroupId(ctx) : -1;
 }
 
 /* ?VirtualProcessorId at Context@Concurrency@@SAIXZ */
 unsigned int __cdecl Context_VirtualProcessorId(void)
 {
+    Context *ctx = try_get_current_context();
     FIXME("()\n");
+    return ctx ? call_Context_GetVirtualProcessorId(ctx) : -1;
+}
+
+DEFINE_THISCALL_WRAPPER(ExternalContextBase_GetId, 4)
+unsigned int __thiscall ExternalContextBase_GetId(const ExternalContextBase *this)
+{
+    FIXME("(%p)->() stub\n", this);
+    return -1;
+}
+
+DEFINE_THISCALL_WRAPPER(ExternalContextBase_GetVirtualProcessorId, 4)
+unsigned int __thiscall ExternalContextBase_GetVirtualProcessorId(const ExternalContextBase *this)
+{
+    FIXME("(%p)->() stub\n", this);
     return -1;
 }
 
+DEFINE_THISCALL_WRAPPER(ExternalContextBase_GetScheduleGroupId, 4)
+unsigned int __thiscall ExternalContextBase_GetScheduleGroupId(const ExternalContextBase *this)
+{
+    FIXME("(%p)->() stub\n", this);
+    return -1;
+}
+
+DEFINE_THISCALL_WRAPPER(ExternalContextBase_Unblock, 4)
+void __thiscall ExternalContextBase_Unblock(ExternalContextBase *this)
+{
+    FIXME("(%p)->() stub\n", this);
+}
+
+DEFINE_THISCALL_WRAPPER(ExternalContextBase_IsSynchronouslyBlocked, 4)
+MSVCRT_bool __thiscall ExternalContextBase_IsSynchronouslyBlocked(const ExternalContextBase *this)
+{
+    FIXME("(%p)->() stub\n", this);
+    return FALSE;
+}
+
+static void ExternalContextBase_dtor(ExternalContextBase *this)
+{
+}
+
+DEFINE_THISCALL_WRAPPER(ExternalContextBase_vector_dtor, 8)
+Context* __thiscall ExternalContextBase_vector_dtor(ExternalContextBase *this, unsigned int flags)
+{
+    TRACE("(%p %x)\n", this, flags);
+    if(flags & 2) {
+        /* we have an array, with the number of elements stored before the first object */
+        INT_PTR i, *ptr = (INT_PTR *)this-1;
+
+        for(i=*ptr-1; i>=0; i--)
+            ExternalContextBase_dtor(this+i);
+        MSVCRT_operator_delete(ptr);
+    } else {
+        ExternalContextBase_dtor(this);
+        if(flags & 1)
+            MSVCRT_operator_delete(this);
+    }
+
+    return &this->context;
+}
+
+static void ExternalContextBase_ctor(ExternalContextBase *this)
+{
+    this->context.vtable = &MSVCRT_ExternalContextBase_vtable;
+}
+
+extern const vtable_ptr MSVCRT_type_info_vtable;
+DEFINE_RTTI_DATA0(Context, 0, ".?AVContext at Concurrency@@")
+DEFINE_RTTI_DATA1(ContextBase, 0, &Context_rtti_base_descriptor, ".?AVContextBase at details@Concurrency@@")
+DEFINE_RTTI_DATA2(ExternalContextBase, 0, &ContextBase_rtti_base_descriptor,
+        &Context_rtti_base_descriptor, ".?AVExternalContextBase at details@Concurrency@@")
+
+#ifndef __GNUC__
+void __asm_dummy_vtables(void) {
+#endif
+    __ASM_VTABLE(ExternalContextBase,
+            VTABLE_ADD_FUNC(ExternalContextBase_GetId)
+            VTABLE_ADD_FUNC(ExternalContextBase_GetVirtualProcessorId)
+            VTABLE_ADD_FUNC(ExternalContextBase_GetScheduleGroupId)
+            VTABLE_ADD_FUNC(ExternalContextBase_Unblock)
+            VTABLE_ADD_FUNC(ExternalContextBase_IsSynchronouslyBlocked)
+            VTABLE_ADD_FUNC(ExternalContextBase_vector_dtor));
+#ifndef __GNUC__
+}
+#endif
+
+void msvcrt_init_scheduler(void *base)
+{
+#ifdef __x86_64__
+    init_Context_rtti(base);
+    init_ContextBase_rtti(base);
+    init_ExternalContextBase_rtti(base);
+#endif
+}
+
+void msvcrt_free_scheduler(void)
+{
+    if (context_tls_index != TLS_OUT_OF_INDEXES)
+        TlsFree(context_tls_index);
+}
+
+void msvcrt_free_scheduler_thread(void)
+{
+    Context *context = try_get_current_context();
+    if (!context) return;
+    call_Context_dtor(context, 1);
+}
+
 #endif /* _MSVCR_VER >= 100 */




More information about the wine-cvs mailing list