I need to download a DLL from a web site on an Intranet and call an exported function in it. The client cannot leave temp files around.
Main Topics
Browse All TopicsI'd like to know how I can call LoadLibrary and load a DLL file that's not physically located on any disk. LoadLibrary loads a DLL file that's on disk and takes the files path name as a parameter. I have the contents of the DLL in memory and would like LoadLibrary to load the DLL from memory instead.
As far as I can see, I have the following options. I'd like some advice on which way to go and if anyone's got a better idea.
1. Create my own network redirector and use a UNC path to LoadLibrary, having the redirector return the data to LoadLibrary from the in-memory-image
NEGATIVE: A lot of work to create a redirector.
2. Create a URL Moniker (protocol) that knows how to retrieve the data from memory and then pass in the URL to LoadLibrary (i.e. myurl://file.dll)
NEGATIVE: LoadLibrary internally may call a low-enough level API to open the actual file where the API bypasses URL mapping -- that is, LoadLibrary may only work if it's an actual mounted file system.
3. Use INJLIB or Microsoft's own "Detours" library to trap calls the CreateFile (or whatever), as they are called by LoadLibrary and return a file HANDLE that'll actually retrieve the file from memory. Perhaps the HANDLE returned is a named-pipe and if that doesn't work. perhaps the calls to Read() are also trapped to return the data. Depending on how much support LoadLibrary needs.
NEGATIVES: The "Detours" library can't be used to do this on non-NT systems. INLIB can be used, but the versions that are currently available on the Net (from May '94 issue of MSJ) only supported NT (no Windows 95 back then). The author of INJLIB supposedly has updated INJLIB to work under newer Win32 OSs, but I can't seem to find that anywhere.
4. Write the memory contents to disk and then call LoadLibrary.
NEGATIVES: There's no way to delete the file after calling LoadLibrary on it. At least it didn't work when I tried it (yes, I called FreeLibrary on it.)
WORKAROUND FOR NEGATIVE:
Use MoveFileEx with MOVEFILE_DELAY_UNTIL_REBOO
Okay, I've rambled on enough about this. I'd like to hear some opinions about which way I should go and why.
It's hard to pronounce a "right answer" for this type of questions, so I guess the only thing I can do is give it to the person that gives me the best argument for a particular approach (weighing complexity vs. functionality, of course.)
I consider this a pretty advanced topic, so I'll set it for 300 points.
This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.
Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.
If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.
Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.
Access the answers to your technology questions today.
30-day free trial. Register in 60 seconds.
Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Try it out and discover for yourself.
30-day free trial. Register in 60 seconds.
Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.
>>The client cannot leave temp files around.
Why not? Most systems today have megabytes of temp files lying about all over the place.
I also don't understand why you can't delete the DLL when you are finished with it. The file should be free to be deleted after you call FreeLibrary() on it. But I'll have to admit that I've not tried this.
You know what, this is why I didn't originally state the reason behind it.
I am looking for a technical solution not someone's opinion of what I ought to do or not do. Keep your opinions to yourself if you don't have a constructive solution to my problem.
I am only looking for technical answers -- I am not interested in whether you feel I should or shouldn't do something.
Thank you!
>> 3. Use INJLIB or Microsoft's own "Detours" library to trap calls the CreateFile (or whatever) [...] NEGATIVES: The "Detours" library can't be used to do this on non-NT systems. INLIB can be used, but the versions that are currently available on the Net (from May '94 issue of MSJ) only supported NT (no Windows 95 back then). The author of INJLIB supposedly has updated INJLIB to work under newer Win32 OSs, but I can't seem to find that anywhere.
Look here for my package, which is something like DetoursEx for winNT/2k/XP/9x/ME:
http://help.madshi.net/Dat
The documentation is for the Delphi version of my package, but it's also available for ya C++ programmers.
However, I'm not sure how many APIs you will have to hook in order to get this whole thing running. LoadLibrary really goes VERY deep... CreateFile is only one part of it. As far as I know CreateFile internally uses memory mapped files for loading dlls - and as far as I know, it doesn't call CreateFileMapping, but instead an internal function, something like InternalCreateFileMapping,
>> 4. Write the memory contents to disk and then call LoadLibrary. NEGATIVES: There's no way to delete the file after calling LoadLibrary on it. At least it didn't
work when I tried it (yes, I called FreeLibrary on it.)
This is exactly the point where we should work at. Normally when you load a dll and then unload it again, you *CAN* delete it. I'm 100% sure about that. There can be several reasons, why it's different in your case:
(1) Maybe the dll called LoadLibrary for itself, so your FreeLibrary call only deferenced the loader count, but didn't really unload the dll. Please check GetModuleHandle after having called FreeLibrary to make sure the dll is really detached from your process.
(2) Maybe the dll is loaded into other processes. This can be the case if the dll is using SetWindowsHookEx or other methods to go into remote processes.
(3) Maybe the dll uses some APIs which are very sensitive. E.g. if your dll uses MCI and doesn't cleanly uninit it, the dll remains in use until the next reboot.
I would suggest investing time into finding out why you can't delete the dll - because you should be able to. And that would be absolutely the easiest and best solution for you. No hacking into deep system APIs...
Regards, Madshi.
Regards,
Thanks. I'll give you more info on not being able to delete the DLL. Okay, the new DLL is called temp.dll. I have another DLL call main.dll. Say a process implictly loads main.dll (by linking to main.lib, the import library). When the process is invoked, main.dll's DllMain() gets called. In there, in the "process attach", I create temp.dll and call LoadLibrary on it, caching the returned hinstance. When the process terminates, it calls main.dll's DllMain() with "process detach". In there, I call FreeLibrary on the cached hinstance of temp.dll and verify that no one else has the DLL loaded. Right after the call to FreeLibrary, I attempt to delete temp.dll, but it fails. However, if the process invokes some well-known routine in main.dll, which in turns does the same logic as above, calling FreeLibrary on the hinstance, then temp.dll *can* be deleted.
I believe that the same behavior occurs when the process loads main.dll explictly (via a call to LoadLibrary).
Now, I did this first about 6 years ago and at the time I was testing under NT 3.51 and the newly released Windows 95 and don't recall if the behavior was on both systems. Suffice it to say, the solution should work on all Win32 systems.
Thanks for madCodeHook -- I'll check it out.
5. Simulate LoadLibrary on the DLL yourself.
5.1 Allocate a big enough virtual memory block, preferably at the preferred address of the DLL.
5.2 Unpack the DLL into the memory, according to section alignment. Patch relocation if relocated.
5.3 Load new DLLs needed by the DLL (use normal LoadLibrary).
5.4 Patch DLL's import table.
5.5 Call DLL's entry point.
www.fengyuan.com
>> In there, I call FreeLibrary on the cached hinstance of temp.dll and verify that no one else has the DLL loaded.
Please call GetModuleFileName(cachedhi
>> Right after the call to FreeLibrary, I attempt to delete temp.dll, but it fails.
What does GetLastError say?
Regards, Madshi.
Hi FengYuan,
hmmm... what if the dll internally calls GetModuleFileName with its own HInstance value to find out the full path where the dll file is loaded from? That call would fail, would it not? I mean, your suggestion is not guaranteed to work with all dlls, some dlls might not work correctly because GetModuleFileName (and related APIs) fail, or am I wrong? Apart from that I do like your suggestion...
Regards, Madshi.
Hi shrif,
I don't know which OS you're working on, but in following article it's mentioned that
at least with Win98 you can't call FreeLibrary() within DllMain within DLL_PROCESS_DETACH:
http://support.microsoft.c
hope that helps,
ZOPPO
>>>I am looking for a technical solution not someone's
>>>opinion of what I ought to do or not do. Keep your
>>>opinions to yourself if you don't have a constructive
>>>solution to my problem.
>>>I am only looking for technical answers -- I am not
>>>erested in whether you feel I should or shouldn't
>>>do something.
Well just EXCUSE ME for trying to understand your problem and help!@
6. Dummy DLL.
6.1 Wipe out code/data in the DLL.
6.2 Write to disk.
6.3 LoadLibrary the DLL.
6.4 Restore old code/data.
www.fengyuan.com
I just ran the following code snippet
#include "stdafx.h"
#include <windows.h>
int main(int argc, char* argv[])
{
::CopyFile("dllunload.dll"
HMODULE hModule=::LoadLibrary("dll
::FreeLibrary(hModule);
::DeleteFile("dlltemp.dll"
return 0;
}
and the dlltemp was unloaded fine and deleted.
Most easiest way, not elegant though - just because the Windows does not allow to do anything else.
In DLL_PROCESS_DETACH, create the .BAT file and call CreateProcess() on it.
-----------------
@echo off
again:
del drive:\path\temp.dll
if not exist drive:\path\temp.dll goto quit
echo waiting
echo waiting
... several times
echo waiting
echo waiting
goto again
quit:
del drive:\path\nameOfTheBatFi
--------------
This BAT file will delete the DLL first, then itself second.
There is no way to really free another dll inside DLL_PROCESS_DETACH, so the bat file is the only option, in my humble opinion. CreateProcess() should use DETACHED_PROCESS of course.
This solution is a universal one for any vesion of Windows, and it is much more reliable that any API interception - detour etc.
Of course if you have time you can improve your skills by writting URL monikers or network redirectors. The only disadvantage is that they are separate programs that need to be distributed, installed etc.
As to the memory-based DDLs, I wish this could be possible. Unfortunately the 100% emulation is not possible, at least without a need to hack Windows. It means this way is not reliable as well.
my earlier code snippet - shows that FreeLibrary does unload the dll - I even experimented by adding GetProc addresses and calling code before calling FreeLibrary - still unloaded and deleted.
do you have anything else in your code keeping the library loaded or file locked? Have you closed all the handles that you used to create the file on the disk?
Shaunn, when you posted the comment of which you speak, it was obvious that you didn't read the previous comments because there I explained the conditions under which FreeLibrary wasn't working with me. I didn't bother to respond to you because I just got through explaining it in a comment prior to yours.
Then, another user, Zoppo, confirmed my findings by posting the knowledgebase article describing the scenario.
Did you miss that comment, too?
Some thoughts:
(1) Are both the process and the main.dll written by you? Then why don't you simply export a function from main.dll, which unloads and deletes test.dll. You can then call this exported function from the process, before you close the process. That would be by far the easiest and cleanest solution (at least IMHO).
(2) If you want to play with madCodeHook, I would suggest using a different approach then the one you thought about. Simulating a DLL load from memory is too difficult, I think. Why not hooking PostQuitMessage and ExitProcess? You can then in the callback function unload the test.dll and delete it - and then thereafter call continue with PostQuitMessage/ExitProces
Regards, Madshi.
Shrif
> it was obvious that you didn't read the previous
> comments because there I explained the conditions under
> which FreeLibrary wasn't working with me
I was responding to the comment
<snip>
4. Write the memory contents to disk and then call LoadLibrary.
NEGATIVES: There's no way to delete the file after calling LoadLibrary on it. At least it didn't
work when I tried it (yes, I called FreeLibrary on it.)
</snip>
the fact I missed your ramble about app -> dll -> dll - was due to the fact I didn't refresh seeing the question - and then posting the comment
However since the comment about not using FreeLibrary in DllMan is mentioned in the helpfile see FreeLibrary (which I assumed you read) and that you didn't respond to Zoppos comment - I assumed that it didn't apply in your case
so no it wasn't obvious that I hadn't read the above comments quite the opposite - I had read them but misinterprted you lack of response to other comments
The fact is you might as well do what madshi suggested and rework your code - something jhance would have mentioned earlier - eg tell us what you want to do and we'll see how to do it - rather then go a really complex route - a slight rework of your code would be a lot easier
There is another possibility, but it is a hack.
UnmapViewOfFile(LPCVOID(hT
CloseHandle(hSomeInternalF
DeleteFile("temp.dll")
hSomeInternalFileHandleFor
This works on my NT4
#include <windows.h>
#include <iostream.h>
#include <conio.h>
void main()
{
HINSTANCE hTempDll=LoadLibrary("b.dl
if(!hTempDll)
{
cout<<"Cannot load DLL"<<endl;
return;
}
CHAR buf[MAX_PATH];
GetModuleFileName(hTempDll
if(!DeleteFile(buf))
{
cout<<"1st DeleteFile failed - as expected"<<endl;
}
UnmapViewOfFile(hTempDll);
if(DeleteFile(buf))
{
cout<<"Deleted!"<<endl;
FreeLibrary(hTempDll);
}
}
Business Accounts
Answer for Membership
by: jhancePosted on 2001-08-15 at 18:54:56ID: 6391123
This is an interesting question....
Perhaps you could comment on why you are wanting to do this. Knowing what you are trying to do might spur some alternate ideas into my mind.