I'm trying to load a dll (through LoadLibraryA) from another dll.
This is the problem:
c:\**EXE_DIR**\myExe.exe // this exe load the MY_DLL_N1.dll
c:\**DLLS_DIR**\MY_DLL_N1.dll // this dll load the MY_DLL_N2.dll
c:\**DLLS_DIR**\MY_DLL_N2.dll
the exe load the MY_DLL_N1.dll ... fine.
MY_DLL_N1.dll try to load (below the code) the MY_DLL_N2.dll (same dir) ... and here is my problem!
int LoadMyDLL()
{
// ...
// same path of the MY_DLL_N1.dll ... right?
handle = LoadLibraryA ("MY_DLL_N2.dll");
// ...
}
that's all .... any help is welcome!
Everything you need to know is located here: Dynamic-Link Library Search Order.
Consider using SetDllDirectory to add your DLL path to the LoadLibrary search path.
handle = LoadLibraryA ("MY_DLL_N2.dll");
Because you do not supply a path, the DLL search order is used. This will look in the executable's directory, but will not search in the directories of any DLLS that are loaded. Hence the failure to find the DLL.
You have a number of options:
Put all the DLLS in the same directory as the executable.
Pass the full path to the DLL when calling LoadLibrary.
Call SetDllDirectory to add the DLL directory to the search path. Make this call from the executable before loading the first DLL. Once you do this you won't need to use the full path when loading the first DLL.
Unless you have a need to share the DLLS between different applications, option 1 is always preferred. This makes it easy for you to be sure that the DLLs you load are the right ones. That's because the executable directory is always searched first.
Related
I'm trying to impletement a C++ dll named (let's say) name.dll, which loads another dll (not mine) that is also named name.dll.
In my name.dll implementation I'm loading the real name.dll using this line :
driver_library = LoadLibrary(_T("c:\\windows\\system32\\name.dll"));
My dll is in a program.exe.local folder so that the program load mine before the real one in System32.
Depending on which program.exe uses my dll, LoadLibrary either works fine or returns my own name.dll handle as driver_library, with GetLastError() returning "file not found".
In https://msdn.microsoft.com/en-us/library/windows/desktop/ms684175(v=vs.85).aspx it is explicit stated that "If the string specifies a full path, the function searches only that path for the module." Why and how does it load itself for some applications ?
What in the program.exe application could affect LoadLibrary's behavior ?
#Franck Boyne commented :
"You have two programs - let's call them fine.exe and own.exe. The fine.exe program loads your own name.dll and then loads the other name.dll from System32. The own.exe program loads your own name.dll but when it calls LoadLibrary you get back another handle to your own name.dll instead of a handle to the one from System32."
About own.exe (which is not at all my "own" application) :
-> name.dll is located in an own.exe.local folder I created, which is located in own.exe directory.
-> own.exe had an application.manifest file that I deleted (the application still launches correctled without it if not using my dll). own.exe does not have an embedded manifest (checked using sigcheck).
-> name.dll is not one of Windows "known dlls" from HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
-> own.exe does not load name.dll using LoadLibrary() (checked by setting a breakpoint into LoadLibrary/A/W/Ex functions)
-> own.exe and name.dll are both 64 bits.
About fine.exe (it's a sample, I have access to the code):
-> name.dll is located in the fine.exe application directory.
-> No manifest file (either embedded or text).
Is it possible your problem program is using DLL Redirection?
From the LoadLibrary documentation (emphasis added) ...
If a path is specified and there is a redirection file for the application, the function searches for the module in the application's directory. If the module exists in the application's directory, LoadLibrary ignores the specified path and loads the module from the application's directory. If the module does not exist in the application's directory, LoadLibrary loads the module from the specified directory. For more information, see Dynamic Link Library Redirection.
Update 6/4/2018
Here's what I think is happening.
Both of your programs are using load-time dynamic linking (sometimes called implicit linking) to link to a DLL called name.dll. I'm assuming both programs just specify name.dll without a full path name. If you want to check I think you can run dumpbin /imports against fine.exe and own.exe to examine the DLL name.
fine.exe
In the case of the program that does what you expect (loads the second name.dll from \Windows\System32) there's no DLL redirection involved so the standard DLL Search Order is followed during the implicit link. The application directory is searched before the system directory so your copy of name.dll gets loaded.
Then your name.dll executes a LoadLibrary call specifying a full path to the file C:\Windows\System32\name.dll. Since there's no redirection going on, the system directory version of name.dll gets loaded as you expect.
own.exe
In the case of the program that doesn't do what you expect (gets a handle to your own version of name.dll twice) there is DLL redirection going on because you have a directory called own.exe.local in the application folder. Since there's redirection going on, during the implicit link the standard search order is ignored and name.dll is loaded from own.exe.local.
Then your name.dll executes a loadlibrary call specifying a full path to the file C:\Windows\System32\name.dll. But this time there is redirection going on. The full path specified in the LoadLibrary call is ignored and the module is loaded from the redirection folder own.exe.local.
Since that copy of name.dll has already been loaded by the implicit linking you just get another handle to the module.
As was pointed out in the comments, the GetLastError result is misleading. The LoadLibrary call didn't return NULL (it returned a handle to your own name.dll) so the value returned by GetLastError doesn't apply to the LoadLibrary call.
In many cases to load some newer API one would use a construct as such:
(FARPROC&)pfnZwQueryVirtualMemory = ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), "ZwQueryVirtualMemory");
But then, considering a chance of Dll hijacking, is it better to specify a DLL's absolute path, as such. Or is it just an overkill?
WCHAR buff[MAX_PATH];
buff[0] = 0;
if(::GetSystemDirectory(buff, MAX_PATH) &&
::PathAddBackslash(buff) &&
SUCCEEDED(::StringCchCat(buff, MAX_PATH, L"ntdll.dll")))
{
(FARPROC&)pfnZwQueryVirtualMemory = ::GetProcAddress(::GetModuleHandle(buff), "ZwQueryVirtualMemory");
}
else
{
//Something went wrong
pfnZwQueryVirtualMemory = NULL;
}
The problem with the latter method is that it doesn't always work (for instance with Comctl32.dll.)
You don't have to do anything special for ntdll.dll and kernel32.dll because they are going to be loaded before you get the chance to do anything, they are also on the known-dlls list.
The dll hijacking issues often include auxiliary libraries. Take version.dll for example, it is no longer on the known-dlls list so explicitly linking to it is problematic, it needs to be loaded dynamically.
The best solution is a combination of 3 things:
Call SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32) if it is available (Win8+ and updated Win7).
Call LoadLibrary with the full path (GetSystemDirectory) before calling GetModuleHandle.
Don't explicitly link to anything other than kernel32, user32, gdi32, shlwapi, shell32, ole32, comdlg32 and comctl32.
If SetDefaultDllDirectories is not available then it is really hard to protect yourself if you don't control the application directory because various Windows functions will delay-load dlls like shcore.dll without full paths (especially the shell APIs). SetDllDirectory("") helps against the current/working directory but there is no good application directory workaround for unpatched pre-Win8 systems, you just have to test with Process Monitor and manually load the problematic libraries early in WinMain.
The application directory is a problem because some users just put everything in the downloads folder and run it from there. This means you might end up with a malicious dll in your application directory.
Update Sorry, guys, I was incorrectly determined the problem. All is working, error was in "other program logic". Please delete or close the question.
Qt5 is designed to load libeay32.dll and ssleay32.dll on program start before any instruction in main() (because it is static).
(Details: it is located in qtbase\src\network\ssl\qsslsocket_openssl_symbols.cpp:
static QPair<QSystemLibrary*, QSystemLibrary*> loadOpenSslWin32()
)
Issue:
my program starts with not its exe dir as working directory
libeay32.dll and ssleay32.dll resides in its exe dir
user cannot install OpenSSL in system dir
user cannot change PATH variable
I cannot recompile Qt, i.e. ship program with static Qt compiled with openssl-linked
Qt loads searches dlls in this order (from qtbase\src\corelib\plugin\qsystemlibrary.cpp):
Application path.
System libraries path.
Trying all paths inside the PATH environment variable.
No. 1 is Application path, but in fact it does not search there.
My program:
int main()
{
// at this point Qt5 already checked and tried to load the DLLs
// so this:
ChangeCurrentWorkingDirectoryToExeDir(); // some function to change cwd to current exe dir
// does not work :-(
// ... other program logic ..
}
How to force Qt5 to reload OpenSSL DLLs after changing working directory?
May be someone already faced this problem...
Update Sorry, guys, I was incorrectly determined the problem. All is working, error was in "other program logic". Please delete or close the question.
QSystemLibrary::load is called with onlySystemDirectory = false for SSL, so QFileInfo(qAppFileName()).path() is the first place where the DLLs are searched. Search order:
application dir
system path (e.g. C:\Windows\System32)
all paths in PATH
I don't find documentation for that, but in our software, Qt finds SSL libeay32.dll and ssleay32.dll when they are in the same directory as the application .exe, given that
the .dll files are not in PATH
the .dll files are not in the working directory
no qt.conf exists
If you have a qt.conf, the default library value might apply, which is .\lib.
Library search orders are discussed on MSDN at Dynamic-Link Library Search Order.
There's a few ways to handle loading libraries, but it sounds like most of them won't apply.
Its not clear to me why you can call ChangeCurrentWorkingDirectoryToExeDir, but you can't call SetDllDirectory. I'm probably missing something obvious.
It seems like your last option is to create an Qt.exe.local file. This is called Dynamic-Link Library Redirection, and will cause the linker to load the DLL specified in the local file.
I'm a .net developer mostly, doing something small in C++ so im having a little trouble.
I'm loading another C++ dll using hInst = LoadLibrary(TEXT("mydll.dll")); and I came to realize that this looks for the dll I'm trying to load in 'C:\' or in 'system32'.
Can someone show me how to load the dll from the current directory (without knowing what the current directory is ahead of time) ??
I know I should be using something like GetFullPathName but I'm having a little trouble getting it to work on my own...
The process current directory can be acquired using the function GetCurrentDirectory():
TCHAR bufCurrentDirectory[MAX_PATH + 1] = { 0 };
DWORD dwNumCharacters = ::GetCurrentDirectory(MAX_PATH, bufCurrentDirectory);
if(dwNumCharacters == 0) error();
Now the path to the process's current directory is in bufCurrentDirectory, unless the function failed. Just append "\\mydll.dll" onto the path, and you have an absolute path to the DLL.
Since the current directory of a process is somewhat variable, it may be better to use the path of the executable. To get the path of the current executable, you can do:
TCHAR bufExePath[MAX_PATH + 1] = { 0 };
DWORD dwNumCharacters = ::GetModuleFileName(NULL, bufExePath, MAX_PATH);
if(dwNumCharacters == 0) error();
Now bufExePath contains the entire path to the exe, including "\\my.exe". Replace my.exe with mydll.dll, and you'll have the absolute path to the DLL. I would recommend this method over the GetCurrentDirectory() method due to security concerns.
I believe loading from current directory is the default and first search. See the MSDN reference
The first directory searched is the
directory containing the image file
used to create the calling process
(for more information, see the
CreateProcess function). Doing this
allows private dynamic-link library
(DLL) files associated with a process
to be found without adding the
process's installed directory to the
PATH environment variable
http://msdn.microsoft.com/en-us/library/ms684175(v=vs.85).aspx
Use GetCurrentDirectory.
I'm including python.h in my Visual C++ DLL file project which causes an implicit linking with python25.dll. However, I want to load a specific python25.dll (several can be present on the computer), so I created a very simple manifest file named test.manifest:
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<file name="python25.dll" />
</assembly>
And I'm merging it with the automatically embedded manifest file generated by Visual Studio thanks to:
Configuration Properties -> Manifest Tool -> Input and Output -> Additional Manifest Files
-->$(ProjectDir)\src\test.manifest
python25.dll is now loaded twice: the one requested by the manifest, and the one that Windows should find through its search order.
Screendump of Process Explorer http://dl.dropbox.com/u/3545118/python25_dll.png
Why is that happening and how can I just load the DLL file pointed by the manifest?
After exhaustive battle with WinSxS and DLL redirection, here's my advice for you:
Some background
Various things can cause a DLL file to be loaded under Windows:
Explicit linking (LoadLibrary) -- the loader uses the current activation context of the running EXE file. This is intuitive.
Implicit linking ("load time linkage", the "auto" ones) -- the loader uses the default activation context of the depending DLL file. If A.exe depends on B.dll depends on C.dll (all implicit linkage), the loader will use B.dll's activation context when loading C.dll. IIRC, it means if B's DllMain loads C.dll, it can be using B.dll's activation context -- most of the time it means the system-wide default activation context. So you get your Python DLL from %SystemRoot%.
COM (CoCreateInstance) -- this is the nasty one. Extremely subtle. It turns out the loader can look up the full path of a DLL file from the registry using COM (under HKCR\CLSID). LoadLibrary will not do any searching if the user gives it a full path, so the activation context can't affect the DLL file resolution. Those can be redirected with the comClass element and friends, see [reference][msdn_assembly_ref].
Even though you have the correct manifest, sometimes someone can still change the activation context at run time using the Activation Context API. If this is the case, there is usually not much you can do about it (see the ultimate solution below); this is just here for completeness. If you want to find out who is messing with the activation context, WinDbg bp kernel32!ActivateActCtx.
Now on to finding the culprit
The easiest way to find out what causes a DLL file to load is to use Process Monitor. You can watch for "Path containing python25.dll" or "Detail containing python25.dll" (for COM lookups). Double clicking an entry will actually show you a stack trace (you need to set the symbol search paths first, and also set Microsoft's PDB server). This should be enough for most of your needs.
Sometimes the stack trace obtained from above could be spawned from a new thread. For this purpose you need WinDbg. That can be another topic, but suffice to say you can sxe ld python25 and look at what other threads are doing (!findstack MyExeModuleName or ~*k) that causes a DLL file to load.
Real world solution
Instead of fiddling with this WinSxS thing, try hooking LoadLibraryW using Mhook or EasyHook. You can just totally replace that call with your custom logic. You can finish this before lunch and find the meaning of life again.
[msdn_assembly_ref]: Assembly Manifests
I made some progress for the understanding of the issue.
First let me clarify the scenario:
I'm building a DLL file that both embeds and extends Python, using the Python C API and Boost.Python.
Thus, I'm providing a python25.dll in the same folder as my DLL file, as well as a boost_python-vc90-mt-1_39.dll.
Then I have an EXE file which is a demo to show how to link to my DLL file: this EXE file doesn't have to be in the same folder as my DLL file, as long as the DLL file can be found in the PATH (I'm assuming that the end user may or may not put it in the same folder).
Then, when running the EXE file, the current directory is not the one containing python25.dll, and that's why the search order is used and some other python25.dll can be found before mine.
Now I figured out that the manifest technique was the good approach: I managed to redirect the loading to "my" python25.dll.
The problem is that this is the Boost DLL file boost_python-vc90-mt-1_39.dll that's responsible for the "double" loading!
If I don't load this one, then python25.dll is correctly redirected. Now I somehow have to figure out how to tell the Boost DLL file not to load another python25.dll...
Dependency Walker is usually the best tool for resolving this kind of problem. I'm not too sure how well it handles manifests though...
Where in this entangled mess is the actual process executable file?
Two possibilities come to mind:
You are writing a Python extension DLL file. So the Python process is loading your DLL file, and it would already have its own python25.dll dependency.
The EXE file loading your DLL file is being built with header files and libraries provided by the DLL file project. So it is inheriting the #pragma comment(lib,"python25.lib") from your header file and as a result is loading the DLL file itself.
My problem with the second scenario is, I'd expect the EXE file, and your DLL file, to be in the same folder in the case that the EXE file is implicitly loading your DLL file. In which case the EXE file, your DLL file and the python25.dll are all already in the same folder. Why then would the system32 version ever be loaded? The search order for implicitly loaded DLL files is always in the application EXE file's folder.
So the actual interesting question implicit in your query is: How is the system32 python26.dll being loaded at all?
Recently, I hit a very similar problem:
My application embedding Python loads the python32.dll from a known location, that is a side-by-side assembly (WinSxS) with Python.manifest
Attempt to import tkinter inside the embedded Python interpreter caused second loading of the very same python32.dll, but under a different non-default address.
The initialisation function of tkinter module (specifically, _tkinter.pyd) was failing because to invalid Python interpreter thread state (_PyThreadState_Current == NULL). Obviously, Py_Initialize() was never called for the second Python interpreter loaded from the duplicate python32.dll.
Why was the python32.dll loaded twice? As I explained in my post on python-capi, this was caused by the fact the application was loading python32.dll from WinSxS, but _tkinter.pyd did not recognise the assembly, so python32.dll was loaded using the regular DLL search path.
The Python.manifest + python32.dll assembly was recognised by the DLL loading machinery as a different module (under different activation context), than the python32.dll requested by _tkinter.pyd.
Removing the reference to Python.manifest from the application embedding Python and allowing the DLL search path to look for the DLLs solved the problem.