summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTannin <devnull@localhost>2014-09-29 20:35:35 +0200
committerTannin <devnull@localhost>2014-09-29 20:35:35 +0200
commitbfa6c9ab1e2f316c53811de6e311212b8a088591 (patch)
tree1903fb7b8758ebacaa91497561ea5277d13f8d2b /src
parent7a7c464b18f2977c3a7aa7e80c4041732b19ba26 (diff)
- moved the hook-recursion-protection to tls
- some code cleanup and consolidation - hook.dll will now report all of its own exceptions - some more logging during startup - changed the way urls are encoded for download requests - now displaying (one of the) process name(s) while waiting for a program to end - bugfix: spawned processes were forced to leave the job
Diffstat (limited to 'src')
-rw-r--r--src/downloadmanager.cpp50
-rw-r--r--src/mainwindow.cpp49
-rw-r--r--src/profile.cpp7
-rw-r--r--src/shared/directoryentry.cpp10
-rw-r--r--src/spawn.cpp13
5 files changed, 84 insertions, 45 deletions
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp
index 82701a05..931201d1 100644
--- a/src/downloadmanager.cpp
+++ b/src/downloadmanager.cpp
@@ -331,7 +331,8 @@ bool DownloadManager::addDownload(const QStringList &URLs,
fileName = "unknown";
}
- QNetworkRequest request(URLs.first());
+ QUrl preferredUrl = QUrl::fromEncoded(URLs.first().toLocal8Bit());
+ QNetworkRequest request(preferredUrl);
return addDownload(m_NexusInterface->getAccessManager()->get(request), URLs, fileName, modID, fileID, fileInfo);
}
@@ -1198,47 +1199,34 @@ void DownloadManager::nxmFileInfoAvailable(int modID, int fileID, QVariant userD
m_RequestIDs.insert(m_NexusInterface->requestDownloadURL(modID, fileID, this, qVariantFromValue(test), QString()));
}
-
-// sort function to sort by best download server
-bool DownloadManager::ServerByPreference(const std::map<QString, int> &preferredServers, const QVariant &LHS, const QVariant &RHS)
+int evaluateFileInfoMap(const QVariantMap &map, const std::map<QString, int> &preferredServers)
{
- int LHSVal = 0;
- int RHSVal = 0;
+ int result = 0;
- QVariantMap LHSMap = LHS.toMap();
- QVariantMap RHSMap = RHS.toMap();
-
- int LHSUsers = LHSMap["ConnectedUsers"].toInt();
- int RHSUsers = RHSMap["ConnectedUsers"].toInt();
+ int users = map["ConnectedUsers"].toInt();
// 0 users is probably a sign that the server is offline. Since there is currently no
// mechanism to try a different server, we avoid those without users
- if (LHSUsers == 0) {
- LHSVal -= 500;
- } else {
- LHSVal -= LHSUsers;
- }
- if (RHSUsers == 0) {
- RHSVal -= 500;
+ if (users == 0) {
+ result -= 500;
} else {
- RHSVal -= RHSUsers;
+ result -= users;
}
- // user preference. This is a bit silly because the more servers on the preferred list the higher the boost
- auto LHSPreference = preferredServers.find(LHSMap["Name"].toString());
- auto RHSPreference = preferredServers.find(RHSMap["Name"].toString());
+ auto preference = preferredServers.find(map["Name"].toString());
- if (LHSPreference != preferredServers.end()) {
- LHSVal += 100 + LHSPreference->second * 20;
- }
- if (RHSPreference != preferredServers.end()) {
- RHSVal += 100 + RHSPreference->second * 20;
+ if (preference != preferredServers.end()) {
+ result += 100 + preference->second * 20;
}
- // premium isn't valued high because premium servers already get a massive boost for having few users online
- if (LHSMap["IsPremium"].toBool()) LHSVal += 5;
- if (RHSMap["IsPremium"].toBool()) RHSVal += 5;
+ if (map["IsPremium"].toBool()) result += 5;
+
+ return result;
+}
- return RHSVal < LHSVal;
+// sort function to sort by best download server
+bool DownloadManager::ServerByPreference(const std::map<QString, int> &preferredServers, const QVariant &LHS, const QVariant &RHS)
+{
+ return evaluateFileInfoMap(LHS.toMap(), preferredServers) > evaluateFileInfoMap(RHS.toMap(), preferredServers);
}
int DownloadManager::startDownloadURLs(const QStringList &urls)
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 5feda937..20738a99 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -1405,6 +1405,15 @@ HANDLE MainWindow::spawnBinaryDirect(const QFileInfo &binary, const QString &arg
}
}
+std::wstring getProcessName(DWORD processId)
+{
+ HANDLE process = ::OpenProcess(PROCESS_QUERY_INFORMATION, false, processId);
+
+ DWORD value = MAX_PATH;
+ wchar_t buffer[MAX_PATH];
+ ::QueryFullProcessImageNameW(process, 0, buffer, &value);
+ return buffer;
+}
void MainWindow::spawnBinary(const QFileInfo &binary, const QString &arguments, const QDir &currentDirectory, bool closeAfterStart, const QString &steamAppID)
{
@@ -1423,11 +1432,43 @@ void MainWindow::spawnBinary(const QFileInfo &binary, const QString &arguments,
QCoreApplication::processEvents();
- while ((::WaitForSingleObject(processHandle, 100) == WAIT_TIMEOUT) &&
- !dialog->unlockClicked()) {
- // keep processing events so the app doesn't appear dead
- QCoreApplication::processEvents();
+ DWORD retLen;
+ JOBOBJECT_BASIC_PROCESS_ID_LIST info;
+
+ {
+ DWORD currentProcess = 0UL;
+ bool isJobHandle = true;
+
+ DWORD res = ::MsgWaitForMultipleObjects(1, &processHandle, false, 1000, QS_KEY | QS_MOUSE);
+ while ((res != WAIT_FAILED) && (res != WAIT_OBJECT_0) && !dialog->unlockClicked()) {
+ if (isJobHandle) {
+ if (::QueryInformationJobObject(processHandle, JobObjectBasicProcessIdList, &info, sizeof(info), &retLen) > 0) {
+ if (info.NumberOfProcessIdsInList == 0) {
+ } else {
+ if (info.ProcessIdList[0] != currentProcess) {
+ currentProcess = info.ProcessIdList[0];
+ dialog->setProcessName(ToQString(getProcessName(currentProcess)));
+ }
+ break;
+ }
+ } else {
+ // the info-object I passed only provides space for 1 process id. but since this code only cares about whether there
+ // is more than one that's good enough. ERROR_MORE_DATA simply signals there are at least two processes running.
+ // any other error probably means the handle is a regular process handle, probably caused by running MO in a job without
+ // the right to break out.
+ if (::GetLastError() != ERROR_MORE_DATA) {
+ isJobHandle = false;
+ }
+ }
+ }
+
+ // keep processing events so the app doesn't appear dead
+ QCoreApplication::processEvents();
+
+ res = ::MsgWaitForMultipleObjects(1, &processHandle, false, 1000, QS_KEY | QS_MOUSE);
+ }
}
+ ::CloseHandle(processHandle);
this->setEnabled(true);
refreshDirectoryStructure();
diff --git a/src/profile.cpp b/src/profile.cpp
index 958084d7..6e9d8f0f 100644
--- a/src/profile.cpp
+++ b/src/profile.cpp
@@ -217,7 +217,7 @@ void Profile::createTweakedIniFile()
}
if (localSavesEnabled()) {
- if (!::WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"1", ToWString(tweakedIni).c_str())) {
+ if (!::WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"0", ToWString(tweakedIni).c_str())) {
error = true;
}
@@ -238,7 +238,7 @@ void Profile::createTweakedIniFile()
void Profile::refreshModStatus()
{
QFile file(getModlistFileName());
- if (!file.exists()) {
+ if (!file.open(QIODevice::ReadOnly)) {
throw MyException(tr("\"%1\" is missing or inaccessible").arg(getModlistFileName()));
}
@@ -249,10 +249,9 @@ void Profile::refreshModStatus()
std::set<QString> namesRead;
// load mods from file and update enabled state and priority for them
- file.open(QIODevice::ReadOnly);
int index = 0;
while (!file.atEnd()) {
- QByteArray line = file.readLine();
+ QByteArray line = file.readLine().trimmed();
bool enabled = true;
QString modName;
if (line.length() == 0) {
diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp
index 24868a93..0adf0812 100644
--- a/src/shared/directoryentry.cpp
+++ b/src/shared/directoryentry.cpp
@@ -72,8 +72,7 @@ public:
}
bool exists(const std::wstring &name) {
- std::map<std::wstring, int>::iterator iter = m_OriginsNameMap.find(name);
- return iter != m_OriginsNameMap.end();
+ return m_OriginsNameMap.find(name) != m_OriginsNameMap.end();
}
FilesOrigin &getByID(Index ID) {
@@ -369,16 +368,14 @@ std::wstring FileEntry::getFullPath() const
bool ignore = false;
result = m_Parent->getOriginByID(getOrigin(ignore)).getPath(); //base directory for origin
recurseParents(result, m_Parent); // all intermediate directories
- result.append(L"\\").append(m_Name); // the actual filename
- return result;
+ return result + L"\\" + m_Name;
}
std::wstring FileEntry::getRelativePath() const
{
std::wstring result;
recurseParents(result, m_Parent); // all intermediate directories
- result.append(L"\\").append(m_Name); // the actual filename
- return result;
+ return result + L"\\" + m_Name;
}
@@ -446,6 +443,7 @@ void DirectoryEntry::addFromOrigin(const std::wstring &originName, const std::ws
boost::scoped_array<wchar_t> buffer(new wchar_t[MAXPATH_UNICODE + 1]);
memset(buffer.get(), L'\0', MAXPATH_UNICODE + 1);
int offset = _snwprintf(buffer.get(), MAXPATH_UNICODE, L"%ls", directory.c_str());
+ buffer.get()[offset] = L'\0';
addFiles(origin, buffer.get(), offset);
}
m_Populated = true;
diff --git a/src/spawn.cpp b/src/spawn.cpp
index 1392ec88..64f4e995 100644
--- a/src/spawn.cpp
+++ b/src/spawn.cpp
@@ -117,6 +117,19 @@ HANDLE startBinary(const QFileInfo &binary,
HANDLE stdOut,
HANDLE stdErr)
{
+ JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo;
+
+ ::QueryInformationJobObject(NULL, JobObjectExtendedLimitInformation, &jobInfo, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION), NULL);
+ jobInfo.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_BREAKAWAY_OK;
+
+ HANDLE jobObject = ::CreateJobObject(NULL, NULL);
+
+ if (jobObject == NULL) {
+ qWarning("failed to create job object: %lu", ::GetLastError());
+ } else {
+ ::SetInformationJobObject(jobObject, JobObjectExtendedLimitInformation, &jobInfo, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
+ }
+
HANDLE processHandle, threadHandle;
std::wstring binaryName = ToWString(QDir::toNativeSeparators(binary.absoluteFilePath()));
std::wstring currentDirectoryName = ToWString(QDir::toNativeSeparators(currentDirectory.absolutePath()));