Как создать процесс из приложения, использующего Native API
При разработке приложений Native API может возникнуть необходимость запустить процесс. В native режиме невозможен запуск Win32-приложений, так как процессы подсистемы Win32 при создании требуют уведомления CSRSS о новом процессе (а он ещё неактивен). Зато в native режиме возможен запуск других native приложений с помощью функции RtlCreateUserProcess.
В параметрах функции нужно в соответствующих структурах передать
полный путь к исполняемому файлу, причём в NT-формате (то есть с префиксом \??\
),
имя файла процесса для отображения в списке процессов и командную строку с параметрами (это строка,
которой был запущен процесс, содержащая его ключи запуска).
Например, запускаем процесс autochk.exe с параметрами, находясь в каталоге C:\windows\system32. Тогда в RtlCreateUserProcess нужно будет передать следующие строки:
- Имя файла для отображения в списке процессов: autochk.exe
- Командная строка: autochk.exe /p \??\C:
- Полный путь: \??\C:\windows\system32\autochk.exe
На снимке экрана вы видите программу проверки диска autochk.exe, запущенную из Native shell. При попытке запустить не native, а Win32 приложение из Native shell произойдёт ошибка и вы увидите синий экран смерти с текстом STOP c0000145. Это происходит потому, что функция CreateNativeProcess в Native shell не проверяет подсистему запускаемого исполняемого файла. Запускать следует либо собственные native приложения, либо native приложения, идущие в комплекте Windows, такие как autocheck.exe, autoconv.exe, autofmt.exe, autolfn.exe. В Native режиме уже запущен smss.exe, можно попытаться запустить его вторую копию, но результат подобного действия непредсказуем!
Существует и более сложный в реализации способ запуска процессов с использованием Native API, описанный на сайте http://ntprog.by.ru/_process.htm. Там есть описания проверки подсистемы и нотификации CSRSS для запуска приложений Win32. Это может пригодиться в случае запуска процесса не в Native режиме, а в обычном режиме работы Windows. Консольная программа nrun.exe от Andrey Shedel реализует запуск native приложений из командной строки обычного режима Windows.
Следующий кусок кода реализует запуск процесса в моей программе Native shell версии 0.10. Для приведения пути в NT-формат используется функция RtlDosPathNameToNtPathName_U. Инициализация параметров процесса происходит с помощью функции RtlCreateProcessParameters.
Текст функции
NTSTATUS CreateNativeProcess(IN PCWSTR file_name, IN PCWSTR cmd_line) { PCWSTR file_part; UNICODE_STRING fname, nt_file, EnvString, NullString, UnicodeSystemDriveString; NTSTATUS status; // Имя исполняемого файла UNICODE_STRING imgname; // Путь к исполняемому файлу в NT-формате UNICODE_STRING imgpath; // Путь, где располагаются библиотеки в формате DOS UNICODE_STRING dllpath; // Командная строка UNICODE_STRING cmdline; // Параметры процесса PRTL_USER_PROCESS_PARAMETERS processparameters; // Информация о процессе RTL_USER_PROCESS_INFORMATION processinformation = {0}; WCHAR Env[2] = {0, 0}; // Окружение процесса PKUSER_SHARED_DATA SharedData = (PKUSER_SHARED_DATA)USER_SHARED_DATA; // Данные ядра // Преобразование пути в NT-формат (прибавление префикса \??\) RtlDosPathNameToNtPathName_U( file_name, &nt;_file, &file;_part, NULL); RtlInitUnicodeString(&imgpath;, nt_file.Buffer); RtlInitUnicodeString(&imgname;, file_part); // %SystemRoot% RtlInitUnicodeString(&dllpath;, SharedData->NtSystemRoot); // Параметры командной строки RtlInitUnicodeString(&cmdline;, cmd_line); // Инициализация параметров процесса status = RtlCreateProcessParameters( &processparameters;, &imgname;, &dllpath;, &dllpath;, &cmdline;, Env, 0, 0, 0, 0); if (!NT_SUCCESS(status)) { RtlCliDisplayString("RtlCreateProcessParameters failed\n"); return FALSE; } DbgPrint("Launching Process: %s, DllPath=%s, CmdLine=%s", &imgname;, &dllpath;, &cmdline;); // Здесь происходит непосредственно запуск процесса status = RtlCreateUserProcess(&imgpath;, OBJ_CASE_INSENSITIVE, processparameters, NULL, NULL, NULL, FALSE, NULL, NULL, &processinformation; ); if (!NT_SUCCESS(status)) { RtlCliDisplayString("RtlCreateUserProcess failed\n"); return FALSE; } status = NtResumeThread(processinformation.ThreadHandle, NULL); if (!NT_SUCCESS(status)) { RtlCliDisplayString("NtResumeThread failed\n"); return FALSE; } return STATUS_SUCCESS; }
Автор: амдф
Дата: 25 января 2011
Избранное
Остальное
Лента atom