Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная работа по процессам full.doc
Скачиваний:
7
Добавлен:
19.12.2018
Размер:
375.3 Кб
Скачать

9.1. Параметры pszApplicationName и pszCommandLine

Эти параметры определяют имя исполняемого файла, которым будет пользоваться новый процесс, и командную строку, передаваемую этому процессу. Начнем cpszComandLine.

Замечание: Следует отметить, что тип параметра pszCommandLine: PTSTR. Он означает, что CreateProcess ожидает передачи адреса строки, которая не является константой. Дело в том, что CreateProcess в процессе своего выполнения модифицирует переданную командную строку, но перед возвратом управления восстанавливает ее.

Например, следующий код приведет к такой ошибке, потому что Visual С++ 6.0 поместит строку «NOTEPAD» в память только для чтения:

STARTUPINFO si = { sizeof(si) }; PROCESS_INFORMATION pi; CreateProcess(NULL, TEXT("NOTEPAD"), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);

Когда CreateProcess попытается модифицировать строку, произойдет ошибка доступа. (В прежних версиях Visual C++ эта строка была бы размещена в памяти для чтения и записи, и вызовы CreateProcess не приводили к ошибкам доступа.)

Лучший способ решения этой проблемы — перед вызовом CreateProcess копировать константную строку во временный буфер:

STARTUPINFO si = { sizeof(si) }; PROCESS_INFORMATION pi; TCHAR szCommandLine[] = TEXT("NOTEPAD"); CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, 0, NULI, NULL, &si, &pi);

Кстати, при вызове ANSI-версии CreateProcess в Windows 2000 таких проблем нет, поскольку в этой версии функции командная строка копируется во временный буфер.

Параметр pszCommandLine позволяет указать полную командную строку, используемую функцией CreateProcess при создании нового процесса, только если параметр pszApplicationName равен NULL (что и бывает в 99% случаев). Вместо NULL можно передать адрес строки с именем исполняемого файла, который надо запустить. Однако тогда придется указать не только его имя, но и расширение, поскольку в этом случае имя не дополняется расширением EXE автоматически. CreateProcess предполагает, что файл находится в текущем каталоге (если полный путь не задан). Если в текущем каталоге файла нет, функция не станет искать его в других каталогах, и на этом все закончится.

Но даже при указанном в pszApplicationName имени файла CreateProcess все равно передает новому процессу содержимое параметра pszCommandLine как командную строку. Допустим, вызвали CreateProcess так:

// размещаем строку пути в области памяти для чтения и записи TCHAR szPath[] = TEXT("WORDPAD README.TXT");

// порождаем новый процесс CreateProcess(TEXT("C:\\WINNT\\SYSTEM32\\NOTEPAD EXE"), szPath,... );

Система запускает Notepad, а в его командной строке мы видим "WORDPAD README.TXT". Но так уж она работает, эта функция CreateProcess. Упомянутая возможность, которую обеспечивает параметр pszApplicationName, на самом деле введена в CreateProcess для поддержки подсистемы POSIX в Windows 2000.

9.2. Параметры psaProcess, psaThread и blnheritHandles

Чтобы создать новый процесс, система должна сначала создать объекты ядра «процесс» и «поток» (для первичного потока процесса). Поскольку это объекты ядра, родительский процесс получает возможность связать с ними атрибуты защиты. Параметры psaProcess и psaThread позволяют определить нужные атрибуты защиты для объектов «процесс» и «поток» соответственно. В эти параметры можно занести NULL, и система закрепит за данными объектами дескрипторы защиты по умолчанию. В качестве альтернативы можно объявить и инициализировать две структуры SECURITY_ATTRIBUTES; тем самым создаются и присваиваются свои атрибуты защиты объектам «процесс» и «поток».

Структуры SECURITY_ATTRIBUTES для параметров psaProcess psaThread используются и для того, чтобы какой-либо из этих двух объектов получил статус наследуемого любым дочерним процессом.

Короткая программа см.ниже демонстрирует, как наследуются описатели объектов ядра. Будем считать, что процесс А порождает процесс В и заносит в параметр psaProcess адрес структуры SECURITY_ATTRIBUTES, в которой элемент blnheritHandle установлен как TRUE. Одновременно параметр psaThread указывает на другую структуру SECURITY_ATTRIBUTES, в которой значение элемента bInheritHandle — FALSE.

Inherit.c

/************************************************************

Module name: Inherit.c

Notices: Copyright (c) 2000 Jeffrey Richter

************************************************************/

#include <Windows.h>

int WINAPI WinMain (HINSTANCE hinstExe, HINSTANCE,

   PSTR pszCmdLine, int nCmdShow) {

   // Подготовка STARTUPINFO стркутуры для порождения процессов.

   STARTUPINFO si = { sizeof(si) };

   SECURITY_ATTRIBUTES saProcess, saThread;

   PROCESS_INFORMATION piProcessB, piProcessC;

   TCHAR szPath[MAX_PATH];

   // Подготовка к порождению процесса B из процесса A.

   // Дескриптор идентифицирует новый процесс 

   // объект должен быть наследуемым.

   saProcess.nLength = sizeof(saProcess);

   saProcess.lpSecurityDescriptor = NULL;

   saProcess.bInheritHandle = TRUE;

   // Дескриптор идентифицирует новый поток 

   // объект должен быть не наследуемым.

   saThread.nLength = sizeof(saThread);

   saThread.lpSecurityDescriptor = NULL;

   saThread.bInheritHandle = FALSE;

   // Порождение процесса B.

   lstrcpy(szPath, TEXT("ProcessB"));

   CreateProcess(NULL, szPath, &saProcess, &saThread,

      FALSE, 0, NULL, NULL, &si, &piProcessB);

   // Стркутура piProcessB содержит два дескриптора

   // относящихся к процессу A:

   // hProcess, который идентифицирует наследуемый объект процесса B

   // и hThread, который идентифицирует объект ядра – главный поток

   // процесса B и не является наследуемым.

   // Подготовка к порождению процесса C из процесса A.

   // Так NULL передается для параметров psaProcess и psaThread

   // , дескрипторы к объектам процесс и 

   // главный поток процесса С – по умолчанию ненаследуемые

   // Если процесс A породит другой новый процесс, этот новый процесс 

// не наследует дескрипторы к объектам процесса и потка процесса С. 

   

   // Так  TRUE передается в качестве параметра bInheritHandles,

   // Процесс C будет наследовать десриптор идентифицирующий процесс 

   // B но не будет наследовать дескриптор его главного потока. 

   lstrcpy(szPath, TEXT("ProcessC"));

   CreateProcess(NULL, szPath, NULL, NULL,

      TRUE, 0, NULL, NULL, &si, &piProcessC);

   return(0);

}

Создавая процесс В, система формирует объекты ядра «процесс» и «поток», а за тем — в структуре, на которую указывает параметр ppiProcInfo, — возвращает их описатели процессу А, и с этого момента тот может манипулировать только что созданными объектами «процесс» и «поток».

Теперь предположим, что процесс А собирается вторично вызвать функцию CreateProcess, чтобы породить процесс С. Сначала ему нужно определить, стоит ли предоставлять процессу С доступ к своим объектам ядра. Для этого используется параметр blnberitHandles, если он приравнен TRUE, система передаст процессу С все наследуемые описатели в этом случае наследуется и описатель объекта ядра "процесс" процесса В. А вот описатель объекта "первичный поток" процесса В не наследуется ни при каком значении bInberitHandles. Кроме того, если процесс А вызывает CreateProcess, передавая через параметр blnberitHandles значение FALSE, процесс С не наследует никаких описателей, используемых в данный момент процессом А.