Commit 9ca1e7d7 authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

Debugger: Move some windows functionality around.

parent 9685a0a4
......@@ -155,4 +155,10 @@ QTCREATOR_UTILS_EXPORT QString getShortPathName(const QString &name, QString *er
return rc;
}
unsigned long winQPidToPid(const Q_PID qpid)
{
const PROCESS_INFORMATION *processInfo = reinterpret_cast<const PROCESS_INFORMATION*>(qpid);
return processInfo->dwProcessId;
}
} // namespace Utils
......@@ -32,6 +32,8 @@
#include "utils_global.h"
#include <QtCore/QProcess> // Q_PID (is PROCESS_INFORMATION*)
QT_BEGIN_NAMESPACE
class QString;
QT_END_NAMESPACE
......@@ -52,5 +54,7 @@ QTCREATOR_UTILS_EXPORT QString winGetDLLVersion(WinDLLVersionType t,
QTCREATOR_UTILS_EXPORT QString getShortPathName(const QString &name,
QString *errorMessage);
QTCREATOR_UTILS_EXPORT unsigned long winQPidToPid(const Q_PID qpid);
} // namespace Utils
#endif // WINUTILS_H
......@@ -29,6 +29,7 @@
#include "corebreakpoint.h"
#include "coreengine.h"
#include "dbgwinutils.h"
#include <utils/qtcassert.h>
......@@ -37,8 +38,6 @@
#include <QtCore/QDebug>
#include <QtCore/QMap>
#include <psapi.h>
enum { debugBP = 0 };
namespace CdbCore {
......@@ -239,83 +238,6 @@ bool BreakPoint::add(CIDebugControl* debugControl,
return true;
}
// Helper for normalizing file names:
// Map the device paths in a file name to back to drive letters
// "/Device/HarddiskVolume1/file.cpp" -> "C:/file.cpp"
static bool mapDeviceToDriveLetter(QString *s)
{
enum { bufSize = 512 };
// Retrieve drive letters and get their device names.
// Do not cache as it may change due to removable/network drives.
TCHAR driveLetters[bufSize];
if (!GetLogicalDriveStrings(bufSize-1, driveLetters))
return false;
TCHAR driveName[MAX_PATH];
TCHAR szDrive[3] = TEXT(" :");
for (const TCHAR *driveLetter = driveLetters; *driveLetter; driveLetter++) {
szDrive[0] = *driveLetter; // Look up each device name
if (QueryDosDevice(szDrive, driveName, MAX_PATH)) {
const QString deviceName = QString::fromWCharArray(driveName);
if (s->startsWith(deviceName)) {
s->replace(0, deviceName.size(), QString::fromWCharArray(szDrive));
return true;
}
}
}
return false;
}
// Helper for normalizing file names:
// Determine normalized case of a Windows file name (camelcase.cpp -> CamelCase.cpp)
// as the debugger reports lower case file names.
// Restriction: File needs to exists and be non-empty and will be to be opened/mapped.
// This is the MSDN-recommended way of doing that. The result should be cached.
static inline QString normalizeFileNameCaseHelper(const QString &f)
{
HANDLE hFile = CreateFile((const wchar_t*)f.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
return f;
// Get the file size. We need a non-empty file to map it.
DWORD dwFileSizeHi = 0;
DWORD dwFileSizeLo = GetFileSize(hFile, &dwFileSizeHi);
if (dwFileSizeLo == 0 && dwFileSizeHi == 0) {
CloseHandle(hFile);
return f;
}
// Create a file mapping object.
HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 1, NULL);
if (!hFileMap) {
CloseHandle(hFile);
return f;
}
// Create a file mapping to get the file name.
void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);
if (!pMem) {
CloseHandle(hFileMap);
CloseHandle(hFile);
return f;
}
QString rc;
WCHAR pszFilename[MAX_PATH];
pszFilename[0] = 0;
// Get a file name of the form "/Device/HarddiskVolume1/file.cpp"
if (GetMappedFileName (GetCurrentProcess(), pMem, pszFilename, MAX_PATH)) {
rc = QString::fromWCharArray(pszFilename);
if (!mapDeviceToDriveLetter(&rc))
rc.clear();
}
UnmapViewOfFile(pMem);
CloseHandle(hFileMap);
CloseHandle(hFile);
return rc.isEmpty() ? f : rc;
}
// Make sure file can be found in editor manager and text markers
// Use '/', correct case and capitalize drive letter. Use a cache.
......@@ -328,7 +250,7 @@ QString BreakPoint::normalizeFileName(const QString &f)
const NormalizedFileCache::const_iterator it = normalizedFileNameCache()->constFind(f);
if (it != normalizedFileNameCache()->constEnd())
return it.value();
QString normalizedName = QDir::fromNativeSeparators(normalizeFileNameCaseHelper(f));
QString normalizedName = QDir::fromNativeSeparators(Debugger::Internal::winNormalizeFileName(f));
// Upcase drive letter for consistency even if case mapping fails.
if (normalizedName.size() > 2 && normalizedName.at(1) == QLatin1Char(':'))
normalizedName[0] = normalizedName.at(0).toUpper();
......
......@@ -167,5 +167,80 @@ unsigned long winGetCurrentProcessId()
return GetCurrentProcessId();
}
// Helper for normalizing file names:
// Map the device paths in a file name to back to drive letters
// "/Device/HarddiskVolume1/file.cpp" -> "C:/file.cpp"
static bool mapDeviceToDriveLetter(QString *s)
{
enum { bufSize = 512 };
// Retrieve drive letters and get their device names.
// Do not cache as it may change due to removable/network drives.
TCHAR driveLetters[bufSize];
if (!GetLogicalDriveStrings(bufSize-1, driveLetters))
return false;
TCHAR driveName[MAX_PATH];
TCHAR szDrive[3] = TEXT(" :");
for (const TCHAR *driveLetter = driveLetters; *driveLetter; driveLetter++) {
szDrive[0] = *driveLetter; // Look up each device name
if (QueryDosDevice(szDrive, driveName, MAX_PATH)) {
const QString deviceName = QString::fromWCharArray(driveName);
if (s->startsWith(deviceName)) {
s->replace(0, deviceName.size(), QString::fromWCharArray(szDrive));
return true;
}
}
}
return false;
}
// Determine normalized case of a Windows file name (camelcase.cpp -> CamelCase.cpp)
// Restriction: File needs to exists and be non-empty and will be to be opened/mapped.
// This is the MSDN-recommended way of doing that.
QString winNormalizeFileName(const QString &f)
{
HANDLE hFile = CreateFile((const wchar_t*)f.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
return f;
// Get the file size. We need a non-empty file to map it.
DWORD dwFileSizeHi = 0;
DWORD dwFileSizeLo = GetFileSize(hFile, &dwFileSizeHi);
if (dwFileSizeLo == 0 && dwFileSizeHi == 0) {
CloseHandle(hFile);
return f;
}
// Create a file mapping object.
HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 1, NULL);
if (!hFileMap) {
CloseHandle(hFile);
return f;
}
// Create a file mapping to get the file name.
void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);
if (!pMem) {
CloseHandle(hFileMap);
CloseHandle(hFile);
return f;
}
QString rc;
WCHAR pszFilename[MAX_PATH];
pszFilename[0] = 0;
// Get a file name of the form "/Device/HarddiskVolume1/file.cpp"
if (GetMappedFileName (GetCurrentProcess(), pMem, pszFilename, MAX_PATH)) {
rc = QString::fromWCharArray(pszFilename);
if (!mapDeviceToDriveLetter(&rc))
rc.clear();
}
UnmapViewOfFile(pMem);
CloseHandle(hFileMap);
CloseHandle(hFile);
return rc.isEmpty() ? f : rc;
}
} // namespace Internal
} // namespace Debugger
......@@ -49,6 +49,14 @@ bool winDebugBreakProcess(unsigned long pid, QString *errorMessage);
unsigned long winGetCurrentProcessId();
/* Helper for (case-)normalizing file names:
* Determine normalized case of a Windows file name (camelcase.cpp -> CamelCase.cpp)
* as the debugger reports lower case file names.
* Restriction: File needs to exist and be non-empty and will be to be opened/mapped.
* The result should be cached as the function can be extensive. */
QString winNormalizeFileName(const QString &f);
} // namespace Internal
} // namespace Debugger
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment