core/win32/callback.c
/* early inject and user32 should reach this, drinject /
 * late inject should never get here, and make sure we have
 * dr_late_injected_primary_thread = true set for that. Assumption: we
 * assume that with our method of injection, the primary thread will
 * not be allowed to execute when the secondary thread is in control,
 * e.g. holds the loader lock.  Any other (tertiary) threads that have
 * reached their APC before us will be left running as 'unknown'.
 * We are also assuming that only the primary thread will
 * ever go through the EXE's image entry.
 */
early inject and user32 should reach this, drinject
late inject should never get here, and make sure we have
dr_late_injected_primary_thread = true set for that. Assumption: we
assume that with our method of injection, the primary thread will
not be allowed to execute when the secondary thread is in control,
e.g. holds the loader lock.  Any other (tertiary) threads that have
reached their APC before us will be left running as 'unknown'.
We are also assuming that only the primary thread will
ever go through the EXE's image entry.
early inject and user32 should reach this drinject late inject should never get here and make sure we have dr_late_injected_primary_thread = true set for that . Assumption : we assume that with our method of injection the primary thread will not be allowed to execute when the secondary thread is in control e . g . holds the loader lock . Any other ( tertiary ) threads that have reached their APC before us will be left running as ' unknown ' . We are also assuming that only the primary thread will ever go through the EXE ' s image entry .
void
take_over_primary_thread(void)
{
    app_pc win32_start_addr = 0;
    NTSTATUS res = query_win32_start_addr(NT_CURRENT_THREAD, &win32_start_addr);
    ASSERT_CURIOSITY(NT_SUCCESS(res) && "failed to obtain win32 start address");
    if (!NT_SUCCESS(res)) {
        win32_start_addr = NULL;
    }
    if ((ptr_uint_t)win32_start_addr < 0x10000 && 
        win32_start_addr != NULL) {
        ASSERT_NOT_TESTED();
        win32_start_addr = NULL;
    }
    ASSERT_CURIOSITY(win32_start_addr != NULL);
    if (win32_start_addr != NULL &&
        win32_start_addr != get_image_entry()) {
        dcontext_t *secondary_dcontext = get_thread_private_dcontext();
        SYSLOG_INTERNAL_WARNING("took over non-primary thread!\n");
        dr_injected_primary_thread = false;
        dr_late_injected_primary_thread = false;
        dr_injected_secondary_thread = true;
        insert_image_entry_trampoline(secondary_dcontext);
    } else {
        dr_injected_primary_thread = true;
    }
}
void take_over_primary_thread ( void ) { app_pc win32_start_addr = 0 ; NTSTATUS res = query_win32_start_addr ( NT_CURRENT_THREAD , & win32_start_addr ) ; ASSERT_CURIOSITY ( NT_SUCCESS ( res ) && " " ) ; if ( ! NT_SUCCESS ( res ) ) { win32_start_addr = NULL ; } if ( ( ptr_uint_t ) win32_start_addr < 0x10000 && win32_start_addr != NULL ) { ASSERT_NOT_TESTED ( ) ; win32_start_addr = NULL ; } ASSERT_CURIOSITY ( win32_start_addr != NULL ) ; if ( win32_start_addr != NULL && win32_start_addr != get_image_entry ( ) ) { dcontext_t * secondary_dcontext = get_thread_private_dcontext ( ) ; SYSLOG_INTERNAL_WARNING ( " \n " ) ; dr_injected_primary_thread = false ; dr_late_injected_primary_thread = false ; dr_injected_secondary_thread = true ; insert_image_entry_trampoline ( secondary_dcontext ) ; } else { dr_injected_primary_thread = true ; } }
early inject and user32 should reach this, drinject
 late inject should never get here, and make sure we have
 dr_late_injected_primary_thread = true set for that.
early inject and user32 should reach this drinject late inject should never get here and make sure we have dr_late_injected_primary_thread = true set for that .
/* note that if we have initialized this thread we already have the value,
     * but making this more generic in case we move it, 
     */ /* assume it was primary if we can't tell */ /* can't be on NULL page */ /* the value is not reliable if the thread has run and there
         * was a ReplyWaitRecievePort - this would no longer be the
         * correct start address.  We're making an assumption that if
         * that is the case then possibly via user32.dll injection
         * some other DLL that got to run before us may have done this.
         */ /* unfortunately the value is also not reliable if Native threads
     * are used as well, and winlogon.exe's parent smss.exe is
     * creating processes directly.  FIXME: pstat however is able to
     * show the value
     */ /* FIXME: could exempt winlogon.exe by name instead */ /* FIXME: while we should be able to always intercept the image
     * entry point, regardless of which threads we really control, we
     * don't need to risk these extra moving parts unless we are
     * certain we are in a secondary thread
     */ /* these will be set to to true only when we reach the image entry */ /* flags the reason for taking over late for use by
         * insert_image_entry_trampoline() 
         */ /* Although we don't really control_all_threads we'll leave it
         * set, and we're hoping that we'll soon take over the primary
         * thread since it really has nothing interesting to do before
         * reaching the image entry point, so it is ok to let it execute
         * as unknown thread for a little bit.  (We will still have to
         * furnish it with a dcontext and stack when we take over.)
         */ /* potentially racy hook (injected threads) */ /* we are in the primary thread */