如何创建虚拟文件?

时间:2010-01-17 12:06:58

标签: c++ windows winapi named-pipes

我想在不将其写入磁盘的情况下模拟文件。我的可执行文件末尾有一个文件,我想给它一个dll的路径。当然,因为它没有真正的路径,我必须伪造它。

我首先尝试在Windows下使用命名管道来执行此操作。这将允许像\\。\ pipe \ mymemoryfile这样的路径,但我不能使它工作,我不确定dll是否会支持这样的路径。

其次,我找到了CreateFileMapping和GetMappedFileName。它们可以用来模拟另一个片段中的文件吗?我不确定这是API的作用。

我正在尝试做的似乎与boxedapp类似。有关他们如何做的任何想法?我想这就像API拦截(像Detour),但这将是很多工作。还有其他办法吗?

为什么?我对这个特定的解决方案很感兴趣,因为我想隐藏数据并且只是为了分发一个文件而且为了使它以这种方式工作的极端原因;) 我同意将数据复制到临时文件会起作用并且是一个更容易的解决方案。

12 个答案:

答案 0 :(得分:6)

使用BoxedApp,不用担心。

答案 1 :(得分:5)

管道用于并发运行的进程之间的通信。它们不存储数据以供以后访问,并且它们与文件没有相同的语义(例如,您无法搜索或回滚管道)。

如果您处于类似文件的行为,最好的办法就是使用文件。在Windows下,您可以将FILE_ATTRIBUTE_TEMPORARY传递给CreateFile作为系统提示,以避免在有足够内存的情况下将数据刷新到磁盘。

如果您担心写入磁盘的性能损失,上述内容应足以避免在大多数情况下对性能产生影响。 (如果系统内存足够低以强制将文件数据输出到磁盘,那么它可能也会大量交换 - 你已经遇到了性能问题。)

如果你因为其他原因试图避免写入磁盘,你能解释一下原因吗?一般来说,很难阻止数据进入磁盘 - 例如,用户可以随时休眠机器。

答案 2 :(得分:5)

您可以将数据存储在NTFS流中。这样,您就可以获得指向您的数据的真实路径,您可以以

的形式提供给您的dll
x:\myfile.exe:mystreamname

这与普通文件非常相似,但只有在使用的文件系统是NTFS时才有效。这在Windows现在是标准配置,但如果您想支持旧系统或希望能够从usb-stick或类似设备运行它,当然不是一个选项。请注意,如果文件作为邮件中的附件发送,或者只是从NTFS分区复制到FAT32分区,则文件中存在的任何流都将丢失。

我认为最兼容的方法是将数据写入实际文件,但是你当然可以在NTFS系统上以一种方式在FAT系统上进行。我建议反对它,因为增加了复杂性。当然,适当的方法是单独分发文件,但由于您已经表明不需要这样,所以在这种情况下,您应该将其写入临时文件并为dll指定该文件的路径。确保将临时文件写入用户的临时目录(可以在C / C ++中使用GetTempPath找到路径。)

您的另一个选择是编写文件系统过滤器驱动程序,但这是我强烈建议的道路。这种方式也失败了使用单个文件的目的......

另外,如果您只想要一个文件进行分发,那么如何使用zip文件或安装程序呢?

答案 3 :(得分:3)

由于您无法控制DLL,因此您必须假定DLL需要实际文件。它可能在某种程度上使得这个假设成为命名管道失败的原因。

最简单的解决方案是在临时目录中创建一个临时文件,将EXE中的数据写入临时文件,然后删除临时文件。

您是否有理由在EXE结尾处嵌入此“伪文件”而不是仅仅将其与我们的应用程序一起分发?你显然已经在你的应用程序中分发了这个第三方DLL,所以还有一个文件似乎不会伤害你吗?

另一个问题,这些数据会改变吗?那是你期望在你的EXE中写回这个“伪文件”的数据?我认为这不会很好。标准用户可能没有对EXE的写入权限,这可能会驱动反病毒。

并且没有CreateFileMapping和GetMappedFileName肯定不会起作用,因为它们没有为您提供可以传递给CreateFile的文件名。如果你能以某种方式让这个DLL接受一个HANDLE那么那就行了。

我甚至不打扰API拦截。只需将DLL传递给实际文件即可。

答案 4 :(得分:1)

阅读你的问题让我想到:如果你可以假装一个内存区域是一个文件并且有一种“虚拟路径”,那么这将允许直接从内存中加载DLL,LoadLibrary通过询问路径名称来禁止设计。这就是人们在想要实现这一目标时编写自己的PE加载器的原因。

我会说你无法用文件映射实现你想要的东西:文件映射的目的是将文件的一部分视为物理内存,而你想要的是倒数。

使用Detours意味着除了从真实文件中获取数据之外,您必须复制截获的DLL函数所做的一切;因此它不是通用的。或者,更复杂,让我们假装DLL使用fopen;然后你提供自己的fopen来检测路径中的特殊模式,你模仿C运行时内部......嗯,真的值得所有的痛苦吗? :d

答案 5 :(得分:1)

请解释为什么您无法从EXE中提取数据并将其写入临时文件。许多应用程序都这样做 - 这是解决这个问题的经典解决方案。

如果你真的必须提供“虚拟文件”,那么最干净的解决方案可能是文件系统过滤器驱动程序。 “干净”并不意味着“好” - 过滤器是一个完全记录和支持的解决方案,因此它比API挂钩,注入等更清晰。但是,文件系统过滤器并不容易。

OSR Online是查找Windows文件系统信息的最佳位置。 NTFSD邮件列表是文件系统开发人员挂出的地方。

答案 6 :(得分:0)

如何使用某种RamDisk并将文件写入此磁盘?我自己尝过一些ramdisks,虽然从来没有找到好的ramdisks,告诉我你是否成功。

答案 7 :(得分:0)

好吧,如果你需要在你的exe中分配虚拟文件,你需要创建一个足够大的矢量,流或char数组来保存你想要写的所有虚拟数据。

这是我能够在没有对磁盘进行任何I / O的情况下考虑的唯一解决方案(即使您没有写入文件)。

如果你需要保留像路径语法这样的文件,只需编写一个模仿该行为的类,而不是写入文件写入内存缓冲区。这很简单。记住KISS。

干杯

答案 8 :(得分:0)

打开名为“NUL:”的文件进行写入。它是可写的,但数据被默默地丢弃。有点像* nix成名的/ dev / null。

你不能记忆地映射它。内存映射意味着读/写访问,而NUL是只写的。

答案 9 :(得分:0)

我猜这个dll不能接受一个流?它几乎是简单的问,但你是否可以使用它。

答案 10 :(得分:0)

使用命名管道时是否尝试使用\?\前缀?许多API支持使用\?\直接传递路径的其余部分,而无需任何解析/修改。

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

答案 11 :(得分:0)

为什么不将它作为资源添加 - http://msdn.microsoft.com/en-us/library/7k989cfy(VS.80).aspx - 与添加图标的方式相同。