Reputation: 137
I am trying to use UrlDownloadToFile OR InternetOpenUrl to visit some link on the Internet from an DLL file. While it works on an .exe file, but it didn't work from a DLL file, and even no any error information. It just failed without any information.
Anyone could give me any help? Thanks in advance.
My code are as below:
extern "C" __declspec(dllexport) int __stdcall Hello()
{
HINTERNET hInt=NULL, hUrl=NULL;
hInt = InternetOpenA("Test Agent", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
hUrl = InternetOpenUrlA(hInt, "http://www.google.com.au", NULL, 0, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_CACHE_WRITE, 0);
if (hUrl)
{
InternetCloseHandle(hUrl);
}
InternetCloseHandle(hInt);
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
Hello();
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
It failed at:
hUrl = InternetOpenUrlA(hInt, "http://www.google.com.au", NULL, 0, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_CACHE_WRITE, 0);
Or:
typedef HRESULT (__stdcall * lpURLDownloadToFile) (LPUNKNOWN pCaller, LPCTSTR szURL, LPCTSTR szFileName, DWORD dwReserved, LPBINDSTATUSCALLBACK lpfnCB);
extern "C" __declspec(dllexport) int __stdcall Hello()
{
HMODULE hModule = LoadLibraryW(L"urlmon.dll");
lpURLDownloadToFile urlD = (lpURLDownloadToFile)GetProcAddress( hModule, "URLDownloadToFileW" );
HRESULT aa = urlD(NULL, L"http://www.google.com.au", L"C:\\Test\\a.html", 0, NULL);
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
Hello();
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
It failed at:
HRESULT aa = urlD(NULL, L"http://www.google.com.au", L"C:\\Test\\a.html", 0, NULL);
If I insert a line like "MessageBox" just above where it fails, the MessageBox will be displayed successfully.
If I insert a line like "MessageBox" just after where it fails, the MessageBox will not be displayed. And there is no any error code returned if I tried to display "hUrl" or "aa".
Upvotes: 2
Views: 1637
Reputation: 7620
Don't do that in DllMain
. See DllMain entry point
The entry-point function should perform only simple initialization or termination tasks. It must not call the LoadLibrary or LoadLibraryEx function (or a function that calls these functions), because this may create dependency loops in the DLL load order. This can result in a DLL being used before the system has executed its initialization code.
EDIT, as you want to inject the Dll and run code in it.
One way to make an injected Dll to start executing code, without relying on DllMain is as follow:
Use a message hook, limited to one thread.
Find a HWND belonging to the process you want to inject. For Internet Explorer, you may enumerate the Top Level Windows, using EnumWindows A main IE Windows has a class IEframe
. Use EnumChildWindows to find a window of class Internet_Explorer Server
. Use GetWindowThreadProcessId to get the associated TID (Thread Identifier).
Use SetWindowsHookEx to install a thread hook. You may choose a WH_CALLWNDPROC
or a WH_GETMESSAGE
hook. Pass the TID obtained in 1. Your DLL is injected, and is processing messages.
Use PostMessage
or SendMessage
or PostThreadMessage
, depending on the hook type you choose in 2, with a registered message. See RegisterWindowMessage
In your hook function, filter for the registered message (obtain it's value in your DllMain and store it in a global variable) and when this message is received, call your custom code.
Warning: this technique is well suited for short living code, you are in a hook function. That's maybe not the place for downloading from the Internet.
Another way is to create a thread in DllMain
, using _beginthreadex
In the thread, you may have a classic RegisterClass / CreateWindow / GetMessage/ DispatchMessage sequence, and your EXE will be able to Send/Post messages to your Dll.
Warning: depending on how you injected the Dll, you must be very carreful about premature unloading of your Dll. If the thread still runs, there may be crashes. Being clean and stable with theses things is not easy. But, if you are just playing/experimenting, don't bother and just LoadLibrary
(not in DllMain) you own library a second time, it will stay here forever.
You can mix the two techniques, that is: use a thread message hook to inject the Dll and start a thread in the hook function.
Upvotes: 1