-2

The main goal is to block maximalize web browser window using subclassing and dll.

I have 2 apps: injector and the dll.

In injector app I load that dll, find window by title, get functions from dll and execute that functions ( their names are hook and unhook ) from dll. So this is standard injector. Of course I check is something NULL and I don't get any errors.

In dll I have 5 functions:

dllMain (here I only set global hInstance variable, which is in shared memory ):

BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
    switch(fdwReason)
    {
        case DLL_PROCESS_ATTACH:
        {
            if (hInstance == NULL)
            {
                hInstance = hinstDLL;                   
            }
            break;
        }
        ...
    }
    return TRUE;
}

Hook ( HandleofTarget is the HWND, which I get from FindWindow ; I use this function in injector ):

extern "C" __declspec(dllexport) bool hook( HWND HandleofTarget)
{
    hTarget=HandleofTarget;
        
    hhook=SetWindowsHookEx(WH_CBT,cbtHookProc,hInstance, GetWindowThreadProcessId(hTarget,NULL));
    if(hhook==NULL)
        return 0;
    else
        return 1;
}

Unhook ( here I unhook hooks - I use this function in injector):

extern "C" __declspec(dllexport) void unhook(void)
{
    if(hhook != NULL)
       UnhookWindowsHookEx( hhook );
}

cbtHookProc ( hook callback, where I change window procedure ):

LRESULT CALLBACK cbtHookProc( int code, WPARAM wParam, LPARAM lParam )
{
    if( code < 0 ) return CallNextHookEx( 0, code, wParam, lParam );
    
    if (code == HCBT_ACTIVATE)
    {
        if((HWND)(wParam)==hTarget)              
        {
            if(done == FALSE)
            {
                g_OldWndProc =(WNDPROC)(SetWindowLongPtr ( (HWND)(wParam), GWLP_WNDPROC,reinterpret_cast<LONG_PTR>(  NewWndProc )));
                done = TRUE;
            }
        }   
    }
    
    return CallNextHookEx( 0, code, wParam, lParam );
}

NewWndProc ( new Window procedure, where I would like to block maximalize ):

LRESULT CALLBACK NewWndProc( HWND hwnd, UINT mesg, WPARAM wParam, LPARAM lParam )
{
    switch( mesg )
    {
    case WM_SYSCOMMAND:
        {
            if(wParam == SC_MAXIMIZE)
            {
                return 1;
            }
        }
        break;
    }

     return CallWindowProc( g_OldWndProc, hwnd, mesg, wParam, lParam );
}

When I test this dll with other apps - it works. When I use this dll with web browser like Internet Edge and Google Chrome - it doesn't works. That web browser, which I try injected works slower, but I can still maximalize that window. When I debuq dll, in web browser after SetWindowsHookEx I see that hook is not NULL, but my code doesn't go to cbtHookProc. What is going on with web browser?

UPDATE:

One more time - thank you Strive Sun - MSFT for helping me. I change the lines in cbtHookProc, but it still doesn't work. My cbtHookProc is don't called by webBrowser - that is problem.

When I looked at your gif I see something what I don't have and I think that is the problem. My injector app looks like this:

    hDll = LoadLibrary( L"dllka10" );
    hHookedWindow=FindWindow(TEXT("Chrome_WidgetWin_1"),TEXT("Nowa karta - Google Chrome"));

    if( hDll && hHookedWindow)
    {
        qDebug()<<"hDll and hHookedWindow are not NULL!";
        funHook =( MYPROC2 ) GetProcAddress( hDll, (LPCSTR) "hook" );
        funUnhook = ( MYPROC ) GetProcAddress( hDll, (LPCSTR) "unhook" );
        if( funHook )
        {
            qDebug()<<funHook(hHookedWindow);
        }
    }

I don't use CreateThread(). Is it important here?

UPDATED 2

LRESULT CALLBACK cbtHookProc( int code, WPARAM wParam, LPARAM lParam )
{
    if( code < 0 ) return CallNextHookEx( 0, code, wParam, lParam );
    
    std::fstream file;
    file.open("C:\\Users\\tom\\Desktop\\logs.txt",std::ios::out|std::ios::app);
    file<<"In cbtHook function!"<<std::endl;
    file.close();
        
    if (code == HCBT_MINMAX)
    {
        if (LOWORD(lParam) == SW_SHOWMAXIMIZED)
        {
            return 1;
        }
        
    }

    return CallNextHookEx( 0, code, wParam, lParam );
}

When I run chrome application - my logs.txt is empty. When I run other app - I have logs.

UPDATED 3

In my dll I have:

#ifdef __GNUC__
HWND hTarget  __attribute__((section (".shared"), shared))   =NULL;
HWND hApp  __attribute__((section (".shared"), shared))        = NULL;
bool done   __attribute__((section (".shared"), shared))            =FALSE;
HINSTANCE hInstance    __attribute__((section (".shared"), shared))                 =NULL;
HHOOK hhook       __attribute__((section (".shared"), shared))          = NULL;
WNDPROC g_OldWndProc   __attribute__((section (".shared"), shared))                    = NULL;
#endif
#ifdef _MSC_VER
#pragma data_seg(".shared")
HWND hTarget=NULL;
HWND hApp = NULL;
bool done=FALSE;
HINSTANCE hInstance=NULL;
HHOOK hhook = NULL;
WNDPROC g_OldWndProc = NULL;
#pragma data_seg()
#pragma comment(linker, "/section:.shared,RWS")
#endif

in my injector I don't have any pragma - I have only ( QT ):

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <iostream>
#include "string.h"
#include "windows.h"
juga92
  • 117
  • 1
  • 7
  • Are you trying to re-invent [single-app kiosk](https://learn.microsoft.com/en-us/windows/configuration/kiosk-single-app) mode? – IInspectable Nov 23 '20 at 19:50
  • Thank you for answer. I would like to run my code in other windows ( for example 7 ) and I see that single-app kiosk is only for windows 10. Am I right? – juga92 Nov 24 '20 at 11:07
  • Kiosk mode has been available at least since Windows XP. So you can enable kiosk mode in Windows 7, it's just that it requires different procedures. Though I probably wouldn't want to expose a system to the general public that's no longer supported. – IInspectable Nov 24 '20 at 15:53

1 Answers1

0

I can't reproduce your problem, but you can try another easier method.

HCBT_MINMAX : Specifies, in the low-order word, a show-window value (SW_) specifying the operation. For a list of show-window values, see the ShowWindow. The high-order word is undefined.

  if (code == HCBT_MINMAX)
    {
        if (LOWORD(lParam) == SW_SHOWMAXIMIZED)
        {
            return 1;
        }
        
    }

No need to use HCBT_ACTIVATE to obtain window handles and compare their handles.

Updated:

Code works fine.

1

My code sample:

DLL:

// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include "stdio.h"
#include <windows.h>


HHOOK hCBT = NULL;
HWND hTarget;
HMODULE thisModule;


LRESULT CALLBACK _cbtProc(int code, WPARAM wParam, LPARAM lParam)
{ 
    if (code < 0) return CallNextHookEx(0, code, wParam, lParam);

    if (code == HCBT_MINMAX)
    {
        if (LOWORD(lParam) == SW_SHOWMAXIMIZED)
        {
            return 1;
        }
        
    }
    return CallNextHookEx(0, code, wParam, lParam);
}

#ifdef __cplusplus    //If used by C++ code.
extern "C" {        //we need to export the C interface
#endif
    __declspec(dllexport) BOOL WINAPI InstallHooks(HWND HandleofTarget)
    {
        hTarget = HandleofTarget;
        
        DWORD tid = GetWindowThreadProcessId(hTarget, NULL);
        hCBT = SetWindowsHookEx(WH_CBT, _cbtProc, thisModule, tid);

        return (hCBT) ? TRUE : FALSE;
    }
#ifdef __cplusplus
}
#endif

#ifdef __cplusplus    //If used by C++ code.
extern "C" {        //we need to export the C interface
#endif
    __declspec(dllexport) void WINAPI RemoveHooks()
    {   
         UnhookWindowsHookEx(hCBT);
         MessageBox(NULL, L"unhook", L" ", MB_OK);
         hCBT = NULL;
    }
#ifdef __cplusplus
}
#endif

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    thisModule = hModule;
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

main.cpp

#include <Windows.h>
#include <stdio.h>
#include <psapi.h>
#include <shlwapi.h>
#include <tchar.h>

#pragma comment(lib,"Kernel32.lib")
#pragma comment(lib,"shlwapi.lib")
#pragma comment(linker, "/SECTION:.shared,RWS")

using namespace std;
HINSTANCE hinstDLL;
typedef void (*RemoveHooks)();

DWORD __stdcall CreateThreadFunc(LPVOID)
{
    while (1)
    {
        if (GetAsyncKeyState(0x50) & 0x0001)
        {
            RemoveHooks removeHooks = (RemoveHooks)GetProcAddress(hinstDLL, "RemoveHooks");
            removeHooks();
        }
    }
    return 0;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    if (message == WM_DESTROY) {      
        PostQuitMessage(0);
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
};

int main()
{
    HWND hwnd = FindWindow(L"Chrome_WidgetWin_1", L"Google Translate - Google Chrome");
 
    CreateThread(NULL, 0, CreateThreadFunc, 0, 0, 0);

    hinstDLL = LoadLibrary(TEXT("D:\\Start from 11.2\\WM_CBT_DLL\\x64\\Debug\\WM_CBT_DLL.dll")); 
    BOOL(*InstallHooks)(HWND);
    InstallHooks = (BOOL(*)(HWND)) GetProcAddress(hinstDLL, "InstallHooks");
    
    BOOL l = InstallHooks(hwnd);

    int err = GetLastError();

    MSG msg = {};

    while (GetMessage(&msg, NULL, 0, 0)) {       
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}
Strive Sun
  • 5,988
  • 1
  • 9
  • 26
  • Thank you for answer. But you write about code in my cbtHookProc function ( or I understand something wrong ). I wrote that problem is that, when I try inject any web browser using dll, my code never go to cbtHookProc function ( before checked if( code < 0 ) I write to file to debuq ), so I can change HCBT_ACTIVATE to HCBT_MINMAX, but my code don't go to function, where that HCBT_MINMAX will be. – juga92 Nov 24 '20 at 11:00
  • @juga92 How do you debug cbtHookProc? You have injected the dll into the browser, the apis call in cbtHookProc will be the responsibility of the browser instead of the program you are currently debugging. – Strive Sun Nov 25 '20 at 02:56
  • @juga92 See my updated. I found that the `Target` value in `cbtHookProc` is always `0/NULL` during testing. So `NewWndProc` cannot be called. The reason is that I also explained before. The dll is called by the browser, so the `Target`value (hTarget=HandleofTarget //not NULL) in the dll of the current program will not be passed to `cbtHookProc`. You can add a MessageBox above if (code == HCBT_ACTIVATE) to see if the pop-up window will be triggered when the browser is activated. – Strive Sun Nov 25 '20 at 03:27
  • Thank you for helping me! But is still doesn't work. Please look at my updated. – juga92 Nov 25 '20 at 07:38
  • @juga92 `CreateThread` is used by me to monitor keystrokes, it is not important. Have you added `MessageBox` to test? – Strive Sun Nov 25 '20 at 07:45
  • @juga92 I added my code sample for your reference. Hope to help you. – Strive Sun Nov 25 '20 at 07:53
  • I have to study them! Very thankful and I added UPDATED 2. – juga92 Nov 25 '20 at 08:04
  • @juga92 The logs.txt on my computer is not empty. It can be judged that it is a chrome problem. Are you using an x64 browser? Try to uninstall and reinstall version 87.0.4280.66 (this is the version I tested) – Strive Sun Nov 25 '20 at 08:17
  • When I run taskmanager->details I see that chrome.exe is 64 bits. My google chrome web browser is in version 87.0.4280.66 ( so the same ). I have other idea - maybe something is wrong with shared memory? I see that in injector you have "/SECTION:.shared,RWS" and in dll you don't have any pragma data_seg. I added update 3 – juga92 Nov 25 '20 at 08:31
  • @juga92 The C++ code I used, and "/SECTION:.shared,RWS"(removed and retested) will not affect chrome . – Strive Sun Nov 25 '20 at 08:47
  • 1
    When I compile your dll and change function's names in my injector - it works :D So thank you very much! I can't give you +1, because I don't have 15 points, but someone In Poland very, very thank you! – juga92 Nov 25 '20 at 08:54
  • @juga92 Glad to help you. Please feel free to [accept](https://stackoverflow.com/help/someone-answers) the answer. – Strive Sun Nov 25 '20 at 08:55
  • The problem was... include iostream library in dll. I don't use any function from this library in my code ( no cin, no cout, nothing). When I delete this line with include-my dll start works properly. Strange situation. I have extra question to you: is it possible don't lose focus in web browser? I have page with js code: http://jsfiddle.net/ysu2vfqr/ When you click on the white rectangle it will be text "focused" and when you clicked outside it (desktop too) text will be "Blured".Is it possible to block this using winapi,subclassing and dll? So I would like to never lose active on web browser – juga92 Nov 25 '20 at 19:49
  • @juga92 [This](https://stackoverflow.com/questions/7430864/windows-7-prevent-application-from-losing-focus) seems to be what you need. – Strive Sun Nov 26 '20 at 02:26
  • @juga92 If this method does not work, you can post a new question to ask for more help. – Strive Sun Nov 26 '20 at 02:35
  • Hello im trying to compile this to use work with the latest version of chrome and its not working. I;ve read that since Google Chrome 72, Google has blocked all dll injections. Does this still work? – T Shoats May 30 '21 at 21:44
  • @TShoats Sorry, I am no longer engaged in this aspect of work. Maybe you can ask a new question for help. – Strive Sun May 31 '21 at 03:12