| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Системное программирование и WinAPI > Виртуальная память |
| Автор: freezeman 27.3.2012, 19:36 |
| Привет всем! Подскажите, пожалуйста. Я сделал перехват winapi функции ReadFile и нужно занести файл, который читался этой функцией в ОП. Какой метод будет самым быстрым? Проецирование или виртуальная память? И ещё, после того как я записал файл в память, мне нужно при следующем перехвате ReadFile передать указатель на мой файл в ОП, просто подменив HANDLE у ReadFile... как получить этот HANDLE у файла в ОП? Или все же проецирование использовать?? Я уже запутался, помогите... |
| Автор: Akira 27.3.2012, 21:55 |
| Честно, несколько раз перечитывал и не понял что нужно. Выдохни и опиши что ты хочешь хочешь сделать и что хукаешь (импорт или dll). Насколько я понял подмену чтения файла, если так, то открывай файл который будешь подсовывать, как открывать зависит от размера, если несколько килло то нет смысла мапить и прописывай HANDLE своего файла, указатель трогать незачем, буфер уже выделен (или нужно?), а так, проще и правильнее (хуки зло) хукнуть CreateFile. |
| Автор: freezeman 27.3.2012, 22:09 | ||
У меня перехватывается функция ReadFile, я набираю статистику по перехвату/обращению и наиболее часто используемые файлы хочу поместить в ОП. Затем при следующем перехвате, если я определю, что файл уже в ОП, то в перехваченную функцию ReadFile нужно как-то передать "указатель" на этот же файл, но в ОП. Вопроса в общем 2: как лучше заносить файл в ОП и как получить HANDLE этого файла в ОП (чтобы просто подставить в перехваченную ReadFile и все) или можно как-то другим методом это реализовать? |
| Автор: Akira 27.3.2012, 23:03 |
| Решение в лоб - Мапить файл и из проекции заполнять буфер (указатель) размер сколько читать передается. ReadFile не трогать. |
| Автор: freezeman 27.3.2012, 23:20 | ||||||
Спасибо за совет, проверю его завтра..) Добавлено через 6 минут и 44 секунды
Но думаю, что это не очень хорошее решение, желательно каким-нибудь образом HANDLE передать в ReadFIle... Если я просто заполню буфер тупо по параметрам вызова ReadFile, то вернуть системе этот ReadFile не получится без проблем... |
| Автор: freezeman 28.3.2012, 11:43 |
| Подскажите, please!!)) |
| Автор: Akira 28.3.2012, 13:06 |
| Если я просто заполню буфер тупо по параметрам вызова ReadFile, то вернуть системе этот ReadFile не получится без проблем... Какие еще проблемы? |
| Автор: freezeman 28.3.2012, 13:35 | ||
После перехвата функции ReadFile нужно вернуть её системе, модифицированную или нет, а если я просто заполню буфер, то что указывать в указателе на файл (первый параметр - HANDLE), NULL? |
| Автор: GremlinProg 28.3.2012, 13:40 |
в данном случае, совсем не обязательно, можно просто вернуть TRUE |
| Автор: freezeman 28.3.2012, 13:44 | ||
Ок, а подскажите ещё, пожалуйста, как этот буфер заполнить... |
| Автор: Akira 28.3.2012, 14:12 |
| Например успешно промапил файл и считал то return true если нет,то return false. Примеры работы с проекциями с мотри в MSDN или в гугле - Чтение фала + FileMapping, примеров овер 9000 на всех языках. |
| Автор: GremlinProg 28.3.2012, 14:12 |
это зависит от твоей конкретной реализации свопа, если перехватывать CreateFile и в нем создавать объект мепирования (CreateFileMapping), как предлагает Akira, то дескриптор этого маппинга и нужно вернуть из CreateFile, в таком случае, на ReadFile нужно вызвать MapViewOfFile со смещением и размером, пришедшими из ReadFile, MapViewOfFile вернет указатель на исходный буфер, вот данные из этого буфера и нужно перекинуть в буфер, пришедший в ReadFile и вернуть TRUE, конечно, если MapViewOfFile вернет NULL, ReadFile должен вернуть FALSE, соответственно только на CloseHandle, нужно соответственно закрыть дескриптор исходного файла вот и вся работа по твоей задаче, замечу только, что система такой хук не перварит без дополнительного фильтра, который будет отсеивать процессы, работающие с драйверами устройств, так что не стоит его внедрять в автозагрузку, чревато |
| Автор: freezeman 28.3.2012, 14:46 | ||
Понятно, а если так реализовать: у меня набирается статистика по обращениям к файлам, затем по алгоритму выбираются файлы, которые нужно поместить в ОП, а после очередного перехвата ReadFile, если этот файл, к которому идет обращение функцией ReadFile, занесен в ОП, то считать его из ОП. Это было общее описание задачи. Если я на этапе копирования файла в ОП, сделаю проекцию и назову её по имени файла+какие-нибудь доп. атрибуты, а когда произойдет след перехват я проверю сущ ли такая проекция, если да, то заполню буфер как вы описали, если нет просто верну ReadFile до перехвата... И ещё при проекции скорость чтения из неё так как из ОП или как с жесткого диска?? |
| Автор: Akira 28.3.2012, 15:02 |
| Можно и из ОП раз так хочется (только где столько памяти взять? |
| Автор: freezeman 28.3.2012, 16:58 | ||||
Уффф... для вас, для кого-нибудь ещё на форуме это, конечно, не сложно... Я программист .NET и с WINAPI не работал, пишу сейчас на С++ и параллельно изучаю особенности языка...
У меня в этом то и дело, что файлов маленьких будет много, а общий размер я буду выделять и, если сумма объёмов этих файлов превышает ограничение, то они просто не учитываются, возвращаются как есть... Перехват у меня есть функции ReadFile, через проекцию сведения о перехваченном файле передаются в мою службу, где там обрабатываются, принимается решение заносить их в ОП или нет, когда занес группу файлов в ОП, я планировал сделать проекцию (для межпроцессного взаимодействия), где хранил сведения о уже занесенных файла в ОП...Когда произошел перехват вновь, открывается эта проекция и проверяет на наличие этого файла в ОП... ну дальше понятно, что я должен считать его с ОП... но как это сделать, как это реализовать....не знаю(( И не совсем подходит описанная схема...Моожет через кучу, заносить туда, а потом, как писал Akira, считать в буффер и все?? |
| Автор: Akira 28.3.2012, 18:06 |
| Как читать особой разницы нет, реализация примерно одинакова. Почитай про работу с указателями. Хранить, если много параметров которые надо хранить то можно завести структуру и сделать масив. Например, как то так struct Save { char name[MAX_PATH]; void* ptr }; А в память грузи так, как тебе нравится. Функция что бы получить из HANDLE имя - NtQueryObject(hFileHandle,ObjectNameInformation,(PVOID)lpBuffer, size, &ret); |
| Автор: freezeman 28.3.2012, 20:15 | ||||
Получил имя из HANDLE чуть-чуть по другому, и передаю тоже в структуре массив TCHAR, но при передаче, почему-то путь ограничивается 18 символами, хотя в момент преобразования HANDEL в путь к файлу он бывает корректен.
То есть сначала загрузить, а потом просто прочитать из памяти, как вы описывали ранее и вернуть в случае успеха TRUE... буду пробовать, спасибо большое! |
| Автор: Akira 28.3.2012, 20:23 |
| но при передаче, почему-то путь ограничивается 18 символами Мб проблема в типах (WCHAR) покажи код получения имени. Add: freezeman Если не кто не ответит то завтра напишу ибо я уже иду на вторые сутки без сна так что проблема отлечить int от char. |
| Автор: freezeman 28.3.2012, 20:32 | ||||
В тестовом примере ставлю точку останова, проверяю и все нормально, но когда передаю через проекцию передает только первые 18 символов... Код получения путь к файлу по его HANDLE:
Скорее всего дело в типе, может получать не в массиве TCHAR, а просто в массиве char? |
| Автор: freezeman 30.3.2012, 08:27 |
| А как узнать какие именно данные будут считываться, какая часть файла? Можно ли получить из параметров readfile? Я подумал, что при вызове системой функции ReadFile считывается определенный блок из файла, но в параметрах кроме количества толком ничего нет, как узнать что именно читается? |
| Автор: xvr 30.3.2012, 13:24 |
Если файл был открыт в OVERLAPPED режиме, то в структуре overlapped (последний параметр) передается смещение, откуда читать. Иначе чтение производится с текущей позиции. Ее можно отслеживать самому, или запросить у системы (через SetFilePointer(handle,0,NULL,FILE_CURRENT) ) |
| Автор: Akira 30.3.2012, 14:28 |
| freezeman А зачем ты путь конвертируешь? В этот нет нужды, да и в хукнутой функции это точно не нужно делать. |
| Автор: freezeman 30.3.2012, 15:35 | ||
А как я узнаю, какой именно файл читает ReadFile и есть ли он у меня в памяти... ведь HANDLE не будет при следующем обращении совпадать... |
| Автор: Akira 30.3.2012, 15:41 |
| Я об этом - QueryDosDevice достаточно этого - GetMappedFileName Конвертирование нужно что бы из этого \Device\HarddiskVolume1\Temp\ сделать C:\Temp в твоем случае это излишне. |
| Автор: freezeman 30.3.2012, 15:51 | ||||
Проверю... Подскажите как мне заполнить буфер, который указан в перехваченной функции ReadFile... Вот алгоритм: 1 создать однонаправленный динамический список, загрузить туда файлы, отфильтрованные по алгоритму 2 проверить в перехваченной ReadFile на наличие этого файла в моем динамическом списке 3 если файл в памяти, то нужно заполнить буфер со смещением overlapped 4 иначе просто вернуть ReadFile системе. Подскажите, пожалуйста, как реализовать 3 пункт, как заполнить буфер со смещением? Добавлено через 53 секунды
Спасибо, отлично... |
| Автор: Akira 30.3.2012, 16:20 |
| Я же говорил, читай про работу с указателями. Примерно так char* str = "primer"; void* pout = str; void* pin; memcpy(pin, pout, 4); printf("%s", pin); |
| Автор: freezeman 30.3.2012, 16:45 | ||
Спасибо большое! почитаю, разберусь!) |