Получение номера задачи

Следующие три программы представляют три отдельные функции управления задачами. Все эти функции включены в единый файл JobMgt.c, содержащий все исходные тексты.

Первая из них, программа 6.4, представляет функцию Get JobNumber. Обратите внимание на использование блокирования файлов, а также обработчиков завершения, осуществляющих разблокирование файлов. Эта методика обеспечивает защиту от исключений и непреднамеренного обхода вызова функции разблокирования файлов. Переходы такого рода могут быть случайно вставлены в процессе сопровождения кода, даже если исходная программа корректна. Обратите также внимание на блокирование попыток записи за пределами конца файла в тех случаях, когда файл должен быть расширен за счет добавления новой записи.

Программа 6.4. JobMgt: создание информации о новой задаче

/* Вспомогательная функция управления задачами. */

#include "EvryThng.h"

#include "JobMgt.h" /* Листинг приведен в приложении А. */

void GetJobMgtFileName (LPTSTR);

 

LONG GetJobNumber(PROCESS_INFORMATION *pProcessInfo, LPCTSTR Command)

/* Создать номер задачи для нового процесса и ввести информацию о новом процессе в базу данных задачи. */

{

HANDLE hJobData, hProcess;

JM_JOB JobRecord;

DWORD JobNumber = 0, nXfer, ExitCode, FsLow, FsHigh;

TCHAR JobMgtFileName[MAX_PATH];

OVERLAPPED RegionStart;

if (!GetJobMgtFileName(JobMgtFileName)) return –1;

/* Предоставление результата в виде строки "\tmp\UserName.JobMgt" */

hJobData = CreateFile(JobMgtFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

if (hJobData == INVALID_HANDLE_VALUE) return –1;

/* Блокировать весь файл плюс одну возможную запись для получения исключительного доступа. */

RegionStart.Offset = 0;

RegionStart.OffsetHigh = 0;

RegionStart.hEvent = (HANDLE)0;

FsLow = GetFileSize(hJobData, &FsHigh);

LockFileEx(hJobData, LOCKFILE_EXCLUSIVE_LOCK, 0, FsLow + SJM_JOB, 0, &RegionStart);

__try {

/* Чтение записи для нахождения пустого сегмента. */

while(ReadFile(hJobData, &JobRecord, SJM_JOB, &nXfer, NULL) && (nXfer > 0)) {

if (JobRecord.ProcessId == 0) break;

hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, JobRecord.ProcessId);

if (hProcess == NULL) break;

if (GetExitCodeProcess(hProcess, &ExitCode) && (ExitCode != STILL_ACTIVE)) break;

JobNumber++;

}

/* Либо найден пустой сегмент, либо мы находимся в конце файла и должны создать новый сегмент. */

if (nXfer != 0) /* Не конец файла. Резервировать. */

SetFilePointer(hJobData, –(LONG)SJM_JOB, NULL, FILE_CURRENT);

JobRecord.ProcessId = pProcessInfo->dwProcessId;

_tcsnccpy(JobRecord.CommandLine, Command, MAX_PATH);

WriteFile(hJobData, &JobRecord, SJM_JOB, &nXfer, NULL);

} /* Конец try-блока. */

__finally {

UnlockFileEx(hJobData, 0, FsLow + SJM_JOB, 0, &RegionStart);

CloseHandle(hJobData);

}

return JobNumber + 1;

}