Is it somehow possible to run .exe without some of the (mainly 3rd party) dlls which may (or may not) be present? The reason for this is that if some of the drivers are not present, I want only to block using the HWs, not to block program execution.
For example: Run .exe which checks if there is desired .dll libraries and make action if not:
Warn user that some of the libraries are missing.
Forbid to use some part of code until the appropriate library is present.
I found out, that library checking is possible with function like this:
bool checkLibrary(std::string dllName) {
std::wstring stemp = std::wstring(dllName.begin(), dllName.end());
return LoadLibrary(stemp.c_str()) != NULL;
}
But when I run .exe, it shows me allways error, that .dll is missing. It looks like that OS or APP finds all dependecies before start of the .exe, but seems to be static linked. How link dlls dynamically when its functions is needed?
This is an option in Visual Studio. It's called Delay-Load Linking (/DELAYLOAD). By default, Visual Studio will set it up entirely for you, including the call to LoadLibrary.
Since you want to be notified about load failures, you'll need to set up a hook function. This will need to handle the dliFailLoadLib notification. Here you can show a custom error message, and set a "disabled" flag for your app's internal use.
Continuing with missing functions is a bit trickier. You'll need to handle more events though. If you set a "disabled" flag for internal use, you could just return &ExitProcessWrapper for each and every function that's not supposed to be called. This wrapper just calls ExitProcess(0), in case you overlooked something.
If you use headers you automatically link to library so on .exe loading it looks for that library. If you want to manually load DLL, you need to open it as you did and replace all calls by calls to place given by https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress
Related
I made changes to a function in a COM DLL. I've been unable to figure out how to debug the changes I made.
Background:
I recently inherited a Visual Studio 2012 C++ project that dates back many
years. I'm running Win7 Professional 64-bit.
The top-level design of the project is this:
The code that does most of the work is encapsulated in COM DLLs.
For each DLL there's a separate wrapper function that calls:
(1) CoInitialize
(2) CoCreateInstance
(3) CoUninitialize
There's a main program that presents a dialog to allow a user to select an option. Based on the selected option, the main program calls the appropriate wrapper function, which then runs the code in the corresponding COM DLL.
Problem Details:
(1) I've been unable to step through the code in the Visual Studio debugger.
(Trying to run in the debugger produces the error "Unable to start program
", where the named DLL is different from the modified one.)
(2) I put "fprintf(stderr, ...)" calls in the modified DLL code, but didn't get any output from the "fprintf" calls. (I do see output from "fprintf" calls I added to the wrapper function that invokes the DLL.)
I also tried opening a temporary debug file using "fopen", writing debug statements to the file, then fflush, and fclose. Also no output.
(3) I noticed a post (Calling fprintf from dynamic library (c++)) that suggested that, although "fprintf(stderr, ...)" should work, it would be better to implement a callback to a debug function in the main program. I attempted to do that.
The changes compile, but the linker reports an undefined reference to the name of the function in the DLL that was intended to allow the main program
to pass in a pointer to a callback function.
I'm confused by the undefined reference, because the modified DLL has a different exported function that the linker is able to resolve.
Specifically:
__declspec(dllexport) void SetLogFunc(LogFunc LogFuncPtr) [The new function.]
__declspec(dllexport) BOOL DoRosSum(SRosSumData* pRosSumData) [The existing function.]
I used the "ack" utility to search the entire codebase for the project,
including Visual Studio project files and binary files, looking for
references to "DoRosSum", and can't find any place where there's a reference
to "DoRosSum", but not also a reference to "SetLogFunc".
("SetLogFunc" is listed by "dumpbin" as an exported function.)
I should also mention that I reverted all my changes except for:
the "SetLogFunc" function in the COM DLL,
the callback debug function in the main program, and
the call to ""SetLogFunc"" in the main program.
so I don't think the problem I'm having getting debug output, or running in the VS2012 debugger, is related to the modification I originally made to the DLL code.
Apologies for the long post. In recent years I've mostly been working in C#, or working on linux systems. I have no experience with COM DLLs, so I may be
missing something simple.
If anyone has any thoughts on how to proceed I would appreciate it.
For the first question,
https://learn.microsoft.com/en-us/visualstudio/debugger/how-to-debug-from-a-dll-project?view=vs-2017
I think you can check if you have done this yet. Usually, if you haven't set up command correctly in project property/debugging, running debugger in VC always show you the message:
Unable to start program '......\your DLL'.
Since DLL need to be execute with an executable(.exe).
I noticed that you said the error message 'the named DLL is different from the modified one'.
Your main program will run with multiple DLL right? I think you also need to make sure you put other DLL(.dll) file in the folder of your main program application.
For undefined reference issue,
If you can compile the functions in DLL sides, it means the logic here is ok. However, linker report undefined error then it should be some issues for exporting this function to main program side.
I suppose you to first check in main program side to see if you include the correct header file.
Like right clicking the function name in main program "Go to Definition" will show you the header file. You can then see if the header file is the correct one.
Then you can check if you export functions correctly. You need to make sure main program link to the new compiled Object File Library(.lib). Every time you compile your DLL project you need to make sure main program link to the new compiled .lib and .dll and include the new header file.
Hope these helps.
Suppose I have an application app.exe which does a load-time link to d.dll, which in turn does a load-time link to dangerous.dll. Suppose that dangerous.dll is considered to have various security vulnerabilities. Suppose also that none of the functionality in dangerous.dll is needed by app.exe, and app.exe does not make any calls to d.dll that require it to use any functions in dangerous.dll.
I want to distribute the app without dangerous.dll, and ideally with minimal or no modifications to app.exe or d.dll. If I just remove dangerous.dll, I get a loading error when starting app.exe because it loads d.ll and d.dll tries to load dangerous.dll, which fails.
Option 1
I could make a "no-op" version of dangerous.dll, that provided all the same export function signatures as dangerous.dll, but had no-op code for all the exported functions themselves. That might not be too bad. I wonder if there already exists a tool that can take a .dll file and output another .dll file that has the same export functions, but ones that do nothing? This has the disadvantage that my no-op version of dangerous.dll would still be visible to the user, and it would look like my application still has the vulnerabilities in dangerous.dll.
Option 2
I wonder if there is some way, without building d.dll from source, I could hack d.dll so that it does not attempt a load-time load of dangerous.dll. It would be okay if this caused any calls from d.dll to a dangerous.dll function to fail/crash, since as I say app.exe should not cause d.ll to use any of the functions in dangerous.dll.
If you have the source for d.dll, then just fix it to not load/use dangerous.dll.
If you don't have the source, just build a dangerous.dll with stub implementations for all exported functions.
Case closed. Move on and spend your time on more productive stuff.
I am looking for a clean way to explicitly load library. Most often, I have a LIB and DLL pair so the LIB will handle all the "load stuff" and I can directly call the function in the dll. When doing this explicitly, I need to do sort of the following:
HMODULE libA = LoadLibrary("dllA.dll"); // NULL if load failed
HMODULE libB = LoadLibrary("dllB.dll"); // NULL if load failed
void (*functionA)(void) = libA ? GetProcAddress(libA,"functionA"):NULL;
void (*functionB)(void) = libB ? GetProcAddress(libB,"functionB"):NULL;
It will be messy if the LoadLibrary() and GetProcAddress() are found all over my code when I need to call function in DLL. I would like to know if there is a clean way such that I can write all the handling within 1-2 files and call the functions as if I am loading the library implicitly through LIB and DLL pair.
Indeed there is a way to get all the implicit linking convenience, while still being able to gracefully handle both library load as well as symbol lookup failures. Visual Studio offers Linker Support for Delay-Loaded DLLs, that give user code the ability to hook into the loader, and implement arbitrary recovery strategies for unavailable symbols (e.g. by returning a no-op stub). This makes it possible to consolidate all failure handling into a single place.
Write a pure interface to the external functions you need. (Platform dependent)
Provide an implementation class (for you platform). For your Windows implementation load the DLL, get the procedure address initially.
Than when the interface function need to be called, the class routes the call into the loaded DLL.
Use an similar way for other platforms.
This is nothing else than using of delay-loaded DLLs. It is just a manual solution. But the approach of using an interface allows you a real platform dependent solution.
I'm trying to build a project. I have a.lib file that I need to use in my project. I know that there are two ways to use this lib:
add it using #pragma comment(lib, "a.lib")
add it to linker dependencies Configuration Properties -> Linker -> Input -> Additional Dependencies
Now, a.lib uses StackWalk64 function DbgHelp. This library is supplied as DbgHelp.lib and DbgHelp.dll. I know that I can use it as a lib using two ways listed above. But what if I don't want to include it into my project and want to use DbgHelp.dll, how can I do that in Visual Studio?
If you want to call a function that is within a DLL, but don't want to link to the LIB file that imports these functions for you, then you can use LoadLibrary and GetProcAddress. (Though if you have the import library and can link to it, why do you want to load these functions manually?)
IF YOU HAVE THE DbgHelp.lib IMPORT LIBRARY, USE IT! LOADING FUNCTIONS MAUNALLY IS ERROR-PRONE IF NOT DONE RESPONSIBLY. USE WITH CAUTION!
// Type definition for a function pointer that can call the function
typedef BOOL (WINAPI *StackWalk64_func)
(
DWORD,
HANDLE,
HANDLE,
LPSTACKFRAME64,
PVOID,
PREAD_PROCESS_MEMORY_ROUTINE64,
PFUNCTION_TABLE_ACCESS_ROUTINE64,
PGET_MODULE_BASE_ROUTINE64,
PTRANSLATE_ADDRESS_ROUTINE64
);
// Within a function . . .
HMODULE hDbgHelpDll = LoadLibrary(TEXT("DbgHelp.dll"));
if (hDbgHelpDll == NULL)
{
// handle error and return
}
StackWalk64_func funStackWalk64
= (StackWalk64_func)GetProcAddress(hDbgHelpDll, "StackWalk64");
if (funStackWalk64 == NULL)
{
// handle error and return
}
// funStackWalk64 is valid and ready to use
Now you can call funStackWalk64 like the function StackWalk64, and pass the function pointer around the place. When you're done using the library, you should free the module handle:
FreeLibrary(hDbgHelpDll);
Please read up: http://www.learncpp.com/cpp-tutorial/a1-static-and-dynamic-libraries/
Implicit Linkage with an import library (using .lib)
In this case the static-library is an "import library", which automates the process of determining the effective functions in the DLL. This is called implicit dynamic linkage.
Explicit Linkage
If you don't want to use the import library you have to determine all functions by yourself, create corresponding pointers to the addresses of the procedures and use them after that.
Usually there's some InitDLL() function in your client code, which does this.
See: https://msdn.microsoft.com/de-de/library/64tkc9y5.aspx
The "GetProcAddress"-function can be used to obtain a handle to the function and call it.
This is called explicit dynamic linkage and requires also the calls to LoadLibrary() and FreeLibrary() on Windows.
More Info: http://www.equestionanswers.com/dll/what-is-implicit-and-explicit-linking-in-dynamic-loading.php
Explicit Linkage on Linux
For linux/unix things work differently. If you want to read up: http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
Usually (and in Visual C++ specifically,) the lib file that comes with a dll is what is called an "import library". It means that the library has no actual function bodies in it; it is just there to appease the linker and instruct it to generate an EXE (or DLL) that would use the first dll at load time.
It is so in this case too. Since you don't have access to the source code for DbgHelp so that you can build it as a real static library, you need to make do with the small import library at link time and the dll file at load/run time.
Note: the whole linking and dynamic linking concepts and mechanisms are obviously a lot more complex than what I have room here to discuss. So, the explanation above is quite narrow and specific to your question.
I have a 3rd party component that includes a .LIB and .DLL file. In order to use the component I link the .LIB into my C++ program, and distribute the .DLL with application. The functionality provided is very specific, and only relevent to a small sub-set of my users, but distributing the .DLL incurs a license fee.
One work around here is to have two versions of my app, one which links in the 3rd party component, the other that doesn't, but I'd rather avoid the extra time involved in maintaining and distributing a second build.
Ideally, I'd like to simply exclude the .DLL from the distribution, but if I do this I get the error 'This application has failed to start because XXXXX.DLL was not found. Re-Installing the application may fix this problem'. Is this an exception that I can catch and deal with in my code? Alternatively, can I delay the loading of the .DLL until an attempt is made to call the specific functionality provided, and handle it then, or simply check for the existence of the .DLL and act accordingly?
The environment is VS 2003 and VS 2008.
There is no way to stop the binding after linked with the dll.
The only way that youo have is if you dynamically load the
dll during runtime.
Dll resolving is done before your exe starts running.
Code could look somehow like that.
If this does not work for your third party dll you could write an own dll that wrapps the third party dll and which can be loaded dynamically at runtime.
HINSTANCE lib = LoadLibraryEx("C:\dlls\thirdparty.dll", NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if(0 != lib) {
// Dll is present so use it
typedef CObj ( __cdecl *tFunction ) (const wchar_t*, const int&);
tFunction functionEntry = (tFunction)(GetProcAddress( lib,"EntryFunction"));
assert(0 != functionEntry);
// call the function
CObj obj = functionEntry(L"Hello", 1);
}
else {
// dll not present
}
Update: Please make sure that you use fullpath to your dll to make sure not any dll is pulled that has this name.
Visual Studio has support for delay-loaded DLLs. Using this functionality, a DLL is loaded when you call a function from that library for the first time. But you should check the license of your component to see if that's allowed.
You could load the DLL dynamically using the LoadLibrary() API function
But then you must use the GetProcAddress() on every function exported by the DLL that your application needs to call.
You could use LoadLibrary function to explicitly load DLL and the check the result. If successful then use GetProcAddress to find your CreateMyInterfaceImpl function. Otherwise use fake implementation of your interface or don't use it at all.