Posts Tagged ‘C++’

Template Class for Dynamic Linking

Friday, June 5th, 2009

Dynamic linking (or runtime linking) is the method of finding and calling a function in a DLL at runtime. The most common use for it is when you can’t be certain that the DLL or function will exist. For example, if you calling a new WINAPI function which only exists in Vista, but you want your application to still run on XP, you will need to use dynamic linking.

The process is simple: load the DLL, get the address of the function and make the call. You need just 3 WNAPI calls to get the job done. Of course, there is error checking too, so a typical function call requires several lines of code, and if you want to save the pointer for use later, you still have worry about keeping track of the handle to the DLL and releasing it when you are done.

So I made a template class to encapsulate the entire process, creating essentially a smart pointer for dynamic functions.

template <typename FunctionPtr> class CDynamicFunction
{
public:
    // Constructor automatically binds the function.
    CDynamicFunction(CString dllName, CString procName)
    {
        _module = ::LoadLibrary(dllName);
        if (_module == NULL)
        {
            // error, DLL probably doesn't exist
            _procAddress = NULL;
        }
        else
        {
            // Get the function pointer - this will be NULL if the function doesn't exist.
            _procAddress = (FunctionPtr)(::GetProcAddress(_module,procName));
        }
    }

    // Destructor automatically releases the DLL.
    virtual ~CDynamicFunction(void)
    {
        if (_module != NULL)
        {
            ::FreeLibrary(_module);
            _module = NULL;
        }
    }

    // Use this method like a regular function. Check for NULL first, in case the function
    // couldn't be linked.
    virtual operator FunctionPtr()
    {
        return _procAddress;
    }

private:
    HMODULE     _module;
    FunctionPtr _procAddress;
};

To use the template class do the following:

1. Typedef a pointer to the function you want to import. The syntax below is for a Windows API call, but you can define it as needed.

typedef LONG (WINAPI *pMyEntryPoint) (HWND hwnd, int xyz);

2. Instantiate the class either in a local stack frame, or in another class. The DLL is loaded upon instantiation and it will be automatically unloaded when the class goes out of scope.

CDynamicFunction<pMyEntryPoint> myEntryPoint("blah.dll", "MyEntryPoint");

3. Check the result of the class and call your function:

if(myEntryPoint == NULL)
{
    // handle error
}
else
{
    LONG result = myEntryPoint(hwnd, x);
}

Simple and reliable, and it avoids the common errors that come from writing the same code in many different places.

Version Info

Saturday, February 16th, 2008

You would think that retrieving version information from a program would be a basic and simple task. For example if you want to display your version number in an About box. For a long time I’ve stored version numbers in a resource (as they should be) but used a separate #define in the code, which is easy to access and display in an About box. Finally I got tired of this redundancy and dug up some old code I had (circa 1998!) and holy crap, it still works. And holy crap, the API hasn’t changed either.

The code was in C, and ugly, so I made a new class based on the old code. It has a static method to get the fixed portion of the version resource, and another method to get a string. one to get a string.  Here is the string version:

CString CMyVersion::GetStringItem (CString modulename, CString itemName)
{
    CString result = "";
    if (modulename.IsEmpty())
    {
        modulename = CCoreFile::GetProgramPath();
    }

    DWORD handle; // not used, will be set to 0.
    DWORD size = ::GetFileVersionInfoSize (modulename, &handle);
    if (size > 0)
    {
        VOID* block = ::HeapAlloc (::GetProcessHeap(), HEAP_ZERO_MEMORY, size);
        if (block != NULL)
        {
            if (::GetFileVersionInfo (modulename, 0, size, block))
            {
                // The pointer returned in buffer is freed automatically when block is freed.
                // This assumes the english language block
                itemName = "\StringFileInfo\040904E4" + itemName;
                LPBYTE buffer;
                UINT length;
                if (::VerQueryValue (block, itemName, (LPVOID*)&buffer, &length))
                {
                    result = CString(buffer);
                }
            }

            ::HeapFree(::GetProcessHeap(), 0, block);
        }
    }

    return result;
}

Note the limitation, this method assumes you want an item in the English language version of the StringFileInfo block. Since I don’t foresee myself needing my version number in Swahili, I think this limitation will be fine.

To get the file or product version using this class:

CString fileVersion = CMyVersion::GetStringItem(modulename, "FileVersion");

CString productVersion = CMyVersion::GetStringItem(modulename, "ProductVersion");

Getting the fixed part of the version resource is similar:

BOOL CMyVersion::GetFixedInfo (CString modulename, VS_FIXEDFILEINFO* info)
{
    BOOL result = FALSE;

    if (modulename.IsEmpty())
    {
        modulename = CCoreFile::GetProgramPath();
    }

    DWORD handle; // not used, will be set to 0.
    DWORD size = ::GetFileVersionInfoSize (modulename, &handle);
    if (size > 0)
    {
        VOID* block = ::HeapAlloc (::GetProcessHeap(), HEAP_ZERO_MEMORY, size);
        if (block != NULL)
        {
            if (::GetFileVersionInfo (modulename, 0, size, block))
            {
                // The pointer returned in buffer is freed automatically when block is freed.
                LPBYTE buffer;
                UINT length;
                if (::VerQueryValue (block, “\”, (LPVOID*)&buffer, &length))
                {
                    length = min(length, sizeof(*info));
                    ::CopyMemory(info, buffer, length);
                    result = TRUE;
                }
            }

            ::HeapFree(::GetProcessHeap(), 0, block);
        }
    }

    return result;
}

The Windows Version API certainly is robust, and supportive of multiple languages, but for goodness sake, didn’t the author realize that most of its usefulness would be in retrieving a version number? Why go through all of this nonsense for such a simple task?

Deleting Browser History

Friday, October 12th, 2007

Here is another exercise in futility. Using the IE ActiveX (er, COM?) interface to automate Internet Explorer. I’ve got an app that navigates to a web page, but I don’t want it to leave an entry in the browser history list. Sounds simple enough. And hey look, there’s a flag you can pass to the IWebBrowser2.Navigate method: navNoHistory. Sweet!

I thought I was done in 10 minutes. But it turns out, that flag only pertains to the browser’s session history. Not the global history, which is where you see your link listed in the side-bar when you open the history list. Doh!

As usual, the docs are completely vague and unhelpful:

navNoHistory – Do not add the resource or file to the history list. The new page replaces the current page in the list.

Nothing about sessions versus global. And new page replaces the wha?

Ok, so I poked around some more and found another interface: IUrlHistoryStg. And look, it has a method: DeleteUrl. Well surely I’m done now. Not.

Ok. Here is what it says under More Information in that article:

DeleteUrl is not designed to delete the Internet Explorer History Shell folder entries.

Just great. The method to delete urls from the history folder is not designed to delete urls from the history folder. But wait…you can use this other method that requires 15x more lines of code, and pops up a dialog box which you can’t suppress. Just freaking brilliant!

Plan C: Wininet always has something. Yeah. Well, sort of. Ok, not really. <sigh> DeleteUrlCacheEntry yielded the same results: successful operation, but the history entry remained.

I should point out, the result codes for either of these methods  indicated the operations were successful. I also tried feeding them bogus urls, to verify they would fail on bad data, and they did. So both IUrlHistoryStg.DeleteUrl and WinInet’s DeleteUrlCacheEntry will tell you they successfully deleted your url, but in fact didn’t.

Lovely.

I spent the better part of a day on this, by the way. I also tried traversing the cache and overwriting what was there, but none of it worked.

I should also point out, these Delete Url imposters may actually work, as according to the docs, when you delete a url, it is only flagged, and  whenever the "cache scavenger" feels like getting off it’s lazy ass and doing its job, it will then actually delete the url. Anyone got an API call for "kick-the-lazy-ass-welfare-sucking-cache-scavenger-into-high-gear"??

But I digress. It might be nice if once in a while Microsoft could document their API’s as such: "DeleteUrl is a fictitious API that looks like it might do what you want it to do, but after you spend 3 hours testing it out, will actually turn out to do nothing but leave you feeling empty and jaded." Of course, if I ever read such an entry in the help file, I would probably spend the 3 hours finding out that it didn’t (er, did?) work as advertised. :)

MFC and Multiple Inheritance

Thursday, October 11th, 2007

A lot of programmers scoff at multiple inheritance, and it is not something I would use very often, but there are times when it makes sense. Recently I did some refactoring to some dialog classes, which are based on MFC. Looking at what we had, it was a perfect case for using multiple inheritance. But then I found out after trying to implement it that apparently the folks who wrote MFC don’t believe in multiple inheritance either. They have this to say in the linked article:

We have found that MI is not required to write a class library, nor is it required for writing serious applications.

Are you kidding me?! That’s a rather condescending remark to say the least, especially from the folks who brought us COM! I would suggest to Microsoft that MFC is not required for writing serious applications either.

The Details…

What I had to deal with were some dialogs that are assembled on the fly. We have control classes that do special things, so naturally there is a class for each one: label, checkbox, edit, button, etc. The previous implementation used a wrappered approach: there was a class for each control and private to that class was an instance of an MFC control. Then each class defined its own methods for all of the usual control functions, like positioning, font, color, etc. with each method operating on its own private control. A lot of redundant code, and compounding it was a lot of application-specific code repeated in each class as well.

So my main goal for this refactor was to eliminate as much redundant code as possible.

First I needed a base class for my controls, to handle the application functions common to all of them. This eliminated a lot of redundancy, but I still had the same SetText, SetColor, etc. defined in each class. Here is where multiple inheritance would be key. I wanted to make my base control class a descendant of CWnd (base class to MFC controls), so that I could handle all of the common control operations in one class. Then I would make each of my control classes descendants of the MFC controls they implement. Only the functions specific to each control, like handling a checkbox would need to go in the descendant classes. 90% of the work can be done in one base class.

The structure is like this:

class CMyControl : virtual public CWnd {…}

class CMyEdit : public CEdit, public CMyControl {…}

With this structure, I can handle all of the basic control operations, like setting text, changing colors, moving, etc. in CMyControl. Each derived control class can deal only with what it needs to.

You might be wondering, aren’t there two copies of CWnd in the v-table? One for CMyControl’s base class, and one for CMyEdit’s instance of CEdit? Normally there would be, and that would be a problem, but that’s why C++ gives you the option to declare a virtual base class. This tells the compiler to keep only one instance of CWnd in the class, so any operations on CMyControl’s CWnd will actually operate on CEdit’s CWnd.

It is a beautiful design, and one that eliminates all redundant code. Except for one small problem: IT WON’T COMPILE!!

It won’t compile because of how MFC is implemented, and given the remark I quoted above, I think some folks at Microsoft need to go back to OOP school. ;-)

The workaround I ended up using, was to remove the virtual base class, and instead use a GetCWnd method so that each descendant class can return a pointer to it’s underlying CWnd. I made GetCWnd a pure virtual method in the base class so that each descendant is required to implement it.

So now, instead of a nice clean call like this:

mycontrol.SetWindowText("This is great!");

I have to write:

mycontrol.GetCWnd()->SetWindowText("This really blows!");

Sure, I could go and write a pass-through method for each and every CWnd method, but who wants to do that?

Even worse, MFC message handlers have to be repeated in each descendant class! Ugh. I’ve got handlers for things like CtlColor and OnSetCursor. It’s the exact same code for each class, but now I have to copy and paste it into each of my control classes. Note: if you find yourself cutting and pasting code into multiple classes, then something is wrong!

All in all, the classes are much better than they were, but they could have been perfect.

Technorati Tags: , ,

Dealing with Vista’s Low Cookies

Tuesday, September 11th, 2007

Vista with Internet Explorer 7 introduced a new security level called protected mode. Among other things, this mode stores cookies in a separate cache, which is inaccessible to normal mode processes. This "feature" caused me a bit of a problem with a Windows application I support.

Users download this application from a web site. When the application runs, it makes additional requests to the web site. The web site keeps track of these requests with cookies. The problem is that a typical user with default settings is going to hit the download in protected mode, thus leaving the cookie in the low integrity cache. But, the application runs in normal mode, so when it makes requests to the web site, the web site is unable to read the original cookie it left. There is no way for the normal mode application to get at this quarantined cookie. No easy way at least.

I should point out that this app is using automation to open Internet Explorer and download additional content. Even though it’s accessing the same web site, because the app is running in normal mode, the site is now accessed in normal mode as well. If you’re downloading files using wininet, you’ll get the same result. Web site sees the normal cache and can’t get the cookie it left the first time.

The solution I came up with is to run a low integrity process to read the cookie from the low cache and write it to a place where the application can read it, and then save it as a normal cookie. For the low integrity process, I run another copy of the application so there’s no extra baggage; it’s all self contained.

Step by step, here is the process:

1. Check if we’re running on Vista. You could also check if the browser is in protected mode, but finding or not finding the cookie is pretty much the same.

2. Run a new copy of the app in low integrity mode (you could have a separate app for this). What I do is pass a command line parameter to tell the app it needs to find the low cookie. Basically just get the filename for the current process using GetModuleFileName and use this sample code to start the new process.

Also note that since this app needs to run on all versions of windows, entry points to new Vista functions need to be dynamically loaded.

In the command line, I also pass the location where the cookie is to be written. You’ll need a location that both low and normal processes can access. Luckily Microsoft does provide such a thing. You can call SHGetKnownFolderPath with FOLDERID_LocalAppDataLow to get a folder that both processes can read and write.

3. When the low integrity process runs, it uses InternetGetCookie to read the cookie from the low cache. Because the process is low integrity, it automatically reads from the low cache.

Reading cookies in a C++ app is not as simple as you would think. I could make another post on that. In short, what you get back from InternetGetCookie is a string with all cookies for a given url separated by semicolons. Each cookie in the string is in the format name=data. So I ended up with some convoluted parsing routines. Well, maybe your cookies are written differently, but this is what I had to deal with. Anyway…

4. After finding the right cookie, the low integrity process writes it to a text file.

5. The main process, after waiting for the low process to finish, reads back the cookie data and uses InternetSetCookie to write the cookie to the normal cache. One caveat I found is that you have to append an expiration to the cookie string:

"; expires = Fri, 01-Jan-2038 00:00:00 GMT"

And that’s it. Now the web site can read the cookie it left on the initial download. Pretty big hoop for a basic operation that used to work all by itself for years. Thanks Microsoft!