The win32 function NetShareDel takes three arguments, LPCWSTR LPCWSTR and DWORD.
So I use the following list for argtypes:
import ctypes as C
C.windll.Netapi32.NetShareDel.argtypes = [LPCWSTR, LPCWSTR, c_int]
C.windll.Netapi32.NetShareDel.restype = c_int
C.windll.Netapi32.NetShareDel(server, shareName, 0)
That works fine, but I can't figure out what to use for NetShareAdd, especialle the byte array for NET_SHARE_INFO struct and the last byref(c_int) argument.
Here's the code:
def Share(server, shareName, dir):
info = SHARE_INFO_2()
STYPE_DISKTREE = 0
info.shi2_netname = shareName
info.shi2_path = dir
info.shi2_type = STYPE_DISKTREE
info.shi2_remark = "Shared: " + time.strftime("%Y%m%d-%H:%M")
info.shi2_max_uses = -1
info.shi2_passwd = ""
info.shi2_current_uses = 0
info.shi2_permissions = 0xFFFFFFFF
i = c_int()
bytearray = buffer(info)[:]
windll.Netapi32.NetShareAdd.argtypes = [LPCWSTR, c_int, ????, ????]
windll.Netapi32.NetShareAdd(server, 2, bytearray, C.byref(i))
What would be the correct argtypes list for NetShareAdd?
Got it working finally
First the line
bytearray = buffer(info)[:]
was changed into byte pointer type
byteptr = C.POINTER(C.wintypes.BYTE)(info)
and then the argtypes and call will become POINTER(BYTE) too of course:
C.windll.Netapi32.NetShareAdd.argtypes = [LPCWSTR, c_int, C.POINTER(C.wintypes.BYTE), C.POINTER(c_int)]
C.windll.Netapi32.NetShareAdd.restype = c_int
windll.Netapi32.NetShareAdd(server, 2, byteptr, C.byref(i))
Related
I want to use Ctypes to enumerate the device, the following examples are C++ language I am not very good at converting, the following code is half of what I wrote
My question is how to conversion this
//Enumerate through all devices in Set
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (i=0;SetupDiEnumDeviceInfo(hDevInfo,i,
&DeviceInfoData);i++)
https://social.msdn.microsoft.com/forums/windowsdesktop/en-US/43ab4902-75b9-4c5c-9b54-4567c825539f/how-to-enumerate-hardware-devices-by-using-setupdi?forum=vcgeneral
import ctypes as ct
from ctypes import wintypes as w
SetupAPI = ct.WinDLL('SetupAPI')
SetupAPI.SetupDiGetClassDevsW.argtypes = w.LPVOID,w.PWCHAR,w.HWND,w.DWORD
SetupAPI.SetupDiGetClassDevsW.restype = w.HANDLE
SetupAPI.SetupDiEnumDeviceInfo.argtypes = w.HANDLE,w.DWORD,w.HANDLE
SetupAPI.SetupDiEnumDeviceInfo.restype = w.BOOLEAN
DIGCF_DEFAULT = 0x00000001
DIGCF_PRESENT = 0x00000002
DIGCF_ALLCLASSES = 0x00000004
DIGCF_PROFILE = 0x00000008
DIGCF_DEVICEINTERFACE = 0x00000010
ClassGuid = None
Enumerator = None
hwndParent = None
Flags = DIGCF_PRESENT | DIGCF_ALLCLASSES
DeviceInfoSet = None
MemberIndex = None
DeviceInfoData = None
class SP_DEVINFO_DATA(ct.Structure):
_fields_ = [
('cbSize',w.DWORD),
('ClassGuid',w.LPVOID),
('DevInst',w.DWORD),
('Reserved',w.ULONG),
]
SP_DEVINFO_DATA = SP_DEVINFO_DATA()
hDevInfo = SetupAPI.SetupDiGetClassDevsW(
ClassGuid,
Enumerator,
hwndParent,
Flags
)
SP_DEVINFO_DATA.cbSize = ct.sizeof(SP_DEVINFO_DATA)
DeviceInfoSet = hex(hDevInfo)
MemberIndex = 1
DeviceInfoData = ct.byref(SP_DEVINFO_DATA)
SetupDiEnumDeviceInfo = SetupAPI.SetupDiEnumDeviceInfo(
DeviceInfoSet,
MemberIndex,
DeviceInfoData
)
print(SetupDiEnumDeviceInfo)
Here's a complete, typesafe example to enumerate a particular device type, in this case USB host controllers:
import ctypes as ct
from ctypes import wintypes as w
import uuid
SetupAPI = ct.WinDLL('SetupAPI')
# ULONG_PTR is defined as an unsigned integer of the same size as a pointer on the OS,
# which is ct.ulonglong on 64-bit or ct.ulong on 32-bit. w.WPARAM happens to follow
# that same definition.
ULONG_PTR = w.WPARAM
# For type safety. A ctypes function will only accept HDEVINFO not any old HANDLE.
class HDEVINFO(w.HANDLE):
pass
# A class to initialize and print GUIDs
class GUID(ct.Structure):
_fields_ = (('Data1', ct.c_ulong),
('Data2', ct.c_ushort),
('Data3', ct.c_ushort),
('Data4', ct.c_ubyte * 8))
def __repr__(self):
return f"GUID('{self}')"
def __str__(self):
return (f'{{{self.Data1:08x}-{self.Data2:04x}-{self.Data3:04x}-'
f'{bytes(self.Data4[:2]).hex()}-{bytes(self.Data4[2:]).hex()}}}')
def __init__(self,guid=None):
if guid is not None:
data = uuid.UUID(guid)
self.Data1 = data.time_low
self.Data2 = data.time_mid
self.Data3 = data.time_hi_version
self.Data4[0] = data.clock_seq_hi_variant
self.Data4[1] = data.clock_seq_low
self.Data4[2:] = data.node.to_bytes(6,'big')
PGUID = ct.POINTER(GUID)
# See https://learn.microsoft.com/en-us/windows-hardware/drivers/install/guid-devinterface-usb-host-controller
GUID_DEVINTERFACE_USB_HOST_CONTROLLER = GUID('{3ABF6F2D-71C4-462A-8A92-1E6861E6AF27}')
class SP_DEVINFO_DATA(ct.Structure):
_fields_ = (('cbSize', w.DWORD),
('ClassGuid', GUID),
('DevInst', w.DWORD),
('Reserved', ULONG_PTR))
def __repr__(self):
return f'SP_DEVINFO_DATA(ClassGuid={self.ClassGuid}, DevInst={self.DevInst})'
# Per docs, the cbSize member must be set to the size of this structure.
def __init__(self):
self.cbSize = ct.sizeof(SP_DEVINFO_DATA)
PSP_DEVINFO_DATA = ct.POINTER(SP_DEVINFO_DATA)
SetupAPI.SetupDiGetClassDevsW.argtypes = PGUID, w.PWCHAR, w.HWND, w.DWORD
SetupAPI.SetupDiGetClassDevsW.restype = HDEVINFO
SetupAPI.SetupDiEnumDeviceInfo.argtypes = HDEVINFO, w.DWORD, PSP_DEVINFO_DATA
SetupAPI.SetupDiEnumDeviceInfo.restype = w.BOOL
SetupAPI.SetupDiDestroyDeviceInfoList.argtypes = HDEVINFO,
SetupAPI.SetupDiDestroyDeviceInfoList.restype = w.BOOL
DIGCF_DEFAULT = 0x00000001
DIGCF_PRESENT = 0x00000002
DIGCF_ALLCLASSES = 0x00000004
DIGCF_PROFILE = 0x00000008
DIGCF_DEVICEINTERFACE = 0x00000010
ClassGuid = GUID_DEVINTERFACE_USB_HOST_CONTROLLER
Enumerator = None
hwndParent = None
Flags = DIGCF_DEVICEINTERFACE | DIGCF_PRESENT
devinfo = SP_DEVINFO_DATA()
# Query for the device interface,
# then enumerate them one by one by incrementing a zero-based index
hDevInfo = SetupAPI.SetupDiGetClassDevsW(ClassGuid, Enumerator, hwndParent, Flags)
try:
MemberIndex = 0
while SetupAPI.SetupDiEnumDeviceInfo(hDevInfo, MemberIndex, ct.byref(devinfo)):
print(devinfo)
MemberIndex += 1
finally:
SetupAPI.SetupDiDestroyDeviceInfoList(hDevInfo)
Output:
SP_DEVINFO_DATA(ClassGuid={36fc9e60-c465-11cf-8056-444553540000}, DevInst=144)
SP_DEVINFO_DATA(ClassGuid={36fc9e60-c465-11cf-8056-444553540000}, DevInst=137)
SP_DEVINFO_DATA(ClassGuid={36fc9e60-c465-11cf-8056-444553540000}, DevInst=17)
SP_DEVINFO_DATA(ClassGuid={36fc9e60-c465-11cf-8056-444553540000}, DevInst=78)
SP_DEVINFO_DATA(ClassGuid={36fc9e60-c465-11cf-8056-444553540000}, DevInst=24)
SP_DEVINFO_DATA(ClassGuid={36fc9e60-c465-11cf-8056-444553540000}, DevInst=98)
SP_DEVINFO_DATA(ClassGuid={36fc9e60-c465-11cf-8056-444553540000}, DevInst=123)
SP_DEVINFO_DATA(ClassGuid={36fc9e60-c465-11cf-8056-444553540000}, DevInst=41)
My system has eight USB host controllers and the class GUID matches:
I want to hide the console and show. But after I hid it does not show
ctypes.windll.user32.ShowWindow(ctypes.windll.user32.FindWindowW(None, "L"), 1 if click_thread.hide_status else 0 )
Make sure to fully define the .argtypes and .restype of each function you use. ctypes defaults aren't always best. Below works:
import ctypes as ct
from ctypes import wintypes as w
SW_HIDE = 0
SW_SHOW = 5
dll = ct.WinDLL('user32')
# BOOL ShowWindow(HWND hWnd, int nCmdShow);
dll.ShowWindow.argtypes = w.HWND, ct.c_int
dll.ShowWindow.restype = w.BOOL
# HWND FindWindowW(LPCWSTR lpClassName, LPCWSTR lpWindowName);
dll.FindWindowW.argtypes = w.LPCWSTR, w.LPCWSTR
dll.FindWindowW.restype = w.HWND
h = dll.FindWindowW(None, 'Console')
dll.ShowWindow(h, SW_HIDE)
input(': ')
dll.ShowWindow(h, SW_SHOW)
I am trying to write bytearray into the ctypes c_uint8 buffer of a ctypes structure
class RpRes(LittleEndianStructure):
_pack_ = 1
_fields_ = [
("count", c_uint16),
("buf", c_uint8 * 512)
]
def read_func(req):
res = RpRes()
buf = os.read(req.fd, req.count)
res.buf.from_buffer(buf)
res.count = len(buf)
return res
res.buf.from_buffer(buf)
gives the below error:
AttributeError: 'c_ubyte_Array_512' object has no attribute
'from_buffer'
How can this be accomplished?
This worked for me.
def read_func(req):
res = RpRes()
buf = os.read(req.fd, req.count)
res.buf = (c_uint8 * sizeof(res.buf))(*buf)
res.count = len(buf)
return res
I've received a void pointer from a foreign function via ctypes, containing an array of c_double arrays:
[[12.0, 13.0], [14.0, 15.0], …]
I'm accessing it via the restype parameter:
from ctypes import Structure, POINTER, c_void_p, c_size_t, c_double, c_uint32, c_char_p, cast, cdll
class _CoordResult(Structure):
""" Container for returned FFI coordinate data """
_fields_ = [("coords", _FFIArray)]
class _FFIArray(Structure):
"""
Convert sequence of float lists to a C-compatible void array
example: [[1.0, 2.0], [3.0, 4.0]]
"""
_fields_ = [("data", c_void_p),
("len", c_size_t)]
def _void_array_to_nested_list(res, _func, _args):
""" Dereference the FFI result to a list of coordinates """
shape = (res.coords.len, 2)
array_size = np.prod(shape)
mem_size = 8 * array_size
array_str = string_at(res.coords.data, mem_size)
array = [list(pair) for pair in ((POINTER(c_double * 2).from_buffer_copy(res.coords)[:res.coords.len]))]
drop_array(res.coords)
return array
decode_polyline = lib.decode_polyline_ffi
decode_polyline.argtypes = (c_char_p, c_uint32)
decode_polyline.restype = _CoordResult
decode_polyline.errcheck = _void_array_to_nested_list
However, this gives me back nonsense values, because the pointer dereference in _void_array_to_nested_list is wrong.
The solution doesn't have to use NumPy, but that seems like the best approach.
I can't test this right now, but this is what I would try:
import numpy as np
result = ...
shape = (10, 2)
array_size = np.prod(shape)
mem_size = 8 * array_size
array_str = ctypes.string_at(result, mem_size)
array = np.frombuffer(array_str, float, array_size).reshape(shape)
array will be read only, copy it if you need a writable array.
Here is a solution that uses ctypes.cast or numpy.ctypeslib.as_array, and no ctypes.string_at just in case if it makes an extra copy of memory region.
class _FFIArray(Structure):
_fields_ = [("data", c_void_p), ("len", c_size_t)]
class Coordinate(Structure):
_fields_ = [("latitude", c_double), ("longitude", c_double)]
class Coordinates(Structure):
_fields_ = [("data", POINTER(Coordinate)), ("len", c_size_t)]
decode_polyline = lib.decode_polyline_ffi
decode_polyline.argtypes = (c_char_p, c_uint32)
decode_polyline.restype = _FFIArray
# assuming that the second argument is the length of polyline,
# although it should not be needed for `\0` terminated string
res = decode_polyline(polyline, len(polyline))
nres = Coordinates(cast(res.data, POINTER(Coordinate)), res.len)
for i in range(nres.len):
print(nres.data[i].latitude, nres.data[i].longitude)
# if just a numpy (np) array is needed
xs = np.ctypeslib.as_array((c_double * res.len * 2).from_address(res.data))
# "New view of array with the same data."
xs = xs.view(dtype=[('a', np.float64), ('b', np.float64)], type=np.ndarray)
xs.shape = res.len
I am trying to capture the screen using only the ctypes modules. Unfortunately I cannot retrieve raw pixel from CGDataProviderCopyData. I need to get an access to raw data:
#!/usr/bin/env python
# coding: utf-8
from sys import maxsize
from ctypes import POINTER, Structure, c_double, byref, c_void_p, c_int32, c_uint32, c_float, cdll
from ctypes.util import find_library
CGFloat = c_double if maxsize > 2 ** 32 else c_float
class CGPoint(Structure):
_fields_ = [('x', CGFloat), ('y', CGFloat)]
class CGSize(Structure):
_fields_ = [('width', CGFloat), ('height', CGFloat)]
class CGRect(Structure):
_fields_ = [('origin', CGPoint), ('size', CGSize)]
# Library
cgs = cdll.LoadLibrary(find_library('CoreGraphics'))
# Argtypes
cgs.CGGetActiveDisplayList.argtypes = [c_uint32, POINTER(c_uint32), POINTER(c_uint32)]
cgs.CGDisplayBounds.argtypes = [c_uint32]
cgs.CGRectStandardize.argtypes = [CGRect]
cgs.CGDisplayRotation.argtypes = [c_uint32]
cgs.CGWindowListCreateImage.argtypes = [CGRect, c_uint32, c_uint32, c_uint32]
cgs.CGImageGetWidth.argtypes = [c_void_p]
cgs.CGImageGetHeight.argtypes = [c_void_p]
cgs.CGImageGetDataProvider.argtypes = [c_void_p]
cgs.CGDataProviderCopyData.argtypes = [c_void_p]
cgs.CGDataProviderRelease.argtypes = [c_void_p]
# Restypes
cgs.CGGetActiveDisplayList.restype = c_int32
cgs.CGDisplayBounds.restype = CGRect
cgs.CGRectStandardize.restype = CGRect
cgs.CGDisplayRotation.restype = c_float
cgs.CGWindowListCreateImage.restype = c_void_p
cgs.CGImageGetWidth.restype = c_uint32
cgs.CGImageGetHeight.restype = c_uint32
cgs.CGImageGetDataProvider.restype = c_void_p
cgs.CGDataProviderCopyData.restype = c_void_p
cgs.CGDataProviderRelease.restype = c_void_p
# Monitors
max_displays = 32
display_count = c_uint32(0)
active_displays = (c_uint32 * max_displays)()
cgs.CGGetActiveDisplayList(max_displays, active_displays, byref(display_count))
for idx in range(display_count.value):
display = active_displays[idx]
rect = cgs.CGDisplayBounds(display)
rect = cgs.CGRectStandardize(rect)
image_ref = cgs.CGWindowListCreateImage(rect, 1, 0, 0)
width = int(cgs.CGImageGetWidth(image_ref))
height = int(cgs.CGImageGetHeight(image_ref))
prov = cgs.CGImageGetDataProvider(image_ref)
data = cgs.CGDataProviderCopyData(prov)
# How to get raw pixels from data`?
MacOS X version 10.11.3.
Python versions 2.7.10 and 2.6.9.
I have no experience with the CoreGraphics API, but looking at the documentation it looks like CGDataProviderCopyData returns a CFDataRef object. The documentat for CFDataRef has a section on "Examining a CFData Object" which describes a CFDataGetLength function and a CFDataGetBytePtr function which return the length of the data and a UInt8*.
https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CGDataProvider/#//apple_ref/c/func/CGDataProviderCopyData
https://developer.apple.com/library/ios/documentation/CoreFoundation/Reference/CFDataRef/index.html
Thanks to Snorfalorpagus, I finally succeed:
#...
data = cgs.CGDataProviderCopyData(prov)
data_ref = cgs.CFDataGetBytePtr(data)
buf_len = cgs.CFDataGetLength()
image_data = cast(data_ref, POINTER(c_ubyte * buf_len))
cgs.CGDataProviderRelease(prov)
# Raw pixels are in image_data.contents