otto sleger
otto sleger

Reputation: 143

How to detect if function is implemented in installed library?

I have my program for windows, which uses windows system library (let's name it "sysLib"), and it implements function "libFun1". My program can look like this:

#include <sysLib.h>

void myFunction() {
    //some magic here
}

int main() {
    myFunction();
    libFun1();
    return 0;
}

later, library gets update, in which new "libFun2" function is added and it perfectly does what my "myFunction" do and even does it better. So I update my program to look like this:

#include <sysLib.h>

int main() {
    libFun2();
    libFun1();
    return 0;
}

I compile it and push update to clients.

But there are some clients, who doesn't have last version of windows and they have the old version of "sysLib" which doesn't implement "libFun2", so program for them doesn't work (doesn't even start).

I figured out, that if i compile my program with "delayimp.lib /DELAYLOAD:sysLib.dll", program is now startable, but falls when "libFun2" is called.

I would like to now update my code to looku something like this:

#include <sysLib.h>

void myFunction() {
    //some magic here
}

int main() {
    if(/*libFun2 exists*/) {
         libFun2();
    } else {
         myFunction();
    }
    libFun1();
    return 0;
}

How can i detect, if "libFun2" function exists inside library and make logic around it?

I know that in linux is possible to do if(libFun2), but this doesn't work in windows

UPDATE:

I found out, that it can be catched by __try __except combination, but it doesnt work for me...

https://learn.microsoft.com/en-us/cpp/build/reference/error-handling-and-notification?view=msvc-170

Upvotes: 0

Views: 430

Answers (2)

otto sleger
otto sleger

Reputation: 143

Solution is pretty simple:

#include <sysLib.h>
#include <delayimp.h>
int CheckDelayException(int exception_value)
{
    if (exception_value == VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND) ||
        exception_value == VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND))
    {
        // This example just executes the handler.
        return EXCEPTION_EXECUTE_HANDLER;
    }
    // Don't attempt to handle other errors
    return EXCEPTION_CONTINUE_SEARCH;
}

void myFunction() {
    __try {
         libFun2();
         return;
    } __except (CheckDelayException(GetExceptionCode())) {
         myFunction();
    }
    //some magic here
}

int main() {
    myFunction();
    libFun1();
    return 0;
}

https://learn.microsoft.com/en-us/cpp/build/reference/error-handling-and-notification?view=msvc-170

UPDATE: moved __try into function for better usage in code, if multiple calls are used

Upvotes: 0

Anders
Anders

Reputation: 101616

bool hasExport(LPCSTR mod, LPCSTR func)
{
  HMODULE handle = LoadLibraryA(mod);
  return handle && GetProcAddress(handle, func);
}

...

if (hasExport("syslib", "libfun2"))
  libfun2(); // must be delay loaded
else
  ...

This code assumes that you don't need to unload the library again. It also does not care if the library was already loaded. Use GetModuleHandle or FreeLibrary if you need a different behavior.

In this specific case, since you have a replacement function you could instead use a delayload hook and handle dliFailGetProc by returning the fallback function.

Upvotes: 5

Related Questions