Categories: MSDN / DotNet / Java / Scripts / Linux / PHP Ask - La ask - La Answer

SetwindowsHookEx, GetItem, Crash in ComCtl32.DLL

Hello All...

First off, I would like to thank ChainsaW, Steve, and Damit for their help
with this particular situation. However, I am still having problems...

For those who dont know, let me reiterate my problem:

I am writing an application that gets a CTabCtrl item. The CTabCtrl item
(TCITEM) resides in a different process different than my application. I
am using the CTabCtrl in Wordpad to test my application.

The code looks something like this:

void MyFunc(HWND hWnd, int id)
{
CTabCtrl* Tab = new CTabCtrl;
Tab->Attach(hWnd);

Tab->GetItem(id, NULL);
// The TCITEM normally passed is handled in the following
// DLL function (via the Hook processing), so I use NULL just
// to send the message so it will get intercepted

Tab->Detach();
delete Tab;
}

In my application, a hook is set using SetWindowsHookEx (as sugggested by
ChainsaW and in Jeffrey Richter's book 'Advanced Windows Programming').
This hooks a DLL I created that looks for the TCM_GETITEM message. The hook
is set in all threads (using a thread id of 0), and seems to set fine, as
my DLL function is called when a SendMessage occurs.

My DLL function looks like this

HWND hApp; // Set in a DLL SetHandle function
BOOL bBranch = FALSE; // Needed for branch to next hook
TCITEM gItem;
char gstr[255];

LRESULT WINAPI CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
CWPSTRUCT* Msg;
Msg = (CWPSTRUCT*)lParam;
if((nCode < 0) || bBranch)
{
return CallNextWindowsHookEx(nCode, wParam, lParam);
}
if(Msg->message == TCM_GETITEM)
{
gItem.mask = TCIF_TEXT;
gItem.pszText = gstr;
gItem.cchTextMax = 255;
int id = Msg->wParam;
bBranch = TRUE; // required so does CallWndProc does not process following
SendMessage)
if(SendMessage(gApp, TCM_GETITEM, id, &gItem);
{
// gItem.pszText still = "", should equal the name of the Tab.
printf("%s", gItem.pszText);
}
bBranch = FALSE;
return CallNextWindowsHook(nCode, wParam, lParam);
}
return CallNextWindowsHookEx(nCode, wParam, lParam);
}

Apologies for the long posting, but there is a lot of information here...

While I am in DEBUG step-through, Wordpad does not crash when I SendMessage
in CallWndProc. However, it does not return the name of the Tab Item as
expected, but only "" for the pszText member. In DEBUG execute, Wordpad
causes a page fault in ComCtl32.dll.

Now for the questions:

1. Thanks to the help of Steve, Damit, and ChainsaW, I now understand that
Windows32 processes do not share memory. My understanding is in order to
access another processes memory, you can inject a DLL into the other (remote)
process by using SetWindowsHookEx. Now the DLL can 'see' the memory in the
remote process. So, if you create a pointer or structure in the DLL, the
remote process can use information in that pointer or structure. Therefore,
if I create the TCITEM structure and char[255] in my DLL, those should be
available to the remote process, so it can put data in them and my DLL can
see that data. Am I correct in believing this?? Because I still get the
page fault when I do this.

2. As stated in number 1, a process cannot 'see' a data in another process.
However, when I SendMessage WM_GETTEXT with a pointer to a char[255], it
works just fine. In this case, there is a pointer in my process that the
other process can 'see' and use. This does not work with CTreeView messages
or CTabCtrl messages. However, both &TCITEM and &char[255] are just references
to memory locations. How come one works and the other doesn't??

3. And finally (thanks for your patience) is there another way to send a
message other than SendMessage or PostMessage, so I dont have to set the
bBranch flag in my code. The method must wait for the message to be processed.

ANY help or insight you can give is VERY MUCH appreciated. I have done a
lot of research on this problem, but to no avail, and this part is CRITICAL
to my application. I have seen other applications do it, but I can't get
mine to do it.

If you have any questions, let me know!!

-Johnny
[4488 byte] By [Johnny] at [2007-11-10 12:52:35]
# 1 Re: SetwindowsHookEx, GetItem, Crash in ComCtl32.DLL
"Johnny" <aeroslacker@hotmail.com> wrote in message
news:38e3a30d$1@news.dev-archive.com...

: In my application, a hook is set using SetWindowsHookEx (as sugggested by
: ChainsaW and in Jeffrey Richter's book 'Advanced Windows Programming').
: This hooks a DLL I created that looks for the TCM_GETITEM message. The
hook
: is set in all threads (using a thread id of 0), and seems to set fine, as
: my DLL function is called when a SendMessage occurs.

Is your HHOOK in a shard section and static? Also, that section needs to be
exported by the linker:

e.g.

#pragma data_seg(".shared")
static HHOOK hHook = NULL;
static HINSTANCE hInst = NULL;
// any other variables which need to be shared by all instances of the DLL
#pragma data_seg()

#pragma comment(linker, "/section:.shared,rws")

[code]

One thing in your code - I don't see any calls to CallNextHookEx or any
mention of hHook; does your CallNextWindowsHookEx function do this?

[snip]

; Therefore,
: if I create the TCITEM structure and char[255] in my DLL, those should be
: available to the remote process, so it can put data in them and my DLL can
: see that data. Am I correct in believing this?? Because I still get the
: page fault when I do this.

You need to add them to the shared section, so that they are visible to the
remote process:

#pragma data_seg(".shared")
// ...
static TCITEM tci = NULL;
static char[255] pszText = NULL;
#pragma data_seg()

//...

[WM_GETTEXT]
: This does not work with CTreeView messages
: or CTabCtrl messages. However, both &TCITEM and &char[255] are just
references
: to memory locations. How come one works and the other doesn't??

WM_GETTEXT and WM_SETTEXT are exceptions to #1. Windows performs special
handling behind the scenes to ensure that the pointer supplied is accessible
by all processes.

: 3. And finally (thanks for your patience) is there another way to send a
: message other than SendMessage or PostMessage, so I dont have to set the
: bBranch flag in my code. The method must wait for the message to be
processed.

According to the SDK documentation, SendMessage only returns after the
window procedure has processed the message. Are you, perhaps, using the MFC
variant?
>>

The SendMessage function sends the specified message to a window or windows.
It calls the window procedure for the specified window and does not return
until the window procedure has processed the message.

To send a message and return immediately, use the SendMessageCallback or
SendNotifyMessage function. To post a message to a thread's message queue
and return immediately, use the PostMessage or PostThreadMessage function.
<<

--
Damit Senanayake | damit@mvps.org | http://members.xoom.com/damit
Please reply to newsgroups, not by e-mail. | ICQ: 6930718
Damit Senanayake at 2007-11-11 20:52:47 >