2222
2323#include < comdef.h>
2424#include < Lmcons.h>
25+ #include < psapi.h>
26+ #include < RestartManager.h>
2527#include < shlguid.h>
2628#include < shlobj.h>
2729#include < string>
@@ -43,6 +45,72 @@ static const char runPathC[] = R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\C
4345
4446namespace OCC {
4547
48+ QVector<Utility::ProcessInfosForOpenFile> Utility::queryProcessInfosKeepingFileOpen (const QString &filePath)
49+ {
50+ QVector<ProcessInfosForOpenFile> results;
51+
52+ DWORD restartManagerSession = 0 ;
53+ WCHAR restartManagerSessionKey[CCH_RM_SESSION_KEY + 1 ] = {0 };
54+ auto errorStatus = RmStartSession (&restartManagerSession, 0 , restartManagerSessionKey);
55+ if (errorStatus != ERROR_SUCCESS) {
56+ return results;
57+ }
58+
59+ LPCWSTR files[] = {reinterpret_cast <LPCWSTR>(filePath.utf16 ())};
60+ errorStatus = RmRegisterResources (restartManagerSession, 1 , files, 0 , NULL , 0 , NULL );
61+ if (errorStatus != ERROR_SUCCESS) {
62+ RmEndSession (restartManagerSession);
63+ return results;
64+ }
65+
66+ DWORD rebootReasons = 0 ;
67+ UINT rmProcessInfosNeededCount = 0 ;
68+ std::vector<RM_PROCESS_INFO> rmProcessInfos;
69+ auto rmProcessInfosRequestedCount = static_cast <UINT>(rmProcessInfos.size ());
70+ errorStatus = RmGetList (restartManagerSession, &rmProcessInfosNeededCount, &rmProcessInfosRequestedCount, rmProcessInfos.data (), &rebootReasons);
71+
72+ if (errorStatus == ERROR_MORE_DATA) {
73+ rmProcessInfos.resize (rmProcessInfosNeededCount, {});
74+ rmProcessInfosRequestedCount = static_cast <UINT>(rmProcessInfos.size ());
75+ errorStatus = RmGetList (restartManagerSession, &rmProcessInfosNeededCount, &rmProcessInfosRequestedCount, rmProcessInfos.data (), &rebootReasons);
76+ }
77+
78+ if (errorStatus != ERROR_SUCCESS || rmProcessInfos.empty ()) {
79+ RmEndSession (restartManagerSession);
80+ return results;
81+ }
82+
83+ for (size_t i = 0 ; i < rmProcessInfos.size (); ++i) {
84+ const auto processHandle = OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION, FALSE , rmProcessInfos[i].Process .dwProcessId );
85+ if (!processHandle) {
86+ continue ;
87+ }
88+
89+ FILETIME ftCreate, ftExit, ftKernel, ftUser;
90+
91+ if (!GetProcessTimes (processHandle, &ftCreate, &ftExit, &ftKernel, &ftUser)
92+ || CompareFileTime (&rmProcessInfos[i].Process .ProcessStartTime , &ftCreate) != 0 ) {
93+ CloseHandle (processHandle);
94+ continue ;
95+ }
96+
97+ WCHAR processFullPath[MAX_PATH];
98+ DWORD processFullPathLength = MAX_PATH;
99+ if (QueryFullProcessImageNameW (processHandle, 0 , processFullPath, &processFullPathLength) && processFullPathLength <= MAX_PATH) {
100+ const auto processFullPathString = QDir::fromNativeSeparators (QString::fromWCharArray (processFullPath));
101+ const QFileInfo fileInfoForProcess (processFullPathString);
102+ const auto processName = fileInfoForProcess.fileName ();
103+ if (!processName.isEmpty ()) {
104+ results.push_back (Utility::ProcessInfosForOpenFile{rmProcessInfos[i].Process .dwProcessId , processName});
105+ }
106+ }
107+ CloseHandle (processHandle);
108+ }
109+ RmEndSession (restartManagerSession);
110+
111+ return results;
112+ }
113+
46114void Utility::setupFavLink (const QString &folder)
47115{
48116 // First create a Desktop.ini so that the folder and favorite link show our application's icon.
0 commit comments