diff options
author | Tim Jenssen <tim.jenssen@nokia.com> | 2012-04-25 14:14:56 +0200 |
---|---|---|
committer | Tim Jenssen <tim.jenssen@nokia.com> | 2012-04-27 16:23:20 +0200 |
commit | 0a8755ace26f1174e9ed99e5060c4d8da0ba010d (patch) | |
tree | 7d73b3e0151b06707d8b9df5cef25be7203a420f /src/libs/kdtools | |
parent | ff6179ea53debd66e63738382b3af62087b81af7 (diff) |
now installer can disallow to install from a remote location
- at the moment the implementation is windows only
- in some cases it is problematically to install big installers from a
remote location: if the connection is lost -> crash
- the installer itself can have the flag DependsOnLocalInstallerBinary in the config.xml file
- or a component can request that installer.setDependsOnLocalInstallerBinary()
Change-Id: I0c8d70ca89dd55d2d0c52bf3418f11c95b5290a1
Reviewed-by: Oliver Wolff <oliver.wolff@nokia.com>
Reviewed-by: Karsten Heimrich <karsten.heimrich@nokia.com>
Diffstat (limited to 'src/libs/kdtools')
-rw-r--r-- | src/libs/kdtools/kdsysinfo.h | 3 | ||||
-rw-r--r-- | src/libs/kdtools/kdsysinfo_win.cpp | 123 |
2 files changed, 124 insertions, 2 deletions
diff --git a/src/libs/kdtools/kdsysinfo.h b/src/libs/kdtools/kdsysinfo.h index 6c8079fcd..810e3dbc1 100644 --- a/src/libs/kdtools/kdsysinfo.h +++ b/src/libs/kdtools/kdsysinfo.h @@ -70,6 +70,9 @@ struct ProcessInfo quint64 installedMemory(); QList<VolumeInfo> mountedVolumes(); QList<ProcessInfo> runningProcesses(); +#ifdef Q_OS_WIN +bool pathIsOnLocalDevice(const QString &path); +#endif } // namespace KDUpdater diff --git a/src/libs/kdtools/kdsysinfo_win.cpp b/src/libs/kdtools/kdsysinfo_win.cpp index 45342aee5..92d87d680 100644 --- a/src/libs/kdtools/kdsysinfo_win.cpp +++ b/src/libs/kdtools/kdsysinfo_win.cpp @@ -29,8 +29,9 @@ #include <Winnetwk.h> #pragma comment(lib, "mpr.lib") -#include <QtCore/QDir> -#include <QtCore/QLibrary> +#include <QDebug> +#include <QDir> +#include <QLibrary> const int KDSYSINFO_PROCESS_QUERY_LIMITED_INFORMATION = 0x1000; @@ -209,4 +210,122 @@ QList<ProcessInfo> runningProcesses() return param.processes; } +// REPARSE_DATA_BUFFER structure from msdn help: http://msdn.microsoft.com/en-us/library/ff552012.aspx +typedef struct _REPARSE_DATA_BUFFER { + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + union { + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + struct { + UCHAR DataBuffer[1]; + } GenericReparseBuffer; + }; +} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; + +QString junctionTargetPath(const QString &path) +{ + HANDLE fileHandle; + fileHandle = CreateFile(path.utf16(), FILE_READ_EA, FILE_SHARE_READ | FILE_SHARE_WRITE | + FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | + FILE_FLAG_OPEN_REPARSE_POINT, NULL); + if (fileHandle == INVALID_HANDLE_VALUE) { + qDebug() << QString::fromLatin1("Could not open: '%1'; error: %2\n").arg(path).arg(GetLastError()); + return path; + } + + REPARSE_DATA_BUFFER* reparseStructData = (REPARSE_DATA_BUFFER*)calloc(1, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); + + DWORD bytesReturned; + // fill the reparseStructData + BOOL isOk = DeviceIoControl(fileHandle, FSCTL_GET_REPARSE_POINT, NULL, 0, reparseStructData, + MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytesReturned, NULL); + if (isOk == FALSE) { + DWORD deviceIOControlError = GetLastError(); + if (deviceIOControlError == ERROR_NOT_A_REPARSE_POINT) + qDebug() << QString::fromLatin1("Could not reparse information (windows symlink) for %1").arg(path); + else { + qDebug() << QString::fromLatin1("Get DeviceIoControl for %1 failed with error: %2").arg( + path).arg(deviceIOControlError); + } + CloseHandle(fileHandle); + return path; + } + CloseHandle(fileHandle); + + QString realPath = path; + if (IsReparseTagMicrosoft(reparseStructData->ReparseTag)) { + size_t realPathLength = 0; + WCHAR *realPathWCHAR = 0; + if (reparseStructData->ReparseTag == IO_REPARSE_TAG_SYMLINK){ + realPathLength = reparseStructData->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(WCHAR); + realPathWCHAR = new WCHAR[realPathLength + 1]; + wcsncpy_s(realPathWCHAR, realPathLength + 1, &reparseStructData->SymbolicLinkReparseBuffer.PathBuffer[ + reparseStructData->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(WCHAR)], realPathLength); + } else if (reparseStructData->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { + realPathLength = reparseStructData->MountPointReparseBuffer.PrintNameLength / sizeof(WCHAR); + realPathWCHAR = new WCHAR[realPathLength + 1]; + wcsncpy_s(realPathWCHAR, realPathLength + 1, &reparseStructData->MountPointReparseBuffer.PathBuffer[ + reparseStructData->MountPointReparseBuffer.PrintNameOffset / sizeof(WCHAR)], realPathLength); + } else { + qDebug() << QString::fromLatin1("Path %1 is not a symlink and not a mount point.").arg(path); + } + if (realPathLength != 0) { + realPathWCHAR[realPathLength] = 0; + realPath = QString::fromStdWString(realPathWCHAR); + delete [] realPathWCHAR; + } + + } else { + qDebug() << QString::fromLatin1("Path %1 is not reparse point.").arg(path); + } + free(reparseStructData); + return realPath; +} + +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(junctionTargetPath(currentPath)); + } + } 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 |