Win32 Subclassing with CVF

Win32 Subclassing with CVF

pcurtis@kiltel.com's picture

I need to subclass a window in a different process. Evidently, the way to do this is to inject my DLL via a hook into the target process' address space. For this to work, my DLL needs to be able to pass a few data values (the hook and target window handles) between the source and target process' address spaces.

There is a fair amount of chat (MSDN, Richter, etc.) on how to do this in C, which apparently allows linker directives to be imbedded directly into the source code to create a named data segment for any variable, which can then be given the "/section:myseg,RWS" link attribute, so data in that segment will be identically available (shared) among all process instances of the DLL.

Can this be done in F90? I cannot find any means within DevStudio to name data segments and set their sharing attributes, and the CVF documentation doesn't address this issue. Alternatively, if anyone can provide a working example of DLL injection which solves this problem in some other way, that would be greatly appreciated.

TIA,
Paul Curtis, pcurtis@kiltel.com

7 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.
Steve Lionel (Intel)'s picture

I know you can specify /section by just typing it in on the Link settings page. I don't know offhand how you would create your own section.

Steve

Steve
gfthomas8's picture

I've only read about this dll injection business but I have no direct experience in doing it.

Search for /SECTION in the VC++ docs to find out how to set the attributes of a section, including 'sharing' with the target process(es).

Jugoslav Dujic's picture

I know about global hooking technique only in general; I've never used it myself. Perhaps the attached file could help establish a global memory segment (via MapViewOfFile). Disclaimer: I didn't use it and I forgot where I downloaded it from (probably www.fortranlib.com). On a quick glance, you should create your own DllEntryPoint:
[/pre]
INTEGER FUNCTION DllEntryPoint(hModule, fdwReason, lpvReserved)
!DEC$ATTRIBUTES STDCALL:: DllEntryPoint
USE DFWIN

IMPLICIT NONE

INTEGER:: hModule, fdwReason, lpvReserved

SELECT CASE (fdwReason)
CASE(DLL_PROCESS_ATTACH)
DllEntryPoint=1
CASE DEFAULT
DllEntryPoint=1
END SELECT

END FUNCTION DllEntryPoint[/pre]
On DLL_PROCESS_ATTACH, try to OpenShareBuffer, and if it fails CreateShareBuffer. Use cray pointers to read from *bufferAddress. Of course, bufferAddress must be global to DllEntryPoint and hook routine.
HTH
Jugoslav

Jugoslav www.xeffort.com
pcurtis@kiltel.com's picture

Thanks for the replies. However... DLL injection is evidently too complicated and I needed a quick fix, so I dropped back & punted.

The original goal was to subclass the other (child) process, launched from my main thread, to trap SC_MINIMIZE messages and prevent its being minimized (my app gets rid of the taskbar, start button, etc.). The other process is typically Notepad, Excel or Paint.

Here is a poor-man's method of doing the same thing; it works fine, but lacks elegance:


TYPE(T_WINDOWPLACEMENT) :: wp
INTEGER :: rval

IF (IsWindow(hwnd_ChildProcess) /= 0) THEN
wp%length = SIZEOF(wp)
rval = GetWindowPlacement (hwnd_ChildProcess, wp)
IF (wp%showCmd == SW_SHOWMINIMIZED) THEN
wp%showCmd = SW_SHOWNORMAL
rval = SetWindowPlacement (hwnd_ChildProcess, wp)
CALL SetFocus (hwnd_ChildProcess)
END IF
END IF

gfthomas8's picture

Now I see what you were doing. You don't need to subclass for this. If I want the character map, say, to be always available and not minimized I do:

integer id !global

...
! poll Windows for the app; if it's not running, start it, and if it is, restore it

use ... !whatever api mods required
type(T_STARTUPINFO) StartInfo
type(T_PROCESS_INFORMATION) ProcessInfo
integer r
...
If (FindWindow(NULL, "Unicode Character Map") /= 0) then
StartInfo%wShowWindow = SW_NORMAL
StartInfo%cb = len(StartInfo)
r = CreateProcess(NULL, "charmap.exe"C, 0, 0, 0, 0, CREATE_SEPARATE_WOW_VDM, NULL, StartInfo, ProcessInfo)
Sleep(500)
id = ProcessInfo%hProcess
r = CloseHandle(ProcessInfo%hThread)
Else
r = ShowWindow(FindWindow(NULL, "Unicode Character Map"), SW_RESTORE)
End If

...
!Do cleanup
integer r
use ... !whatever api mods required
If id > 0 Then
r = TerminateProcess(id, 0)
r = CloseHandle(id)
End If

The user is free to minimize or close the app and you respond by opening it up again. In the case of Excel, etc. they could loose data but the app will let them know and they'll soon get the message.

This is similar to what you've been doing. I don't consider it inelegant.

Jugoslav Dujic's picture

Maybe changing Excel's window styles (remove WS_MINIMIZEBUTTON & WS_THICKFRAME, add possibly WS_DLGFRAME) could be a more ellegant solution?

Jugoslav www.xeffort.com

Login to leave a comment.