Создание процесса с использованием Native API

Как создать процесс из приложения, использующего 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
Native shell версии 0.10 с запущенной программой проверки диска autochk.exe
Native shell версии 0.10 с запущенной
программой проверки диска 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


При копировании материалов хорошим тоном будет указание авторства и ссылка на сайт.