7#include "private/qlockfile_p.h"
8#include "private/qfilesystementry_p.h"
11#include "QtCore/qdatetime.h"
12#include "QtCore/qdir.h"
13#include "QtCore/qdebug.h"
14#include "QtCore/qfileinfo.h"
15#include "QtCore/qthread.h"
17#include <qt_windows.h>
26 WIN32_FILE_ATTRIBUTE_DATA data;
27 return GetFileAttributesEx(fileName, GetFileExInfoStandard, &data);
32 const DWORD dwShareMode = 0;
33 SECURITY_ATTRIBUTES securityAtts = {
sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
34 HANDLE fh = CreateFile(qt_castToWchar(QDir::toNativeSeparators(fileName)),
35 GENERIC_READ | GENERIC_WRITE,
39 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
41 bool success = (fh != INVALID_HANDLE_VALUE);
46 const DWORD lastError = GetLastError();
47 if (lastError == ERROR_FILE_NOT_FOUND)
53QLockFile::LockError QLockFilePrivate::tryLock_sys()
55 const QFileSystemEntry fileEntry(fileName);
62 const DWORD dwShareMode = FILE_SHARE_READ;
63 SECURITY_ATTRIBUTES securityAtts = {
sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
64 HANDLE fh = CreateFile((
const wchar_t*)fileEntry.nativeFilePath().utf16(),
65 GENERIC_READ | GENERIC_WRITE,
69 FILE_ATTRIBUTE_NORMAL,
71 if (fh == INVALID_HANDLE_VALUE) {
72 const DWORD lastError = GetLastError();
74 case ERROR_SHARING_VIOLATION:
75 case ERROR_ALREADY_EXISTS:
76 case ERROR_FILE_EXISTS:
77 return QLockFile::LockFailedError;
78 case ERROR_ACCESS_DENIED:
81 return fileExists((
const wchar_t*)fileEntry.nativeFilePath().utf16())
82 ? QLockFile::LockFailedError
83 : QLockFile::PermissionError;
85 qWarning(
"Got unexpected locking error %llu", quint64(lastError));
86 return QLockFile::UnknownError;
92 QByteArray fileData = lockFileContents();
93 DWORD bytesWritten = 0;
94 QLockFile::LockError error = QLockFile::NoError;
95 if (!WriteFile(fh, fileData.constData(), fileData.size(), &bytesWritten, NULL) || !FlushFileBuffers(fh))
96 error = QLockFile::UnknownError;
100bool QLockFilePrivate::removeStaleLock()
103 return deleteFile(fileName);
106bool QLockFilePrivate::isProcessRunning(qint64 pid,
const QString &appname)
108 HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
114 if (!::GetExitCodeProcess(procHandle, &exitCode))
116 ::CloseHandle(procHandle);
117 if (exitCode != STILL_ACTIVE)
120 const QString processName = processNameByPid(pid);
121 if (!processName.isEmpty() && processName != appname)
127QString QLockFilePrivate::processNameByPid(qint64 pid)
129 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, DWORD(pid));
133 wchar_t buf[MAX_PATH];
134 const DWORD length = GetModuleFileNameExW(hProcess, NULL, buf,
sizeof(buf) /
sizeof(
wchar_t));
135 CloseHandle(hProcess);
138 QString name = QString::fromWCharArray(buf, length);
139 int i = name.lastIndexOf(u'\\');
141 name.remove(0, i + 1);
142 i = name.lastIndexOf(u'.');
148int QLockFilePrivate::openNewFileDescriptor(
const QString &fileName)
159 HANDLE handle = CreateFile(
reinterpret_cast<
const wchar_t *>(fileName.utf16()), GENERIC_READ,
160 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr,
161 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
nullptr);
162 if (handle == INVALID_HANDLE_VALUE)
164 int fd = _open_osfhandle(intptr_t(handle), _O_RDONLY);
172void QLockFile::unlock()
177 CloseHandle(d->fileHandle);
179 static const int maxAttempts = 500;
180 while (!deleteFile(d->fileName) && ++attempts < maxAttempts) {
184 if (attempts == maxAttempts) {
185 qWarning() <<
"Could not remove our own lock file" << d->fileName
186 <<
". Either other users of the lock file are reading it constantly for 500 ms, "
187 "or we (no longer) have permissions to delete the file";
191 d->lockError = QLockFile::NoError;
static bool deleteFile(const QString &fileName)
static QT_BEGIN_NAMESPACE bool fileExists(const wchar_t *fileName)