Use Callout table instead of direct GetProcAddress.
UserYield moved to USER.

diff --git a/loader/task.c b/loader/task.c
index c0acb3c..b0aba02 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -604,20 +604,13 @@
         USER_ExitWindows();
     }
 
-    if (!__winelib)
-    {
     /* FIXME: Hack! Send a message to the initial task so that
      * the GetMessage wakes up and the initial task can check whether
      * it is the only remaining one and terminate itself ...
      * The initial task should probably install hooks or something
      * to get informed about task termination :-/
      */
-        HTASK16 hTask = PROCESS_Initial()->task;
-        HMODULE16 hModule = GetModuleHandle16( "USER" );
-        FARPROC16 postFunc = WIN32_GetProcAddress16( hModule, "PostAppMessage" );
-        if (postFunc) 
-            Callbacks->CallPostAppMessageProc( postFunc, hTask, WM_NULL, 0, 0 );
-    }
+    Callout.PostAppMessage16( PROCESS_Initial()->task, WM_NULL, 0, 0 );
 
     /* Remove the task from the list to be sure we never switch back to it */
     TASK_UnlinkTask( hCurrentTask );
@@ -1043,33 +1036,6 @@
     TRACE(task, "%04x: back from DirectedYield(%04x)\n", pCurTask->hSelf, hTask );
 }
 
-
-/***********************************************************************
- *           UserYield  (USER.332)
- */
-void WINAPI UserYield(void)
-{
-    TDB *pCurTask = (TDB *)GlobalLock16( GetCurrentTask() );
-    MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( pCurTask->hQueue );
-
-    if ( !THREAD_IsWin16( THREAD_Current() ) )
-    {
-        FIXME(task, "called for Win32 thread (%04x)!\n", THREAD_Current()->teb_sel);
-        return;
-    }
-
-    /* Handle sent messages */
-    while (queue && (queue->wakeBits & QS_SENDMESSAGE))
-        QUEUE_ReceiveMessage( queue );
-
-    OldYield();
-
-    queue = (MESSAGEQUEUE *)GlobalLock16( pCurTask->hQueue );
-    while (queue && (queue->wakeBits & QS_SENDMESSAGE))
-        QUEUE_ReceiveMessage( queue );
-}
-
-
 /***********************************************************************
  *           Yield16  (KERNEL.29)
  */
@@ -1084,7 +1050,7 @@
     }
 
     if (pCurTask) pCurTask->hYieldTo = 0;
-    if (pCurTask && pCurTask->hQueue) UserYield();
+    if (pCurTask && pCurTask->hQueue) Callout.UserYield();
     else OldYield();
 }
 
@@ -1260,7 +1226,7 @@
  */
 HQUEUE16 WINAPI SetThreadQueue( DWORD thread, HQUEUE16 hQueue )
 {
-    THDB *thdb = THREAD_IdToTHDB( thread );
+    THDB *thdb = thread? THREAD_IdToTHDB( thread ) : THREAD_Current();
     HQUEUE16 oldQueue = thdb? thdb->teb.queue : 0;
 
     if ( thdb )
@@ -1279,7 +1245,7 @@
  */
 HQUEUE16 WINAPI GetThreadQueue( DWORD thread )
 {
-    THDB *thdb = THREAD_IdToTHDB( thread );
+    THDB *thdb = thread? THREAD_IdToTHDB( thread ) : THREAD_Current();
     return (HQUEUE16)(thdb? thdb->teb.queue : 0);
 }
 
@@ -1288,7 +1254,7 @@
  */
 VOID WINAPI SetFastQueue( DWORD thread, HANDLE32 hQueue )
 {
-    THDB *thdb = THREAD_IdToTHDB( thread );
+    THDB *thdb = thread? THREAD_IdToTHDB( thread ) : THREAD_Current();
     if ( thdb ) thdb->teb.queue = (HQUEUE16) hQueue;
 }
 
@@ -1300,14 +1266,10 @@
     THDB *thdb = THREAD_Current();
     if (!thdb) return 0;
 
-    if (!(thdb->teb.queue))
-    {
-        HMODULE16 hModule = GetModuleHandle16( "USER" );
-        FARPROC16 proc = WIN32_GetProcAddress16( hModule, "InitThreadInput" );
-        Callbacks->CallBootAppProc( proc, 0, THREAD_IsWin16(thdb)? 4 : 5 );  /* FIXME! */
-    }
+    if (!thdb->teb.queue)
+        Callout.InitThreadInput( 0, THREAD_IsWin16(thdb)? 4 : 5 );
 
-    if (!(thdb->teb.queue))
+    if (!thdb->teb.queue)
         FIXME( task, "(): should initialize thread-local queue, expect failure!\n" );
 
     return (HANDLE32)thdb->teb.queue;
diff --git a/miscemu/main.c b/miscemu/main.c
index 3e216d0..c9a2375 100644
--- a/miscemu/main.c
+++ b/miscemu/main.c
@@ -41,30 +41,26 @@
     return TRUE;
 }
 
-typedef BOOL32 (*WINAPI tGetMessage)(MSG32* lpmsg,HWND32 hwnd,UINT32 min,UINT32 max);
-typedef BOOL32 (*WINAPI tTranslateMessage)(const MSG32* msg);
-typedef LONG   (*WINAPI tDispatchMessage)( const MSG32* msg );
 
 /***********************************************************************
  *           Main loop of initial task
  */
 void MAIN_EmulatorRun( void )
 {
+    extern void THUNK_InitCallout( void );
     char startProg[256], defProg[256];
     HINSTANCE32 handle;
     int i;
-
-    tGetMessage		pGetMessage;
-    tTranslateMessage	pTranslateMessage;
-    tDispatchMessage	pDispatchMessage;
-    HMODULE32		hModule;
-    MSG32		msg;
+    MSG32 msg;
 
     /* Load system DLLs into the initial process (and initialize them) */
     if (   !LoadLibrary16("GDI.EXE" ) || !LoadLibrary32A("GDI32.DLL" )
         || !LoadLibrary16("USER.EXE") || !LoadLibrary32A("USER32.DLL"))
         ExitProcess( 1 );
 
+    /* Get pointers to USER routines called by KERNEL */
+    THUNK_InitCallout();
+
     /* Add the Default Program if no program on the command line */
     if (!MAIN_argv[1])
     {
@@ -107,19 +103,10 @@
 
     /* Start message loop for desktop window */
 
-    hModule = GetModuleHandle32A( "USER32" );
-    pGetMessage       = (tGetMessage)GetProcAddress32( hModule, "GetMessageA" ); 
-    pTranslateMessage = (tTranslateMessage)GetProcAddress32( hModule, "TranslateMessage" ); 
-    pDispatchMessage  = (tDispatchMessage)GetProcAddress32( hModule, "DispatchMessageA" ); 
-
-    assert( pGetMessage );
-    assert( pTranslateMessage );
-    assert( pDispatchMessage );
-
-    while ( GetNumTasks() > 1 && pGetMessage( &msg, 0, 0, 0 ) )
+    while ( GetNumTasks() > 1 && Callout.GetMessage32A( &msg, 0, 0, 0 ) )
     {
-        pTranslateMessage( &msg );
-        pDispatchMessage( &msg );
+        Callout.TranslateMessage32( &msg );
+        Callout.DispatchMessage32A( &msg );
     }
 
     ExitProcess( 0 );