1
0
Fork 0

DBG: initial version of Wininet download library

This commit is contained in:
Duncan Ogilvie 2018-01-10 00:11:55 +01:00
parent 3ab836225f
commit ba6ad4cefc
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
4 changed files with 358 additions and 0 deletions

View File

@ -0,0 +1,321 @@
/* Created by John Åkerblom 10/26/2014 */
#include "downslib.h"
#include <windows.h>
#include <Wininet.h>
#pragma comment(lib, "Wininet.lib")
#define DEFAULT_TIMEOUT 3000
#define DEFAULT_USERAGENT "downslib"
char* _strchr(const char* str, char c)
{
const char* p;
for(p = str; *p != '\0'; p = AnsiNext(p))
{
if(*p == c)
return (char*)p;
}
return NULL;
}
static const char* _path_from_url(const char* url)
{
const char* path = NULL;
/* First look for a dot to get to domain part of URL */
path = _strchr(url, '.');
if(path != NULL)
++path;
else
path = url;
path = _strchr(path, '/');
return path;
}
static int _get_content_length(const char* host,
const char* object,
int use_ssl,
const char* useragent,
unsigned int timeout,
int* total_bytes)
{
HINTERNET hInternet = NULL;
HINTERNET hConnection = NULL;
HINTERNET hRequest = NULL;
DWORD dwRead = 0;
DWORD dwLen = 0;
DWORD dwFlags = 0;
/* */
int ret = 0;
hInternet = InternetOpenA(useragent,
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
0);
if(hInternet == NULL)
{
return 1;
}
InternetSetOptionA(hInternet,
INTERNET_OPTION_RECEIVE_TIMEOUT,
&timeout,
sizeof(DWORD));
hConnection = InternetConnectA(hInternet,
host,
INTERNET_DEFAULT_HTTP_PORT,
NULL,
NULL,
INTERNET_SERVICE_HTTP,
0,
0);
dwFlags = INTERNET_FLAG_RELOAD;
if(use_ssl)
{
dwFlags |= INTERNET_FLAG_SECURE;
dwFlags |= INTERNET_FLAG_IGNORE_CERT_DATE_INVALID;
dwFlags |= INTERNET_FLAG_IGNORE_CERT_CN_INVALID;
}
hRequest = HttpOpenRequestA(hConnection,
"HEAD",
object,
NULL,
NULL,
NULL,
dwFlags,
0);
if(HttpSendRequestA(hRequest, NULL, 0, NULL, 0) == FALSE)
{
if(GetLastError() == ERROR_INTERNET_INVALID_CA && use_ssl)
{
dwFlags = 0;
dwLen = sizeof(dwFlags);
InternetQueryOptionA(hRequest, INTERNET_OPTION_SECURITY_FLAGS, (LPVOID)&dwFlags, &dwLen);
dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
InternetSetOptionA(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof(dwFlags));
}
}
dwLen = sizeof(*total_bytes);
if(HttpQueryInfoA(hRequest,
HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
(LPVOID)total_bytes,
&dwLen,
0) == FALSE)
{
ret = 2;
}
if(hRequest != NULL)
InternetCloseHandle(hRequest);
if(hConnection != NULL)
InternetCloseHandle(hConnection);
if(hInternet != NULL)
InternetCloseHandle(hInternet);
return ret;
}
static int _download(const char* url,
const char* host,
const char* object,
int use_ssl,
const wchar_t* filename,
const char* useragent,
unsigned int timeout,
downslib_cb cb)
{
HINTERNET hInternet = NULL;
HINTERNET hUrl = NULL;
HANDLE hFile = NULL;
DWORD dwWritten = 0;
DWORD dwFlags = 0;
DWORD dwError = 0;
DWORD dwRead = 0;
DWORD dwLen = 0;
BOOL bRet = FALSE;
/* */
int read_bytes = 0;
int total_bytes = 0;
char buffer[2048];
int ret = 0;
/* Try to retrieve content-length, not essential */
_get_content_length(host,
object,
use_ssl,
useragent,
timeout,
&total_bytes);
hInternet = InternetOpenA(useragent,
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
0);
if(hInternet == NULL)
{
return 1;
}
dwFlags = INTERNET_FLAG_RELOAD;
if(use_ssl)
{
dwFlags |= INTERNET_FLAG_SECURE;
dwFlags |= INTERNET_FLAG_IGNORE_CERT_DATE_INVALID;
dwFlags |= INTERNET_FLAG_IGNORE_CERT_CN_INVALID;
}
if((hUrl = InternetOpenUrlA(hInternet, url, NULL, 0, dwFlags, 0)) == NULL)
{
ret = 2;
goto cleanup;
}
hFile = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if(hFile == NULL)
{
ret = 3;
goto cleanup;
}
while(InternetReadFile(hUrl, buffer, sizeof(buffer), &dwRead))
{
read_bytes += dwRead;
/* We are done if nothing more to read, so now we can report total size in our final cb call */
if(dwRead == 0)
{
total_bytes = read_bytes;
}
if(cb != NULL)
{
if(cb(read_bytes, total_bytes) != 0)
{
ret = 4;
goto cleanup;
}
}
/* Exit if nothing more to read */
if(dwRead == 0)
{
break;
}
WriteFile(hFile, buffer, dwRead, &dwWritten, NULL);
/* FlushFileBuffers(hFile); */
}
if(total_bytes > 0 && read_bytes != total_bytes)
{
ret = 5;
}
cleanup:
if(hFile != NULL)
CloseHandle(hFile);
if(hUrl != NULL)
InternetCloseHandle(hUrl);
if(hInternet != NULL)
InternetCloseHandle(hInternet);
return ret;
}
static int _host_and_object_from_url(const char* url, char** host, const char** object)
{
const char* object_tmp = _path_from_url(url);
char* past_protocol = NULL;
char* host_tmp = NULL;
int ret = 0;
int len = 0;
// Point past the protocol part of URL, e.g past "HTTP://"
past_protocol = _strchr(url, '/');
if(past_protocol == NULL)
{
// Malformed url
return 1;
}
past_protocol += 2; // Move past the two slashes in protocol specification
if(object_tmp == NULL)
{
len = lstrlenA(past_protocol) + 1;
}
else
{
len = object_tmp - past_protocol + 1;
}
host_tmp = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 1);
lstrcpynA(host_tmp, past_protocol, len);
*host = host_tmp;
*object = object_tmp;
return 0;
}
static void _free_host(char* host)
{
HeapFree(GetProcessHeap(), 0, host);
}
int downslib_download(const char* url,
const wchar_t* filename,
int use_ssl,
const char* useragent,
unsigned int timeout,
downslib_cb cb)
{
const char* object = NULL;
char* host = NULL;
int ret = 0;
ret = _host_and_object_from_url(url, &host, &object);
if(ret != 0)
{
return ret;
}
ret = _download(url,
host,
object,
use_ssl,
filename,
useragent ? useragent : DEFAULT_USERAGENT,
timeout ? timeout : DEFAULT_TIMEOUT,
cb);
_free_host(host);
return ret;
}
int downslib_easy_download(const char* url, const wchar_t* filename, int use_ssl)
{
return downslib_download(url,
filename,
use_ssl,
DEFAULT_USERAGENT,
DEFAULT_TIMEOUT,
NULL);
}

View File

@ -0,0 +1,20 @@
/* Created by John Åkerblom 10/26/2014 */
#ifndef __DOWNSLIB_H_DEF__
#define __DOWNSLIB_H_DEF__
#include <wchar.h>
int downslib_easy_download(const char* url, const wchar_t* filename, int use_ssl);
typedef int (*downslib_cb)(int read_bytes, int total_bytes);
int downslib_download(const char* url,
const wchar_t* filename,
int use_ssl,
const char* useragent,
unsigned int timeout,
downslib_cb cb);
#endif

View File

@ -111,6 +111,7 @@
<ClCompile Include="value.cpp" />
<ClCompile Include="variable.cpp" />
<ClCompile Include="watch.cpp" />
<ClCompile Include="WinInet-Downloader\downslib.c" />
<ClCompile Include="x64dbg.cpp" />
<ClCompile Include="xrefs.cpp" />
<ClCompile Include="_exports.cpp" />
@ -243,6 +244,7 @@
<ClInclude Include="TraceRecord.h" />
<ClInclude Include="types.h" />
<ClInclude Include="watch.h" />
<ClInclude Include="WinInet-Downloader\downslib.h" />
<ClInclude Include="xrefs.h" />
<ClInclude Include="yara\yara\integers.h" />
<ClInclude Include="yara\yara\stream.h" />

View File

@ -102,6 +102,15 @@
<Filter Include="Header Files\Symbols">
<UniqueIdentifier>{1f9e6c1d-74b2-4f72-bbe2-5fa68094d5fd}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Third Party">
<UniqueIdentifier>{73b6410d-7eef-4131-a04f-56abc14d84f5}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Third Party\WinInet-Downloader">
<UniqueIdentifier>{e47a911a-a6f6-415d-9eec-4f79f478d0a0}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Third Party\WinInet-Downloader">
<UniqueIdentifier>{cdf955c6-b066-4b06-87f0-7a02b9bbfc55}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
@ -446,6 +455,9 @@
<ClCompile Include="symbolsourcedia.cpp">
<Filter>Source Files\Symbols</Filter>
</ClCompile>
<ClCompile Include="WinInet-Downloader\downslib.c">
<Filter>Source Files\Third Party\WinInet-Downloader</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="dbghelp\dbghelp.h">
@ -979,5 +991,8 @@
<ClInclude Include="symbolsourcedia.h">
<Filter>Header Files\Symbols</Filter>
</ClInclude>
<ClInclude Include="WinInet-Downloader\downslib.h">
<Filter>Header Files\Third Party\WinInet-Downloader</Filter>
</ClInclude>
</ItemGroup>
</Project>