Search code examples
c++readfilewininet

Downloading content from web URL


I'm trying to get data from the URL address using WinInet.h. Here is my simplified code:

LPCTSTR url = (LPCTSTR) "https://example.com"; // 2.9.1
HINTERNET connection = InternetOpenA(NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
HINTERNET request = InternetOpenUrlA(connection, url, NULL, 0, INTERNET_FLAG_RELOAD, 0);

char status_code[10];
DWORD info_size = 10000;
HttpQueryInfoA(request, HTTP_QUERY_STATUS_CODE, status_code, &info_size, NULL);

DWORD size;
DWORD dwRead = 0;
InternetQueryDataAvailable(request, &size, 0, 0); // size = 5

char * buffer = new char[size]; // size = 5
InternetReadFile(request, buffer, size, &dwRead);
OutputDebugString(buffer); // 1.2.3ýýýý

InternetCloseHandle(connection);
InternetCloseHandle(request);

It works well, but the data on the URL address is 2.9.1 but the buffer returns 2.9.1ýýýý.

If I try to print char after char, this is the result:

for (int i = 0; i < size; i++)
    OutputDebugString(&buffer[i]);

char[0] = 2.9.1ýýýý
char[1] = .9.1ýýýý
char[2] = 9.1ýýýý
char[3] = .1ýýýý
char[4] = 1ýýýý

Can anyone explain to me why this is happening?


Solution

  • The data you're receiving is a C-style string, i.e. a null-character terminated array of characters. The important part here is that a string of 5 characters actually requires an array of size 6, for example:

    "hello"
    

    is made up of an array of 6 characters, 'h', 'e', 'l', 'l', 'o', '\0'.

    OutputDebugString will go through the array printing the characters until it reaches a '\0'.

    In this case you're not allocating anywhere for the terminating '\0' to go, so OutputDebugString will keep going until there happens to be a '\0' in memory (or until it reaches memory it's not allowed to access).

    Change this bit:

    char * buffer = new char[size]; // size = 5
    InternetReadFile(request, buffer, size, &dwRead);
    

    to be

    char * buffer = new char[size + 1]; // size = 5, allocate 6 chars
    InternetReadFile(request, buffer, size, &dwRead);
    buffer [size] = '\0';