Работаю над подменой буферов и раньше была проблема при чтении — вылетал БСОД.
PreRead возвращал FLT_PREOP_SUCCESS_WITH_CALLBACK. В таком случае PostRead процедура выполнялась на DPC уровне. Но в PostRead я использую — FltSendMessage, которая выполняется не выше APC. Нужна она для того что бы кусок зашифрованного файла переслать в юзер мод, где он преобразуется к оригиналу и потом этот кусок запихнуть в новый подменяемый буфер.
Я это исправил с помощью возвращаемого значения FLT_PREOP_SYNCHRONIZE в PreRead. Теперь PostRead выполняется на APC уровне.
Что написано на msdn про FLT_PREOP_SYNCHRONIZE:
The minifilter driver is returning the I/O operation to the filter manager for further processing, but it is not completing the operation. In this case, the filter manager calls the minifilter's post-operation callback in the context of the current thread at IRQL <= APC_LEVEL.
БСОДа больше нету и с текстовыми файлам все норм, почти все норм. Но с картинками почему-то беда при чтении.
Сохраняються в папке, т.е. шифруются она правильно. Это проверял. Записывается хедер с нужной информацией и само содержимое файла.
Но открыть у меня картинку не получается. Отображает ошибку в окне просмотра, что файл поврежден.
Если рассмотреть на примере картинки с названием 14kb.jpg, у которой AllocationSize = 16384, а EndOfFile = 13023(значение изменял принудительно) вот что вижу в DbgView:
00000103 SB!SwapPreRead: Name = C:\Private\14kb.jpg, readLen = 4096.
00000104 SB!SwapPreRead: Pid = 2444 newB = 84354000 newMdl = 86210D60 oldB = 06C285FC oldMdl = 00000000 len = 4096 byteOffset = 4096(0).
00000105 SB!SwapPreRead: Name = C:\Private\14kb.jpg, readLen = 4096.
00000106 SB!SwapPreRead: Pid = 2444 newB = 842E6000 newMdl = 86210E30 oldB = 00000000 oldMdl = 8428A388 len = 4096 byteOffset = 4096(0).
00000107 SB!SwapPostRead: Pid = 2444 i = 0 CopySize = 4080 ReplySize = 0 OffsetOrig = 0 OffsetEnc = 0.
00000108 SB!SwapPostRead: Pid = 2444 newB = 842E6000 status = 0x0 info = 13023 byteOffset = 0(0) Freeing.
00000109 SB!SwapPreRead: Name = C:\Private\14kb.jpg, readLen = 12288.
00000110 SB!SwapPreRead: Pid = 4 newB = 862A9000 newMdl = 86210E30 oldB = 00000000 oldMdl = 8428A388 len = 12288 byteOffset = 12288(4096).
00000111 SB!SwapPostReadWhenSafe: Pid = 2444 newB = 84354000 status = 0x0 info = 13023 byteOffset = 0(0) Freeing.
00000112 SB!SwapPostRead: Pid = 4 i = 0 CopySize = 8928 ReplySize = 8927 OffsetOrig = 0 OffsetEnc = 0.
00000113 SB!SwapPostRead: Pid = 4 newB = 862A9000 status = 0x0 info = 13023 byteOffset = 4096(0) Freeing.
Почему-то всегда сначала проскакивает PreRead с 4096, потом 12288 байтами. В сумме будет 16384, что соответствует AllocationSize.
Пара наблюдений:
1. При клике на картинку, проскакивают Read запросы, в то время как на текстовые файлы нет.
2. В памяти подменяемый буфер соответствует оригиналу картинки. Так как пробывал, в то время когда драйвер мониторит папку, копировать картинку в другую папку. Копируется норм, потому что потом этот скопировавшийся файл я могу открыть и увижу оригинальное изображение.
И еще одно, как правильно делать смещение, когда у тебя в файле есть хеадер с дополнитеьной информацией.
В PostCreate считую хеадер с помощью FltReadFile с флагом FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET. Далее в PostQueryInformation изменял
fileAllInformation->PositionInformation.CurrentByteOffset.QuadPart = FILE_HEADER_LENGTH;
и
filePositionInformation->CurrentByteOffset.QuadPart = FILE_HEADER_LENGTH;
В PreRead же делала так:
iopb->Parameters.Read.ByteOffset.QuadPart = FILE_HEADER_LENGTH;
получалось вечное зацикливание и сейчас просто добавляю FILE_HEADER_LENGTH:
RtlCopyMemory(bufToUserMode, encryptBuf + FILE_HEADER_LENGTH, size);