Здравствуйте все. В двух словах задача такова: есть зашифрованный файл и есть фильтр, который этот файл расшифровывает. Фильтр может произвольно включаться и отключаться пользователем. Ситуация первая: фильтр отключён, произведено чтение зашифрованного файла. Файл попадает в кэш. Пользователь Включает фильтр, открывает файл в каком-либо редакторе (notepad или F3/F4 в ФАР) - данные в редактор попадают из кэша - т.е. в зашифрованном виде. Ситуация вторая: фильтр включён, произведено чтение зашифрованного файла. Файл расшифровывается и попадает в кэш. Пользователь ОТключает фильтр, открывает файл в каком-либо редакторе (notepad или F3/F4 в ФАР) - данные в редактор попадают из кэша - т.е. в РАСшифрованном виде, что не допустимо. Аналогичная ситуация описана у PavPS http://www.wasm.ru/forum/viewtopic.php?id=7455. PavPS пишет, что нашёл решение в функциях IoSynchronousPageWrite / IoPageRead, что меня озадачивает, т.к. в IFS сказано, что это функции системные и вообще пользуйтесь CcCopyWrite, CcPrepareMdlWrite, IoBuildSynchronousFsdRequest, CcCopyRead and CcMdlRead. В Инете путного описания этих функций не нашёл, а у Руссиновича во "Внутреннем устройстве W2k" упоминание о них есть только 1 раз на схеме прохождения запроса NtReadFile/NtWriteFile. Из этой схемы следует, что IoSynchronousPageWrite / IoPageRead вызываются CCManager'ом если запрошенных данных из читаемого/записываемого файла нет в кэшированных страницах. Отсюда вывод - надо их перехватить. Перехват через SST или сплайсинг в драйвере-фильтре - это по-моему извращение. Вызов CcCopyRead не помогает - данные в буфере кэша не обновляются. Исходя из вышесказанного решил очищать кэш. очистку буферов должен выполнять следующий код: Код (Text): // Определение того, что открывается именно тот файл, // который надо расшифровывать..... if(CcIsFileCached(irpSp->FileObject)){ pFCB = (PFSRTL_COMMON_FCB_HEADER)(irpSp->FileObject->FsContext); DbgPrint("pFCB->PagingIoResource"); AAA=(DWORD)(pFCB->PagingIoResource); B2H(buf1,AAA); DbgPrint(buf1); DbgPrint("pFCB->Resource"); AAA=(DWORD)(pFCB->Resource); B2H(buf1,AAA); DbgPrint(buf1); DbgPrint("irpSp->FileObject->SectionObjectPointer"); AAA=(DWORD)(irpSp->FileObject->SectionObjectPointer); B2H(buf1,AAA); DbgPrint(buf1); KeEnterCriticalRegion(); DbgPrint("ExAcquireResourceExclusiveLite(pFCB->PagingIoResource, FALSE);"); ExclusiveOk=ExAcquireResourceExclusiveLite(pFCB->PagingIoResource, FALSE); AAA=(DWORD)(ExclusiveOk); B2H(buf1,AAA); DbgPrint(buf1); DbgPrint("ExAcquireResourceExclusiveLite(pFCB->Resource, FALSE);"); ExclusiveOk=ExAcquireResourceExclusiveLite(pFCB->Resource, FALSE); AAA=(DWORD)(ExclusiveOk); B2H(buf1,AAA); DbgPrint(buf1); DbgPrint("CcPurgeCacheSection(irpSp->FileObject->SectionObjectPointer, NULL, 0, FALSE);"); ExclusiveOk=CcPurgeCacheSection(irpSp->FileObject->SectionObjectPointer, NULL, 0, FALSE); AAA=(DWORD)(ExclusiveOk); B2H(buf1,AAA); DbgPrint(buf1); DbgPrint("ExReleaseResourceLite(pFCB->PagingIoResource);"); ExReleaseResourceLite (pFCB->PagingIoResource); DbgPrint("ExReleaseResourceLite (pFCB->Resource);"); ExReleaseResourceLite(pFCB->Resource); KeLeaveCriticalRegion(); DbgPrint("=========== PurgeCache end ============="); } Этот код будучи вставленным в обработчик IRP_MJ_CREATE не вызывается никогда - т.е. файл, типа, не кэширован, но при попытке его открыть через Explorer данные вытаскиваются именно из кэша, причём во многих случаях файл открывается, а вызова IRP_MJ_READ не происходит. А если этот код вставить в IRP_MJ_READ, то происходит DeadLock в CcPurgeCacheSection. При этом тот поток в контексте которого это выполнялось виснет намертво (обычно это поток Explorer'а), а система начинает вести себя странно - некоторые приложения начинают тормозить, Еxplorer вообще глючит безбожно, короче через 5 минут требуется перезагрузка, даже в том случае, если я выгружаю свой драйвер-фильтр. Вот что отображается в DbgView (который продолжает на удивление стабильно работать): Код (Text): 00000000 0.00000000 ------ Loading begin ------ 00000001 0.00004749 ------ DeviceObject ------ 00000002 0.00005112 81 ea 90 20 00000003 0.00005476 ------ pdoex->AttachedTo ------ 00000004 0.00005839 00 00 00 00 00000005 0.01261641 ------ SystemID ------ 00000006 0.01262535 80 00 03 e0 00000007 0.01262926 ------ HarddiskVolume3 PDO ------ 00000008 0.01263289 81 ea 90 20 00000009 0.01263764 ------ Loading end ------ 00000010 11.71699333 pFCB->PagingIoResource 00000011 11.71700382 81 7b 3f 08 00000012 11.71700859 pFCB->Resource 00000013 11.71701050 81 d8 a2 68 00000014 11.71701527 irpSp->FileObject->SectionObjectPointer 00000015 11.71701908 81 7d ad 54 00000016 11.71702290 ExAcquireResourceExclusiveLite(pFCB->PagingIoResource, FALSE); 00000017 11.71702766 00 00 00 00 00000018 11.71703148 ExAcquireResourceExclusiveLite(pFCB->Resource, FALSE); 00000019 11.71703529 00 00 00 01 00000020 11.71704006 CcPurgeCacheSection(irpSp->FileObject->SectionObjectPointer, NULL, 0, FALSE); Вопрос такой: кто знает как вызывать CcPurgeCacheSection без дэдлока, или каким-либо образом обработать чтение / запись в кэш откликнитесь пожалуйста.... Здесь более логичной мне видится обработка чтения / записи в кэш, но скудность познаний не позволяет её реализовать... Ещё вопрос: как может быть так, что открывается файл, а вызова IRP_MJ_READ нет. Какие функции отрабатывают в этом случае? Хэлп, плиз.
IRP_MJ_READ конечно же вызывается. Но только один раз, для фрагмента не помещенного в кэш. Я отлавливал подобную ситуацию следующим образом: ставил 2 хука: IoCreateFile IoCompleteRequest при открытии файла, ПОСЛЕ выполнения IoCreateFile проверял, мой ли это файлик и делал CcPurgeCacheSection затем в обработчике IoCompleteRequest начинал отлавливать выполненные IRP_MJ_READ и расшифровывал загружаемые фрагменты непосредственно в буфере\MDL