From fd98ce97bc44e7efac7c3943fc5756c364afdd75 Mon Sep 17 00:00:00 2001 From: kh1 Date: Mon, 27 May 2013 15:42:28 +0200 Subject: Split our own implementation of sysinfo. Change-Id: I3e66e0e4f60d7a9f91bd3c4e941e5b957725c2fc Reviewed-by: Tim Jenssen Reviewed-by: Niels Weber --- src/libs/installer/installer.pro | 2 +- src/libs/installer/sysinfo_win.cpp | 224 +++++++++++++++++++++++++++++++++++++ src/libs/kdtools/kdsysinfo_win.cpp | 183 +----------------------------- 3 files changed, 227 insertions(+), 182 deletions(-) create mode 100644 src/libs/installer/sysinfo_win.cpp diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro index 956814d50..ec884e5a3 100644 --- a/src/libs/installer/installer.pro +++ b/src/libs/installer/installer.pro @@ -197,7 +197,7 @@ unix:!macx:SOURCES += adminauthorization_x11.cpp LIBS += -l7z win32 { - SOURCES += adminauthorization_win.cpp + SOURCES += adminauthorization_win.cpp sysinfo_win.cpp LIBS += -loleaut32 -luser32 # 7zip LIBS += -ladvapi32 -lpsapi # kdtools diff --git a/src/libs/installer/sysinfo_win.cpp b/src/libs/installer/sysinfo_win.cpp new file mode 100644 index 000000000..618d6cfdb --- /dev/null +++ b/src/libs/installer/sysinfo_win.cpp @@ -0,0 +1,224 @@ +/************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include "kdsysinfo.h" + +#include "link.h" + +#ifdef Q_CC_MINGW +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0501 +# endif +#endif + +#include +#include +#include + +#include + +#ifndef Q_CC_MINGW +#pragma comment(lib, "mpr.lib") +#endif + +#include +#include +#include + +namespace KDUpdater { + +VolumeInfo updateVolumeSizeInformation(const VolumeInfo &info) +{ + ULARGE_INTEGER bytesTotal; + ULARGE_INTEGER freeBytesPerUser; + + VolumeInfo update = info; + if (GetDiskFreeSpaceExA(qPrintable(info.volumeDescriptor()), &freeBytesPerUser, &bytesTotal, NULL)) { + update.setSize(bytesTotal.QuadPart); + update.setAvailableSize(freeBytesPerUser.QuadPart); + } + return update; +} + +/*! + Returns a list of volume info objects that are mounted as network drive shares. +*/ +QList networkVolumeInfosFromMountPoints() +{ + QList volumes; + QFileInfoList drives = QDir::drives(); + foreach (const QFileInfo &drive, drives) { + const QString driveLetter = QDir::toNativeSeparators(drive.canonicalPath()); + const uint driveType = GetDriveTypeA(qPrintable(driveLetter)); + switch (driveType) { + case DRIVE_REMOTE: { + char buffer[1024] = ""; + DWORD bufferLength = 1024; + UNIVERSAL_NAME_INFOA *universalNameInfo = (UNIVERSAL_NAME_INFOA*) &buffer; + if (WNetGetUniversalNameA(qPrintable(driveLetter), UNIVERSAL_NAME_INFO_LEVEL, + LPVOID(universalNameInfo), &bufferLength) == NO_ERROR) { + VolumeInfo info; + info.setMountPath(driveLetter); + info.setVolumeDescriptor(QLatin1String(universalNameInfo->lpUniversalName)); + volumes.append(info); + } + } break; + + default: + break; + } + } + return volumes; +} + +/*! + Returns a list of volume info objects based on the given \a volumeGUID. The function also solves mounted + volume folder paths. It does not return any network drive shares. +*/ +QList localVolumeInfosFromMountPoints(PTCHAR volumeGUID) +{ +#ifndef UNICODE +#define fromWCharArray fromLatin1 +#endif + QList volumes; + DWORD bufferSize; + TCHAR volumeNames[MAX_PATH + 1] = { 0 }; + if (GetVolumePathNamesForVolumeName(volumeGUID, volumeNames, MAX_PATH, &bufferSize)) { + QStringList mountedPaths = QString::fromWCharArray(volumeNames, bufferSize).split(QLatin1Char(char(0)), + QString::SkipEmptyParts); + foreach (const QString &mountedPath, mountedPaths) { + VolumeInfo info; + info.setMountPath(mountedPath); + info.setVolumeDescriptor(QString::fromWCharArray(volumeGUID)); + volumes.append(info); + } + } + return volumes; +#ifndef UNICODE +#undef fromWCharArray +#endif +} + +QList mountedVolumes() +{ + QList tmp; + TCHAR volumeGUID[MAX_PATH + 1] = { 0 }; + HANDLE handle = FindFirstVolume(volumeGUID, MAX_PATH); + if (handle != INVALID_HANDLE_VALUE) { + tmp += localVolumeInfosFromMountPoints(volumeGUID); + while (FindNextVolume(handle, volumeGUID, MAX_PATH)) { + tmp += localVolumeInfosFromMountPoints(volumeGUID); + } + FindVolumeClose(handle); + } + tmp += networkVolumeInfosFromMountPoints(); + + QList volumes; + while (!tmp.isEmpty()) // update volume size information + volumes.append(updateVolumeSizeInformation(tmp.takeFirst())); + return volumes; +} + +bool pathIsOnLocalDevice(const QString &path) +{ + if (!QFileInfo(path).exists()) + return false; + + if (path.startsWith(QLatin1String("\\\\"))) + return false; + + QDir dir(path); + do { + if (QFileInfo(dir, QString()).isSymLink()) { + QString currentPath = QFileInfo(dir, QString()).absoluteFilePath(); + return pathIsOnLocalDevice(Link(currentPath).targetPath()); + } + } while (dir.cdUp()); + + const UINT DRIVE_REMOTE_TYPE = 4; + if (path.contains(QLatin1Char(':'))) { + const QLatin1Char nullTermination('\0'); + // for example "c:\" + const QString driveSearchString = path.left(3) + nullTermination; + WCHAR wCharDriveSearchArray[4]; + driveSearchString.toWCharArray(wCharDriveSearchArray); + UINT type = GetDriveType(wCharDriveSearchArray); + if (type == DRIVE_REMOTE_TYPE) + return false; + } + + return true; +} + +bool CALLBACK TerminateAppEnum(HWND hwnd, LPARAM lParam) +{ + DWORD dwID; + GetWindowThreadProcessId(hwnd, &dwID); + + if (dwID == (DWORD)lParam) + PostMessage(hwnd, WM_CLOSE, 0, 0); + return true; +} + +bool killProcess(const ProcessInfo &process, int msecs) +{ + DWORD dwTimeout = msecs; + if (msecs == -1) + dwTimeout = INFINITE; + + // If we can't open the process with PROCESS_TERMINATE rights, then we give up immediately. + HANDLE hProc = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, false, process.id); + if (hProc == 0) + return false; + + // TerminateAppEnum() posts WM_CLOSE to all windows whose PID matches your process's. + EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM)process.id); + + // Wait on the handle. If it signals, great. If it times out, then kill it. + bool returnValue = false; + if (WaitForSingleObject(hProc, dwTimeout) != WAIT_OBJECT_0) + returnValue = TerminateProcess(hProc, 0); + + CloseHandle(hProc); + return returnValue; +} + +} \ No newline at end of file diff --git a/src/libs/kdtools/kdsysinfo_win.cpp b/src/libs/kdtools/kdsysinfo_win.cpp index 0fa605ef9..f5d099317 100644 --- a/src/libs/kdtools/kdsysinfo_win.cpp +++ b/src/libs/kdtools/kdsysinfo_win.cpp @@ -22,28 +22,13 @@ #include "kdsysinfo.h" -#include "link.h" - -#ifdef Q_CC_MINGW -# ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 -# endif -#endif +#include +#include #include #include #include -#include - -#ifndef Q_CC_MINGW -#pragma comment(lib, "mpr.lib") -#endif - -#include -#include -#include - const int KDSYSINFO_PROCESS_QUERY_LIMITED_INFORMATION = 0x1000; namespace KDUpdater { @@ -56,100 +41,6 @@ quint64 installedMemory() return quint64(status.ullTotalPhys); } -VolumeInfo updateVolumeSizeInformation(const VolumeInfo &info) -{ - ULARGE_INTEGER bytesTotal; - ULARGE_INTEGER freeBytesPerUser; - - VolumeInfo update = info; - if (GetDiskFreeSpaceExA(qPrintable(info.volumeDescriptor()), &freeBytesPerUser, &bytesTotal, NULL)) { - update.setSize(bytesTotal.QuadPart); - update.setAvailableSize(freeBytesPerUser.QuadPart); - } - return update; -} - -/*! - Returns a list of volume info objects that are mounted as network drive shares. -*/ -QList networkVolumeInfosFromMountPoints() -{ - QList volumes; - QFileInfoList drives = QDir::drives(); - foreach (const QFileInfo &drive, drives) { - const QString driveLetter = QDir::toNativeSeparators(drive.canonicalPath()); - const uint driveType = GetDriveTypeA(qPrintable(driveLetter)); - switch (driveType) { - case DRIVE_REMOTE: { - char buffer[1024] = ""; - DWORD bufferLength = 1024; - UNIVERSAL_NAME_INFOA *universalNameInfo = (UNIVERSAL_NAME_INFOA*) &buffer; - if (WNetGetUniversalNameA(qPrintable(driveLetter), UNIVERSAL_NAME_INFO_LEVEL, - LPVOID(universalNameInfo), &bufferLength) == NO_ERROR) { - VolumeInfo info; - info.setMountPath(driveLetter); - info.setVolumeDescriptor(QLatin1String(universalNameInfo->lpUniversalName)); - volumes.append(info); - } - } break; - - default: - break; - } - } - return volumes; -} - -/*! - Returns a list of volume info objects based on the given \a volumeGUID. The function also solves mounted - volume folder paths. It does not return any network drive shares. -*/ -QList localVolumeInfosFromMountPoints(PTCHAR volumeGUID) -{ - QList volumes; - DWORD bufferSize; - TCHAR volumeNames[MAX_PATH + 1] = { 0 }; - if (GetVolumePathNamesForVolumeName(volumeGUID, volumeNames, MAX_PATH, &bufferSize)) { - QStringList mountedPaths = -#ifdef UNICODE - QString::fromWCharArray(volumeNames, bufferSize).split(QLatin1Char(char(0)), QString::SkipEmptyParts); -#else - QString::fromLatin1(volumeNames, bufferSize).split(QLatin1Char(char(0)), QString::SkipEmptyParts); -#endif - foreach (const QString &mountedPath, mountedPaths) { - VolumeInfo info; - info.setMountPath(mountedPath); -#ifdef UNICODE - info.setVolumeDescriptor(QString::fromWCharArray(volumeGUID)); -#else - info.setVolumeDescriptor(QString::fromLatin1(volumeGUID)); -#endif - volumes.append(info); - } - } - return volumes; -} - -QList mountedVolumes() -{ - QList tmp; - TCHAR volumeGUID[MAX_PATH + 1] = { 0 }; - HANDLE handle = FindFirstVolume(volumeGUID, MAX_PATH); - if (handle != INVALID_HANDLE_VALUE) { - tmp += localVolumeInfosFromMountPoints(volumeGUID); - while (FindNextVolume(handle, volumeGUID, MAX_PATH)) { - tmp += localVolumeInfosFromMountPoints(volumeGUID); - } - FindVolumeClose(handle); - } - tmp += networkVolumeInfosFromMountPoints(); - - QList volumes; - while (!tmp.isEmpty()) // update volume size information - volumes.append(updateVolumeSizeInformation(tmp.takeFirst())); - return volumes; -} - struct EnumWindowsProcParam { QList processes; @@ -228,74 +119,4 @@ QList runningProcesses() return param.processes; } -bool CALLBACK TerminateAppEnum(HWND hwnd, LPARAM lParam) -{ - DWORD dwID; - GetWindowThreadProcessId(hwnd, &dwID); - - if (dwID == (DWORD)lParam) - PostMessage(hwnd, WM_CLOSE, 0, 0); - - return true; -} - -bool killProcess(const ProcessInfo &process, int msecs) -{ - DWORD dwTimeout = msecs; - if (msecs == -1) - dwTimeout = INFINITE; - - // If we can't open the process with PROCESS_TERMINATE rights, - // then we give up immediately. - HANDLE hProc = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, false, process.id); - - if (hProc == 0) - return false; - - // TerminateAppEnum() posts WM_CLOSE to all windows whose PID - // matches your process's. - EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM)process.id); - - // Wait on the handle. If it signals, great. If it times out, - // then you kill it. - bool returnValue = false; - if (WaitForSingleObject(hProc, dwTimeout) != WAIT_OBJECT_0) - returnValue = TerminateProcess(hProc, 0); - - CloseHandle(hProc) ; - - return returnValue; -} - -bool pathIsOnLocalDevice(const QString &path) -{ - if (!QFileInfo(path).exists()) - return false; - - if (path.startsWith(QLatin1String("\\\\"))) - return false; - - QDir dir(path); - do { - if (QFileInfo(dir, QString()).isSymLink()) { - QString currentPath = QFileInfo(dir, QString()).absoluteFilePath(); - return pathIsOnLocalDevice(Link(currentPath).targetPath()); - } - } while (dir.cdUp()); - - const UINT DRIVE_REMOTE_TYPE = 4; - if (path.contains(QLatin1Char(':'))) { - const QLatin1Char nullTermination('\0'); - // for example "c:\" - const QString driveSearchString = path.left(3) + nullTermination; - WCHAR wCharDriveSearchArray[4]; - driveSearchString.toWCharArray(wCharDriveSearchArray); - UINT type = GetDriveType(wCharDriveSearchArray); - if (type == DRIVE_REMOTE_TYPE) - return false; - } - - return true; -} - } // namespace KDUpdater -- cgit v1.2.3