It depends on the kinds of the functions.
For plain (non-COM) functions, the only way is to use LoadLibrary
and GetProcAddress
. If either fails, you know the OS is missing that function. Writing those function pointer type declarations for function pointers duplicating existing function signatures can be tedious, though in VC++2010 you can use decltype
for that. For example:
HMODULE user32 = LoadLibraryW(L"user32");
if (user32 != NULL)
{
auto messageBoxW = reinterpret_cast<decltype(MessageBoxW)*>(GetProcAddress(user32, "MessageBoxW"));
if (messageBoxW != NULL)
{
messageBoxW(HWND_DESKTOP, L"Hello!", NULL, MB_OK);
}
}
However, many Shell APIs are exposed via COM components and interfaces. Those cases are different. Sometimes you need to deal with entirely new components; e.g. IApplicationDestinations
is a new interface in Win7, and the coclass that implements it is also new. In those cases, you can just do CoCreateInstance
, and check the return value for REGDB_E_CLASSNOTREG
- this means that such coclass isn't registered on the system (and, effectively, isn't supported).
Sometimes, however, new OS versions introduce new interfaces on existing coclasses. An example is ITaskbarList3
, new in Win7, but provided on existing coclass that implements ITaskbarList
and dates back to Win95. In those cases, you should first instantiate the coclass for the most basic interface, and then use QueryInterface
to obtain new interface versions, and detect that they're not supported by checking return value for E_NOINTERFACE
.