Download a file using URLDownloadToFile C function

Scripting's Avatar author of Download a file using URLDownloadToFile C function
This is an article on Download a file using URLDownloadToFile C function in C.

Using URLDownloadToFile function



In this article I would want to show you how to download a file from internet using URLDownloadToFile function in C language. I think everybody has ever experienced the downloading a file with Internet Explorer. IE is using directly this function, but It uses some callback and GUI stuff too, I will show you how to download a file without any comlex callbacks nor GUI, it's gonna be pure download performing code.

So here we go.

Stuff needed:
  1. Internet Explorer 3.0 (or just urlmon.dll library)
  2. Internet connection (to make sure it works)
  3. C Compiler (I used Dev-C++ but code is optimized to work with every compiler)
The syntax of the function is following:
Code:
HRESULT URLDownloadToFile(
  LPUNKNOWN pCaller,
  LPCTSTR szURL,
  LPCTSTR szFileName,
  _Reserved_  DWORD dwReserved,
  LPBINDSTATUSCALLBACK lpfnCB
);
  • pCaller - This argument has to do something with ActiveX component, but I won't cover this in the tutorial, thus it will be always NULL unless we want to use ActiveX.
  • szURL - A pointer to a string value that contains the URL to download. Cannot be set to NULL. If the URL is invalid, INET_E_DOWNLOAD_FAILURE is returned.
  • szFileName - A pointer to a string value containing the name or full path of the file to create for the download. If szFileName includes a path, the target directory must already exist.
  • dwReserved - Even I don't know exactly what's that good for, but we will always use 0 for this...
  • lpfnCBv - this param is used to receive download status, but his really another level , will be always NULL for our basic purposes

Ok, so what can this function return?
  • S_OK - The S_OK return value just indicates that the download has started properly. Not that it has finished downloading, (for that information you will have to use the LPBINDSTATUSCALLBACK lpfnCB parameter to get a status callback). Note that it returns S_OK even if the file download succeeds but the file creation fails (e.g. because you specified a non-existent folder, drive, etc). Hence, you should ensure the file exists before attempting to operate on it.
  • E_OUTOFMEMORY - This is returned when the buffer length is invalid, or there is insufficient memory to complete the operation.

These two were the most common return codes, but as you may think, it's far not everything.

I won't describe another return codes, as they are very rare and not used commonly.
But here is shor list of them (still not all )

INET_E_INVALID_URL (800C000)
INET_E_NO_SESSION (800C0003)
INET_E_CANNOT_CONNECT (800C0004)
INET_E_RESOURCE_NOT_FOUND (800C0005)
INET_E_OBJECT_NOT_FOUND (800C0006)
INET_E_DATA_NOT_AVAILABLE (800C0007)
INET_E_DOWNLOAD_FAILURE (800C0008)
INET_E_AUTHENTICATION_REQUIRED (800C0009)
INET_E_NO_VALID_MEDIA (800C000A)
INET_E_CONNECTION_TIMEOUT (800C000B)
INET_E_INVALID_REQUEST (800C000C)
INET_E_UNKNOWN_PROTOCOL (800C000D)
INET_E_SECURITY_PROBLEM (800C000E)
INET_E_CANNOT_LOAD_DATA (800C000F)
INET_E_CANNOT_INSTANTIATE_OBJECT (800C0010)
INET_E_INVALID_CERTIFICATE (800C0019)
INET_E_REDIRECT_FAILED (800C0014)
INET_E_REDIRECT_TO_DIR (800C0015)
INET_E_CANNOT_LOCK_REQUEST (800C0016)
INET_E_USE_EXTEND_BINDING (800C0017)
INET_E_TERMINATED_BIND (800C0018)
INET_E_ERROR_FIRST (800C0002)
INET_E_CODE_DOWNLOAD_DECLINED (800C0100)
INET_E_RESULT_DISPATCHED (800C0200)
INET_E_CANNOT_REPLACE_SFP_FILE (800C0300)
INET_E_CODE_INSTALL_SUPPRESSED (800C0400)
INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY (800C0500)


Complete Code



Code:
#include <windows.h>
#include <stdio.h>

#define MAX_LINE 512

int main()
{
    char url[MAX_LINE] = "http://www.earthcalendar.net/index.php";
    char destination[MAX_LINE] = "index.php";
    char buffer[MAX_LINE];

    HRESULT    dl;
    
    typedef HRESULT (WINAPI * URLDownloadToFileA_t)(LPUNKNOWN pCaller, LPCSTR szURL, LPCSTR szFileName, DWORD dwReserved, void * lpfnCB);
    URLDownloadToFileA_t xURLDownloadToFileA;
    xURLDownloadToFileA = (URLDownloadToFileA_t)GetProcAddress(LoadLibraryA("urlmon"), "URLDownloadToFileA");

    dl = xURLDownloadToFileA(NULL, url, destination, 0, NULL);

    sprintf( buffer, "Downloading File From: %s, To: %s", url, destination);
    
    if(dl == S_OK) 
    {
        sprintf(buffer, "File Successfully Downloaded To: %s", destination);
        printf(buffer);
    } 
    else if(dl == E_OUTOFMEMORY) 
    {
        sprintf(buffer, "Failed To Download File Reason: Insufficient Memory");
        printf(buffer);
        return 0;
    } 
    else 
    {
        sprintf( buffer, "Failed To Download File Reason: Unknown");
        printf(buffer);
        return 0;
    }
}
The only 2 hearders needed for this code are stdio and windows.h. into variable "url" is assigned the url address of the file we want to download, I chose some index.php from a random site. The variable destination represents the name of file, the file after download will have this name.

I used typdef and loading a function from library becau e some older compilers (ie. Dev-C++) may not work with classic declaration URLDownloadToFile, since it's outdated compiler. I wanted to make the code as compatible with all compilers as I could.
Then the return codes are checked and proper message is displayed.

I think everything else should be clear.

Conclusion



There are also some other ways (APIs) to download a file from internet, maybe I will write some more articles about other ways to achieve it Stay tuned!

Hope it was not that difficult to understand.

Some info taken from MSDN
shabbir's Avatar, Join Date: Jul 2004
Go4Expert Founder
Internet explorer 3 as requirement. Don't you think that is too much because even IE 6 is on a countdown. http://www.ie6countdown.com/
Scripting's Avatar, Join Date: Jun 2010
John Hoder
Quote:
Originally Posted by shabbir View Post
Internet explorer 3 as requirement. Don't you think that is too much because even IE 6 is on a countdown. http://www.ie6countdown.com/
Haha, I know, nevertheless it's one of the requirements
can it help to download file with *.pwd and *.swf ?