C++ At Work

Installing a Hook, Strings in Managed C++, and More

Paul DiLascia

Code download available at:CAtWork0601.exe(146 KB)

Q I want to call SetWindowsHookEx to set a WH_CBT hook to do something. But I know MFC also installs this hook. This means in one thread WH_CBT is installed twice. Can I do this?

Q I want to call SetWindowsHookEx to set a WH_CBT hook to do something. But I know MFC also installs this hook. This means in one thread WH_CBT is installed twice. Can I do this?

Ken Dang

A The short answer is yes. You can install several hooks of the same type as long as you follow the proper procedure. Windows® hooks are designed to operate in a daisy-chain fashion similar to subclassing. To install a hook, you call SetWindowsHookEx with the type of hook and a pointer to your hook procedure. SetWindowsHookEx returns a handle to the old hook:

HHOOK hOldHook; // global ... hOldHook = SetWindowsHookEx(WH_CBT, MyCbtProc, ...);

A The short answer is yes. You can install several hooks of the same type as long as you follow the proper procedure. Windows® hooks are designed to operate in a daisy-chain fashion similar to subclassing. To install a hook, you call SetWindowsHookEx with the type of hook and a pointer to your hook procedure. SetWindowsHookEx returns a handle to the old hook:

HHOOK hOldHook; // global ... hOldHook = SetWindowsHookEx(WH_CBT, MyCbtProc, ...);

Now Windows calls your hook procedure whenever one of the hook events happens. When your procedure is done handling the event, it's supposed to call the next hook by calling—what else?—CallNextHookEx:

LRESULT CALLBACK MyCbtProc(int code, ...) { if (code==/* whatever */) { // do something } return CallNextHookEx(hOldHook, code, ...); }

Of course, there's no one forcing you to call CallNextHookEx, but if you don't, your application is likely to break. In the case of the computer-based training (CBT) hook, MFC uses it to trap window creation. Windows calls the CBT hook with HCBT_CREATEWND whenever it creates a window. MFC handles HCBT_CREATEWND by subclassing the window and attaching it to its CWnd object. The details are a bit complex, but the simplified version goes something like this:

// simplified from wincore.cpp LRESULT _AfxCbtFilterHook(int code, WPARAM wp, ...) { if (code==HCBT_CREATEWND) { CWnd* pWndInit = pThreadState->m_pWndInit; HWND hWnd = (HWND)wp; pWndInit->Attach(hWnd); SetWindowLongPtr(hWnd, GWLP_WNDPROC, &AfxWndProcafxWndProc); } return CallNextHookEx(...); }

I've omitted the grungies to highlight what's important. MFC attaches the window object to its HWND and subclasses it by installing AfxWndProc. This is how MFC connects C++ window objects to their HWNDs. AfxWndProc is the procedure that routes WM_XXX messages (via a very circuitous path) to your message map handlers.

When Windows calls the CBT hook, it passes the HWND as WPARAM. But how does MFC know which CWnd-derived object to attach? By setting a global. To create a window, you must call CWnd::Create or CWnd::CreateEx. The former calls the latter, so all paths go through CWnd::CreateEx. Before creating the window, CWnd::CreateEx installs the CBT hook and sets a global. In code it looks something like this:

// simplified from wincore.cpp BOOL CWnd::CreateEx(...) { AfxHookWindowCreate(this); ::CreateWindowEx(...); AfxUnhookWindowCreate(); return TRUE; }

AfxHookWindowCreate installs the CBT hook _AfxCbtFilterHook. It also saves a pointer to the window object in the thread's state as pThreadState->m_pWndInit:

void AFXAPI AfxHookWindowCreate(CWnd* pWnd) { _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData(); pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx( WH_CBT, _AfxCbtFilterHook, NULL, ::GetCurrentThreadId()); pThreadState->m_pWndInit = pWnd; }

Think of the thread state as a place to hold thread-wide globals. So now the action goes like this. Your app calls CWnd::Create or CWnd::CreateEx. CWnd::CreateEx installs a CBT hook, sets a global pointer to the CWnd being created, and finally calls ::CreateWindowEx to actually create the window. After it creates the window—but before sending any messages like WM_CREATE or WM_GETMINMAXINFO—Windows calls the CBT hook with HCBT_CREATEWND. Then _AfxCbtFilterHook gets control and subclasses the window and connects it to its CWnd. MFC knows which CWnd to use because it previously stored the CWnd pointer in pThreadState->m_pWndInit. Pretty clever, eh?

After _AfxCbtFilterHook returns control to Windows, Windows sends WM_GETMINMAXINFO and WM_CREATE messages to your window, which MFC now processes in the normal way, by routing control to your OnGetMinMaxInfo and OnCreate handlers. This is only possible because the HWND is now attached to its CWnd object. When ::CreateWindowEx returns control to CWnd::CreateEx, CWnd::CreateEx calls AfxUnhookWindowCreate to remove the CBT hook and set pThreadState->m_pWndInit = NULL. The only reason for the CBT hook is to trap window creation so MFC can connect the CWnd to its HWND. The hook exists only for the duration of the call to ::CreateWindowEx.

Astute readers may wonder why MFC goes through all that trouble—why not just attach and subclass the window in CWnd::CreateEx? That would work fine, except for one problem. The CWnd object would miss any messages sent from ::CreateWindowEx—such as WM_GETMINMAXINFO, WM_NCCREATE and WM_CREATE. The problem is ::CreateWindow Ex doesn't let you specify a window proc when you create your window. You have to subclass it afterwards. But by then, several messages have already gone by. In order to handle all the messages, including the early creation messages, MFC has to connect the window object before the messages are sent. The only way to do that is using a CBT hook, because Windows calls the CBT hook just after it creates the window, but before sending it any messages. So the whole point and purpose of the CBT hook is to trap window creation in order to connect CWnd objects to their HWNDs before the window receives any messages.

That's way more than you need to know in answer to your question, but it's good to understand when, where, and why MFC uses its CBT hook. I also wanted to show you how MFC uses the thread global m_pWndInit to pass the CWnd to the hook function. Often you'll need to do something similar. SetWindowsHookEx has no void* param you can pass along to your hook procedure. If your hook proc needs information in the form of data, the only way to pass it is through a global. In most situations a normal static will do; you don't need a thread-specific global unless your data is thread-specific. MFC uses the thread state because it maintains a separate window map for each thread. The window map holds all the CWnds for a thread; it's what links each CWnd with its HWND.

But as far as multiple hooks are concerned, you can install as many as you like as long as you remember to call ::CallNextHook. You won't interfere with MFC.

Q I'm in the process of converting an existing C++ class library to the Managed Extensions so I can expose it to my .NET Framework-based clients. Some of my code calls API functions that require the HINSTANCE of the current running module. I don't want to use the HINSTANCE of my DLL; I want the caller to supply the HINSTANCE of the EXE calling my DLL. I can declare the HINSTANCE parameter as an IntPtr, but how do my .NET-based clients get the app's HINSTANCE to pass to my function? For example, how would they do it in C#?

Q I'm in the process of converting an existing C++ class library to the Managed Extensions so I can expose it to my .NET Framework-based clients. Some of my code calls API functions that require the HINSTANCE of the current running module. I don't want to use the HINSTANCE of my DLL; I want the caller to supply the HINSTANCE of the EXE calling my DLL. I can declare the HINSTANCE parameter as an IntPtr, but how do my .NET-based clients get the app's HINSTANCE to pass to my function? For example, how would they do it in C#?

Hunter Gerson

A Good question! This one stumped me for about 15 minutes. In MFC you can call AfxGetInstanceHandle(). MFC stores the HINSTANCE in its Application object, in CWinApp::m_hInstance. So if you're using the Microsoft® .NET Framework, you might think that you should take a look in the Application object for Application.HInstance or an Application property or some such thing. Why not? Because it's not there!

A Good question! This one stumped me for about 15 minutes. In MFC you can call AfxGetInstanceHandle(). MFC stores the HINSTANCE in its Application object, in CWinApp::m_hInstance. So if you're using the Microsoft® .NET Framework, you might think that you should take a look in the Application object for Application.HInstance or an Application property or some such thing. Why not? Because it's not there!

If you search the Framework documentation for "hinstance," you'll discover there's a method Marshal.GetHINSTANCE. Well, that sounds promising. This static Marshal method requires the module whose HINSTANCE you want to obtain:

// In C# Module m; ... IntPtr h = Marshal.GetHINSTANCE(m);

Now you know how to get the HINSTANCE—but where do you get the module? Again, you might think to look in the Application class for something like Application.GetModule. Or perhaps Application is derived from module, that would make sense. Alas, neither is true. Well, maybe there's a Module property. Nope. Well, not quite. There is a Module property, but it's not a property of the Application, it's a Type property. In the .NET Framework, every object has a Type and every Type has a Module. Type.Module represents whichever module implements the type. So to get the HINSTANCE of the calling module, your clients can write:

Type t = myObj.GetType(); Module m = t.Module; IntPtr h = Marshal.GetHINSTANCE(m);

You can also use typeof (--typeof in C++)to get the type without an object instance, as in typeof(MyApp). Just tell your customers to make sure they use a type that's implemented in the calling module. If you use some other type—for example, one of the Framework types like String—you'll get the wrong module.

Figure 1 shows a simple C# console app, ShowModule, that illustrates this. Figure 2 shows it running. ShowModule displays module information including the HINSTANCE for two types: the MyApp class defined in the application itself and the String[] (String array) type defined in mscorlib.

Figure 1 Getting an HINSTANCE in C#

using System; using System.Reflection; using System.Runtime.InteropServices; class MyApp { // main entry point static void Main(string[] args) { ShowModule(typeof(MyApp)); // show module for MyApp (me) ShowModule(args.GetType()); // show module for String[] (CLR) } // Helper to display module info and HINSTANCE given Type. static void ShowModule(Type t) { Module m = t.Module; Console.WriteLine("Module info for type {0}:", t); Console.WriteLine(" Name = {0}", m.Name); Console.WriteLine(" FullyQualifiedName = {0}", m.FullyQualifiedName); Console.WriteLine(" HINSTANCE = 0x{0:x}\n", (int)Marshal.GetHINSTANCE(m)); } }

Figure 2 Module Information

Figure 2** Module Information **

Q How do I convert an MFC CString to a String in managed C++? I have the following C++ function:

int ErrMsg::ErrorMessage(CString& msg) const { msg.LoadString(m_nErrId); msg += _T("::Error"); return -1; }

How do I rewrite this using managed C++ and replacing CString in the parameter list with String? I can't figure out how to declare the parameters, what to do with the const, and how to load a managed String from a resource file. I read that Strings can't be modified because they're immutable, but I want to modify the string passed.

Q How do I convert an MFC CString to a String in managed C++? I have the following C++ function:

int ErrMsg::ErrorMessage(CString& msg) const { msg.LoadString(m_nErrId); msg += _T("::Error"); return -1; }

How do I rewrite this using managed C++ and replacing CString in the parameter list with String? I can't figure out how to declare the parameters, what to do with the const, and how to load a managed String from a resource file. I read that Strings can't be modified because they're immutable, but I want to modify the string passed.

Sumit Prakash

A There are several things going on here, so let's tackle them one at a time. First, the const declaration. There's no notion of const methods in the .NET Framework, so you can forget about that. Sorry, that's just the way it is.

A There are several things going on here, so let's tackle them one at a time. First, the const declaration. There's no notion of const methods in the .NET Framework, so you can forget about that. Sorry, that's just the way it is.

Next, how to declare your new function. You know you want to change CString to String, but what's the exact syntax? Your function modifies the CString passed, which is why you used a reference. In .NET, it's true that Strings are immutable. You can't modify the contents of a String. All the methods that seem to modify a String actually return a new String. For example:

String* str = S"hello"; str = str->ToUpper();

String::ToUpper returns a new String, which you can assign to str. If you want to modify the String itself, you need a different class, StringBuilder. But you don't need StringBuilder here because you're not actually modifying the String, you're modifying the variable that references it. In order to see this, consider what your function would look like in C#:

int ErrorMessage(ref string msg) { msg = ...; return -1; }

The msg parameter is declared as ref, which means that when ErrorMessage alters msg, it alters the variable passed, not the String object itself, as shown here:

string str = ""; err.ErrorMessage(ref str);

Now instead of referencing the empty string, str references whatever string ErrorMessage set it to. So in C#, you'd use a ref parameter. But, there's no ref keyword in C++, nor is there any managed __ref keyword. C++ doesn't need one, because it already has references! And the compiler is smart enough to make them work with managed code. All you have to do is remember that in C++, managed objects are always pointers or handles. Just replace CString with String* (or String^ if you're using Visual Studio® 2005 with C++/CLI). The new declaration looks like this:

int ErrMsg::ErrorMessage(String*& msg){ msg = "foo"; return -1; }

That is, the new function takes a reference to a (managed) String pointer. If you want to be really explicit, you can even use __gc, as in ErrorMessage(String __gc * __gc & msg). In the real world, you don't need __gc because the compiler knows String is a managed class. If you're using C++/CLI, you'd use a tracking reference-to-handle as in: ErrorMessage(String^% msg). Amazingly, it all makes perfect sense. But that's not the end of the story, because there's yet another way you can declare ErrorMessage. You can use a pointer-to-pointer, like so:

int ErrMsg::ErrorMessage(String** msg){ *msg = "foo"; return -1; }

Even in C++, the difference between a reference and a pointer is slight. The main difference is that a reference must always be initialized and can't be NULL. Otherwise the difference is mainly syntactic—whether you use . or -> to dereference the object. Internally, references are implemented as pointers. In .NET, there are no pointers. Everything is a reference. Or everything is a pointer, if you peer under the hood.So whether you use a reference-to-pointer or pointer-to-pointer, either way your String parameter looks to the outside Framework world like a ref parameter. I wrote a C# program, RefTest, that shows this (see Figure 3 and Figure 4).

Figure 4 C# Consumer of C++ Library

using System; using MyLib; // C++ lib class MyApp { // main entry point static int Main(string[] args) { ErrMsg em = new ErrMsg(); String str = null; // Test declaration 1: reference-to-pointer <span class="clsRed" xmlns="https://www.w3.org/1999/xhtml">em.Message1(ref str);</span> Console.WriteLine("Message1: str = {0}", str); // Test declaration 2: pointer-to-pointer <span class="clsRed" xmlns="https://www.w3.org/1999/xhtml">em.Message2(ref str);</span> Console.WriteLine("Message2: str = {0}", str); // Test old-style resource strings: There are only 2. for (int i=1; i<=3; i++) { <span class="clsRed" xmlns="https://www.w3.org/1999/xhtml">em.GetString(ref str, i);</span> Console.WriteLine("Resource String #{0} = {1}", i, str); } return 0; } }

Figure 3 Library that Uses Pass-By-Reference Parameters

Mylib.cpp

#using <mscorlib.dll> #include <atlstr.h> // CString using namespace System; using namespace System::Runtime::InteropServices; namespace MyLib { public __gc class ErrMsg { public: // reference-to-pointer int Message1(String*& str) { str = "Hello, world #1"; return 0; } // pointer-to-pointer int Message2(String** str) { *str = "Hello, world #2"; return 0; } // Load string from DLL resource file. Note explicit module handle. int GetString(String*& str, int id) { CString s; if (s.LoadString(::GetModuleHandle(_T("MyLib.dll")), id)) { str = s; // Copy to caller's string. Compiler knows what to do. return 0; } // Note: need to box id sinve String::Format expects an Object. str = String::Format("Error: String {0} not found.", __box(id)); return -1; } }; }

MyLib.rc

// Resource file has two strings STRINGTABLE BEGIN 1 "Resource string #1" 2 "Resource string #2" END

RefTest uses a library class ErrMsg written in C++. ErrMsg is a managed class with two methods, Message1 and Message2, which set their String parameter to a message "Hello, world #1" and "Hello, world #2", respectively. One uses String** and the other uses String*&. Either way, C# callers must use the ref keyword when calling either Message1 or Message2.

The "ref" is required in both cases. If you remove it, you'll get "error CS1503: Argument '1': cannot convert from 'string' to 'ref string'." Note that it's legal to call Message1 with str=null. To your C++ function, str isn't NULL, it's a reference to null. You should be aware of this if your function accesses the String passed. For example:

int ErrMsg::Message1(String*& str) { int len = str->Length; ... }

This compiles fine, but it throws an exception if the caller passes str=null. You should rewrite your code to gracefully handle the case of str=null, as shown in the following:

int ErrMsg::Message2(String*& str) { if (str==NULL) return -1; ... }

So, which should you use—pointer or reference? It doesn't much matter. Personally, I prefer the reference (&) because it mirrors ref, looks cleaner, and requires less typing to dereference the object.

So much for the declaration. Now to the final point. How do you load a resource string? As you discovered, there's no LoadString method in the String class. That's because the .NET Framework doesn't do resources the Windows way. The .NET Framework takes an entirely different approach, one I described in my November 2002 MSDN®Magazine article (see .NET GUI Bliss: Streamline Your Code and Simplify Localization Using an XML-Based GUI Language Parser) as "infinitely flexible, but tedious for small tasks."

The .NET way is to use satellite assemblies of text or XML resource (.resx) files. In .NET, there are two kinds of resources: strings and objects. For strings, all you have to do is create a .txt file with name=value pairs and run resgen.exe. Your app then calls ResourceManager.GetString to fetch the string. For everything else, you have to write a program that serializes the object to a .resx file, then call ResourceManger.GetObject to load it at run time. For details, read the documentation or my GUI article. In it, I showed how to write a FileRes class and FileResGen program that vastly simplify the process for file-based resources like image files (.BMP, .GIF, .JPG, and so on).

The advantage of doing resources the .NET way is they're easier to localize. Just translate the text/resource and store it in a subfolder with the same name as the locale—en for English, fr for French, or kv for Komi. The Framework automatically loads the proper assembly based on the user's CultureInfo.CurrentUICulture (MFC does something similar with satellite DLLs based on GetSystemDefaultUILanguage.) So if you want to be a full-fledged .NET citizen, you should probably rewrite your library to use satellites and ResourceManager. But if localization isn't important (perhaps you're loading internal error messages not seen by users) or time is short, you can still load old-style string resources from your .RC file. But you have to call ::LoadString or use CString internally to load the string, then copy it to the caller's String object. That's the wonderful thing about writing in C++! You can call Windows directly without explicitly using P/Invoke, and use your favorite ATL/MFC classes as usual. The only trick here is that since you want to load the string from your DLL, not the calling application, you must explicitly tell LoadString to use your DLL's HINSTANCE:

CString s; HINSTANCE h = ::GetModuleHandle(_T("MyLib.dll")); // use DLL's handle s.LoadString(h, id);

Figure 3 shows the full working code. Figure 5 shows the results if you compile and run RefTest. As always, you can download RefTest and all the other code from the MSDN Magazine Web site.

Figure 5 RefTest in Action

Figure 5** RefTest in Action **

Happy programming!

Send your questions and comments for Paul to  cppqa@microsoft.com.

Paul DiLascia is a freelance software consultant and Web/UI designer-at-large. He is the author of Windows++: Writing Reusable Windows Code in C++ (Addison-Wesley, 1992). In his spare time, Paul develops PixieLib, an MFC class library available from his Web site, www.dilascia.com.