Как передать дескриптор программы процессу, который она создала? - PullRequest
0 голосов
/ 07 сентября 2018

У меня есть две программы, Parent и Kid

Я хочу, чтобы Кид получил Ручку Родителя после того, как Родитель создал Кида с помощью CreateProcess. Кажется, что самый простой способ передать этот дескриптор - поместить дескриптор в аргументы командной строки CreateProcess, но я не вижу способа получить дескриптор родителя внутри родителя. GetCurrentProcess возвращает странное ненулевое значение, а DuplicateHandle не работает без ручки малыша (Невозможно, поскольку мне нужно создать Малыша, чтобы получить ручку, но CreateProcess также является единственным шансом отправь ручку родителя ребенку).

Есть ли способ, которым я могу дать Kid это Parent's Обращаться легко?

Ответы [ 3 ]

0 голосов
/ 07 сентября 2018

Кажется, что самый простой способ передать этот дескриптор - поместить дескриптор в аргументы командной строки CreateProcess

Это один способ сделать это, но это не только способ.

Другой простой способ - Parent отправить свой идентификатор процесса с GetCurrentProcessId() на Kid, а затем Kid может использовать OpenProcess(), чтобы получить дескриптор к Parent.

я никак не могу увидеть, как Ручка Родителя находится внутри Родителя.

GetCurrentProcess(), который возвращает псевдо-дескриптор, представляющий вызывающий процесс. Все API, которые принимают дескриптор процесса, примут этот псевдо-дескриптор при использовании в контексте вызывающего процесса.

Но, для целей передачи дескриптора вызывающего процесса другому процессу, Parent должен будет использовать DuplicateHandle() для преобразования псевдо-дескриптора в реальный дескриптор (установите Parent как исходный и целевой процессы). Это задокументированное поведение.

GetCurrentProcess возвращает странное ненулевое значение, а DuplicateHandle не работает без ручки малыша

После того, как Parent продублирует псевдо-дескриптор из GetProcessHandle() в реальный дескриптор, он может передать этот дубликат в Kid в командной строке. Просто убедитесь, что дубликат является наследуемым, а затем используйте bInheritHandles=TRUE в вызове CreateProcess() или передайте STARTUPINFOEX в CreateProcess(), содержащий PROC_THREAD_ATTRIBUTE_HANDLE_LIST (см. Программный контроль того, какие дескрипторы наследуются новыми процессами в Win32 ).

Невозможно, так как мне нужно создать Малыша, чтобы получить Ручку к нему

Если вы не хотите использовать наследуемые дескрипторы, то Parent может альтернативно создать Kid без передачи какого-либо дескриптора в командной строке, а затем дублировать псевдо-дескриптор GetCurrentProcess() с Kid в качестве целевого процесса. затем используйте выбранный вами механизм IPC, чтобы отправить дубликат на Kid после его запуска.

но CreateProcess - это также единственный шанс отправить ручку Родителя Малышу

Нет, это не только способ. МПК это другой способ.

0 голосов
/ 07 сентября 2018

Прежде всего нам нужно получить идентификатор процесса родительского процесса в Kid. это можно сделать по телефону NtQueryInformationProcess с ProcessBasicInformation. а внутри PROCESS_BASIC_INFORMATION (эта структура объявлена ​​в ntddk.h ) существует InheritedFromUniqueProcessId член. строго говоря, это может быть не родительский идентификатор процесса, если вы используете PROC_THREAD_ATTRIBUTE_PARENT_PROCESS при создании Kid, но если вы не используете этот атрибут при вызове CreateProcess - InheritedFromUniqueProcessId - это будет ваш родитель идентификатор процесса.

чем нам нужно понять, что родитель может прерваться и после этого нового процесса начать с тем же идентификатором. поэтому после того, как мы открываем процесс с InheritedFromUniqueProcessId, нам нужно проверить, что это действительно родительский, а не новый процесс, созданный после родительского выхода и повторного использования этого идентификатора. это может быть сделано по времени начала процесса запроса - очевидно, если это не родительский процесс, который он начал уже после родительского выхода (до того, как этот идентификатор не может быть повторно использован), и родительский выход после того, как он запустил kid. поэтому InheritedFromUniqueProcessId может быть не родительским только в том случае, если время создания> = время создания ребенка. мы можем запросить время создания процесса на ProcessTimes с NtQueryInformationProcess. итоговый код может быть:

NTSTATUS OpenParent(PHANDLE phProcess, ULONG DesiredAccess)
{
    HANDLE hProcess;
    KERNEL_USER_TIMES kut, _kut;
    PROCESS_BASIC_INFORMATION pbi;

    NTSTATUS status;

    if (0 <= (status = NtQueryInformationProcess(
        NtCurrentProcess(), ProcessBasicInformation, 
        &pbi, sizeof(pbi), 0)) && 
        0 <= (status = NtQueryInformationProcess(
        NtCurrentProcess(), ProcessTimes, 
        &kut, sizeof(kut), 0)))
    {

        static OBJECT_ATTRIBUTES zoa = { sizeof(zoa) };
        CLIENT_ID cid = { (HANDLE)pbi.InheritedFromUniqueProcessId };
        if (0 <= (status = NtOpenProcess(&hProcess, DesiredAccess|
            PROCESS_QUERY_LIMITED_INFORMATION, &zoa, &cid)))
        {

            if (0 > (status = NtQueryInformationProcess(
                hProcess, ProcessTimes, &_kut, sizeof(_kut), 0)) || 
                kut.CreateTime.QuadPart <= _kut.CreateTime.QuadPart)
            {
                NtClose(hProcess);
                return STATUS_PROCESS_IS_TERMINATING;
            }

            *phProcess = hProcess;
        }
    }

    return status;
}
0 голосов
/ 07 сентября 2018

Попробуйте получить родительский PID из собственного дескриптора процесса:

DWORD pid = GetProcessId(Parent);

Тогда у ребенка, получив пид, верните ручку обратно:

OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);

PID может быть легко передан, так как его число.

Для получения более подробной информации см. Следующее:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...