OfficeAssistant_Win10/OfficeAssistant_msvc/netio.cpp

645 lines
21 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

//
// Created by HW on 2023/07/27.
//
#include <QProcess>
#include <QScreen>
#include <QCryptographicHash>
#include <wbemidl.h>
#include "netio.h"
#include "config.h"
#include <cstdlib>
#include <ctime>
#include <QEventLoop>
#include <QTimer>
#include <cstring>
#include <QJsonArray>
#include <QSysInfo>
#include <QStorageInfo>
#include <comutil.h>
#include <iostream>
#include <QGuiApplication>
#include <QApplication>
#include <ctime>
#include <qDebug>
#include "globalvariables.h"
#include "buttonstruct.h"
#pragma comment(lib, "wbemuuid.lib")
#ifdef _DEBUG
#pragma comment(lib, "Qt5Networkd.lib")
#else
#pragma comment(lib, "Qt5Network.lib")
#endif
#pragma comment(lib,"comsuppw.lib")
//读取注册表获取MachineUUID
bool IsWin11AndLater()
{
//Windows 10 从内部版本 10240 开始,以内部版本 19044 结束。Windows 11 从内部版本 22000 开始,那么:
//Environment.OSVersion.Version.Build >= 22000;
NTSTATUS(WINAPI * RtlGetVersion)(LPOSVERSIONINFOEXW);
OSVERSIONINFOEXW osInfo;
*(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");
if (NULL != RtlGetVersion)
{
osInfo.dwOSVersionInfoSize = sizeof(osInfo);
RtlGetVersion(&osInfo);
return (osInfo.dwMajorVersion >= 10 && osInfo.dwBuildNumber >= 22000);
}
return false;
}
RequestBodyBase::RequestBodyBase(){
wchar_t unix_time[65]={0};
wsprintf(unix_time,L"%ld",std::time(0));
QString request_id=QString::fromWCharArray(unix_time);
//打开配置文件
QString dir=QApplication::applicationDirPath();
QFile *infFile=new QFile(dir+"/config/information.kmd");
if(!infFile->open(QIODevice::ReadOnly|QIODevice::Text)){
QMessageBox::critical(nullptr,QString::fromLocal8Bit("错误"), QString::fromLocal8Bit("无法打开配置文件"));
delete infFile;
exit(1);
}
//读取配置文件
QByteArray bytes;
bytes=infFile->readAll();
infFile->close();
delete infFile;
//转化为json
qJsonDocument=QJsonDocument::fromJson(bytes);
if(qJsonDocument.isObject()){
//读取数据,写入对应字段
QJsonObject obj_root=qJsonDocument.object();
if(obj_root.value("product")==QJsonValue::Undefined){
QMessageBox::warning(nullptr, QString::fromLocal8Bit("错误"), QString::fromLocal8Bit("配置文件损坏"));
exit(1);
}
product=obj_root.value("product").toString();
if(obj_root.value("parter_id")==QJsonValue::Undefined){
QMessageBox::warning(nullptr, QString::fromLocal8Bit("错误"), QString::fromLocal8Bit("配置文件损坏"));
exit(1);
}
parter_id=obj_root.value("parter_id").toString();
}else{
//处理错误
QMessageBox::warning(nullptr, QString::fromLocal8Bit("错误"), QString::fromLocal8Bit("配置文件损坏"));
exit(1);
}
//获取操作系统版本
this->os="Windows";
OSVERSIONINFOEXW os;
os.dwOSVersionInfoSize=sizeof(os);
GetVersionEx((OSVERSIONINFO *)&os);
NTSTATUS(WINAPI * RtlGetVersion)(LPOSVERSIONINFOEXW);
*(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");
if (RtlGetVersion != nullptr) {
RtlGetVersion(&os);
switch (os.dwMajorVersion) {//主版本号
case 5: //不兼容Windows 2000因此5.x一定是Windows XP
os_version = "Windows XP";
break;
case 6:
switch (os.dwMinorVersion) { //次版本号
case 0:
os_version = "Windows Vista or Windows Server 2008";
break;
case 1:
os_version = "Windows 7 or Windows Server 2008 R2";
break;
case 2:
os_version = "Windows 8 or Windows Server 2012";
break;
case 3:
os_version = "Windows 8.1 or Windows Server 2012 R2";
break;
default:
os_version = "Unknown";
}
case 10: //这几个系统都是10.0
if (IsWin11AndLater()) {
os_version = "Windows 11 or Windows Server 2022";
}
else {
os_version = "Windows 10, Windows Server 2016 or Windows Server 2019";
}
break;
default:
os_version = "Unknown";
}
}
else {
os_version = "Unknown";
}
this->release = RELEASE;
this->version = VERSION;
//读取MachineGUID并取MD5作为device_id
QByteArray hash = QCryptographicHash::hash(getMachineGUID().toUtf8(), QCryptographicHash::Md5);
device_id = hash.toHex();
//加入json序列
QJsonValue value = device_id;
QJsonObject obj_root = qJsonDocument.object();
obj_root.insert("device_id", value);
QJsonValue version_json = this->version;
obj_root.insert("version", version_json);
QJsonValue release_json = this->release;
obj_root.insert("release", release_json);
qJsonDocument.setObject(obj_root);
QJsonValue os_json(this->os);
QJsonValue os_version_json(this->os_version);
QString key_hash = QCryptographicHash::hash(QString(KEY).toUtf8(), QCryptographicHash::Md5).toHex();
QByteArray request_id_byte = request_id.toUtf8();
QByteArray sign_byte= QCryptographicHash::hash(key_hash.toUtf8()+request_id_byte, QCryptographicHash::Md5);
sign = sign_byte.toHex();
QJsonValue sign_json(sign);
QJsonValue requestId_json=QJsonValue(request_id);
obj_root=qJsonDocument.object();
//插入request_id
obj_root.insert(QString::fromLocal8Bit("request_id"),requestId_json);
obj_root.insert(QString::fromLocal8Bit("os"), os_json);
obj_root.insert(QString::fromLocal8Bit("os_version"), os_version_json);
obj_root.insert(QString::fromLocal8Bit("sign"), sign_json);
qJsonDocument.setObject(obj_root);
url_param = "?";
url_param += "product=";
url_param += product;
url_param += "&parter_id=";
url_param += parter_id;
url_param += "&os=";
url_param += this->os;
url_param += "&os_version=";
url_param += os_version;
url_param += "&device_id=";
url_param += device_id;
url_param += "&request_id=";
url_param += request_id;
url_param += "&version=";
url_param += version;
url_param += "&release=";
url_param += release;
url_param += "&sign=";
url_param += sign;
qDebug() << url_param;
}
void ConfigRequest::sendRequest(ConfigResponse *configResponse) {
timer = new QTimer(this);
QNetworkAccessManager *httpMgr = new QNetworkAccessManager();
QNetworkRequest requestInfo;
//HTTP请求
//请求头
QString url = CONFIG_URL;
requestInfo.setUrl(QUrl(CONFIG_URL));
requestInfo.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));
//保存响应的变量
reply = httpMgr->post(requestInfo,qJsonDocument.toJson());
qDebug() << qJsonDocument.toJson();
//开启一个循环,直到超时或者获取到数据为止
connect(reply,&QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
//设置定时器防止超时
connect(timer,&QTimer::timeout,this,&ConfigRequest::cancelDownload);
timer->start(5000);
//启动循环
eventLoop.exec();
timer->stop();
//delete httpMgr;
QJsonDocument result;
configResponse->succeed = false;
//memset(configResponse,0,sizeof(*configResponse));
auto error = reply->error();
//如果没有错误
if(reply->error() == QNetworkReply::NoError) {
result = QJsonDocument::fromJson(reply->readAll());
}else{
//如果有错误
configResponse->succeed=false;
//delete reply;
delete timer;
delete httpMgr;
return;
}
//qDebug() << result.toJson();
//如果数据完整
if(result.isObject()){
QJsonObject obj_root=result.object();
QJsonArray array;
array = obj_root.value("data").toObject().value("menu").toArray();
QJsonObject obj_basic = obj_root.value("data").toObject().value("basic").toObject();
configResponse->basic.logo_url = obj_basic.value("logo").toString();
configResponse->basic.device_id = obj_basic.value("device_id").toString();
configResponse->basic.dev_id = obj_basic.value("dev_id").toString();
configResponse->basic.token = obj_basic.value("token").toString();
configResponse->basic.backgroud_color = obj_basic.value("backgroud_color").toString();
configResponse->basic.title_color = obj_basic.value("title_color").toString();
configResponse->basic.title_cover_color = obj_basic.value("title_cover_color").toString();
auto i=0;
for(auto value:array){
QJsonObject object=value.toObject();
Button button;
button.img=object.value("img").toString();
// button.img_cover=object.value("img_cover").toString();
button.title=object.value("title").toString();
button.categroy_id = object.value("category_id").toString();
button.op = object.value("op").toString();
button.func=object.value("func").toString();
button.url=object.value("url").toString();
configResponse->buttons << button;
i++;
}
configResponse->succeed = true;
}else{
//数据不完整
configResponse->succeed=false;
//delete reply;
delete timer;
delete httpMgr;
return;
}
delete httpMgr;
}
void RequestBodyBase::cancelDownload() {
disconnect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
eventLoop.quit();
reply->abort();
}
void RequestBodyBase::sendRequest() {
timer = new QTimer(this);
QNetworkAccessManager *httpMgr = new QNetworkAccessManager();
QNetworkRequest requestInfo;
//HTTP请求
//请求头
requestInfo.setUrl(QUrl(OP_URL));
requestInfo.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));
//保存响应的变量
reply = httpMgr->post(requestInfo,qJsonDocument.toJson());
//开启一个循环,直到超时或者获取到数据为止
connect(reply,&QNetworkReply::finished, this, &RequestBodyBase::cancelDownload);
//设置定时器防止超时
connect(timer,&QTimer::timeout,&eventLoop,&QEventLoop::quit);
timer->start(5000);
//启动循环
eventLoop.exec();
delete timer;
delete httpMgr;
delete reply;
}
DeviceRequest::DeviceRequest() : RequestBodyBase() {
//CPU
QString cpu = QSysInfo::currentCpuArchitecture();
//内存大小
MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
GlobalMemoryStatusEx(&status);
int ram = status.ullTotalPhys / 1024 / 1024;
//硬盘大小
QStorageInfo storage = QStorageInfo::root();
int disk = storage.bytesTotal() / static_cast<qulonglong>(1024 * 1024 * 1024);
//显卡型号
QStringList gpus;
BOOL success;
DWORD deviceIndex = 0;
DISPLAY_DEVICE displayDevice;
displayDevice.cb = sizeof(displayDevice);
while (EnumDisplayDevices(NULL, deviceIndex, &displayDevice, 0)) {
WCHAR valueName[128];
DWORD valueSize;
DWORD valueType;
BYTE valueData[MAX_PATH];
HKEY hKey;
WCHAR keyName[128];
wsprintf(keyName, L"SYSTEM\\CurrentControlSet\\Control\\Video\\%s\\HardwareInformation",
displayDevice.DeviceID);
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
valueSize = sizeof(valueData);
wsprintf(valueName, L"HardwareInformation.AdapterString");
if (RegQueryValueEx(hKey, valueName, NULL, &valueType, valueData, &valueSize) == ERROR_SUCCESS) {
Q_ASSERT(valueType == REG_SZ);
QString adapterString = QString::fromWCharArray((wchar_t *) valueData, valueSize / sizeof(wchar_t) - 1);
gpus.append(adapterString);
}
RegCloseKey(hKey);
}
deviceIndex++;
displayDevice.cb = sizeof(displayDevice);
}
//主板型号
QString motherboard = QSysInfo::prettyProductName();
//WMI获取网卡型号
HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hr)) {
std::cerr << "Failed to initialize COM library." << std::endl;
return;
}
QStringList netCards;
hr = CoInitializeSecurity(
NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE,
NULL
);
if (FAILED(hr)) {
std::cerr << "Failed to initialize security." << std::endl;
CoUninitialize();
return;
}
IWbemLocator* pLoc = NULL;
hr = CoCreateInstance(
CLSID_WbemLocator,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
(LPVOID*)&pLoc
);
if (FAILED(hr)) {
std::cerr << "Failed to create IWbemLocator object." << std::endl;
CoUninitialize();
return;
}
IWbemServices* pSvc = NULL;
hr = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"),
NULL,
NULL,
0,
NULL,
0,
0,
&pSvc
);
if (FAILED(hr)) {
std::cerr << "Failed to connect to WMI service." << std::endl;
pLoc->Release();
CoUninitialize();
return;
}
hr = CoSetProxyBlanket(
pSvc,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
if (FAILED(hr)) {
std::cerr << "Failed to set security blanket." << std::endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return;
}
IEnumWbemClassObject* pEnumerator = NULL;
hr = pSvc->ExecQuery(
_bstr_t("WQL"),
_bstr_t("SELECT * FROM Win32_NetworkAdapter WHERE PhysicalAdapter = TRUE AND NetConnectionStatus = 3"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator
);
if (FAILED(hr)) {
std::cerr << "Failed to execute WQL query for Win32_NetworkAdapter." << std::endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return;
}
IWbemClassObject* pClassObj = NULL;
ULONG uReturn = 0;
while (pEnumerator) {
hr = pEnumerator->Next(WBEM_INFINITE, 1, &pClassObj, &uReturn);
if (uReturn == 0) {
break;
}
VARIANT vtProp;
hr = pClassObj->Get(L"Caption", 0, &vtProp, 0, 0);
if (SUCCEEDED(hr)) {
QString str=QString::fromWCharArray(vtProp.bstrVal);
VariantClear(&vtProp);
netCards.append(str);
}
pClassObj->Release();
}
//WMI获取声卡型号
hr = pSvc->ExecQuery(
_bstr_t("WQL"),
_bstr_t("SELECT * FROM Win32_SoundDevice"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator
);
if (FAILED(hr)) {
std::cerr << "Failed to execute WQL query for Win32_SoundDevice." << std::endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return;
}
QStringList audioCards;
while (pEnumerator) {
hr = pEnumerator->Next(WBEM_INFINITE, 1, &pClassObj, &uReturn);
if (uReturn == 0) {
break;
}
VARIANT vtProp;
hr = pClassObj->Get(L"Name", 0, &vtProp, 0, 0);
if (SUCCEEDED(hr)) {
QString str=QString::fromWCharArray(vtProp.bstrVal);
VariantClear(&vtProp);
audioCards.append(str);
}
pClassObj->Release();
}
hr = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_PhysicalMemory"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator
);
if (FAILED(hr))
{
std::cout << "Query failed. Error code: " << hr << std::endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return;
}
QStringList RAMModel;
while (pEnumerator)
{
hr = pEnumerator->Next(WBEM_INFINITE, 1, &pClassObj, &uReturn);
if (uReturn == 0)
{
break;
}
VARIANT vtProp;
hr = pClassObj->Get(L"Manufacturer", 0, &vtProp, 0, 0);
if (SUCCEEDED(hr))
{
std::wcout << "Manufacturer: " << vtProp.bstrVal << std::endl;
VariantClear(&vtProp);
}
hr = pClassObj->Get(L"PartNumber", 0, &vtProp, 0, 0);
if (SUCCEEDED(hr))
{
RAMModel.append(QString::fromWCharArray(vtProp.bstrVal));
VariantClear(&vtProp);
}
pClassObj->Release();
}
pSvc->Release();
pLoc->Release();
CoUninitialize();
DISPLAY_DEVICE d = { sizeof(DISPLAY_DEVICE) };
::EnumDisplayDevices(NULL, 0, &d, 0);
QString monitor=QString::fromWCharArray(d.DeviceString, wcslen(d.DeviceString));
//发送
//构造JSON
QJsonDocument *device=new QJsonDocument;
QJsonObject *object=new QJsonObject;
object->insert("CPU",QJsonValue(cpu));
object->insert("RAM",QJsonValue(ram));
object->insert("Hard_Disk",QJsonValue(disk));
QJsonArray *gpu_array=new QJsonArray;
for(auto gpu:gpus) {
gpu_array->append(gpu);
}
object->insert("GPU",*gpu_array);
delete gpu_array;
object->insert("Mother_Board",motherboard);
QJsonArray *RAMModel_json=new QJsonArray;
for(auto RAM:RAMModel){
RAMModel_json->append(RAM);
}
object->insert("Net_Card",*RAMModel_json);
delete RAMModel_json;
QJsonArray *netCards_json=new QJsonArray;
for(auto netCard:netCards){
netCards_json->append(netCard);
}
object->insert("Net_Card",*netCards_json);
delete netCards_json;
QJsonArray *audioCards_json=new QJsonArray;
for(auto audioCard:audioCards){
audioCards_json->append(audioCard);
}
object->insert("Audio_Card",*audioCards_json);
delete audioCards_json;
object->insert("Monitor",monitor);
device->setObject(*object);
delete object;
QJsonObject obj_root=qJsonDocument.object();
obj_root.insert("data",QString(device->toJson()));
delete device;
qJsonDocument.setObject(obj_root);
timer = new QTimer(this);
QNetworkAccessManager *httpMgr = new QNetworkAccessManager();
QNetworkRequest requestInfo;
//HTTP请求
//请求头
requestInfo.setUrl(QUrl(DEVICE_URL));
requestInfo.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));
//保存响应的变量
reply = httpMgr->post(requestInfo,qJsonDocument.toJson());
//开启一个循环,直到超时或者获取到数据为止
connect(reply,&QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
//设置定时器防止超时
connect(timer,&QTimer::timeout,this,&DeviceRequest::cancelDownload);
timer->start(5000);
//启动循环
eventLoop.exec();
delete httpMgr;
}
bool SoftwareRequest::sendRequest(QHash<QString, Record> *records)
{
timer = new QTimer(this);
QNetworkAccessManager* httpMgr = new QNetworkAccessManager();
QNetworkRequest requestInfo;
//HTTP请求
//请求头
QJsonArray array;
for(auto record : *records)
{
array.append(record.orig_name);
}
QJsonObject obj_root = qJsonDocument.object();
obj_root.insert("orig_names", array);
qJsonDocument.setObject(obj_root);
QString url = SOFTWARE_URL;
requestInfo.setUrl(url);
requestInfo.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));
//保存响应的变量
reply = httpMgr->post(requestInfo, qJsonDocument.toJson());
qDebug() << qJsonDocument.toJson();
//开启一个循环,直到超时或者获取到数据为止
connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
//设置定时器防止超时
connect(timer, &QTimer::timeout, this, &SoftwareRequest::cancelDownload);
timer->start(5000);
//启动循环
eventLoop.exec();
timer->stop();
QJsonDocument result;
// auto error = reply->error();
//如果没有错误
if (reply->error() == QNetworkReply::NoError) {
result = QJsonDocument::fromJson(reply->readAll());
}
else {
//如果有错误
delete timer;
delete httpMgr;
return false;
}
//qDebug() << result.toJson();
//如果数据完整
if (result.isObject()) {
QJsonObject obj_root2 = result.object();
QJsonArray array = obj_root2.value("data").toObject().value("menu").toArray();
for (auto value : array) {
QJsonObject object = value.toObject();
QString orig_name = object.value("orig_name").toString();
(*records)[orig_name].logo = object.value("img").toString();
(*records)[orig_name].op = object.value("op").toString();
(*records)[orig_name].func = object.value("func").toString();
(*records)[orig_name].url = object.value("url").toString();
}
}
else {
//数据不完整
//delete reply;
delete timer;
delete httpMgr;
return false;
}
delete httpMgr;
return true;
}