strutura Python ctypes sendo substituída ao alocar mais memória
No Python 3.2, estou criando um objeto de estrutura a partir dos dados retornados pela função ctypes.windll.kernel32.DeviceIoControl. Depois disso, posso acessar os campos Estrutura e retornar os dados. No entanto, se eu fizer algo que usa uma memória, como abrir um arquivo, os dados dentro da estrutura são modificados. Na primeira parte do resultado que colei nos resultados, é o que se espera. No entanto, após a abertura de um arquivo e os campos de estruturas impressos novamente, os valores foram alterados. Não sei por que os dados estão sendo modificados ou como impedir que eles aconteça
Structures:
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
A Principal
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)))
Saída
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