如果我使用CreateFile
创建一个文件句柄,用于" \\?\ NUL"或" \\?\ pipe \",句柄映射到为" \ Device \ Null"打开的File对象。或" \ Device \ NamedPipe"内核设备对象。由于GetFinalPathNameByHandle
函数支持VOLUME_NAME_NT
属性,该属性已经返回像" \ Device \ HarddiskVolume1 \"这样的字符串,我以为我能够为设备获取类似的路径处理。但是,调用总是失败,无论是ERROR_INVALID_FUNCTION
还是ERROR_INVALID_PARAMETER
,都取决于打开文件的访问标记。
事实上,几乎所有对类似函数的调用都失败了 - 比如GetFileInformationByHandle
,GetFileInformationByHandleEx
,甚至调用NT函数,例如NtQueryInformationFile
- 返回STATUS_INVALID_PARAMETER
。唯一不会失败的功能是GetFileType
(能够识别管道),GetVolumeInformationByHandle
(能够识别驱动程序)和NtQueryInformationFile
FileModeInformation
。
所有这些功能在任何标准文件上使用时都有效,但设备文件句柄不支持它们。如何从设备句柄获取路径信息?是否有一些Nt
或Io
函数可以使用?如果我唯一拥有的是手柄,还有其他方法可以识别设备吗?
答案 0 :(得分:0)
正如RbMm和eryksun指出的那样,实现该对象的驱动程序必须能够处理IRP_MJ_QUERY_INFORMATION
,但如果没有,则该对象的名称可以是通过 NtQueryObject 获取,将 ObjectNameInformation (1)传递给它,它将获得带有对象名称的OBJECT_NAME_INFORMATION
结构。
因为我打算用C#调用它,所以这里是它的P / Invoke代码:
static class Ntdll
{
[DllImport("ntdll.dll")]
static extern int NtQueryObject(
IntPtr Handle, int ObjectInformationClass,
IntPtr ObjectInformation, int ObjectInformationLength,
out int ReturnLength
);
public static int NtQueryObject(IntPtr Handle, int ObjectInformationClass, IntPtr ObjectInformation, int ObjectInformationLength)
{
int length;
int status = NtQueryObject(Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, out length);
if(status != 0) throw new Win32Exception(RtlNtStatusToDosError(status));
return length;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct OBJECT_NAME_INFORMATION
{
public ushort Length;
public ushort MaximumLength;
public string Buffer;
}
[DebuggerStepThrough]
public static void NtQueryObject(IntPtr Handle, out OBJECT_NAME_INFORMATION ObjectNameInformation)
{
IntPtr buffer = Marshal.AllocHGlobal(1024);
try{
Ntdll.NtQueryObject(Handle, 1, buffer, 1024);
ObjectNameInformation = Marshal.PtrToStructure<Ntdll.OBJECT_NAME_INFORMATION>(buffer);
}finally{
Marshal.FreeHGlobal(buffer);
}
}
}
然后可以通过将"\\?\GlobalRoot"
添加到 Buffer 成员来构建路径。