Search code examples
cwinapi64-bitsetfocus

C - win32: AttachThreadInput & SetFocus, 64bit: no clue


I've commented in most of what I know. I'm fairly confident the issue arises at AttachThreadInput. It was only designed to function under 32bit, I think. Believe me, if I could solve this myself, I would be happy to. I read the full documentation for events in Windows (here) and I'm no closer to a solution. If you have any ideas I would love to hear them.

#include <stdio.h>
#include <windows.h>

int main()
{
    //Structure prereqs for CreateProcess
    STARTUPINFO         siStartupInfo;
    PROCESS_INFORMATION piProcessInfo;
    memset(&siStartupInfo, 0, sizeof(siStartupInfo));
    memset(&piProcessInfo, 0, sizeof(piProcessInfo));
    siStartupInfo.cb = sizeof(siStartupInfo);

    if(CreateProcess("c:\\windows\\notepad.exe", "", 0, 0, FALSE, CREATE_DEFAULT_ERROR_MODE, 0, 0, &siStartupInfo, &piProcessInfo) == FALSE)
    {
        GetLastError();
    }
    Sleep(1000);

    //Target thread, I can't seem to get this to return anything !0
    DWORD dwTargetThread = GetWindowThreadProcessId(piProcessInfo.hProcess,NULL);
    //For example:
    //if(dwTargetThread == 0) return -1;

    //Print debugging info
    if (GetCurrentThreadId() == dwTargetThread) return -1; else printf("\nMy thread: %u\n\npiProcessInfo.hThread: %u\n\nDWORD dwTargetThread: %u\n\nunsigned int dwTargetThread: %u", GetCurrentThreadId(), piProcessInfo.hThread,dwTargetThread, GetWindowThreadProcessId(piProcessInfo.hProcess,NULL));

    //I've tried using piProcessInfo.hThread for AttachTo but I can't cast it to a DWORD as it's 64bit
    AttachThreadInput(GetCurrentThreadId(),dwTargetThread,TRUE);
    printf("\n\nAttached...\n");
    Sleep(1000);

    //Set the focus & bring to foreground
    SetFocus(piProcessInfo.hProcess);
    printf("Focus set...\n");
    Sleep(1000);
    SetForegroundWindow(piProcessInfo.hProcess);
    printf("Brought to foreground...\n");
    Sleep(1000);

    //I know I shouldn't use PostMessage for keyboard input but it's just for the example
    PostMessage(piProcessInfo.hProcess, WM_CHAR,  'g', 0);
    printf("Message queued\n");

    //No better than SetForegroundWindow:
    //SetWindowPos(piProcessInfo.hProcess, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}

Solution

  • GetWindowThreadProcessId receives as input a window handle. You are passing a process handle which is an altogether different beat. Naturally this results in failure. The subsequent calls to SetFocus, SetForegroundWindow, PostMessage and SetWindowPos commit the same mistake.

    Use EnumWindows or FindWindow to get hold of the Notepad window handle.

    AttachThreadInput operates with thread IDs. You tried to pass a handle to the function and in a 64 bit process handles are 64 bits wide and thread IDs are still 32 bits wide. Of course, AttachThreadInput works perfectly well under 64 bit. The lesson to learn here is that casts are indicative of programming errors. If you need to cast parameters to the appropriate type then usually that means that you are passing the wrong thing to the function. Avoid casting.