Oftentimes in the software development world, a need arises to leverage the functionality of a closed-source application. The nature of this need can vary widely, but a simple use case is when a user has a piece of software for performing a task, but no interface is available for automating it. Our particular example involved a USB webcam with some vendor provided software for enabling a facial detection feature. The facial detection was used for zooming in and centering on the subject’s face. The standard functionality of the camera could be controlled using the Windows DirectShow API, but accessing this particular facial detection feature was only possible through the proprietary interface.
There’s a variety of free, open-source tools for automating third party software, but unfortunately they do their job through the same interface the operator may be using. They rely on executing commands in a script for sending keystrokes, reading pixel values, or clicking mouse buttons at predetermined locations. With some clever hacking, they can be used for solving complex automation needs. However, for our particular use case, our client needed a robust and seamless user experience. Using the automation tools to achieve a simple button click proved intrusive and distracting, so a simple automation script wouldn’t cut it.
Dynamic Link Libraries (DLLs) have been an integral part of Windows since its infancy. They provide a convenient means of encapsulating pieces of functionality into separate containers that can be accessed by programs. The idea is that they can be linked into a piece of software at load-time (static import) or during run-time (dynamic import).
One example of the usefulness of run-time DLL linking is when a developer wants to selectively control the features of some software. Functionality can be limited through the inclusion or exclusion of certain DLLs, based on a user’s particular license. If the program doesn’t find the DLLs during run-time, it can gracefully fail and inform the user that the feature is unavailable. Having the capability to access software features through a DLL instead of the standard GUI sounds like a great way to automate a task, but unfortunately if the DLLs were never intended to be used by another developer, the task can be non-trivial.
When compiling DLL code for use in your own application, the linker will generate an import library containing an import address table. This has all the information needed for referencing the functions. When the code is written that references the DLL, it uses the import library as a map to point to locations in memory where the functions are. Additionally, the referencing code uses header files that were shared with the original DLL code so it knows nature of the data types, the exported function names, and the class declarations.
When the source for the DLL is compiled in C (or in C++ by using the extern “C” convention) no name decoration is employed. When compiling code for use as a DLL, the function names must be ‘exported’ through the use of the __declspec(dllexport) keyword (in Visual C++). This embeds the symbolic names of the functions into the DLL, whereas the symbolic information would be discarded during compilation otherwise.
In our case, we had a web cam with software for the facial detection feature. We needed to toggle this functionality from a higher level GUI developed in C# with WPF. I knew one part of the solution would require writing a utility DLL in C++ to do the dirty work of importing the rogue library and providing utility functions that could be more easily imported into our C# app using Platform Invocation Services (P/Invoke).
I managed to send calls to a proprietary API of a C++ DLL. It accomplished our goal, but the complexity was greater than anticipated. There isn’t always a general purpose solution when trying to do something outside of the box, and some cases will inevitably require an ad-hoc approach. I’ve written a brief follow-up article that describes the techniques involved in more technical detail.