user1748640
user1748640

Reputation: 137

urldownloadtofile OR InternetOpenUrl not working from DLL

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);

Update:

Upvotes: 2

Views: 1637

Answers (1)

manuell
manuell

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.

  1. 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).

  2. 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.

  3. Use PostMessage or SendMessage or PostThreadMessage, depending on the hook type you choose in 2, with a registered message. See RegisterWindowMessage

  4. 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

Related Questions