Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Mobile

Mobile Development: Subclass Foreign Window using injectDLL

4.11/5 (2 votes)
4 Nov 2015CPOL2 min read 5.1K  
Mobile Development: Subclass foreign Window using injectDLL

Recently, we needed to show and hide the SIP (Software Input Panel) inside a full screen Remote Desktop Mobile session.

The first challenge is to control the SIP without having a menu bar with the SIP symbol inside. To get this working, you can assign a hardware keyboard button, it must be an App button, to show the SIP. See Settings>Personal>Buttons and assign “<Input Panel>” to the hardware key.

app_button_to_input_panel RDM_fullscreen_option RDM_fullscreen RDM_fullscreen_with_SIP

Unfortunately, the SIP will be hidden immediately after being shown if RDM is started with Full Screen option.

To overcome this, I looked at the Windows Messages inside the RDM window tree and found that there is a Windows Message WM_WININICHANGE send to the main RDM window every time the SIP is shown. Inside the UIMainClass window, the SIP show will result in some more messages, Now, if we can suppress the WM_WININICHANGE message, the SIP may stay until hidden manually, hopefully.

tsshellwnd_on_sip_show  UIMainClass_on_SIP_show

But how can one hook in a foreign Message Pump (WndProc)? Fortunately, there is a general option provided by Windows CE / Mobile to inject one or more DLLs into every started process. Simply add your DLL to the registry key HKLM\System\Kernel\InjectDLL. The type of InjectDLL is REG_MULTISZ.

Now the DLL that I wrote compares the Module File Name of the process that is calling DLL_ATTACH with the Module File Name of RDM, which is “\Windows\wpctsc.exe” on Windows Mobile/Embedded Handheld. If the Module File Name matches, the code looks for the Windows Class “TSSHELLWND”. If this is found, the RDM window has been loaded and initialized. Now the DLL code looks for the child window with class “UIMainClass”. This window marks a remote session has been started. If found, the code uses SetWindowLong and hooks a custom WndProc into the main RDM window. This custom WndProc simply looks for the Window Message that hides the SIP and just returns a TRUE, as if the message has been processed. The other window messages are forwarded unchanged to the original WndProc. The message we filter is WM_WININICHANGE with lParam==133071496.

Remember that ‘subclassing’ a window is only possible from inside the process that created the window. But using InjectDLL, the DLL code is part of the RDM process (and all others) and you can subclass the ‘foreign’ window.

RDM_fullscreen_with_SIP

The only ‘disadvantage’ here is the position of the SIP. As there is no menu bar, the SIP is floating above the lower border. But there are custom SIPs you can move around, if this is a no-go for you.

The demo RDMinjectDLL.dll has to be copied to \Windows and then you need to edit the registry of the device:

REGEDIT4
[HKEY_LOCAL_MACHINE\System\Kernel]
"InjectDLL"=hex(7):\
 5C,57,69,6E,64,6F,77,73,5C,52,44,4D,69,6E,6A,65,63,74,44,6C,6C,2E,64,6C,\
 6C,00

The hex codes are nothing other than the string\Windows\RDMinjectDLL.dll” (without quotes). After changing the registry, the device needs to be rebooted.

During development, I had to remove the reg entry, reboot, deploy a new version, change the reg back and reboot again to test the new version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)