- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试理解和使用 win32file。我需要获取 USN 期刊,并且很难理解我在网上找到的代码片段。这是我找到的代码片段 -
format = 'qqqqqLLLLqqqqq'
length = struct.calcsize(format)
out_buffer = win32file.DeviceIoControl(volh, winioctlcon.FSCTL_GET_NTFS_VOLUME_DATA, None, length)
data = struct.unpack(format, out_buffer)
现在我对 C 及其结构感到非常生疏。我现在了解到的是 format
是 96 字节缓冲区,它将从 DeviceIoControl
所以我尝试将格式更改为 'QQQQQQQQQQQQQQQQQQQQ'
来看看会发生什么(因为我有点不知道实际会发生什么),结果我得到了一个更大的 这次是out_buffer
。所以我想把它拆开 -
struct.unpack(format, out_buffer)
令我惊讶的是,我得到了 -
struct.error: unpack requires a string argument of length 152
所以我添加了另一个“Q”来增加大小并得到了相同的结果。我不明白为什么 'qqqqqLLLLqqqqq' 有效,而 'QQQQQQQQQQQQQQQQQQQQ' 无效。所以我的问题是 -
我的理解是,如果缓冲区大于输出,我们可以解包,那么为什么解包不起作用?
每次我想从 DeviceIoControl 获取某些内容时是否都必须记住这些格式?
向我指出资源也将是一个额外的好处,因为我需要构建代码来阅读 USN 期刊,而且我认为“点击尝试”不会让我到达任何地方
最佳答案
让我们将问题分成更小的部分,然后逐一解决。
win32file 模块是 [GitHub]: mhammond/pywin32 - Python for Windows (pywin32) Extensions 的一部分这是 WinAPI 的 Python 包装器
不幸的是,它没有官方文档页面(或者我不知道),所以下面是我能找到的最好的文档页面(我已经使用它很多年了)。另一种永远不会失败的方法(但吸引力较差)是直接查看代码
[ActiveState.Docs]: win32file.DeviceIoControl是 [MS.Docs]: DeviceIoControl function 的包装
DeviceIoControl 的行为有所不同,具体取决于 dwIoControlCode(第二个nd 参数)。对于FSCTL_GET_NTFS_VOLUME_DATA,它用特定于卷的数据填充缓冲区。来自 [MS.Docs]: FSCTL_GET_NTFS_VOLUME_DATA IOCTL :
lpOutBuffer
A pointer to the output buffer, an NTFS_VOLUME_DATA_BUFFER (@CristiFati: !!! Broken URL !!!) structure. The file record associated with the file identifier specified in the input buffer is returned in this buffer. Refer to the Remarks section of the documentation for the NTFS_VOLUME_DATA_BUFFER structure for specific information on how to determine the correct size of this buffer.
这是上述损坏的 URL 的替代方案:[MSDN]: NTFS_VOLUME_DATA_BUFFER structure 。由于我不确定它的有效期有多长,因此我粘贴了下面的结构定义(来自Windows Kits 8.1:winioctl.h em>(第 #4987 行)):
typedef struct {
LARGE_INTEGER VolumeSerialNumber;
LARGE_INTEGER NumberSectors;
LARGE_INTEGER TotalClusters;
LARGE_INTEGER FreeClusters;
LARGE_INTEGER TotalReserved;
DWORD BytesPerSector;
DWORD BytesPerCluster;
DWORD BytesPerFileRecordSegment;
DWORD ClustersPerFileRecordSegment;
LARGE_INTEGER MftValidDataLength;
LARGE_INTEGER MftStartLcn;
LARGE_INTEGER Mft2StartLcn;
LARGE_INTEGER MftZoneStart;
LARGE_INTEGER MftZoneEnd;
} NTFS_VOLUME_DATA_BUFFER, *PNTFS_VOLUME_DATA_BUFFER;
[Python 3.Docs]: struct - Interpret bytes as packed binary data模块,用于二进制数据和“正常”数据之间的转换。它包含所有格式字符含义(q、Q、L、...)等等。您还可以查看[SO]: Python struct.pack() behavior了解更多(实用)细节
看完以上 Material ,事情应该变得更清楚了。
一些注意事项:
我还准备了一个虚拟的 Python 示例。
code00.py:
#!/usr/bin/env python3
import sys
import struct
import win32file
import win32api
import win32con
import winioctlcon
VOLUME_LETTER = "E"
FILE_READ_ATTRIBUTES = 0x0080
FILE_EXECUTE = 0x0020
vol_data_buf_fmt = "qqqqqLLLLqqqqq" # This is the format that matches NTFS_VOLUME_DATA_BUFFER definition (96 bytes). Note: Instead of each 'q' you could also use 'Ll' as 'LARGE_INTEGER' is an union
BINARY_FORMAT_LIST = [
vol_data_buf_fmt,
"QQQQQQQQQQQQQQQQQQQ",
]
def print_formats(): # Dummy func
print("Formats and lengths:")
for format in BINARY_FORMAT_LIST:
print(" {:s}: {:d}".format(format, struct.calcsize(format)))
def main():
#print_formats()
vol_unc_name = "\\\\.\\{:s}:".format(VOLUME_LETTER)
print("volume: ", vol_unc_name)
access_flags = FILE_READ_ATTRIBUTES | FILE_EXECUTE # Apparently, doesn't work without FILE_EXECUTE
share_flags = win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE # Doesn't work withou FILE_SHARE_WRITE
creation_flags = win32con.OPEN_EXISTING
attributes_flags = win32con.FILE_ATTRIBUTE_NORMAL
vol_handle = win32file.CreateFile(vol_unc_name, access_flags, share_flags, None, creation_flags, attributes_flags, None)
buf_len = struct.calcsize(vol_data_buf_fmt)
for i in [buf_len]:
print(" Passing a buffer size of: {:d}".format(i))
buf = win32file.DeviceIoControl(vol_handle, winioctlcon.FSCTL_GET_NTFS_VOLUME_DATA, None, i)
print(" DeviceIocontrol returned a {:d} bytes long {:}".format(len(buf), type(buf)))
out = struct.unpack_from(vol_data_buf_fmt, buf)
print("\n NumberSectors: {:}\n TotalClusters: {:}\n BytesPerCluster: {:}".format(out[1], out[2], out[6]))
win32api.CloseHandle(vol_handle)
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main()
输出:
(py35x64_test) e:\Work\Dev\StackOverflow\q053318932>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" ./code00.py
Python 3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32
volume: \\.\E:
Passing a buffer size of: 96
DeviceIocontrol returned a 96 bytes long <class 'bytes'>
NumberSectors: 494374911
TotalClusters: 61796863
BytesPerCluster: 4096
不用说,将TotalClusters乘以BytesPerCluster,我就得到了的正确字节数(由Win报告) E:开车。
关于python - win32file.DeviceIoControl 上的结构解包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53318932/
我们在用户模式下有 OverLapped 结构。例如我们可以调用 DeviceIoControl与重叠的成员在完成此调用时引发事件。但是什么内核模式?如何通过回调在内核中发送异步 DeviceIoCo
我在使用 DeviceIOControl 时遇到一些问题。我正在尝试从物理驱动器读取磁盘几何结构,但从未设置输出缓冲区。 这是我的代码示例,一个简单的函数,应该获取磁盘几何形状并返回磁盘是否可移动:
我正在尝试将 INOUT_PARAM 发送到我的内核驱动程序,看来我已经成功了。当我尝试编辑它并将其发送回应用程序时,我收到以下错误: 这是应用程序代码: typedef struct _INOUT_
我正在尝试在我的硬盘上进行分区偏移。我这样做: PDRIVE_LAYOUT_INFORMATION_EX partitions; DWORD partitionsSize = sizeof(DRIVE
当我运行以下代码时,我对内存位置的访问无效 WIN32_FIND_DATAW FD; WCHAR cPath[MAX_PATH], cFindPath[MAX_PATH]; if (!GetCurre
我正在为它写一个 Windows CE 服务和一个 API 库,它包装了 DeviceIoControl与图书馆沟通所需的电话。我可以确定,传递给 DeviceIoControl 函数的内存缓冲区编码
我正在尝试将一些数据从我的内核驱动程序传递到用户应用程序。 我已经在驱动程序和应用程序共享的头文件中定义了结构: typedef struct _CallBack { HANDLE
我使用 DeviceIoControl 返回物理磁盘扇区的大小。它总是返回 512 个字节,直到最近它开始返回 4096 个字节。检查生成的 STORAGE_ACCESS_ALIGNMENT_DESC
我正在尝试与用于创建 TUN 接口(interface) (WinTun) 的驱动程序交互,但为了从它们发送和接收数据,我需要注册一个环形缓冲区。我正在使用的代码看起来像这样(我省略了使用 Setup
我正在尝试理解和使用 win32file。我需要获取 USN 期刊,并且很难理解我在网上找到的代码片段。这是我找到的代码片段 - format = 'qqqqqLLLLqqqqq' length =
我正在尝试调用 DeviceIoControl(IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS) API,作为 shown here ,但我需要它首先“告诉我”它需要多少内存
我可以向应用程序发送数据驱动程序。 在应用中: DeviceIoControl(dHandle, IOCTL_TEST, (PVOID)InputBuffer, sizeof(InputBuffer)
在回答我的问题之前,我将回顾一下我目前正在使用的东西,以便您对我已经做过/尝试过的事情有一个很好的了解。 我有一个多线程用户模式 Windows 桌面应用程序,它向 KMDF 驱动程序发出 Dev
我正在使用 DeviceIoControl 开发 C# 项目.我咨询过相关Pinvoke.net page我的签名: [DllImport("Kernel32.dll", SetLastError =
根据我的理解,DeviceIOControl和ioctl是相同的功能。它们都向硬件发送控制代码并返回响应。为了重用代码,我尝试创建一个能够以跨平台方式工作的函数。因此,我决定使用 DeviceIOCo
我尝试使用 DeviceIoControl 函数(Win32 API 函数)弹出我的 CDROM 驱动器,当我的 CDROM 驱动器没有磁盘时它工作正常,但是在插入磁盘后,Marshal .GetLa
我的操作系统是 Win7 64 位。我正在尝试通过 DeviceIoControl 将变量的值而不是它的地址(进程 ID,DWORD)传递给我的驱动程序。试了好几次,都是蓝屏或者错误码998。 在用户
我在使用 DeviceIOControl 将 128 字节缓冲区放入我的驱动程序时遇到问题,我使用此代码: int Initialize(unsigned char* public_signature
此代码在 Windows 7 上启动时完全没问题: HANDLE hVol = CreateFile(L"\\\\.\\c:", GENERIC_WRITE | GENERIC_READ,
我正在尝试通过 DeviceIOControl 初始化磁盘并创建 NTFS 分区,而不使用 DiskPart 或 WMI。 使用下面的代码我可以初始化磁盘并创建一个 RAW 分区,但我无法调整参数以使
我是一名优秀的程序员,十分优秀!