Thread overview
(WinAPI) FindWindowW always fails
Oct 08, 2020
Deen O'Connor
Oct 08, 2020
Dennis
Oct 08, 2020
Deen O'Connor
Oct 08, 2020
Bastiaan Veelo
October 08, 2020
I was coding my project, and at some point it required to get widow rectangle. GetWindowRect function returned ERROR_INVALID_WINDOW_HANDLE (0x578) error. This is where i detected the error. I then checked what the return value of FindWindowW was, and it was 0. GetLastError showed that there was ERROR_NOT_ALL_ASSIGNED (0x514) error.

So, to re-create the error, i did the following:
1 - Opened an app that has a window. In my case this was x32dbg, i chose it because it has a short window name without any spaces.
2 - Wrote a small program to check if the error will happen again:
import std.stdio;
import std.conv;
import core.sys.windows.windows;

void main(string[] args) {
    wstring wndName = "x32dbg";
    HWND hWnd = FindWindowW(null, cast(wchar*)&wndName);
    if (hWnd is null) {
        writeln("Error 0x" ~ to!string(GetLastError(), 16) ~ " in FindWindowW()!");
    } else {
        writeln("x32dbg window: 0x" ~ to!string(cast(uint)hWnd, 16));
    }
}
3 - Ran this code with rdmd

Output said that there was an error.
This also happened with every window i tried to find no matter what. FindWindowA also failed.

The only reason i'm writing this is because i can find the window with x32dbg and a very similar C++ code works fine.
So, am i doing something wrong, or is this a bug?
October 08, 2020
On Thursday, 8 October 2020 at 19:39:05 UTC, Deen O'Connor wrote:
>     wstring wndName = "x32dbg";
>     HWND hWnd = FindWindowW(null, cast(wchar*)&wndName);

Dont take the address of the `wstring`, use `wndName.ptr` instead.

wstring is internally a fat pointer that looks like this:

struct wstring {
    size_t length;
    immutable(wchar)* ptr;
}

When taking the address `&wndName`, you get a pointer to this struct on the stack, not the actual string literal.
October 08, 2020
On Thursday, 8 October 2020 at 19:39:05 UTC, Deen O'Connor wrote:
> I was coding my project, and at some point it required to get widow rectangle. GetWindowRect function returned ERROR_INVALID_WINDOW_HANDLE (0x578) error. This is where i detected the error. I then checked what the return value of FindWindowW was, and it was 0. GetLastError showed that there was ERROR_NOT_ALL_ASSIGNED (0x514) error.
>
> So, to re-create the error, i did the following:
> 1 - Opened an app that has a window. In my case this was x32dbg, i chose it because it has a short window name without any spaces.
> 2 - Wrote a small program to check if the error will happen again:
> import std.stdio;
> import std.conv;
> import core.sys.windows.windows;
>
> void main(string[] args) {
>     wstring wndName = "x32dbg";
>     HWND hWnd = FindWindowW(null, cast(wchar*)&wndName);
>     if (hWnd is null) {
>         writeln("Error 0x" ~ to!string(GetLastError(), 16) ~ " in FindWindowW()!");
>     } else {
>         writeln("x32dbg window: 0x" ~ to!string(cast(uint)hWnd, 16));
>     }
> }
> 3 - Ran this code with rdmd
>
> Output said that there was an error.
> This also happened with every window i tried to find no matter what. FindWindowA also failed.
>
> The only reason i'm writing this is because i can find the window with x32dbg and a very similar C++ code works fine.
> So, am i doing something wrong, or is this a bug?

I using like this:

                HWND hwnd = FindWindow( "Window", "Panel" );

                if ( hwnd )
                {
                    PostMessage( hwnd, APP_MAIN_MENU, 0, 0 );
                }

>     wstring wndName = "x32dbg";
>     HWND hWnd = FindWindowW(null, cast(wchar*)&wndName);

I think some like this...

LPCWSTR toLPCWSTR( string s ) nothrow // const wchar_t*
{
    import std.utf : toUTFz, toUTF16z, UTFException;
    try                        { return toUTF16z( s ); }
    catch ( UTFException e )   { return "ERR"w.ptr; }
    catch ( Exception e )      { return "ERR"w.ptr; }
}
alias toLPCWSTR toPCWSTR;

wstring wndName = "x32dbg";
HWND hWnd = FindWindowW( null, wndName.toLPCWSTR );


October 08, 2020
On Thursday, 8 October 2020 at 19:49:04 UTC, Dennis wrote:
> Dont take the address of the `wstring`, use `wndName.ptr` instead.

It worked, thanks a lot!

October 08, 2020
On Thursday, 8 October 2020 at 19:39:05 UTC, Deen O'Connor wrote:
>     HWND hWnd = FindWindowW(null, cast(wchar*)&wndName);
...
> So, am i doing something wrong, or is this a bug?

You are taking the address of a slice and pass it as if it were a C string. You can use toUtf16z for a conversion, but do note the limitations of toUtfz.

-Bastiaan

PS this is more a subject for the Learn forum.
October 08, 2020
On Thursday, 8 October 2020 at 19:39:05 UTC, Deen O'Connor wrote:
> ...
> import std.stdio;
> import std.conv;
> import core.sys.windows.windows;
>
> void main(string[] args) {
>     wstring wndName = "x32dbg";
>     HWND hWnd = FindWindowW(null, cast(wchar*)&wndName);
>     if (hWnd is null) {
>         writeln("Error 0x" ~ to!string(GetLastError(), 16) ~ " in FindWindowW()!");
>     } else {
>         writeln("x32dbg window: 0x" ~ to!string(cast(uint)hWnd, 16));
>     }
> }

and may be you find interesting this construction:
writefln( "x32dbg window: %X", hWnd );