summaryrefslogtreecommitdiff
path: root/rbutil
diff options
context:
space:
mode:
Diffstat (limited to 'rbutil')
-rw-r--r--rbutil/rbutilqt/base/utils.cpp122
-rw-r--r--rbutil/rbutilqt/base/utils.h1
2 files changed, 123 insertions, 0 deletions
diff --git a/rbutil/rbutilqt/base/utils.cpp b/rbutil/rbutilqt/base/utils.cpp
index f58d8c34e3..099f9c7742 100644
--- a/rbutil/rbutilqt/base/utils.cpp
+++ b/rbutil/rbutilqt/base/utils.cpp
@@ -764,6 +764,128 @@ QMap<QString, QList<int> > Utils::findRunningProcess(QStringList names)
764} 764}
765 765
766 766
767/** Suspends/resumes processes
768 * @param pidlist a list of PIDs to suspend/resume
769 * @param suspend processes are suspended if true, or resumed when false
770 * @return a list of PIDs successfully suspended/resumed
771 */
772QList<int> Utils::suspendProcess(QList<int> pidlist, bool suspend)
773{
774 QList<int> result;
775#if defined(Q_OS_WIN32)
776 // Enable debug privilege
777 HANDLE hToken = NULL;
778 LUID seDebugValue;
779 TOKEN_PRIVILEGES tNext, tPrev;
780 DWORD sPrev;
781 if(LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &seDebugValue)) {
782 if(OpenProcessToken(GetCurrentProcess(),
783 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
784 memset(&tNext, 0, sizeof(tNext));
785 tNext.PrivilegeCount = 1;
786 tNext.Privileges[0].Luid = seDebugValue;
787 tNext.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
788 if(!AdjustTokenPrivileges(hToken, FALSE, &tNext, sizeof(tNext),
789 &tPrev, &sPrev) || GetLastError() != 0) {
790 CloseHandle(hToken);
791 hToken = NULL;
792 LOG_ERROR() << "AdjustTokenPrivileges(next) error" << GetLastError();
793 }
794 }
795 else {
796 LOG_ERROR() << "OpenProcessToken error" << GetLastError();
797 }
798 }
799 else {
800 LOG_ERROR() << "LookupPrivilegeValue error" << GetLastError();
801 }
802
803 // Suspend/resume threads
804 for(int i = 0; i < pidlist.size(); i++) {
805 HANDLE hdl = INVALID_HANDLE_VALUE;
806 THREADENTRY32 entry;
807 int n_fails = 0;
808
809 hdl = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
810 if(hdl == INVALID_HANDLE_VALUE) {
811 LOG_ERROR() << "CreateToolhelp32Snapshot error" << GetLastError();
812 continue;
813 }
814 entry.dwSize = sizeof(THREADENTRY32);
815 if(!Thread32First(hdl, &entry)) {
816 LOG_ERROR() << "Process32First error" << GetLastError();
817 CloseHandle(hdl);
818 continue;
819 }
820
821 do {
822 if(entry.th32OwnerProcessID != (DWORD)(pidlist[i]))
823 continue;
824 HANDLE thr = OpenThread(THREAD_SUSPEND_RESUME,
825 FALSE, entry.th32ThreadID);
826 if(!thr) {
827 LOG_ERROR() << "OpenThread" << entry.th32ThreadID
828 << "error" << GetLastError();
829 n_fails++;
830 continue;
831 }
832 if(suspend) {
833 // Execution of the specified thread is suspended and
834 // the thread's suspend count is incremented.
835 if(SuspendThread(thr) == (DWORD)(-1)) {
836 LOG_ERROR() << "SuspendThread" << entry.th32ThreadID
837 << "error" << GetLastError();
838 n_fails++;
839 }
840 }
841 else {
842 // Decrements a thread's suspend count. When the
843 // suspend count is decremented to zero, the
844 // execution of the thread is resumed.
845 if(ResumeThread(thr) == (DWORD)(-1)) {
846 LOG_ERROR() << "ResumeThread" << entry.th32ThreadID
847 << "error" << GetLastError();
848 n_fails++;
849 }
850 }
851 CloseHandle(thr);
852 } while(Thread32Next(hdl, &entry));
853 if (!n_fails)
854 result.append(pidlist[i]);
855 CloseHandle(hdl);
856 }
857
858 // Restore previous debug privilege
859 if (hToken) {
860 if(!AdjustTokenPrivileges(hToken, FALSE,
861 &tPrev, sPrev, NULL, NULL) || GetLastError() != 0) {
862 LOG_ERROR() << "AdjustTokenPrivileges(prev) error" << GetLastError();
863 }
864 CloseHandle(hToken);
865 }
866#endif
867#if defined(Q_OS_MACX)
868 int signal = suspend ? SIGSTOP : SIGCONT;
869 for(int i = 0; i < pidlist.size(); i++) {
870 pid_t pid = pidlist[i];
871 if(kill(pid, signal) != 0) {
872 LOG_ERROR() << "kill signal" << signal
873 << "for PID" << pid << "error:" << errno;
874 }
875 else {
876 result.append(pidlist[i]);
877 }
878 }
879#endif
880#if defined(Q_OS_LINUX)
881 // not implemented for Linux!
882#endif
883 LOG_INFO() << (suspend ? "Suspending" : "Resuming")
884 << "PIDs" << pidlist << "result" << result;
885 return result;
886}
887
888
767/** Eject device from PC. 889/** Eject device from PC.
768 * Request the OS to eject the player. 890 * Request the OS to eject the player.
769 * @param device mountpoint of the device 891 * @param device mountpoint of the device
diff --git a/rbutil/rbutilqt/base/utils.h b/rbutil/rbutilqt/base/utils.h
index 7dfd797cbd..ca9c1d61af 100644
--- a/rbutil/rbutilqt/base/utils.h
+++ b/rbutil/rbutilqt/base/utils.h
@@ -55,6 +55,7 @@ public:
55 static QString resolveDevicename(QString path); 55 static QString resolveDevicename(QString path);
56 static QString resolveMountPoint(QString device); 56 static QString resolveMountPoint(QString device);
57 static QMap<QString, QList<int> > findRunningProcess(QStringList names); 57 static QMap<QString, QList<int> > findRunningProcess(QStringList names);
58 static QList<int> suspendProcess(QList<int> pidlist, bool suspend);
58 static bool ejectDevice(QString device); 59 static bool ejectDevice(QString device);
59}; 60};
60 61