#include <Windows.h>
#include <wininet.h>
#include <stdio.h>
#include <string>
#include <io.h>
using namespace std;
#pragma comment(lib, "wininet.lib")
const DWORD DWORD_MAX_CCH_OF_TEST_URL = 256;
const DWORD DWORD_MAX_CCH_OF_HOST_NAME = 128;
const DWORD DWORD_MAX_CCH_OF_URL_PATH = 256;
int breakpointDownload(const std::wstring& url, const std::wstring& folder, void(*cb)(double),std::wstring& name)
{
int index = url.find_last_of(L'/');
std::wstring filename = url.substr(index + 1);
index = filename.find_first_of(L'?');
if (index != std::wstring::npos)
filename = filename.substr(0,index);
if (!folder.empty())
filename = folder + L"\\" + filename;
std::wstring tempfile = filename + L".dl";
_wremove(filename.c_str());
HINTERNET hInetOpen = NULL;
HINTERNET hInetConnect = NULL;
HINTERNET hInetRequest = NULL;
HANDLE lhFile = NULL;
URL_COMPONENTS ldCrackedURL;
ZeroMemory(&ldCrackedURL, sizeof(URL_COMPONENTS));
ldCrackedURL.dwStructSize = sizeof(URL_COMPONENTS);
TCHAR szHostName[DWORD_MAX_CCH_OF_HOST_NAME] = { 0 };
ldCrackedURL.lpszHostName = szHostName;
ldCrackedURL.dwHostNameLength = DWORD_MAX_CCH_OF_HOST_NAME;
wchar_t szUrlPath[DWORD_MAX_CCH_OF_URL_PATH] = { 0 };
ldCrackedURL.lpszUrlPath = szUrlPath;
ldCrackedURL.dwUrlPathLength = DWORD_MAX_CCH_OF_URL_PATH;
if (FALSE == InternetCrackUrl(url.c_str(),url.size(), 0, &ldCrackedURL))
{
return 0;
}
hInetOpen = InternetOpen(L"MSIE/1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (NULL == hInetOpen)
{
return 0;
}
hInetConnect = InternetConnect(hInetOpen, ldCrackedURL.lpszHostName, ldCrackedURL.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
if (NULL == hInetConnect)
{
return 0;
}
lhFile = CreateFile(tempfile.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (lhFile == INVALID_HANDLE_VALUE)
{
return 0;
}
LARGE_INTEGER ldFileSize;
if (FALSE == GetFileSizeEx(lhFile, &ldFileSize))
{
return 0;
}
LONGLONG lllStartPos = 0;
if(0 == ldFileSize.QuadPart)
{
}
else
{
if (INVALID_SET_FILE_POINTER == SetFilePointer(lhFile, 0, NULL, FILE_END))
{
return 0;
}
lllStartPos = ldFileSize.QuadPart;
}
wchar_t lscRangeStartPosition[30] = { 0 };
if (0 != _i64tow_s((__int64)(lllStartPos), lscRangeStartPosition, sizeof(lscRangeStartPosition), 10))
{
return 0;
}
wstring loAdditionalHeader = L"Range: bytes=";
loAdditionalHeader += lscRangeStartPosition;
loAdditionalHeader += L"-\r\n";
const wchar_t* lplpszAcceptTypes[] = { L"*/*", NULL };
hInetRequest = HttpOpenRequest(hInetConnect,L"GET", ldCrackedURL.lpszUrlPath,L"HTTP/1.1", NULL,lplpszAcceptTypes, 0, 0);
if (NULL == hInetConnect)
{
return 0;
}
if (FALSE == HttpSendRequest(hInetRequest, loAdditionalHeader.c_str(), loAdditionalHeader.size(), NULL, 0))
{
return 0;
}
DWORD ldwStatusCode;
DWORD ldwCbOfStatusCode = sizeof(ldwStatusCode);
if (FALSE == HttpQueryInfo(hInetRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &ldwStatusCode, &ldwCbOfStatusCode, 0))
{
return 0;
}
if (416 == ldwStatusCode)
{
_wrename(tempfile.c_str(), filename.c_str());
name = filename;
return 1;
}
else if (200 != ldwStatusCode && 206 != ldwStatusCode)
{
return 0;
}
DWORD dwFile = 10000;
DWORD dwSize = sizeof(DWORD);
if (FALSE == HttpQueryInfo(hInetRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwFile, &dwSize, 0))
{
}
else
dwFile += lllStartPos;
BYTE lpbBufferToReceiveData[2048];
DWORD ldwCbBuffer = 2048;
DWORD ldwCrtCbReaded;
DWORD ldwCbWritten = 0;
bool lbIsOk = false;
LONGLONG lllCbAllRead = lllStartPos;
do
{
if (FALSE == InternetReadFile(hInetRequest, lpbBufferToReceiveData, ldwCbBuffer, &ldwCrtCbReaded))
{
break;
}
if (ldwCrtCbReaded == 0)
{
break;
}
if (FALSE == WriteFile(lhFile, lpbBufferToReceiveData, ldwCrtCbReaded, &ldwCbWritten, NULL) || ldwCbWritten != ldwCrtCbReaded)
{
break;
}
ZeroMemory(lpbBufferToReceiveData, ldwCrtCbReaded);
lllCbAllRead += ldwCrtCbReaded;
double p = lllCbAllRead * 100.0 / dwFile;
if (p > 100)
p = 100;
if (cb)
cb(p);
} while (true);
if (NULL != lhFile)
{
CloseHandle(lhFile);
}
if (NULL != hInetRequest)
{
InternetCloseHandle(hInetRequest);
}
if (NULL != hInetConnect)
{
InternetCloseHandle(hInetConnect);
}
if (NULL != hInetOpen)
{
InternetCloseHandle(hInetOpen);
}
_wrename(tempfile.c_str(), filename.c_str());
name = filename;
return 1;
}