Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
75 / 9 / 1
Регистрация: 07.06.2016
Сообщений: 132

Сторонний процесс не видит мьютекс

25.06.2016, 15:48. Показов 1615. Ответов 15
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день. Мой процесс, используя манифест, запускается "как от Администратора". Затем он активирует встроенную админку и запускает сам себя через CreateProcessWithLogonW уже под Администратором. Проблема в том, что получается цикл, бесконечно запускающий процессы. Я вычитал у Рихтера, как этого можно избежать, используя CreateMutex. Сначала создается мьютекс "testMUT" и если этого объекта нет, программа понимает, что запустилась первый раз, и идет выполнение CreateProcessWithLogonW. Когда же новый процесс запускается, он опять проверяет, есть ли этот мьютекс и если есть, он должен исполнять основной код, минуя открытие нового процесса. Проблема в том, что новый процесс не видит созданного мьютекса и GetLastError всегда возвращает ноль, т.е. мьютекс создается заново. Это происходит, потому что новый процесс создан в другой сессии или по каким-либо другим причинам? Что тут лучше использовать? Пробовал передачу переменных через окружение - принимающий процесс тоже не видит.


// rights.exe:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    HANDLE impl, pHandle, tHand=0, hProc = GetCurrentProcess(),mut;
    int b;
 
    SECURITY_ATTRIBUTES sa;
     sa.nLength = sizeof(sa);
     sa.lpSecurityDescriptor = NULL;
     sa.bInheritHandle = TRUE;
 
    mut = CreateMutex(&sa, FALSE, TEXT("testMUT"));
     cout << "Mut error:" << (int)GetLastError() << endl;
      if ((int)GetLastError == 183)     // если объект уже есть, то исполняем основной код
    {
        CloseHandle(mut);
        cout << "Main code" << endl;
                
        cin >> b;
      }
      else                                     //если объекта нет, инициируем запуск нового процесса
      {
          cout << "Init" << endl;
          WinExec(...активация Админки через CMD);
 
            PROCESS_INFORMATION pi = { 0 };
 
            if (!CreateProcessWithLogonW(L"Администратор", (LPCWSTR)"MyCompName", (LPCWSTR)"1", LOGON_WITH_PROFILE, L"C:\\...\\rights.exe", NULL, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, NULL, &pi)) cout << "Error Admin enter:" << GetLastError() << endl;
      };
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
25.06.2016, 15:48
Ответы с готовыми решениями:

Закрыть сторонний процесс
Добрый день, требуется сделать так, чтоб при определённых обстоятельствах ексель закрывал определённый процесс Set WshShell =...

Завершить сторонний процесс
Возможно ли, что бы программа выключала(убивала) процессы текущих приложений?

Завершить сторонний процесс
Столкнулся со следующей проблемой: Открыл из VB файл &quot;C:\Documents and Settings\Евгений\Рабочий стол\День.exe&quot; Как его закрыть из...

15
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
25.06.2016, 16:01
C++
1
2
mut = CreateMutex(&sa, FALSE, TEXT("testMUT"));
     cout << "Mut error:" << (int)GetLastError() << endl;
Уже миллион раз писали: успех функции нужно проверять по возвращаемому
значению и только в случае ошибки звать GetLastError. В противном случае
значение GetLastError не определено и может содержать "мусор", оставшийся
от предыдущих функций.

Цитата Сообщение от NatiF Посмотреть сообщение
Мой процесс, используя манифест, запускается "как от Администратора". Затем он активирует встроенную админку и запускает сам себя через CreateProcessWithLogonW уже под Администратором.
Чего-чего? Процесс, запустившийся от администратора, перезапускает
сам себя от администратора?


Цитата Сообщение от NatiF Посмотреть сообщение
Проблема в том, что новый процесс не видит созданного мьютекса и GetLastError всегда возвращает ноль, т.е. мьютекс создается заново.
Может быть, родительский процесс завершается слишком рано и мьютекс уничтожается
вместе с ним еще до того, как его откроет дочерний?
0
75 / 9 / 1
Регистрация: 07.06.2016
Сообщений: 132
25.06.2016, 16:19  [ТС]
[QUOTE]успех функции нужно проверять по возвращаемому
значению и только в случае ошибки звать GetLastError. [QUOTE]

Переписал.

C++
1
2
3
4
5
6
7
 mut = CreateMutex(&sa, FALSE, TEXT("testMUT"));
    if (mut==0) cout << "Mut error:" << (int)GetLastError() << endl;
    if (mut != 0) cout << "Mut:" << mut << endl;
      if ((int)GetLastError == 183)
    {
        CloseHandle(mut);
        cout << "Main code" << endl;
Mut всегда нулевой получается. Значит мьютекса уже нет на момент запуска процесса.

Чего-чего? Процесс, запустившийся от администратора, перезапускает
сам себя от администратора?
Да, он входит в учетку Администратора, которая по умолчанию неактивирована. Я так понял, что вход под ней дает больше прав, чем простое поднятие прав через "запуск от Администратора". Может новый процесс не видеть мьютекс из-за того, что запущен в другой сессии?

Может быть, родительский процесс завершается слишком рано и мьютекс уничтожается
вместе с ним еще до того, как его откроет дочерний?
Специально поставил там запрос ввода с клавиатуры, чтобы родительский не завершался. Новый процесс все равно не видит мьютекс, как будто его нет.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
25.06.2016, 17:05
Цитата Сообщение от NatiF Посмотреть сообщение
Переписал.
Полный код бы глянуть...

Цитата Сообщение от NatiF Посмотреть сообщение
Я так понял, что вход под ней дает больше прав, чем простое поднятие прав через "запуск от Администратора".
Не дает.

Цитата Сообщение от NatiF Посмотреть сообщение
Может новый процесс не видеть мьютекс из-за того, что запущен в другой сессии?
С чего бы процессу быть запущенным в другой сессии?
0
75 / 9 / 1
Регистрация: 07.06.2016
Сообщений: 132
25.06.2016, 17:30  [ТС]
Вот.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <stdafx.h>
#pragma comment(linker,"/BASE:0x13140000")
 
using namespace std;
 
int main()
{
    HMODULE hKern;
    DWORD ThreadID, sbuff=3, pID = 4656, inv;
    char DLLpath[] = "C:\\Users\\Ужгород\\Documents\\Visual Studio 2015\\Projects\\MyDLL2\\Debug\\MyDLL2.dll";
    SIZE_T dwritten, PathSize = sizeof(DLLpath);
    HANDLE impl, pHandle, tHand=0, hProc = GetCurrentProcess(),mut;
    LPVOID InjAddr;
    LPTHREAD_START_ROUTINE LLaddr2;
    BOOL fEnable = 1;
    int b;
 
    SECURITY_ATTRIBUTES sa;
     sa.nLength = sizeof(sa);
     sa.lpSecurityDescriptor = NULL;
     sa.bInheritHandle = TRUE;
   
    mut = CreateMutex(&sa, FALSE, TEXT("NoFATE"));
    if (mut==0) cout << "Mut error:" << (int)GetLastError() << endl;
    if (mut != 0) cout << "Mut:" << mut << endl;
      if ((int)GetLastError == 183)
    {
        CloseHandle(mut);
        cout << "Main code" << endl;
    TOKEN_PRIVILEGES tp;
    tp.PrivilegeCount = 1;
 
    if (!OpenProcessToken(hProc, TOKEN_ADJUST_PRIVILEGES, &tHand)) cout << "Error OpenToken:" << GetLastError() << endl;
    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid)) cout << "Error LookUp:" << GetLastError() << endl;
    tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
    if (!AdjustTokenPrivileges(tHand, FALSE, &tp, sizeof(tp), NULL, NULL)) cout << "Error Adjust: " << GetLastError() << endl;
    cout << "Last error Adjust:" << GetLastError() << endl;
    CloseHandle(tHand);
    
      }
      else
      {
          cout << "Init" << endl;
          WinExec("CMD.EXE", SW_HIDE);
          system("net user Администратор /active:yes");
          system("net user Администратор /passwordreq:yes");
          system("net user Администратор 1");
          system("exit");
 
            PROCESS_INFORMATION pi = { 0 };
 
            if (!CreateProcessWithLogonW(L"Администратор", (LPCWSTR)"DESKTOP_MAOJOR", (LPCWSTR)"1", LOGON_WITH_PROFILE, L"C:\\Users\\Ужгород\\Documents\\Visual Studio 2015\\Projects\\rights\\Debug\\rights.exe", NULL, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, NULL, &pi)) cout << "Error Admin enter:" << GetLastError() << endl;
            cout << "OK" << endl;
            cin >> b;
      };
            
 
 
 
  return 0;
}
Не дает.
А вообще разница есть?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
25.06.2016, 17:57
C++
1
if ((int)GetLastError == 183)
Здесь адрес функции GetLastError приводится к int и сравнивается с 183.
Ну бредятина же

Строка 28:
C++
1
CloseHandle(mut);
А зачем мы закрываем мьютекс, который только что создали?
Понятно, что после этого он перестает существовать и дочерний процесс его не видит.

Цитата Сообщение от NatiF Посмотреть сообщение
А вообще разница есть?
А ты открой процесс в Process Explorer, зайди на вкладку "Security" и сравни
набор SID-ов и привилегий - будет одно и то же.
1
75 / 9 / 1
Регистрация: 07.06.2016
Сообщений: 132
25.06.2016, 18:14  [ТС]
Ну бредятина же
Да, я, наверное сам себя перехитрил.
C++
1
if (GetLastError() == 183)
так вроде должно быть достаточно.

А зачем мы закрываем мьютекс, который только что создали?
Он должен закрываться только, если дочерним процессом уже выполняется основной код (GetLastError возвращает 183) и мьютекс больше не нужен. Но туда управление никогда не передается, потому что мьютекса всегда нет.

набор SID-ов и привилегий - будет одно и то же.
Да, тогда смысла в этих действиях немного. Но все равно не понятно, почему он не видит мьютекс.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
26.06.2016, 07:57
C++
1
2
3
4
mut = CreateMutex(&sa, FALSE, TEXT("NoFATE"));
if (mut==0) cout << "Mut error:" << (int)GetLastError() << endl;
if (mut != 0) cout << "Mut:" << mut << endl;
if ((int)GetLastError == 183)
Я уже писал выше, что GetLastError нельзя использовать как признак
успешности или ошибочности выполнения функции. Правильно как-то так:
C++
1
2
3
4
5
6
7
8
if (mut)
{
    // ... Здесь делаем что-то с мьютексом.
}
else
{
    // ... А вот здесь должна быть обработка ошибки.
}
Вот пример кода, где процесс сам себя перезапускает, проверяя при
этом, что он - копия:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <Windows.h>
#include <cstdio>
#include <vector>
#include <conio.h>
 
 
 
int main()
{
    PROCESS_INFORMATION pi = {0};
    HANDLE hMutex = NULL;
 
    hMutex = CreateMutexW(NULL, TRUE, L"MyMutex12345");
    if (hMutex && (ERROR_ALREADY_EXISTS == GetLastError()))
    {
        printf("[I] I am a second copy!\r\n");
        printf("[I] Press any key to exit...\r\n");
        _getch();
    }
    else
    {
        DWORD const BuffSize = 32780;
        std::vector<wchar_t> Buffer(BuffSize);
        DWORD const nChars = GetModuleFileNameW(NULL, &Buffer[0], BuffSize);
        if ( (0 == nChars) || (nChars == BuffSize) )
        {
            printf("[E] GetModuleFileNameW failed, err = 0x%.8lx.\r\n", GetLastError());
            goto Finish;
        }
        STARTUPINFOW si = {0};
        GetStartupInfoW(&si);
        if (!CreateProcessW(&Buffer[0], NULL, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi))
        {
            printf("[E] CreateProcessW failed, err = 0x%.8lx.\r\n", GetLastError());
            goto Finish;
        }
        printf("[I] Child process id = %lu\r\n", pi.dwProcessId);
        WaitForSingleObject(pi.hProcess, INFINITE);
        printf("[I] Child process exited.\r\n");
    }
 
Finish:
 
    if (pi.hProcess) { CloseHandle(pi.hProcess); }
    if (pi.hThread)  { CloseHandle(pi.hThread); }
    if (hMutex)      { CloseHandle(hMutex); }
 
    return 0;
}
Вывод:
[I] Child process id = 2152
[I] I am a second copy!
[I] Press any key to exit...
[I] Child process exited.
Press any key to continue . . .
1
26.06.2016, 08:04

Не по теме:

За использование goto нужно давать по рукам.

0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
26.06.2016, 08:20
greg zakharov, критикуя - предлагай.
А то давать по рукам у нас все очень хорошо умеют.
0
Покинул форум
3700 / 1483 / 355
Регистрация: 07.05.2015
Сообщений: 2,903
26.06.2016, 09:54

Не по теме:

Убежденный, мы с Вами на брудершафт не пили, так что "тыкать" не нужно.

Предлагаю: сделать вывод ошибки более информативным:
C
1
2
3
4
5
6
7
8
9
10
void PrintWin32Error() {
  LPVOID msg;
  FormatMessage(
      FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
      NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
      (LPTSTR) &msg, 0, NULL
  );
  printf("%s\n", msg);
  LocalFree(msg);
}
А if'ы сделать вложенными, то есть:
C
1
2
3
4
5
if ... {
   if ... {
      ...
   } else PrintWin32Error();
} else PrintWin32Error();
goto - крайне вредный оператор (Вы это и сами прекрасно знаете).
0
27.06.2016, 04:23

Не по теме:

Ничего в goto зазорного нет. 1, 2 метки на функцию и столько же переходов это не много. Бывают такие ситуации в которых только это и спасает. Ну, если только не раздувать код ради не использования оного.

0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
27.06.2016, 09:30

Не по теме:


Цитата Сообщение от greg zakharov Посмотреть сообщение
Убежденный, мы с Вами на брудершафт не пили, так что "тыкать" не нужно.
Будь проще.
Общение "на ты" не является проявлением неуважения или чего-то такого.



Цитата Сообщение от greg zakharov Посмотреть сообщение
goto - крайне вредный оператор (Вы это и сами прекрасно знаете).
Согласен. В реальных проектах я ресурсы освобождаю обычно через всевозможные
RAII-обертки, но тянуть их в демонстрационный пример - это извращение.
0
232 / 135 / 19
Регистрация: 10.11.2015
Сообщений: 305
28.06.2016, 07:26

Не по теме:

За вложенные if'ы (более 1-2) нужно давать по рукам



Добавлено через 19 минут

Не по теме:

Убежденный, а можно пример кода из реального проекта? Просто сейчас перехожу с Си на С++ и не могу окончательно выработать подход к освобождению ресурсов при ошибках в WinAPI. Хотелось бы посмотреть как вы это делаете.

0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
28.06.2016, 14:33

Не по теме:


Ну например, с хэндлами можно работать как-то так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//
// Упрощенно. Здесь не хватает закрытых конструктора копирования и
// оператора присваивания, а также, возможно, реализации 'operator HANDLE *'
// и оператора взятия адреса (для HKEY, например).
//
struct auto_handle
{
    explicit auto_handle(HANDLE Handle) : m_Handle(Handle) {}
    ~auto_handle()
    {
        if (GOOD_HANDLE(m_Handle)) {
            CloseHandle(m_Handle);
        }
    }
 
private:
    HANDLE m_Handle;
};
 
// ...
 
HANDLE const hFile = CreateFileW(...);
if (INVALID_HANDLE_VALUE == hFile)
{
    // Обработка ошибки.
}
else
{
    auto_handle FileHandle(hFile);
 
    // Здесь работаем с hFile и можно не беспокоиться о CloseHandle.
    // И не страшны нам ни throw, ни return.
}



Аналогичные врапперы пишутся для всех других ресурсов - ключи реестра,
COM-объекты с подсчетом ссылок, объекты синхронизации, acquire/release,
inc/dec и т.д.
1
232 / 135 / 19
Регистрация: 10.11.2015
Сообщений: 305
28.06.2016, 16:10
Убежденный, то что нужно. Спасибо!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
28.06.2016, 16:10
Помогаю со студенческими работами здесь

Сторонний процесс Excel
Доброе время суток! Возникла такая задача. Левая программа (не важно какая) запускает Excel с уже сгенерированной информацией. Не...

Как остановить сторонний процесс
Здравствуйте. Есть такая проблема. Надо иногда перезапускать консольное приложение, к коду которого я не имею доступа. Как запускать я...

Найти и завершить сторонний процесс
Здравствуйте! Мне известно имя *.exe файла (имя из диспетчера задач), который запущен. Как мне его закрыть из моей программы? Понимаю, что...

Инжект Dll в сторонний процесс
Цель: Есть игра на Unity (простенькая, сам писал). Нужно сделать так, чтобы каждые 10 секунд в окне игры вылезало msgbox. Я знаю что...

Инжектирование dll в сторонний процесс напрямую из ресурсов
Извините за подобное название темы, не знал как назвать более понятно. В общем, что мы имеем: 1. DLL, написанная на C++. 2. Инжектор...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru