之前在写一个文件过滤驱动时遇到将文件移动到另一个目录的需求,为了避免重入,首先想到的就是利用IoCreateFileSpecifyDeviceObjectHint获得其句柄并用ZwSetInformationFile将其移动到另一目录,但测试时发现ZwSetInformationFile始终返回STATUS_INVALID_DEVICE_OBJECT_PARAMETER错误。
上网搜了一下,发现有位仁兄也遇到了同样的问题(http://www.eggheadcafe.com/software/aspnet/31694886/rename-fails-on-handle-ob.aspx),跟踪了一下,发现系统用IopGetFileObjectExtension返回的值作为PDEVICE_OBJECT类型传入到IoCreateFileEx中,而实际上IopGetFileObjectExtension返回的是一个指向PDEVICE_OBJECT的指针,即指针的指针。
手工在内存中更改该参数后ZwSetInformationFile返回成功,并且文件也正确移动到了指定的目录。这个错误也许是文件对象扩展的格式更改了,也许是IopOpenLinkOrRenameTarget内部代码更改了没同步,总之,现在只有通过手工创建IRP的方式来绕过这个问题。
利用IRP的方式意味着不能用文件句柄了,只有自己打开文件对象并发送IRP。
首先需要打开要移动的文件,获得文件对象:
手工打开及关闭文件的接口: