Problem - TCHAR as LPARAM to a window that belongs to another process/thread - c++

So i am playing/implementingtomyown with windows via c book examples and there is something about dll injection part that boggles me and i can't solve it.
I created a dialog that belongs to another thread/process and i am trying to send it TCHAR variable so it can then use that var in some function(both the function and tchar are in the same dll file)
So when the dialog is created and sitting well in another thread i send it a message.
First i declare tchar
TCHAR finalpath[MAX_PATH];
Then later i just fill it with info( i do this in the dll thread, not in the dialog's thread, let me also mention that i must do this in the dll thread because thats only way to fill the required tchar(i am required to get dll working directory and fill it in tchar))
So, when i get this info in my tchar i am trying to send a message to the dialog and use tchar as LPARAM(wparam is hwnd btw)
SendMessage(hWndDIPS, WM_APP, (WPARAM) lista, (LPARAM)finalpath);
Afterwards i do basic schoolwork in another threads dialog procedure loop...
INT_PTR WINAPI Dlg_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
chHANDLE_DLGMSG(hWnd, WM_CLOSE, Dlg_OnClose);
case WM_APP:
SaveListViewItemPositions((HWND) wParam, (TCHAR)lParam);
break;
}
return(FALSE);
}
Function that is supposed to receive the parameter(this function resides in shared dll and is called by the procedure as you see above is defined as follows..
void SaveListViewItemPositions(HWND hWndLV, TCHAR sejv[]) {
...}
The compiler error i get from this is
Error 7 error C2664: 'SaveListViewItemPositions' : cannot convert parameter 2 from 'TCHAR' to 'TCHAR []'
So i have no idea why is this happening. If tchar is array then i need to use it in parameters with [] added as thats how arrays are used in parameters(not to mention that if i dont do it it gives me more errors and i cant use the parameter in function anyways)
So why is it not converting then?
If there is another solution to make this dialog to receive a tchar var then please explain.
Thanks

Even after you'll fix your type declarations and properly cast the LPARAM to a TCHAR*, your code will be incorrect. The 'parameter' you pass in to that window procedure is a pointer, and as any pointer, is only valid within a process address space. The receiver window will have to use ReadProcessMemory and copy the string from your process into its own process. Of course, this implies that the receiver process knows your process id, and has proper privileges to be able to read from your memory. And you also need to pass in the length of the string, since ReadProcessMemory cannot guess where the NULL terminator is (although I reckon that with a MAX_PATH max length, this is not a serious issue).
So you are correct, this is a headache, and more so down the road. The privilege issue may be a show stopper.
There are several IPC mechanisms you could use. An easy one is an anonymous named pipe, see Anonymous Pipe Operations. Shared memory is another, see Using Shared Memory in a Dynamic-Link Library. COM would also work (have the process you 'control' create an instance of a class that is hosted in your process server, and let the COM marshaling do the rest, see Marshaling Details). Or you could hand-marshal a COM interface between the process boundary (see CoMarshalInterface).

I think that your problem is that you're typecasting the LPARAM to a TCHAR instead of an array of TCHARs (TCHAR*). Try changing that and see if it fixes things.

Related

Why does c++ send WM_DRAWITEM to the parent process?

I started recently learning C++ and WinAPI, I want to be able to create my own programs
I am subclassing a button (into separate file, because I like things clean and organized - is that a bad idea?), because I want to have few of the kind with same parameters. I also want to draw it, and the question that pops to my mind is: wouldn't it be better to have it all in the class file? Meaning all parameters including custom draw. It is annoying to go to main file to change the looks and set all other parameters in the class file. I use codeblocks.
EDIT (explanation):
#include <Windows.h>
#include <Winuser.h>
#include "CustomButton.h"
/*global vars*/
WNDPROC CustomButton::CustomButtonLongPtr;
/*functions*/
LRESULT CALLBACK CustomButtonProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
CustomButton * CustomButton::CreateCustomButton(HINSTANCE hInstance, HWND hwnd, int pos_x, int pos_y, int width, int height)
{
CustomButton * p_CustomButton = new CustomButton;
HWND customButton = CreateWindowEx(0, "BUTTON", "OK", WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, pos_x, pos_y, width, height, hwnd, (HMENU)200, (HINSTANCE)GetWindowLong(hwnd, GWLP_HINSTANCE), p_CustomButton);
if(customButton == NULL)
{
delete p_CustomButton;
MessageBox(NULL, "Problem creating the Search box.", "Error", 0);
return 0;
}
CustomButton::CustomButtonLongPtr = (WNDPROC)SetWindowLongPtr(customButton, GWLP_WNDPROC, (LONG_PTR)&CustomButton::CustomButtonProc);
return p_CustomButton;
}
I want to use WM_DRAWITEM for this button in CustomButtonProc and I am wondering why did the developers think that it would be smarted to allow to use it only in parent WinProc.
This is a little complicated to explain.
You're probably coming from a background where you plug a function into an outlet to handle events, something like
extern void onClicked(void);
button->OnClicked = onClicked;
And while it's fully possible for Windows to have done this from the start, you have to remember that Windows was originally designed to run on systems with severely limited memory, so it was important that controls not waste memory. And there are a lot of events you can get from a button:
void (*OnClicked)(void);
void (*OnDoubleClicked)(void);
void (*OnDisabled)(void);
void (*OnHighlight)(void);
void (*OnKillFocus)(void);
void (*OnPaint)(void);
void (*OnSetFocus)(void);
void (*OnUnhighlight)(void);
void (*OnUnpushed)(void);
HBRUSH (*OnCtlColorButton)(void);
Having these for every button in your program — that is, push buttons, checkboxes, radio buttons, and groupboxes — with most of them likely to be unused would just be a massive waste of memory.
Because Windows needs a way to communicate between the system and a window and between windows, Microsoft decided to create a message-passing interface where each message had a 16-bit code and two pointer-sized (originally one 32-bit and one 16-bit) parameters and a pointer-sized return value. And there aren't a lot of messages that Windows needs for itself, giving both window classes and the application a lot of real estate for using messages to communicate. So why not use a message to signal the event?
Using a message avoids the waste of memory while still allowing the button to pass data to and return data from its target window. So the logic follows that all a button would need to do is
/* this is not the correct syntax but let's use it for expository purposes */
#define BN_CLICKED someNumberHere
case WM_LBUTTONUP:
SendMessage(GetParent(hwnd), BN_CLICKED, hwnd);
break;
and the parent would handle that:
case BN_CLICKED:
if (whichButton == button1)
doButton1Stuff();
break;
No wasted memory, but still flexible and extensible. And even more importantly, also binary-compatible: if more events were added later, the size of the function pointer table would need to change, and newer programs that tried to use newer events on older systems would clobber random memory. With messages, these programs would just have dead code.
Now why send the message to the parent? If we view windows as communication endpoints, then this is obvious: you want the button to tell its parent that it was clicked because you're communicating that the button was clicked!
But more important, you didn't write the button's window procedure. Microsoft did, and they provide the same one to every program. If you could handle the message in the button procedure, where would you put it? You can't change the button procedure, after all.
(Nowadays we have something called "subclassing" which allows you to override a single window's window procedure to do custom processing. It's not used for event handling because it's more work than just sending up to the parent.)
All of this extends to custom draw; just substitute "custom draw" for "clicked" and it should still make sense. Hopefully this explanation was clear, even with that mental substitution.
If you want, you can write your own facility to handle events in the function pointer way. Keep a map of window handles to event functions and call a global dispatch function in all your window procedures to handle the event messages WM_COMMAND, WM_NOTIFY, and (for trackbars) WM_HSCROLL and WM_VSCROLL. How you do this is up to you, but think about whether you really want to do it this way; sometimes it's necessary, but sometimes it isn't. If you do, remember to provide a way to pass arbitrary data to the event function that's decided at event connection time, so the event handler can do something reasonable without relying on global state.
Thanks to comments by RemyLebeau and IInspectable I was able to also find solution to my frustration, which I am going to explain here for anybody else who's scratching their heads over this very issue.
This solution does not require VCL nor any component from Visual Studio and such.
First define your own custom message, in the way that you can reach it inside WndProc:
#define MY_DRAWITEM (WM_APP+1)
UINT uDrawButtonMsg = RegisterWindowMessage(_T("MY_DRAWITEM"));
Then find out what number it is assigned:
std::cout << uDrawButtonMsg; //for example 49648
And send this message from WndProc to your subclassed control from any message you wish, for example WM_DRAWITEM:
case WM_DRAWITEM:
{
::SendMessage(p_CustomButton->customButton, uDrawButtonMsg, wParam, lParam);
break;
}
And then in your subclass just catch the message by the 5 digit number you looked for while ago:
if(49648 == uMsg)
{
//do your DRAWITEM stuff here
}
Thanks to everybody who contributed to this article helping with exaplanation, tips and also historical background!

CreateDialog in BHO always fails with error 1813 (resource not found)

I'm working on a BHO written a long time ago in C++, without the use of any of the VS wizards. As a result, this project deviates from the COM conventions and the boilerplate for a COM product. I worked with COM long ago, but never really did any Windows GUI/dialog stuff...
I'm trying to add a dialog box to allow the user to set the values of some new settings:
// serverDialog will be NULL
HWND serverDialog = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_PROPPAGE_SETTINGS), NULL, DialogProc);
id (!serverDialog)
{
int error = GetLastError(); //1813
...
}
....
1813 means that the resource cannot be found. The IDD used there is in resource.h, which I manually included where needed.
DialogProc is defined as:
INT_PTR CALLBACK DialogProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
return FALSE;
}
Which I know I will have to change later if I want the dialog to actually process messages, but I haven't gotten that far yet. The 1813 error suggests failure before the dialog is even created as does the NULL dialog handle returned.
To add the dialog I used the Add Resource wizard and added a small property page.
I've tried to follow advice here, but to no avail.
Thanks!
You are passing GetModuleHandle(NULL) as the instance of the module that contains the resource. But GetModuleHandle(NULL) defines the executable file module. You need to pass the instance of the module containing your code. This question covers that topic: How do I get the HMODULE for the currently executing code?
You probably ought to pass a window handle to the hWndParent parameter so that the dialog is owned.

Nested Dialog Procedures

I'm not sure how to call Dialog Procedures of certain classes and was looking for some help.
I'm aware for a normal Message Procedure you can do this in the MessageProc:
case WM_CREATE:
{
CREATESTRUCT* cs = (CREATESTRUCT*)_lParam;
pApplication = (CApplication*)cs->lpCreateParams;
return pApplication->MessageProc(_Msg, _wParam, _lParam);
}
which will allow you to create a Message Proc independent to the class.
However due to the fact I don't know exactly how the first two lines work (just the definition that they return the 'this' pointer of the application), I can't work out what to do to get my Dialog Procedures to do a similar thing
case WM_INITDIALOG:
{
//How can I get the pointer to the inspector that
//I want to call the dialog proc on?
return pInspector->DlgProc(_hWndDlg, _Msg, _wParam, _lParam);
}
Any help to both get the pointer to the inspector working and also clarify exactly what the other two lines are doing in WM_CREATE would be appreciated
When a window is created, it receives a WM_CREATE message with a pointer to a CREATESTRUCT structure, and in there is a pointer-sized userdata field (lpCreateParams). This value comes from the lpParam argument passed to the CreateWindowEx() function.
This is the general mechanism which lets you associate your own class or data structure with an instance of a window.
This pointer generally needs to be saved somewhere in order to use it later on. One common way of doing this is to store it in a window property:
case WM_CREATE:
{
CREATESTRUCT* cs = (CREATESTRUCT*)_lParam;
pApplication = (CApplication*)cs->lpCreateParams;
SetProp(hWnd, L"my.property", (HANDLE)pApplication);
}
Then to retrieve the value when handling other messages:
pApplication = (CApplication*)GetProp(hWnd, L"my.property");
Dialogs are not exactly like normal windows, so although a similar mechanism exists, it is implemented differently. When a dialog procedure receives the WM_INITDIALOG message, the lParam value is equivalent to the lpCreateParams value in a WM_CREATE message.
In order to save your pInspector value it would need to have been provided as the dwInitParam value when the dialog was created, but assuming that it was, you can handle this in a similar way:
case WM_INITDIALOG:
{
pInspector = (CInspector*)lParam;
SetProp(hWnd, L"my.property", (HANDLE)pInspector);
}
And to retrieve the value when handling other messages:
pInspector = (CInspector*)GetProp(hWnd, L"my.property");

Low level keyboard hook: differentiate between key codes

I'm trying to limit the access of the users of my program to the keyboard. To do that I've defined a low level keyboard hook:
LRESULT CALLBACK lowLevelKeyboardProc(int key, WPARAM wParam, LPARAM lParam)
{
KBDLLHOOKSTRUCT* pkbhs = (KBDLLHOOKSTRUCT*)lParam;
switch (key)
{
case HC_ACTION:
....
and hooked it:
m_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)lowLevelKeyboardProc, 0, 0);
I need the users to be able to use only the alphanumeric chars, ~, #, # ... only the chars that can be in a password (printable chars).
What would be the easiest way to differentiate between those chars and all the others using the low level keyboard hook parameters: int key, WPARAM wParam, LPARAM lParam ?
The program is written in c++ and compiled in VC2010.
All help is appreciated!
Before actually answering your question, I have a couple of questions for you:
Why would you want to do this globally, using a global low-level keyboard hook?
Although sometimes they are the only way to solve a problem, using a global hook like this is generally strongly discouraged for many reasons. There are many better ways of preventing a user from entering invalid or unacceptable data. For example, I would just disable the keys you don't want for a particular control or set of controls (e.g. all textboxes). That way, the user can still use keyboard shortcuts and other non-alphanumeric keys to interact with your application, which is critical for accessibility reasons. Remember that a global hook will affect all of the other threads running on the machine, not just your app—that is probably not what you want.
Even if you do decide to use a global hook, are you sure that you really need to disable all of the non-alphanumeric keys? What about Backspace and Delete? Shouldn't the user be able to delete things? And what about Tab? Enter? And what about modifier keys, like Shift, Ctrl, and Alt: are those allowed?
Please seriously reconsider whether you really need a low-level hook before continuing forward with this design. If you need help on devising another solution, please ask a new question, describing what you want to accomplish (e.g., I want to prevent users from entering any non-alphanumeric characters in a textbox control; here is the code I use to create my textbox…).
But if you insist on ignoring my advice, the solution is rather simple: investigate the members of the KBDLLHOOKSTRUCT structure that is passed to the hook procedure. The vkCode member gives you the virtual key code of the key that was pressed. Chances are, that is all the information you need. But just in case it's not, the hardware scan code of the key is also provided in the scanCode member.
Unfortunately, the code that you currently have is wrong. The first parameter to the hook callback procedure is indeed an int, but it is not a key code. Rather, it is a code that signals how the hook procedure should process the message. Use it like this:
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// If nCode is greater than or equal to HC_ACTION, process the message.
if (nCode >= HC_ACTION)
{
KBDLLHOOKSTRUCT* pkbhs = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
// Handle the keys as you wish here.
//
// Remember that pkbhs->vkCode gives you the virtual key code
// of the key that was pressed.
//
// To prevent a particular key from being processed, you should
// return a non-zero value (e.g. 1) immediately.
}
// Pass the message on.
return CallNextHookEx(m_hHook, nCode, wParam, lParam);
}
And when you install the hook, there is absolutely no need to cast the function pointer. Pointless casts like this just hide potential compile-time errors, leading to a crash at runtime. Write it simply:
m_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, lowLevelKeyboardProc, 0, 0);

In-Proc COM object sharing across another Process

Before I ask this question I would like to make it clear that I know there are libraries and techniques for Inter process communcation. This though, is a learning question about COM.
I also do know about out-of-proc servers but that's not what I am looking for.
The question:
What I want to know, because I don't know this, is it possible, and if yes how, to share an in-proc COM object (object defined in a DLL) living in one process (has been instantiated in the process) across another process? Ie, how do I obtain a pointer to the in-proc object from proces A in process B?
Thanks in advance.
Yes, it's possible. The underlying principle is the same regardless of whether you are sharing a single object instance between apartments in a single process, or between separate processes.
There's two approaches here: perhaps the simplest is to use the Running Object Table: this is essentially a workstation-wide table of named COM objects. You have one process add an object to the table with a well-known name, and have the other process look up that object.
The other approach is to use marshaling. Marshaling is the process of using a COM API to get a series of bytes that describe the location of an object. You can then copy that series of bytes to another process using any means you want to (shared memory, file, pipe, etc), and then use another COM API in the receiving process to unmarshal the object; COM then creates a suitable remoting proxy in that process that communicates back to the original one. Check out the APIs CoMarshalInterface and CoUnmarshalInterface for more details.
Note that both of these require that you have suitable remoting support in place for the object; the interfaces you are using need to be described in IDL and compiled and registered appropriately.
--
I don't have code handy for either of these cases unfortunately.
For the CoMarshalInterface approach, the process is something like:
Use CreateStreamOnHGlobal (with NULL hglobal) to create an IStream that's backed by a HGLOBAL that COM allocates as needed
Use CoMarshalInterface to marshal the interface pointer to the stream (which in turn writes it to the memory backed by the HGLOBAL)
Use GetHGlobalFromStream to get the HGLOBAL from the stream
Use GlobalLock/GlobalSize to lock the HGLOBAL and access the marhaled data (GlobalUnlock when done)
Use whatever means you want to to copy the bytes to the target process.
On the far side, use:
GlobalAlloc/GlobalLock/GlobalUnlock to create a new HGLOBAL and populate it with the marshaled data
CreateStreamOnHGlobal with your new HGLOBAL
Pass this stream to CoUnmarshalInterface
Normal COM and Windows refcounting/resource rules apply across all of this; AddRef/Release as appropriate; use GlobalFree to free any HGLOBALs that you allocate, etc.
There is also another possible solution using the window message WM_GETOBJECT:
In the application, which has the object, you simply create a window with your own class. In the handler, you need to handle the window message like this (I use IDispatch as example interface):
LRESULT WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_GETOBJECT:
{
if(lParam == OBJID_NATIVEOM)
{
return LresultFromObject(IID_IDispatch, wParam, g_MyGlobalIDispatchPointer);
}
else
{
// Not handled
break;
}
}
return 0;
}
// Default
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
The other application must find that specific window an get the object via AccessibleObjectFromWindow
In example:
HWND hWndCommunicator = FindWindow(_T("MyWindowClassOfTheOtherApplication"), _T("MyWindowTitleOfTheOtherApplication"));
if(hWndCommunicator)
{
IDispatch* poObject = nullptr;
HRESULT hr = AccessibleObjectFromWindow(hWndCommunicator, static_cast<DWORD>(OBJID_NATIVEOM), IID_IDispatch, &poWindow);
if(SUCCEEDED(hr))
{
// Do something with the object of the other process
// i. e. poObject->Invoke
}
}
Marshalling is automatically done using this solution.
That's what CoRegisterClassObject and CoGetClassObject is for.