Как создать виртуальный файл?

Я хотел бы симулировать файл, не записывая его на диск. У меня есть файл в конце моего исполняемого файла, и я хотел бы указать его путь к dll. Конечно, поскольку у него нет реального пути, я должен подделать его.

Сначала я попытался использовать именованные каналы под Windows, чтобы сделать это. Это позволит использовать путь как \\.\Pipe\mymemoryfile, но я не могу заставить его работать, и я не уверен, что dll будет поддерживать такой путь.

Во-вторых, я нашел CreateFileMapping и GetMappedFileName. Могут ли они использоваться для имитации файла в фрагменте другого? Я не уверен, что это то, что делает этот API.

То, что я пытаюсь сделать, похоже на boxedapp. Любые идеи о том, как они это делают? Я предполагаю, что это что-то вроде перехвата API (Like Detour), но это будет очень много работы. Есть ли другой способ сделать это?

Почему? Я заинтересован в этом конкретном решении, потому что я хотел бы скрыть данные и в интересах распространения только одного файла, но также и для вызывающих причин для его работы таким образом;) Я согласен, что копирование данных во временный файл будет работать и будет намного проще.

Ответы

Ответ 1

Данные можно хранить в потоке NTFS. Таким образом, вы можете получить реальный путь, указывающий на ваши данные, которые вы можете предоставить вашей DLL в виде

x:\myfile.exe:mystreamname

Это работает точно как обычный файл, однако он работает только в том случае, если файловая система используется NTFS. В настоящее время это стандартно для Windows, но, конечно, это не вариант, если вы хотите поддерживать старые системы или хотите, чтобы это можно было запустить с USB-накопителя или аналогичного. Обратите внимание, что любые потоки, присутствующие в файле, будут потеряны, если файл будет отправлен в виде вложения в почте или просто скопирован из раздела NTFS в раздел FAT32.

Я бы сказал, что наиболее совместимым способом было бы записать ваши данные в фактический файл, но вы, конечно, можете сделать это одним из способов в системах NTFS, а другой - в FAT-системах. Я рекомендую против этого из-за дополнительной сложности. Соответствующим способом было бы распределить ваши файлы отдельно, но, поскольку вы указали, что не хотите этого, вы должны в этом случае записать его во временный файл и предоставить DLL путь к этому файлу. Убедитесь, что вы записываете временный файл в каталог временных файлов пользователей (вы можете найти путь, используя GetTempPath в C/С++).

Другой вариант - написать драйвер фильтра файловой системы, но это дорога, о которой я настоятельно рекомендую. Этот тип поражения также использует один и тот же файл...

Кроме того, если вам нужен только один файл для распространения, как насчет использования zip файла или установщика?

Ответ 2

Трубы предназначены для связи между процессами, запущенными одновременно. Они не хранят данные для последующего доступа и не имеют той же семантики, что и файлы (например, вы не можете искать или перематывать канал).

Если вы придерживаетесь поведения, похожего на файл, лучше всего всегда использовать файл. В Windows вы можете передать FILE_ATTRIBUTE_TEMPORARY в CreateFile как подсказку системе, чтобы избежать сброса данных на диск, если там достаточно памяти.

Если вас беспокоит снижение производительности записи на диск, этого может быть достаточно, чтобы избежать влияния на производительность в большинстве случаев. (Если в системе недостаточно памяти для принудительного вывода файловых данных на диск, возможно, в любом случае она также сильно поменяется местами - у вас уже есть проблема с производительностью.)

Если вы пытаетесь избежать записи на диск по какой-либо другой причине, вы можете объяснить, почему? В общем, довольно сложно остановить попадание данных на диск - например, пользователь всегда может перевести компьютер в спящий режим.

Ответ 3

Используйте BoxedApp и не волнуйтесь.

Ответ 4

Поскольку у вас нет контроля над DLL, вы должны предположить, что DLL ожидает фактический файл. Вероятно, в какой-то момент это предположение вызывает то, что именованные вами трубы терпят неудачу.

Самое простое решение - создать временный файл в каталоге temp, записать данные из EXE в временный файл и затем удалить временный файл.

Есть ли причина, по которой вы встраиваете этот "псевдофайл" в конец EXE, а не просто распространяете его с помощью нашего приложения? Вы, очевидно, уже распространяете эту стороннюю DLL с вашим приложением, чтобы еще один файл не казался вам больным?

Другой вопрос, будут ли эти данные меняться? То есть вы ожидаете записать данные "псевдофайла" в своем EXE? Я не думаю, что это будет хорошо работать. Стандартные пользователи могут не иметь доступа на запись к EXE и, вероятно, будут использовать антивирусные орехи.

И никакие CreateFileMapping и GetMappedFileName определенно не будут работать, поскольку они не дают вам имя файла, которое может быть передано CreateFile. Если бы вы могли каким-то образом заставить эту DLL принять HANDLE, это сработало бы.

И я бы даже не потрудился с перехватом API. Просто передайте DLL путь к acutal файлу.

Ответ 5

Чтение вашего вопроса заставило меня подумать: если вы можете притвориться, что область памяти является файлом и имеет для нее "виртуальный путь", то это позволит загружать DLL непосредственно из памяти, что является тем, что LoadLibrary запрещает дизайн, попросив имя пути. И поэтому люди пишут свой собственный загрузчик PE, когда хотят этого.

Я бы сказал, что вы не можете достичь того, чего хотите с сопоставлением файлов: целью сопоставления файлов является обработка части файла, как если бы это была физическая память, и вы хотите получить обратную.

Использование Detours предполагает, что вам нужно будет реплицировать все, что перехватила DLL-функция, кроме как получить данные из реального файла; следовательно, он не является общим. Или, еще более сложным, допустим, что DLL использует fopen; то вы предоставляете свой собственный fopen, который обнаруживает специальный шаблон в пути, и вы мнимете внутренние среды C... Хм, действительно ли это стоит всей боли?: D

Ответ 6

Пожалуйста, объясните, почему вы не можете извлечь данные из EXE и записать их во временный файл. Многие приложения делают это - это классическое решение этой проблемы.

Если вы действительно должны предоставить "виртуальный файл", самым чистым решением, вероятно, является драйвер фильтра файловой системы. "чистый" не означает "хороший" - фильтр является полностью документированным и поддерживаемым решением, поэтому он более чистый, чем API-соединение, инъекция и т.д. Однако фильтры файловой системы нелегки.

OSR Online - лучшее место для поиска информации о файловой системе Windows. В списке рассылки NTFSD находятся разработчики файловой системы.

Ответ 7

Как насчет использования какого-то RamDisk и записи файла на этот диск? Я сам пробовал какие-то ramdisks, хотя никогда не нашел хорошего, скажите, успешно ли вы.

Ответ 8

Ну, если вам нужно иметь виртуальный файл, выделенный в вашем exe, вам нужно будет создать массив vector, stream или char, достаточно большой для хранения всех виртуальных данных, которые вы хотите записать.

Это единственное решение, о котором я могу думать без ввода-вывода на диск (даже если вы не пишете файл).

Если вам нужно сохранить файл как синтаксис пути, просто напишите класс, который имитирует это поведение, и вместо того, чтобы писать в файл, пишите в буфер памяти. Это так просто, как это получается. Помните KISS.

Приветствия

Ответ 9

Откройте файл с именем "NUL:" для записи. Он доступен для записи, но данные молча отбрасываются. Kinda нравится /dev/null of * nix fame.

Вы не можете его отобразить на карте. Memory-mapping подразумевает доступ для чтения/записи, а NUL - только для записи.

Ответ 10

Я предполагаю, что эта dll не может взять поток? Его почти просто спросить, НО, возможно, вы могли бы просто использовать это.

Ответ 11

Вы пытались использовать префикс \?\при использовании именованных каналов? Многие API поддерживают с помощью \? \, Чтобы передать оставшуюся часть пути напрямую без каких-либо синтаксических разборов/модификаций.

http://msdn.microsoft.com/en-us/library/aa365247(VS.85,lightweight).aspx