Python and C
P Boy
prettyboy988-google at yahoo.com
Fri Mar 10 16:49:49 EST 2006
I have written some C extension before but it was pretty tedious. I
have recently found another approach by using ctypes
(http://starship.python.net/crew/theller/ctypes/). Which you develop
your C module in dynamic library (DLL in Windows world), the from
Python, you can call the C functions in the DLL using ctypes.
I have a library from Microsoft, ewfapi.dll, ewfapi.lib (not required),
and ewfapi.h (see download) which I want to program the EWF capability
in Windows XP Embedded. I was thinking about writing a Python C
extension for it, but using ctypes is much easier. I only need to
redefine some data structures from the header file, and not worry about
common C tasks such as memory management, reference counting, etc.
Ewfapi files can be downloaded from
http://www.microsoft.com/downloads/details.aspx?FamilyID=eb3b3d35-ae95-4864-ba3c-d488d3980972&displaylang=en
I have some sample usage in Python shown below, which I can
interactively control the EWF feature using Python shell (in an XP
embedded machine).
# ewf.py
import ctypes
import string
# These are the functions from the EWF API
##EwfMgrGetDriveLetterFromVolumeName(volumeName)
##
##EwfMgrVolumeNameListIsEmpty(volumeEntry)
##
##EwfMgrVolumeNameEntryPop(volumeEntry)
##
##EwfMgrVolumeNameListDelete
##
##EwfMgrOpenProtected
##
##EwfMgrClose = _ewfapiPy.EwfMgrClose
##
##EwfMgrClearCommand = _ewfapiPy.EwfMgrClearCommand
##
##EwfMgrSetPersistentData = _ewfapiPy.EwfMgrSetPersistentData
##
##EwfMgrGetPersistentData = _ewfapiPy.EwfMgrGetPersistentData
##
##EwfMgrCheckpoint = _ewfapiPy.EwfMgrCheckpoint
##
##EwfMgrRestore = _ewfapiPy.EwfMgrRestore
##
##EwfMgrDisable = _ewfapiPy.EwfMgrDisable
##
##EwfMgrEnable = _ewfapiPy.EwfMgrEnable
##
##EwfMgrCommit = _ewfapiPy.EwfMgrCommit
##
##EwfMgrCommitAndDisableLive = _ewfapiPy.EwfMgrCommitAndDisableLive
##
##EwfMgrCommitFile = _ewfapiPy.EwfMgrCommitFile
##
##EwfMgrSetLevel = _ewfapiPy.EwfMgrSetLevel
##
##EwfMgrGetProtectedVolumeConfig =
_ewfapiPy.EwfMgrGetProtectedVolumeConfig
##
##EwfMgrGetProtectedVolumeList = _ewfapiPy.EwfMgrGetProtectedVolumeList
##
##EwfMgrOpenOverlayStore = _ewfapiPy.EwfMgrOpenOverlayStore
##
##EwfMgrGetOverlayStoreConfig = _ewfapiPy.EwfMgrGetOverlayStoreConfig
##
##EwfMgrRegisterLowSpaceNotification =
_ewfapiPy.EwfMgrRegisterLowSpaceNotification
# Short handle to the API
ewfapi = ctypes.windll.ewfapi
# Data structure from EWFAPI.h translated into Python
# Map these enumerations to string
EWF_CMD = { 0 : 'NO Command',
1 : 'Enable',
2 : 'Disable',
3 : 'Set Level',
4 : 'Commit',
}
EWF_STATE = { 0 : 'Enabled',
1 : 'Disabled',
}
EWF_TYPE = { 0 : 'Disk',
1 : 'RAM',
2 : 'RAM Reg',
}
# Forward Declaration
pVolumeNameEntry = ctypes.POINTER('VolumeNameEntry')
# Structure of a linked-list
class VolumeNameEntry(ctypes.Structure):
_fields_ = [('Next', ctypes.POINTER(pVolumeNameEntry)),
('Name', ctypes.c_wchar * 256),
]
# Set the pointer to the structure
ctypes.SetPointerType(pVolumeNameEntry, VolumeNameEntry)
# Volume descriptor
class VolumeDesc(ctypes.Structure):
_fields_ = [('DeviceName', ctypes.c_wchar * 256),
('VolumeID', ctypes.c_ubyte * 16),
]
pVolumeDesc = ctypes.POINTER(VolumeDesc)
# Overlay configuration
class OverlayStoreConfig(ctypes.Structure):
_fields_ = [('FormatVersion', ctypes.c_ulong),
('VolumeSize', ctypes.c_longlong),
('NumSegments', ctypes.c_ulong),
('FreeSegments', ctypes.c_ulong),
('SegmentSize', ctypes.c_ulong),
('MaxVolumes', ctypes.c_ulong),
('NumVolumes', ctypes.c_ulong),
('MaxLevels', ctypes.c_ushort),
('VolumeDescArray', pVolumeDesc),
]
pOverlayStoreConfig = ctypes.POINTER(OverlayStoreConfig)
class Command(ctypes.Structure):
_fields_ = [('Command', ctypes.c_int),
('Param1', ctypes.c_ulong),
('Param2', ctypes.c_ulong),
]
pCommand = ctypes.POINTER(Command)
class FileTime(ctypes.Structure):
_fields_ = [('LowDateTime', ctypes.c_ulong),
('HighDateTime', ctypes.c_ulong),
]
pFileTime = ctypes.POINTER(FileTime)
class LevelDesc(ctypes.Structure):
_fields_ = [('LevelName', ctypes.c_wchar * 64),
('LevelEndTime', FileTime),
('LevelDataSize', ctypes.c_longlong),
]
pLevelDesc = ctypes.POINTER(LevelDesc)
class VolumeConfig(ctypes.Structure):
_fields_ = [('Type', ctypes.c_int),
('State', ctypes.c_int),
('BootCommand', Command),
('PersistentData', ctypes.c_ubyte * 32),
('MaxLevels', ctypes.c_ushort),
('ClumpSize', ctypes.c_ulong),
('CurrentLevel', ctypes.c_ushort),
('DiskMap_RamDataSize', ctypes.c_longlong),
('DiskDataSize', ctypes.c_longlong),
('MemMapSize', ctypes.c_ulong),
('VolumeDesc', VolumeDesc),
('LevelDescArray', pLevelDesc),
]
def formatUnsigned(u):
return '%02X' % u
def unsignedArrayToHex(array):
return string.join(map(formatUnsigned, array)).replace(' ','')
def displayVolumeConfiguration(config, drive):
config_type = EWF_TYPE[config.Type]
print 'Type : %s' % config_type
print 'State : %s' % EWF_STATE[config.State]
print 'Boot Cmd : %s' % EWF_CMD[config.BootCommand.Command]
print 'Param 1 : %u' % config.BootCommand.Param1
print 'Param 2 : %u' % config.BootCommand.Param2
print 'Persistent Data: %s' %
unsignedArrayToHex(config.PersistentData)
print
print 'Maximum Levels : %u' % config.MaxLevels
print 'Clump Size : %u Bytes' % config.ClumpSize
print 'Current Level : %u' % config.CurrentLevel
if config_type == 'Disk':
print 'Disk Map Size : %u Bytes' %
config.DiskMap_RamDataSize
print 'Disk Data Size : %u Bytes' % config.DiskDataSize
else:
print 'RAM Data Size : %u Bytes' %
config.DiskMap_RamDataSize
print 'Memory Map Size : %u Bytes' % config.MemMapSize
print 'Device Name : %s' % config.VolumeDesc.DeviceName
print 'Volume ID : %s' %
unsignedArrayToHex(config.VolumeDesc.VolumeID)
print 'Drive : %s' % drive
def information():
# Get the pointer and convert to linked-list node
volume_list =
VolumeNameEntry.from_address(ewfapi.EwfMgrGetProtectedVolumeList())
while 1:
drive =
chr(ewfapi.EwfMgrGetDriveLetterFromVolumeName(volume_list.Name))
print '%s: = %s' % (drive, volume_list.Name)
handle = ewfapi.EwfMgrOpenProtected(volume_list.Name)
config =
VolumeConfig.from_address(ewfapi.EwfMgrGetProtectedVolumeConfig(handle))
displayVolumeConfiguration(config, drive)
if
ewfapi.EwfMgrVolumeNameListIsEmpty(ctypes.c_void_p.from_address(ctypes.addressof(volume_list))):
break
if __name__ == "__main__ ":
print 'Running'
information()
More information about the Python-list
mailing list