mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-04-24 03:50:23 +10:00
Update Shell and Fix Bugs
This commit is contained in:
@@ -1,20 +1,19 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <WinInet.h>
|
||||
#include <winhttp.h>
|
||||
#include <string>
|
||||
#include "strcode.h"
|
||||
#include "mpstr.h"
|
||||
#include <chrono>
|
||||
#include <rapidjson/writer.h>
|
||||
#include <rapidjson/stringbuffer.h>
|
||||
#include "syncutil.h"
|
||||
|
||||
// Generated by ChatGTP
|
||||
|
||||
using namespace System;
|
||||
using namespace System::Threading;
|
||||
using namespace System::Reflection;
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
|
||||
std::wstring GetLastErrorString ()
|
||||
{
|
||||
@@ -50,6 +49,8 @@ std::wstring GetLastErrorString ()
|
||||
return msg;
|
||||
}
|
||||
|
||||
CriticalSection g_download_cs;
|
||||
|
||||
public ref class DownloadHelper
|
||||
{
|
||||
public:
|
||||
@@ -72,49 +73,163 @@ public ref class DownloadHelper
|
||||
th->Start ();
|
||||
}
|
||||
|
||||
private:
|
||||
HINTERNET hSession = nullptr,
|
||||
hConnect = nullptr,
|
||||
hRequest = nullptr;
|
||||
void CancelHttpHandle (HINTERNET hInternet)
|
||||
{
|
||||
if (hInternet) WinHttpCloseHandle (hInternet);
|
||||
hInternet = nullptr;
|
||||
}
|
||||
std::wstring FormatSpeed (long long speed)
|
||||
{
|
||||
if (speed < 0) return L"--/s";
|
||||
|
||||
const wchar_t* units [] = {L"B/s", L"KB/s", L"MB/s", L"GB/s", L"TB/s"};
|
||||
double s = (double)speed;
|
||||
int idx = 0;
|
||||
|
||||
while (s >= 1024.0 && idx < 4) {
|
||||
s /= 1024.0;
|
||||
if (s / 1024.0 < 1) break;
|
||||
idx++;
|
||||
}
|
||||
|
||||
wchar_t buf [64];
|
||||
swprintf (buf, 64, L"%.2f %s", s, units [idx]);
|
||||
return buf;
|
||||
}
|
||||
public:
|
||||
~DownloadHelper ()
|
||||
{
|
||||
if (hSession) CancelHttpHandle (hSession);
|
||||
if (hConnect) CancelHttpHandle (hConnect);
|
||||
if (hRequest) CancelHttpHandle (hRequest);
|
||||
}
|
||||
private:
|
||||
void Worker ()
|
||||
{
|
||||
CreateScopedLock (g_download_cs);
|
||||
std::wstring url = MPStringToStdW (m_url);
|
||||
std::wstring outPath = MPStringToStdW (m_savePath);
|
||||
|
||||
HINTERNET hInternet = InternetOpenW (L"MyDownloader",
|
||||
INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
|
||||
URL_COMPONENTS urlComp = {0};
|
||||
urlComp.dwStructSize = sizeof (urlComp);
|
||||
|
||||
if (!hInternet)
|
||||
wchar_t host [256];
|
||||
wchar_t path [2048];
|
||||
|
||||
urlComp.lpszHostName = host;
|
||||
urlComp.dwHostNameLength = _countof (host);
|
||||
|
||||
urlComp.lpszUrlPath = path;
|
||||
urlComp.dwUrlPathLength = _countof (path);
|
||||
|
||||
if (!WinHttpCrackUrl (url.c_str (), 0, 0, &urlComp))
|
||||
{
|
||||
ReportError (outPath, L"InternetOpenW Failed: " + GetLastErrorString ());
|
||||
ReportError (outPath, L"WinHttpCrackUrl failed: " + GetLastErrorString ());
|
||||
return;
|
||||
}
|
||||
|
||||
HINTERNET hFile = InternetOpenUrlW (
|
||||
hInternet,
|
||||
url.c_str (),
|
||||
NULL,
|
||||
0,
|
||||
INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE,
|
||||
0
|
||||
BOOL isHttps = (urlComp.nScheme == INTERNET_SCHEME_HTTPS);
|
||||
|
||||
hSession = WinHttpOpen (
|
||||
L"MyDownloader",
|
||||
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
|
||||
WINHTTP_NO_PROXY_NAME,
|
||||
WINHTTP_NO_PROXY_BYPASS,
|
||||
0);
|
||||
|
||||
if (!hSession)
|
||||
{
|
||||
ReportError (outPath, L"WinHttpOpen failed: " + GetLastErrorString ());
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD protocols =
|
||||
WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
|
||||
WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 |
|
||||
WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 |
|
||||
WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 |
|
||||
WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 |
|
||||
WINHTTP_FLAG_SECURE_PROTOCOL_ALL;
|
||||
|
||||
WinHttpSetOption (
|
||||
hSession,
|
||||
WINHTTP_OPTION_SECURE_PROTOCOLS,
|
||||
&protocols,
|
||||
sizeof (protocols)
|
||||
);
|
||||
|
||||
if (!hFile)
|
||||
hConnect = WinHttpConnect (
|
||||
hSession,
|
||||
urlComp.lpszHostName,
|
||||
urlComp.nPort,
|
||||
0);
|
||||
|
||||
if (!hConnect)
|
||||
{
|
||||
InternetCloseHandle (hInternet);
|
||||
ReportError (outPath, L"InternetOpenUrlW Failed: " + GetLastErrorString ());
|
||||
CancelHttpHandle (hSession); hSession = nullptr;
|
||||
ReportError (outPath, L"WinHttpConnect failed: " + GetLastErrorString ());
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD fileSize = 0;
|
||||
DWORD len = sizeof (fileSize);
|
||||
HttpQueryInfoW (hFile, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
|
||||
&fileSize, &len, NULL);
|
||||
hRequest = WinHttpOpenRequest (
|
||||
hConnect,
|
||||
L"GET",
|
||||
urlComp.lpszUrlPath,
|
||||
NULL,
|
||||
WINHTTP_NO_REFERER,
|
||||
WINHTTP_DEFAULT_ACCEPT_TYPES,
|
||||
isHttps ? WINHTTP_FLAG_SECURE : 0);
|
||||
|
||||
HANDLE hOut = CreateFileW (outPath.c_str (), GENERIC_WRITE, 0,
|
||||
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (!hRequest)
|
||||
{
|
||||
CancelHttpHandle (hConnect); hConnect = nullptr;
|
||||
CancelHttpHandle (hSession); hSession = nullptr;
|
||||
ReportError (outPath, L"WinHttpOpenRequest failed: " + GetLastErrorString ());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WinHttpSendRequest (hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0,
|
||||
WINHTTP_NO_REQUEST_DATA, 0, 0, 0))
|
||||
{
|
||||
CancelHttpHandle (hRequest);
|
||||
CancelHttpHandle (hConnect);
|
||||
CancelHttpHandle (hSession);
|
||||
ReportError (outPath, L"WinHttpSendRequest failed: " + GetLastErrorString ());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WinHttpReceiveResponse (hRequest, NULL))
|
||||
{
|
||||
CancelHttpHandle (hRequest); hRequest = nullptr;
|
||||
CancelHttpHandle (hConnect); hConnect = nullptr;
|
||||
CancelHttpHandle (hSession); hSession = nullptr;
|
||||
ReportError (outPath, L"WinHttpReceiveResponse failed: " + GetLastErrorString ());
|
||||
return;
|
||||
}
|
||||
|
||||
// ---- 获取 Content-Length ----
|
||||
DWORD dwSize = sizeof (DWORD);
|
||||
DWORD fileSize = 0;
|
||||
WinHttpQueryHeaders (
|
||||
hRequest,
|
||||
WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
|
||||
NULL,
|
||||
&fileSize,
|
||||
&dwSize,
|
||||
NULL);
|
||||
|
||||
HANDLE hOut = CreateFileW (outPath.c_str (), GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hOut == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
InternetCloseHandle (hFile);
|
||||
InternetCloseHandle (hInternet);
|
||||
CancelHttpHandle (hRequest); hRequest = nullptr;
|
||||
CancelHttpHandle (hConnect); hConnect = nullptr;
|
||||
CancelHttpHandle (hSession); hSession = nullptr;
|
||||
ReportError (outPath, L"Cannot create output file: " + GetLastErrorString ());
|
||||
return;
|
||||
}
|
||||
@@ -125,23 +240,38 @@ public ref class DownloadHelper
|
||||
long long received = 0;
|
||||
|
||||
auto t0 = std::chrono::high_resolution_clock::now ();
|
||||
auto lastCheck = t0;
|
||||
unsigned long long lastBytes = 0;
|
||||
|
||||
while (InternetReadFile (hFile, buffer, sizeof (buffer), &bytesRead) && bytesRead > 0)
|
||||
while (WinHttpReadData (hRequest, buffer, sizeof (buffer), &bytesRead) && bytesRead > 0)
|
||||
{
|
||||
WriteFile (hOut, buffer, bytesRead, &bytesWritten, NULL);
|
||||
received += bytesRead;
|
||||
|
||||
// 计算速度
|
||||
auto t1 = std::chrono::high_resolution_clock::now ();
|
||||
double sec = std::chrono::duration<double> (t1 - t0).count ();
|
||||
long long speed = (long long)(received / (sec > 0 ? sec : 1));
|
||||
auto now = std::chrono::high_resolution_clock::now ();
|
||||
double intervalSec = std::chrono::duration<double> (now - lastCheck).count ();
|
||||
|
||||
long long speed = -1; // -1 表示“保持上次速度”
|
||||
|
||||
// 每 0.5 秒刷新一次速度(可调)
|
||||
if (intervalSec >= 0.5)
|
||||
{
|
||||
unsigned long long bytesInInterval = received - lastBytes;
|
||||
if (intervalSec > 0)
|
||||
speed = (long long)(bytesInInterval / intervalSec); // B/s
|
||||
|
||||
lastCheck = now;
|
||||
lastBytes = received;
|
||||
}
|
||||
|
||||
ReportProgress (received, fileSize, speed);
|
||||
}
|
||||
|
||||
|
||||
CloseHandle (hOut);
|
||||
InternetCloseHandle (hFile);
|
||||
InternetCloseHandle (hInternet);
|
||||
CancelHttpHandle (hRequest); hRequest = nullptr;
|
||||
CancelHttpHandle (hConnect); hConnect = nullptr;
|
||||
CancelHttpHandle (hSession); hSession = nullptr;
|
||||
|
||||
ReportComplete (outPath, received);
|
||||
}
|
||||
@@ -158,7 +288,12 @@ public ref class DownloadHelper
|
||||
w.StartObject ();
|
||||
w.Key ("received"); w.Uint64 (received);
|
||||
w.Key ("total"); w.Uint64 (total);
|
||||
w.Key ("speed"); w.Uint64 (speed);
|
||||
std::wstring speedText = FormatSpeed (speed);
|
||||
std::string speedUtf8 = WStringToString (speedText, CP_UTF8);
|
||||
|
||||
w.Key ("speed");
|
||||
w.String (speedUtf8.c_str ());
|
||||
|
||||
w.Key ("progress"); w.Double (received / (double)total * 100);
|
||||
w.EndObject ();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user