在Python 3.2中,我将从ctypes.windll.kernel32.DeviceIoControl函数返回的数据中创建一个Structure对象。完成此操作后,我可以访问“结构”字段并返回数据。但是,如果我做某事会使用内存,例如打开文件,则会修改结构内部的数据。在输出的第一部分中,我粘贴的是预期的结果。但是,在打开文件并再次打印结构字段后,值已更改。我不确定为什么要修改数据或如何阻止它发生。
结构:
class DISK_GEOMETRY(ctypes.Structure): ''' Disk Geometry Data Structure http://msdn.microsoft.com/en-us/library/aa363972(v=vs.85).aspx ''' _fields_ = [("Cylinders", wintypes.LARGE_INTEGER), ("MediaType", wintypes.BYTE), #MEDIA_TYPE ("TracksPerCylinder", wintypes.DWORD), ("SectorsPerTrack", wintypes.DWORD), ("BytesPerSector", wintypes.DWORD)] class DISK_GEOMETRY_EX(ctypes.Structure): ''' Disk Geometry EX Data Structure http://msdn.microsoft.com/en-us/library/aa363970(v=vs.85).aspx ''' _fields_ = [("Geometry", DISK_GEOMETRY), ("DiskSize", wintypes.LARGE_INTEGER), ("Data[1]", wintypes.BYTE)]
DeviceIoControl:
class DeviceIoControl: def __init__(self, path): self.path = path def __DeviceIoControl(self, devicehandle, IoControlCode, input, output): ''' DeviceIoControl Function http://msdn.microsoft.com/en-us/library/aa363216(v=vs.85).aspx ''' DevIoCtl = ctypes.windll.kernel32.DeviceIoControl DevIoCtl.argtypes = [ wintypes.HANDLE, #HANDLE hDevice wintypes.DWORD, #DWORD dwIoControlCode wintypes.LPVOID, #LPVOID lpInBuffer wintypes.DWORD, #DWORD nInBufferSize wintypes.LPVOID, #LPVOID lpOutBuffer wintypes.DWORD, #DWORD nOutBufferSize ctypes.POINTER(wintypes.DWORD), #LPDWORD lpBytesReturned wintypes.LPVOID] #LPOVERLAPPED lpOverlapped DevIoCtl.restype = wintypes.BOOL if isinstance(output, int): output = ctypes.create_string_buffer(output) input_size = len(input) if input is not None else 0 output_size = len(output) assert isinstance(output, ctypes.Array) BytesReturned = wintypes.DWORD() status = DevIoCtl(devicehandle, IoControlCode, input, input_size, output, output_size, BytesReturned, None) return output[:BytesReturned.value] if status is not 0 else -1 def GetDriveGeometry(self): diskhandle = winapi.CreateHandle( self.path, winapi.NULL, winapi.FILE_SHARE_READ|winapi.FILE_SHARE_WRITE, winapi.LPSECURITY_ATTRIBUTES(), winapi.OPEN_EXISTING, winapi.FILE_ATTRIBUTE_NORMAL, winapi.NULL) if diskhandle == winapi.INVALID_HANDLE_VALUE: return -1 temp = ctypes.cast(self.__DeviceIoControl(diskhandle, winioctl.IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, None, 1024), ctypes.POINTER(winioctl.DISK_GEOMETRY_EX)).contents winapi.CloseHandle(diskhandle) return temp
主要:
device = DeviceIoControl(r"\\.\PhysicalDrive0") devicegeo = device.GetDriveGeometry() print("Disk Size: " +str(devicegeo.DiskSize)) print("BytesPerSector: "+str(devicegeo.Geometry.BytesPerSector)) print("Cylinders: "+str(devicegeo.Geometry.Cylinders)) print("MediaType: "+str(hex(devicegeo.Geometry.MediaType))) print("CtypesAddressOf: "+str(ctypes.addressof(devicegeo))) with open(r"\\.\PhysicalDrive0", 'rb') as f: f.seek(0) MBRdata = f.read(512) print("\nOpened a file\n") print("Disk Size: "+str(devicegeo.DiskSize)) print("BytesPerSector: "+str(devicegeo.Geometry.BytesPerSector)) print("Cylinders: "+str(devicegeo.Geometry.Cylinders)) print("MediaType: "+str(hex(devicegeo.Geometry.MediaType))) print("CtypesAddressOf: "+str(ctypes.addressof(devicegeo)))
输出:
Disk Size: 80000000000 BytesPerSector: 512 Cylinders: 9726 MediaType: 0xc CtypesAddressOf: 12322040 Opened a file Disk Size: 0 BytesPerSector: 1 Cylinders: 2170477562872987649 MediaType: -0x40 CtypesAddressOf: 12322040
一些观察:
DevIoCtl
byref(BytesReturned)
ctypes.cast
bytes
output[:BytesReturned.value]
__DeviceIoControl
FWIW,我只是使用ctypes尝试使用Windows IOCTL调度。也使用\\.\PysicalDrive0和IOCTL_DISK_GET_DRIVE_GEOMETRY。
\\.\PysicalDrive0
IOCTL_DISK_GET_DRIVE_GEOMETRY
我做了这个要点。