Параметры. hFile — дескриптор открытого файла
hFile — дескриптор открытого файла. Дескриптор должен быть создан либо с правами доступа GENERIC_READ, либо с правами доступа GENERIC_READ и GENERIC_WRITE.
dwFlags — определяет вид блокировки файла, а также режим ожидания доступности затребованной блокировки. Этот параметр определяется комбинацией следующих значений:
LOCKFILE_EXCLUSIVE_LOCK — запрос монопольной блокировки в режиме чтения/записи. Если это значение не задано, запрашивается разделяемая блокировка (только чтение).
LOCKFILE_FAIL_IMMEDIATELY — задает режим немедленного возврата функции с возвращаемым значением равным FALSE, если приобрести блокировку не удается. Если это значение не задано, функция переходит в режим ожидания.
dwReserved — значение этого параметра должно устанавливаться равным 0. Следующие два параметра определяют соответственно младшие и старшие 32-битовые значения размера блокируемого участка файла (в байтах).
lpOverlapped — указатель на структуру данных OVERLAPPED, содержащую информацию о начале блокируемого участка. В этой структуре необходимо устанавливать значения трех элементов (остальные элементы игнорируются), первые два из которых определяют смещение начала блокируемого участка от начала файла.
• DWORD Offset (используется именно такое имя параметра, а не OffsetLow).
• DWORD OffsetHigh.
• HANDLE hEvent должен задаваться равным 0.
Чтобы разблокировать файл, следует вызвать функцию UnlockFileEx, все параметры которой, за исключением dwFlags, совпадают с параметрами предыдущей функции:
BOOL UnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped)
Используя блокирование файлов, вы должны принимать во внимание следующие обстоятельства:
• Границы области разблокирования должны в точности совпадать с границами ранее заблокированной области. Не допускается, например, объединение двух ранее заблокированных областей или разблокирование части заблокированной области. Любая попытка разблокирования области, не совпадающей в точности с одной из существующих заблокированных областей, будет неудачной. В этом случае функция вернет значение FALSE, а в выведенном системой сообщении об ошибке будет указано, что данная область блокирования не существует.
• Вновь создаваемая и существующие области блокирования в файле не могут перекрываться, если это приводит к возникновению конфликтной ситуации.
• Возможно блокирование участка, границы которого выходят за пределы файла. Такая операция может оказаться полезной в случае расширения файла процессом или потоком.
• Блокировки не наследуются вновь создаваемыми процессами.
Логику процедуры блокирования, когда вся область или только некоторая ее часть уже содержат заблокированные участки, иллюстрирует табл. 3.1.
Таблица 3.1. Логика предоставления блокировки
| Тип запрашиваемой блокировки | ||
| Существующая блокировка | Разделяемая блокировка | Монопольная блокировка |
| Отсутствует | Предоставляется | Предоставляется |
| Разделяемая блокировка (одна или несколько) | Предоставляется | Отказ |
| Монопольная блокировка | Отказ | Отказ |
Логику предоставления возможности выполнения операций чтения/записи во всей или части области файла, содержащей участки с одной или несколькими блокировками, владельцами которых являются другие процессы, иллюстрирует табл. 3.2.
Таблица 3.2. Блокировки и выполнение операций ввода/вывода
| Операция ввода/вывода | ||
| Существующая блокировка | Чтение | Запись |
| Отсутствует | Успешно выполняется | Успешно выполняется |
| Разделяемая блокировка (одна или несколько) | Выполняется. Вызывающий процесс не обязан быть владельцем блокировки данной области файла. | Не выполняется |
| Монопольная блокировка | Выполняется, если вызывающий процесс является владельцем блокировки, в противном случае — неудачное завершение. | Выполняется, если вызывающий процесс является владельцем блокировки, в противном случае — неудачное завершение. |
Обычно операции чтения и записи выполняются путем вызова функций Read-File и WriteFile или их расширенных версий ReadFileEx и WriteFileEx. Для диагностики ошибок, возникающих в процессе выполнения операций ввода/вывода, следует вызывать функцию GetLastError.
Одна из разновидностей операций ввода/вывода с участием файлов предполагает использование отображения файлов, которое обсуждается в главе 5. Обнаружение конфликтов блокировки на этапе обращения к памяти не производится; такая проверка осуществляется во время вызова функции MapViewOfFile. Указанная функция делает часть файла доступной для процесса, вследствие чего проверка наличия блокировок на этом этапе является необходимой.
Разновидностью функции LockFileEx с ограниченной сферой применимости является функция LockFile, вызов которой, скорее, лишь уведомляет о намерении осуществить блокировку. Эту функцию можно использовать в системах Windows 9x, которые не поддерживают функцию LockFileEx. Функция LockFile предоставляет блокирующему процессу только монопольный доступ, а возврат из функции происходит сразу же. Таким образом, функция LockFile не блокируется. Проверить, предоставлена блокировка или нет, можно путем тестирования возвращаемого функцией значения.