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

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

Следующие три программы представляют три отдельные функции управления задачами. Все эти функции включены в единый файл 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;

 /* Предоставление результата в виде строки " mpUserName.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;

}