Windows Logon as a user without a password with Python - python

I have a situation here. Using Python, I have a process been created (running as SYSTEM or Administrator user) and I need to call an application using a different username without password. So reading this link bellow, the conclusion is that could be possible, Impersonating another user without password, using Kerberos... but I am not finding any solution written in Python and actually I have no idea if there is a better approach for this problem.
https://blogs.msdn.microsoft.com/winsdk/2015/08/28/logon-as-a-user-without-a-password/
Python 3.4.1 x64, Windows 7.
Anyone can help me on this?
Thanks very much!
PS: This could be possible using "win32" modules, however I do not have any process running for this target_user to catch a process token.

Here's a rough draft of a ctypes wrapper to call LsaLogonUser for an MsV1 interactive logon, MsV1 S4U logon (service for user, batch), or Kerberos S4U domain logon.
import os
import ctypes
import collections
from ctypes import wintypes
ntdll = ctypes.WinDLL('ntdll')
secur32 = ctypes.WinDLL('secur32')
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
advapi32 = ctypes.WinDLL('advapi32', use_last_error=True)
MAX_COMPUTER_NAME_LENGTH = 15
SECURITY_LOGON_TYPE = wintypes.ULONG
Interactive = 2
Network = 3
Batch = 4
Service = 5
LOGON_SUBMIT_TYPE = wintypes.ULONG
PROFILE_BUFFER_TYPE = wintypes.ULONG
MsV1_0InteractiveLogon = 2
MsV1_0Lm20Logon = 3
MsV1_0NetworkLogon = 4
MsV1_0WorkstationUnlockLogon = 7
MsV1_0S4ULogon = 12
MsV1_0NoElevationLogon = 82
KerbInteractiveLogon = 2
KerbWorkstationUnlockLogon = 7
KerbS4ULogon = 12
MSV1_0_S4U_LOGON_FLAG_CHECK_LOGONHOURS = 0x2
KERB_S4U_LOGON_FLAG_CHECK_LOGONHOURS = 0x2
KERB_S4U_LOGON_FLAG_IDENTITY = 0x8
TOKEN_SOURCE_LENGTH = 8
NEGOTIATE_PACKAGE_NAME = b'Negotiate'
MICROSOFT_KERBEROS_NAME = b'Kerberos'
MSV1_0_PACKAGE_NAME = b'MICROSOFT_AUTHENTICATION_PACKAGE_V1_0'
DELETE = 0x00010000
READ_CONTROL = 0x00020000
WRITE_DAC = 0x00040000
WRITE_OWNER = 0x00080000
STANDARD_RIGHTS_REQUIRED = (DELETE |
READ_CONTROL |
WRITE_DAC |
WRITE_OWNER)
TOKEN_ASSIGN_PRIMARY = 0x0001
TOKEN_DUPLICATE = 0x0002
TOKEN_IMPERSONATE = 0x0004
TOKEN_QUERY = 0x0008
TOKEN_QUERY_SOURCE = 0x0010
TOKEN_ADJUST_PRIVILEGES = 0x0020
TOKEN_ADJUST_GROUPS = 0x0040
TOKEN_ADJUST_DEFAULT = 0x0080
TOKEN_ADJUST_SESSIONID = 0x0100
TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
TOKEN_ASSIGN_PRIMARY |
TOKEN_DUPLICATE |
TOKEN_IMPERSONATE |
TOKEN_QUERY |
TOKEN_QUERY_SOURCE |
TOKEN_ADJUST_PRIVILEGES |
TOKEN_ADJUST_GROUPS |
TOKEN_ADJUST_DEFAULT |
TOKEN_ADJUST_SESSIONID)
DUPLICATE_CLOSE_SOURCE = 0x00000001
DUPLICATE_SAME_ACCESS = 0x00000002
TOKEN_TYPE = wintypes.ULONG
TokenPrimary = 1
TokenImpersonation = 2
SECURITY_IMPERSONATION_LEVEL = wintypes.ULONG
SecurityAnonymous = 0
SecurityIdentification = 1
SecurityImpersonation = 2
SecurityDelegation = 3
class NTSTATUS(wintypes.LONG):
def to_error(self):
return ntdll.RtlNtStatusToDosError(self)
def __repr__(self):
name = self.__class__.__name__
status = wintypes.ULONG.from_buffer(self)
return '%s(%#010x)' % (name, status.value)
PNTSTATUS = ctypes.POINTER(NTSTATUS)
class BOOL(wintypes.BOOL):
def __repr__(self):
name = self.__class__.__name__
return '%s(%s)' % (name, bool(self))
class HANDLE(wintypes.HANDLE):
__slots__ = 'closed',
def __int__(self):
return self.value or 0
def Detach(self):
if not getattr(self, 'closed', False):
self.closed = True
value = int(self)
self.value = None
return value
raise ValueError("already closed")
def Close(self, CloseHandle=kernel32.CloseHandle):
if self and not getattr(self, 'closed', False):
CloseHandle(self.Detach())
__del__ = Close
def __repr__(self):
return "%s(%d)" % (self.__class__.__name__, int(self))
class LARGE_INTEGER(wintypes.LARGE_INTEGER):
# https://msdn.microsoft.com/en-us/library/ff553204
ntdll.RtlSecondsSince1970ToTime.restype = None
_unix_epoch = wintypes.LARGE_INTEGER()
ntdll.RtlSecondsSince1970ToTime(0, ctypes.byref(_unix_epoch))
_unix_epoch = _unix_epoch.value
def __int__(self):
return self.value
def __repr__(self):
name = self.__class__.__name__
return '%s(%d)' % (name, self.value)
def as_time(self):
time100ns = self.value - self._unix_epoch
if time100ns >= 0:
return time100ns / 1e7
raise ValueError('value predates the Unix epoch')
#classmethod
def from_time(cls, t):
time100ns = int(t * 10**7)
return cls(time100ns + cls._unix_epoch)
CHAR = ctypes.c_char
WCHAR = ctypes.c_wchar
PCHAR = ctypes.POINTER(CHAR)
PWCHAR = ctypes.POINTER(WCHAR)
class STRING(ctypes.Structure):
_fields_ = (('Length', wintypes.USHORT),
('MaximumLength', wintypes.USHORT),
('Buffer', PCHAR))
PSTRING = ctypes.POINTER(STRING)
class UNICODE_STRING(ctypes.Structure):
_fields_ = (('Length', wintypes.USHORT),
('MaximumLength', wintypes.USHORT),
('Buffer', PWCHAR))
PUNICODE_STRING = ctypes.POINTER(UNICODE_STRING)
class LUID(ctypes.Structure):
_fields_ = (('LowPart', wintypes.DWORD),
('HighPart', wintypes.LONG))
def __new__(cls, value=0):
return cls.from_buffer_copy(ctypes.c_ulonglong(value))
def __int__(self):
return ctypes.c_ulonglong.from_buffer(self).value
def __repr__(self):
name = self.__class__.__name__
return '%s(%#x)' % (name, int(self))
PLUID = ctypes.POINTER(LUID)
PSID = wintypes.LPVOID
class SID_AND_ATTRIBUTES(ctypes.Structure):
_fields_ = (('Sid', PSID),
('Attributes', wintypes.DWORD))
PSID_AND_ATTRIBUTES = ctypes.POINTER(SID_AND_ATTRIBUTES)
class TOKEN_GROUPS(ctypes.Structure):
_fields_ = (('GroupCount', wintypes.DWORD),
('Groups', SID_AND_ATTRIBUTES * 1))
PTOKEN_GROUPS = ctypes.POINTER(TOKEN_GROUPS)
class TOKEN_SOURCE(ctypes.Structure):
_fields_ = (('SourceName', CHAR * TOKEN_SOURCE_LENGTH),
('SourceIdentifier', LUID))
def __init__(self, SourceName=None, SourceIdentifier=None):
if SourceName is not None:
if not isinstance(SourceName, bytes):
SourceName = SourceName.encode('mbcs')
self.SourceName = SourceName
if SourceIdentifier is None:
luid = self.SourceIdentifier
ntdll.NtAllocateLocallyUniqueId(ctypes.byref(luid))
else:
self.SourceIdentifier = SourceIdentifier
PTOKEN_SOURCE = ctypes.POINTER(TOKEN_SOURCE)
py_source_context = TOKEN_SOURCE(b"PYTHON ")
py_origin_name = b"Python-%d" % os.getpid()
py_logon_process_name = b"PythonLogonProcess-%d" % os.getpid()
SIZE_T = ctypes.c_size_t
class QUOTA_LIMITS(ctypes.Structure):
_fields_ = (('PagedPoolLimit', SIZE_T),
('NonPagedPoolLimit', SIZE_T),
('MinimumWorkingSetSize', SIZE_T),
('MaximumWorkingSetSize', SIZE_T),
('PagefileLimit', SIZE_T),
('TimeLimit', wintypes.LARGE_INTEGER))
PQUOTA_LIMITS = ctypes.POINTER(QUOTA_LIMITS)
PULONG = ctypes.POINTER(wintypes.ULONG)
LSA_OPERATIONAL_MODE = wintypes.ULONG
PLSA_OPERATIONAL_MODE = PULONG
PHANDLE = ctypes.POINTER(wintypes.HANDLE)
PLPVOID = ctypes.POINTER(wintypes.LPVOID)
LPDWORD = ctypes.POINTER(wintypes.DWORD)
class ContiguousUnicode(ctypes.Structure):
# _string_names_: sequence matched to underscore-prefixed fields
def _get_unicode_string(self, name):
wchar_size = ctypes.sizeof(WCHAR)
s = getattr(self, '_%s' % name)
length = s.Length // wchar_size
buf = s.Buffer
if buf:
return buf[:length]
return None
def _set_unicode_buffer(self, value):
cls = type(self)
wchar_size = ctypes.sizeof(WCHAR)
bufsize = (len(value) + 1) * wchar_size
ctypes.resize(self, ctypes.sizeof(cls) + bufsize)
addr = ctypes.addressof(self) + ctypes.sizeof(cls)
ctypes.memmove(addr, value, bufsize)
def _set_unicode_string(self, name, value):
values = []
for n in self._string_names_:
if n == name:
values.append(value or u'')
else:
values.append(getattr(self, n) or u'')
self._set_unicode_buffer(u'\x00'.join(values))
cls = type(self)
wchar_size = ctypes.sizeof(WCHAR)
addr = ctypes.addressof(self) + ctypes.sizeof(cls)
for n, v in zip(self._string_names_, values):
ptr = ctypes.cast(addr, PWCHAR)
ustr = getattr(self, '_%s' % n)
length = ustr.Length = len(v) * wchar_size
full_length = length + wchar_size
if ((n == name and value is None) or
(n != name and not (length or ustr.Buffer))):
ustr.Buffer = None
ustr.MaximumLength = 0
else:
ustr.Buffer = ptr
ustr.MaximumLength = full_length
addr += full_length
def __getattr__(self, name):
if name not in self._string_names_:
raise AttributeError
return self._get_unicode_string(name)
def __setattr__(self, name, value):
if name in self._string_names_:
self._set_unicode_string(name, value)
else:
super(ContiguousUnicode, self).__setattr__(name, value)
#classmethod
def from_address_copy(cls, address, size=None):
x = ctypes.Structure.__new__(cls)
if size is not None:
ctypes.resize(x, size)
ctypes.memmove(ctypes.byref(x), address, ctypes.sizeof(x))
delta = ctypes.addressof(x) - address
for n in cls._string_names_:
ustr = getattr(x, '_%s' % n)
addr = ctypes.c_void_p.from_buffer(ustr.Buffer)
if addr:
addr.value += delta
return x
class AuthInfo(ContiguousUnicode):
# _message_type_: from a logon-submit-type enumeration
def __init__(self):
self.MessageType = self._message_type_
class MSV1_0_INTERACTIVE_LOGON(AuthInfo):
_message_type_ = MsV1_0InteractiveLogon
_string_names_ = 'LogonDomainName', 'UserName', 'Password'
_fields_ = (('MessageType', LOGON_SUBMIT_TYPE),
('_LogonDomainName', UNICODE_STRING),
('_UserName', UNICODE_STRING),
('_Password', UNICODE_STRING))
def __init__(self, UserName=None, Password=None, LogonDomainName=None):
super(MSV1_0_INTERACTIVE_LOGON, self).__init__()
if LogonDomainName is not None:
self.LogonDomainName = LogonDomainName
if UserName is not None:
self.UserName = UserName
if Password is not None:
self.Password = Password
class S4ULogon(AuthInfo):
_string_names_ = 'UserPrincipalName', 'DomainName'
_fields_ = (('MessageType', LOGON_SUBMIT_TYPE),
('Flags', wintypes.ULONG),
('_UserPrincipalName', UNICODE_STRING),
('_DomainName', UNICODE_STRING))
def __init__(self, UserPrincipalName=None, DomainName=None, Flags=0):
super(S4ULogon, self).__init__()
self.Flags = Flags
if UserPrincipalName is not None:
self.UserPrincipalName = UserPrincipalName
if DomainName is not None:
self.DomainName = DomainName
class MSV1_0_S4U_LOGON(S4ULogon):
_message_type_ = MsV1_0S4ULogon
class KERB_S4U_LOGON(S4ULogon):
_message_type_ = KerbS4ULogon
PMSV1_0_S4U_LOGON = ctypes.POINTER(MSV1_0_S4U_LOGON)
PKERB_S4U_LOGON = ctypes.POINTER(KERB_S4U_LOGON)
class ProfileBuffer(ContiguousUnicode):
# _message_type_
def __init__(self):
self.MessageType = self._message_type_
class MSV1_0_INTERACTIVE_PROFILE(ProfileBuffer):
_message_type_ = MsV1_0InteractiveLogon
_string_names_ = ('LogonScript', 'HomeDirectory', 'FullName',
'ProfilePath', 'HomeDirectoryDrive', 'LogonServer')
_fields_ = (('MessageType', PROFILE_BUFFER_TYPE),
('LogonCount', wintypes.USHORT),
('BadPasswordCount', wintypes.USHORT),
('LogonTime', LARGE_INTEGER),
('LogoffTime', LARGE_INTEGER),
('KickOffTime', LARGE_INTEGER),
('PasswordLastSet', LARGE_INTEGER),
('PasswordCanChange', LARGE_INTEGER),
('PasswordMustChange', LARGE_INTEGER),
('_LogonScript', UNICODE_STRING),
('_HomeDirectory', UNICODE_STRING),
('_FullName', UNICODE_STRING),
('_ProfilePath', UNICODE_STRING),
('_HomeDirectoryDrive', UNICODE_STRING),
('_LogonServer', UNICODE_STRING),
('UserFlags', wintypes.ULONG))
class SECURITY_ATTRIBUTES(ctypes.Structure):
_fields_ = (('nLength', wintypes.DWORD),
('lpSecurityDescriptor', wintypes.LPVOID),
('bInheritHandle', wintypes.BOOL))
def __init__(self, **kwds):
self.nLength = ctypes.sizeof(self)
super(SECURITY_ATTRIBUTES, self).__init__(**kwds)
LPSECURITY_ATTRIBUTES = ctypes.POINTER(SECURITY_ATTRIBUTES)
def _check_status(result, func, args):
if result.value < 0:
raise ctypes.WinError(result.to_error())
return args
def _check_bool(result, func, args):
if not result:
raise ctypes.WinError(ctypes.get_last_error())
return args
def WIN(func, restype, *argtypes):
func.restype = restype
func.argtypes = argtypes
if issubclass(restype, NTSTATUS):
func.errcheck = _check_status
elif issubclass(restype, BOOL):
func.errcheck = _check_bool
# https://msdn.microsoft.com/en-us/library/ms683179
WIN(kernel32.GetCurrentProcess, wintypes.HANDLE)
# https://msdn.microsoft.com/en-us/library/ms724251
WIN(kernel32.DuplicateHandle, BOOL,
wintypes.HANDLE, # _In_ hSourceProcessHandle
wintypes.HANDLE, # _In_ hSourceHandle
wintypes.HANDLE, # _In_ hTargetProcessHandle
PHANDLE, # _Out_ lpTargetHandle
wintypes.DWORD, # _In_ dwDesiredAccess
wintypes.BOOL, # _In_ bInheritHandle
wintypes.DWORD) # _In_ dwOptions
# https://msdn.microsoft.com/en-us/library/ms724295
WIN(kernel32.GetComputerNameW, BOOL,
wintypes.LPWSTR, # _Out_ lpBuffer
LPDWORD) # _Inout_ lpnSize
# https://msdn.microsoft.com/en-us/library/aa379295
WIN(advapi32.OpenProcessToken, BOOL,
wintypes.HANDLE, # _In_ ProcessHandle
wintypes.DWORD, # _In_ DesiredAccess
PHANDLE) # _Out_ TokenHandle
# https://msdn.microsoft.com/en-us/library/aa446617
WIN(advapi32.DuplicateTokenEx, BOOL,
wintypes.HANDLE, # _In_ hExistingToken
wintypes.DWORD, # _In_ dwDesiredAccess
LPSECURITY_ATTRIBUTES, # _In_opt_ lpTokenAttributes
SECURITY_IMPERSONATION_LEVEL, # _In_ ImpersonationLevel
TOKEN_TYPE, # _In_ TokenType
PHANDLE) # _Out_ phNewToken
# https://msdn.microsoft.com/en-us/library/ff566415
WIN(ntdll.NtAllocateLocallyUniqueId, NTSTATUS,
PLUID) # _Out_ LUID
# https://msdn.microsoft.com/en-us/library/aa378279
WIN(secur32.LsaFreeReturnBuffer, NTSTATUS,
wintypes.LPVOID,) # _In_ Buffer
# https://msdn.microsoft.com/en-us/library/aa378265
WIN(secur32.LsaConnectUntrusted, NTSTATUS,
PHANDLE,) # _Out_ LsaHandle
#https://msdn.microsoft.com/en-us/library/aa378318
WIN(secur32.LsaRegisterLogonProcess, NTSTATUS,
PSTRING, # _In_ LogonProcessName
PHANDLE, # _Out_ LsaHandle
PLSA_OPERATIONAL_MODE) # _Out_ SecurityMode
# https://msdn.microsoft.com/en-us/library/aa378269
WIN(secur32.LsaDeregisterLogonProcess, NTSTATUS,
wintypes.HANDLE) # _In_ LsaHandle
# https://msdn.microsoft.com/en-us/library/aa378297
WIN(secur32.LsaLookupAuthenticationPackage, NTSTATUS,
wintypes.HANDLE, # _In_ LsaHandle
PSTRING, # _In_ PackageName
PULONG) # _Out_ AuthenticationPackage
# https://msdn.microsoft.com/en-us/library/aa378292
WIN(secur32.LsaLogonUser, NTSTATUS,
wintypes.HANDLE, # _In_ LsaHandle
PSTRING, # _In_ OriginName
SECURITY_LOGON_TYPE, # _In_ LogonType
wintypes.ULONG, # _In_ AuthenticationPackage
wintypes.LPVOID, # _In_ AuthenticationInformation
wintypes.ULONG, # _In_ AuthenticationInformationLength
PTOKEN_GROUPS, # _In_opt_ LocalGroups
PTOKEN_SOURCE, # _In_ SourceContext
PLPVOID, # _Out_ ProfileBuffer
PULONG, # _Out_ ProfileBufferLength
PLUID, # _Out_ LogonId
PHANDLE, # _Out_ Token
PQUOTA_LIMITS, # _Out_ Quotas
PNTSTATUS) # _Out_ SubStatus
Helpers
def duplicate_token(source_token=None, access=TOKEN_ALL_ACCESS,
impersonation_level=SecurityImpersonation,
token_type=TokenPrimary, attributes=None):
close_source = False
if source_token is None:
close_source = True
source_token = HANDLE()
advapi32.OpenProcessToken(kernel32.GetCurrentProcess(),
TOKEN_ALL_ACCESS, ctypes.byref(source_token))
token = HANDLE()
try:
advapi32.DuplicateTokenEx(source_token, access, attributes,
impersonation_level, token_type, ctypes.byref(token))
finally:
if close_source:
source_token.Close()
return token
def lsa_connect_untrusted():
handle = wintypes.HANDLE()
secur32.LsaConnectUntrusted(ctypes.byref(handle))
return handle.value
def lsa_register_logon_process(logon_process_name):
if not isinstance(logon_process_name, bytes):
logon_process_name = logon_process_name.encode('mbcs')
logon_process_name = logon_process_name[:127]
buf = ctypes.create_string_buffer(logon_process_name, 128)
name = STRING(len(logon_process_name), len(buf), buf)
handle = wintypes.HANDLE()
mode = LSA_OPERATIONAL_MODE()
secur32.LsaRegisterLogonProcess(ctypes.byref(name),
ctypes.byref(handle), ctypes.byref(mode))
return handle.value
def lsa_lookup_authentication_package(lsa_handle, package_name):
if not isinstance(package_name, bytes):
package_name = package_name.encode('mbcs')
package_name = package_name[:127]
buf = ctypes.create_string_buffer(package_name)
name = STRING(len(package_name), len(buf), buf)
package = wintypes.ULONG()
secur32.LsaLookupAuthenticationPackage(lsa_handle, ctypes.byref(name),
ctypes.byref(package))
return package.value
API
# Low-level LSA logon
LOGONINFO = collections.namedtuple('LOGONINFO', ('Token', 'LogonId',
'Profile', 'Quotas'))
def lsa_logon_user(auth_info, local_groups=None, origin_name=py_origin_name,
source_context=None, auth_package=None, logon_type=None,
lsa_handle=None):
if local_groups is None:
plocal_groups = PTOKEN_GROUPS()
else:
plocal_groups = ctypes.byref(local_groups)
if source_context is None:
source_context = py_source_context
if not isinstance(origin_name, bytes):
origin_name = origin_name.encode('mbcs')
buf = ctypes.create_string_buffer(origin_name)
origin_name = STRING(len(origin_name), len(buf), buf)
if auth_package is None:
if isinstance(auth_info, MSV1_0_S4U_LOGON):
auth_package = NEGOTIATE_PACKAGE_NAME
elif isinstance(auth_info, KERB_S4U_LOGON):
auth_package = MICROSOFT_KERBEROS_NAME
else:
auth_package = MSV1_0_PACKAGE_NAME
if logon_type is None:
if isinstance(auth_info, S4ULogon):
logon_type = Batch
else:
logon_type = Interactive
profile_buffer = wintypes.LPVOID()
profile_buffer_length = wintypes.ULONG()
profile = None
logonid = LUID()
htoken = HANDLE()
quotas = QUOTA_LIMITS()
substatus = NTSTATUS()
deregister = False
if lsa_handle is None:
lsa_handle = lsa_connect_untrusted()
deregister = True
try:
if isinstance(auth_package, (str, bytes)):
auth_package = lsa_lookup_authentication_package(lsa_handle,
auth_package)
try:
secur32.LsaLogonUser(lsa_handle, ctypes.byref(origin_name),
logon_type, auth_package, ctypes.byref(auth_info),
ctypes.sizeof(auth_info), plocal_groups,
ctypes.byref(source_context), ctypes.byref(profile_buffer),
ctypes.byref(profile_buffer_length), ctypes.byref(logonid),
ctypes.byref(htoken), ctypes.byref(quotas),
ctypes.byref(substatus))
except WindowsError as e:
if substatus.value:
raise ctypes.WinError(substatus.to_error())
raise
finally:
if profile_buffer:
address = profile_buffer.value
buftype = PROFILE_BUFFER_TYPE.from_address(address).value
if buftype == MsV1_0InteractiveLogon:
profile = MSV1_0_INTERACTIVE_PROFILE.from_address_copy(
address, profile_buffer_length.value)
secur32.LsaFreeReturnBuffer(address)
finally:
if deregister:
secur32.LsaDeregisterLogonProcess(lsa_handle)
return LOGONINFO(htoken, logonid, profile, quotas)
# High-level LSA logons
def logon_msv1(name, password, domain=None, local_groups=None,
origin_name=py_origin_name, source_context=None):
return lsa_logon_user(MSV1_0_INTERACTIVE_LOGON(name, password, domain),
local_groups, origin_name, source_context)
def logon_msv1_s4u(name, local_groups=None, origin_name=py_origin_name,
source_context=None):
domain = ctypes.create_unicode_buffer(MAX_COMPUTER_NAME_LENGTH + 1)
length = wintypes.DWORD(len(domain))
kernel32.GetComputerNameW(domain, ctypes.byref(length))
return lsa_logon_user(MSV1_0_S4U_LOGON(name, domain.value),
local_groups, origin_name, source_context)
def logon_kerb_s4u(name, realm=None, local_groups=None,
origin_name=py_origin_name,
source_context=None,
logon_process_name=py_logon_process_name):
lsa_handle = lsa_register_logon_process(logon_process_name)
try:
return lsa_logon_user(KERB_S4U_LOGON(name, realm),
local_groups, origin_name, source_context,
lsa_handle=lsa_handle)
finally:
secur32.LsaDeregisterLogonProcess(lsa_handle)

Related

Multicast Network Trigger In Python Script

I'm trying to add a multicast network trigger for a camera set up. Currently I am using a conf. file called multicast-trigger.conf
[multicast-trigger]
address = 224.1.1.1
port = 600
payload = 0x05AA9544
and a python script called app_ext_multicast_trigger.py which takes the information from the conf file to send a multicast network trigger.
import sys, os, logging, json, ConfigParser, socket
sys.path.append('/home/root/ss-web')
from camconstants import *
class AppExt(object):
pkg_name = "Multicast network trigger "
pkg_version = "v1.0"
mt_config = None
# =============================================================================
# Package and URL registration logic
# =============================================================================
def __init__(self, _app, _cam, _ci, register_url_callback):
"""
Register new URLs with camera's webserver.
"""
urls = [
( '/trigger2', self.trigger2, "Sends a multicast network trigger packet to trigger all the cameras on the same local network, including trigging this camera." ),
( '/get_multicast_configuration', self.get_multicast_configuration, "Returns a JSON encoded dictionary of the camera's /etc/multicast-trigger.conf file contents." ),
]
register_url_callback(self.pkg_name, self.pkg_version, urls)
self.mt_config = self._mt_read_multicast_config_file('/etc/multicast-trigger.conf')
logging.debug("Multicast trigger URL added: %s" % repr(self.mt_config))
# =============================================================================
# Multicast trigger helper methods
# =============================================================================
def _mt_read_multicast_config_file(self, fn):
"""
Returns dictionary with multicast trigger configuration information read from file fn.
"""
if not os.path.exists(fn):
logging.error("Missing file: %s" % fn)
return None
config = {}
try:
config_parser = ConfigParser.SafeConfigParser()
config_parser.read(fn)
c = config_parser.items('multicast-trigger')
for (key, value) in c:
if key == 'address':
config[key] = value
elif key in ('port', 'payload'):
config[key] = int(value, 0)
except Exception, e:
logging.error("Bad file format: %s" % fn)
logging.error("Ignoring multicast-trigger parameters due to exception - %s" % str(e))
return None
return config
# =============================================================================
# Exposed URLs - URL matches method name
# =============================================================================
def trigger2(self):
"""
Sends a multicast network packet to trigger all cameras on the same local network.
"""
if self.mt_config == None:
logging.error("Missing file: %s" % fn)
ret = CAMAPI_STATUS_INVALID_PARAMETER
else:
try:
logging.debug("Triggering cameras by sending multicast packet: address %s port %d with payload 0x%x" % (self.mt_config['address'], self.mt_config['port'], self.mt_config['payload']))
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)
data=""
v = self.mt_config['payload']
for i in range(4):
data = chr(v & 0xFF) + data
v = v >> 8
sock.sendto(data, (self.mt_config['address'], self.mt_config['port']))
ret = CAMAPI_STATUS_OKAY
except Exception, e:
logging.error("Multi-camera trigger error due to exception - %s" % str(e))
ret = CAMAPI_STATUS_INVALID_PARAMETER
return json.dumps(ret)
def get_multicast_configuration(self):
"""
Returns a JSON encoded dictionary of the camera's /etc/multicast-trigger.conf file.
"""
logging.debug("Returning multicast trigger configuration: %s" % repr(self.mt_config))
return json.dumps(self.mt_config)
This works well and when I go to the ip address of the camera /trigger2 it will send a packet to trigger the other camera on the same network. Now I also have a different piece of equipment which will also trigger the camera via a python script called app_ext_b1 and when run from the device will trigger the camera and save to the device.
import sys, os, logging, json, time, threading, flask, glob, datetime, subprocess, math
from urllib import unquote
from camconstants import *
import tarfile
import sys, os, time, json, datetime, math
class CameraException(Exception):
def __init__(self, code, message):
self.Code = code
self.Message = message
super(CameraException, self).__init__(message)
def AsObject(self):
return { "Code" : self.Code, "Message" : self.Message }
class ExecutionContext:
def __init__(self, id, path):
self.Id = id
self.Error = None
self.path = path
if not self.path.endswith("/"):
self.path = "/" + self.path
self.Key = None
self.Logs = []
self.Results = {}
self._from = time.time()
self.add_log("Id: " + self.Id)
def get_path(self, fname):
return self.path + fname
def execute(self, key, method):
self.Key = key
self.add_log("Executing " + key)
try:
method(self)
except CameraException as camException:
self.add_log("Failed task " + key)
self._add_error(key, camException)
return False
except Exception as error:
self.add_log("Failed task " + key)
self._add_error(key, CameraException(-1, str(error)))
return False
self.add_log("Finished " + key)
return True
def _add_error(self, key, error):
self.Error = error
self.add_log("Error: " + str(error) )
def add_local(self, key, result):
if not self.Key in self.Results:
self.Results[self.Key] = {}
local_result = self.Results[self.Key]
local_result[key] = result
def add_log(self, message):
delta = str(int(1000*(time.time() - self._from))).rjust(6)
fullmsg = str(delta) + ": " + str(self.Key) + " " + message
self.Logs.append(fullmsg)
def add_state(self, save_state, camStatus):
state = {
"save_state": save_state,
"time": int(time.time() * 1000),
"camerastatus": camStatus,
}
stateStr = json.dumps(state)
self.add_log("Setting state to: " + stateStr)
progress_file = open(self.get_path(self.Id + ".state"), "w")
progress_file.write(stateStr)
progress_file.close()
def get_state(self):
try:
stateJson = open(self.get_path(self.Id + ".state"), "r").read()
self.add_log("State: " + stateJson)
state = json.loads(stateJson)
return state
except:
return None
def save_logs(self):
try:
self.Logs.append("Results:\n" + json.dumps(self.Results))
progress_file = open(self.get_path(self.Id + ".log"), "w")
progress_file.write("\n".join(self.Logs))
progress_file.close()
except:
pass
class TriggerInfo:
def __init__(self, triggerTime, releaseTime, fps):
self.TriggerTime = triggerTime
if releaseTime <=0:
releaseTime = triggerTime + releaseTime
self.ReleaseTime = releaseTime
self.Fps = fps
def getFrameForDeltaReleaseMs(self, deltaReleaseMs):
return self.convertMsToFrames(((self.ReleaseTime + float(deltaReleaseMs) / 1000.0) - self.TriggerTime)* 1000)
def convertMsToFrames(self, ms):
return int(self.Fps * float(ms)/ 1000.0)
class FrameSaver:
def __init__(self, cam, ec, params):
self.Cam = cam
self.Tar = None
self.Ec = ec
self.LastImageModified = None
self.id = params["id"]
frameTo = params["frameTo"]
curFrame = params["frameFrom"]
self.Frames = [curFrame]
interval = params["frameInterval"]
curFrame += interval
while curFrame < frameTo:
self.Frames.append(curFrame)
curFrame += interval
self.Frames.append(frameTo)
if not frameTo in self.Frames:
self.Frames.append(frameTo)
def save_frames(self):
for frameNumber in self.Frames:
self._remove_image()
self.Ec.add_log("reviewing frame")
self.Cam.review_frame(1, frameNumber)
self._save_image(frameNumber)
self.Tar.close()
def _remove_image(self):
os.system("rm /home/root/ss-web/static/images/image.jpg")
def _save_image(self, frameNumber):
self.Ec.add_log("save image to tar")
# http://10.11.12.13/static/images/image.jpg
path = "/home/root/ss-web/static/images/image.jpg"
tar = self.create_archive_if_not_exists()
start_time = time.time()
while not os.path.exists(path):
time.sleep(0.050)
if (time.time() - start_time) > 1:
raise CameraException(-1, "Fullball flight: failed to save image for framenumber " + str(frameNumber))
tar.add(path, str(frameNumber) + ".jpg")
def create_archive_if_not_exists(self):
if self.Tar == None:
self.Tar = tarfile.open("/mnt/sdcard/DCIM/" + self.id + ".Frames.tar", "w")
return self.Tar
class CameraCaptureFlow:
def __init__(self, id, camera, options):
self.Camera = camera
self.Options = options
self._state_key = "Unknown"
self.Id = id
self.Fps = 1
self.TriggerInfo = None
self.ReleaseFrame = None
self.SaveFps = None
self.StartFrame = None
self.EndFrame = None
self.PretriggerFillLevel = 100
self.ExecutionContext = ExecutionContext(id, "/mnt/sdcard/DCIM/")
self.ExecutionContext.add_log("Options:\n" + json.dumps(options))
def run(self):
# A trigger flow has already been initiated this id - return - note, it can be None if we are generating the file on top of the old one
if self.ExecutionContext.get_state() != None:
return
self._add_state("Started")
if not self._execute("Info", self.info):
return
if not self._execute("trigger", self.trigger):
self._execute("reinit", self.reinit)
return
if not self._execute("saveselected", self.save_selected):
self._execute("reinit", self.reinit)
return
if not self._execute("remaining ball flight", self.save_remaning_ballflight):
self._execute("reinit", self.reinit)
return
if not self._execute("reinit", self.reinit):
return
self._add_state("Completed")
return
def info(self, context):
self.CurrentConfig = self.Camera.get_current_settings()
self.PretriggerFillLevel = self.Camera.get_pretrigger_fill_level()
self.CamInfo = self.Camera.get_storage_info()
if not "available_space" in self.CamInfo:
raise CameraException(3, "StorageUnavaible")
if self.CamInfo["available_space"] < 50000000:
raise CameraException(4, "StorageInsufficient")
self.Fps = self.CurrentConfig["frame_rate"]
def TriggerCamera(self, context):
if hasattr(self.Camera, "trigger_hw"):
context.add_log("using hardware trigger")
return self.Camera.trigger_hw(None)
return self.Camera.trigger(None)
def wait_for_buffer_ready(self, context, releaseOffset, postCaptureMs):
delta_ms_release = int(1000*(time.time() - releaseOffset))
waitTime = postCaptureMs - delta_ms_release
context.add_log("Time since release : " + str(delta_ms_release) + "ms" )
context.add_log("Post capture time : " + str(postCaptureMs) + "ms" )
if waitTime > 0:
context.add_log("Time since release is less than required for post capture duration")
context.add_log("waiting " +str(waitTime + 100) + "ms to fill up buffers")
time.sleep((waitTime)/1000.0 + 0.1)
def trigger(self, context):
releaseOffset = self.Options["releaseOffsetTime"]
self.wait_for_buffer_ready(context, releaseOffset, self.Options["postCaptureMs"])
context.add_log("Triggering camera")
before = time.time()
triggerResult = self.TriggerCamera(context)
after = time.time()
triggerTime = (before + after) / 2
self.TriggerInfo = TriggerInfo(triggerTime, releaseOffset, self.Fps)
context.add_local("triggerTime", triggerTime)
context.add_local("relaseTime", self.TriggerInfo.ReleaseTime)
if (triggerResult != CAMAPI_STATUS_OKAY):
self._stop_if_saving()
raise CameraException(6, "TriggerFail")
context.add_log("Waiting for camera to trigger")
self.wait_for_status(lambda status: status == CAMAPI_STATE_TRIGGERED, 1)
context.add_log("Waiting for camera to finish triggering")
self.wait_for_status(lambda status: status != CAMAPI_STATE_TRIGGERED, 2)
context.add_log("Triggering finished")
def _stop_if_saving(self):
camStatus = self.Camera.get_camstatus()["state"]
if camStatus == CAMAPI_STATE_SELECTIVE_SAVING:
self.Camera.save_stop(discard_unsaved=True)
self.wait_for_status(lambda status: status == CAMAPI_STATE_REVIEWING or status == CAMAPI_STATE_RUNNING, 5)
raise CameraException(5, "TriggerFailCameraIsSaving")
def save_selected(self, context):
preCapMs = self.Options["preCaptureMs"]
postCapMs = self.Options["postCaptureMs"]
self.ReleaseFrame = self.TriggerInfo.getFrameForDeltaReleaseMs(0)
self.StartFrame = self.TriggerInfo.getFrameForDeltaReleaseMs(-preCapMs)
self.EndFrame = self.TriggerInfo.getFrameForDeltaReleaseMs(postCapMs)
context.add_log("ReleaseFrame: " + str(self.ReleaseFrame))
context.add_local("release_frame", self.ReleaseFrame)
context.add_local("start_frame", self.StartFrame)
context.add_local("end_frame", self.EndFrame)
self._validateSaveParams(context, self.StartFrame, self.EndFrame)
save_params = {}
save_params['buffer_number'] = 1
save_params['start_frame'] = self.StartFrame
save_params['end_frame'] = self.EndFrame
save_params['filename'] = str(self.Options["id"])
context.add_log("selective_save_params\n" + json.dumps(save_params))
before = time.time()
if self.Camera.selective_save(save_params) != CAMAPI_STATUS_OKAY:
raise CameraException(9, "SelectiveSaveFailed")
context.add_log("Waiting for camera to start saving")
self.wait_for_status(lambda status: status == CAMAPI_STATE_SELECTIVE_SAVING, 1)
context.add_log("Waiting for camera to finish saving")
self.wait_for_status(lambda status: status != CAMAPI_STATE_SELECTIVE_SAVING, 300)
context.add_log("Camera finished saving")
after = time.time()
self.SaveFps = math.ceil((self.EndFrame - self.StartFrame) / (after - before))
context.add_local("save_fps", self.SaveFps)
context.add_log("save fps: " + str(self.SaveFps))
def save_remaning_ballflight(self, context):
context.add_log("Checking options")
frameIntervalMs = self.Options["singleFrameCaptureIntervalMs"]
frameCaptureEndMs = self.Options["singleFrameCaptureEndMs"]
# we wish to combine the existing video with the next frames
if frameIntervalMs == None:
return
frameCaptureStartMs = self.Options["postCaptureMs"] + frameIntervalMs
frameInterval = self.TriggerInfo.convertMsToFrames(frameIntervalMs)
frameFrom = self.TriggerInfo.getFrameForDeltaReleaseMs(frameCaptureStartMs)
frameEnd = self.TriggerInfo.getFrameForDeltaReleaseMs(frameCaptureEndMs)
frameSaverParams = {
"id" : self.Id,
"frameFrom" : frameFrom,
"frameTo" : frameEnd,
"frameInterval" : frameInterval
}
frameSaver = FrameSaver(self.Camera, self.ExecutionContext, frameSaverParams)
frameSaver.save_frames()
def _validateSaveParams(self, context, startFrame, endFrame):
duration = self.CurrentConfig["duration"]
pretrigger = self.CurrentConfig["pretrigger"]
context.add_log("Pretrigger Level " + str(self.PretriggerFillLevel))
preTriggerBufferSeconds = duration * pretrigger / 100.0 * (float(self.PretriggerFillLevel) *1.0001 / 100.0)
context.add_log("preTriggerBufferSeconds " + str(preTriggerBufferSeconds))
postTriggerBuffserSeconds = duration * (1 - pretrigger / 100)
minFrame = -preTriggerBufferSeconds * self.Fps + 10
maxFrame = postTriggerBuffserSeconds * self.Fps - 10
if startFrame < minFrame:
msg = "Startframe: " + str(startFrame) + " is less than minimum frame" + str(minFrame)
context.add_log(msg)
raise CameraException(7, "OutOfBufferStartFrame")
if endFrame > maxFrame:
msg = "Endframe: " + str(endFrame) + " is larger than maximum frame" + str(maxFrame)
context.add_log(msg)
raise CameraException(8, "OutOfBufferEndFrame")
def reinit(self, context):
self.Camera.run(self.CurrentConfig)
def wait_for_status(self, predicate, timeout):
before = time.time()
lastStateUpdate = time.time()
lastState = None
while True:
status = self.Camera.get_camstatus()["state"]
deltaTime = time.time() - lastStateUpdate
if status != lastState or deltaTime > 1:
lastState = status
self._update_state(status)
lastStateUpdate = time.time()
if predicate(status):
return True
if time.time() - before > timeout:
return False
time.sleep(.333)
return False
def _update_state(self, camStatus):
self.ExecutionContext.add_state(self._state_key, camStatus)
def _add_state(self, save_state_key):
self._state_key = save_state_key
try:
camStatus = self.Camera.get_camstatus()["state"]
except:
camStatus = CAMAPI_STATE_UNCONFIGURED
self._update_state(camStatus)
def _execute(self, key, method):
success = self.ExecutionContext.execute(key, method)
if not success:
self._add_state("Failed")
return success
def save_logs(self):
self.ExecutionContext.save_logs()
class AppExt(object):
pkg_name = "B1 application extension"
pkg_version = "v1.8.1"
app = None
cam = None
ci = None
def __init__(self, _app, _cam, _ci, register_url_callback):
self.app = _app
self.cam = _cam
self.ci = _ci
urls = [
(
'/get_extension_b1_version',
self.get_version,
"returns version of B1 extension"
),
(
'/get_time_offset',
self.get_time_offset,
"Gets the camera time offset"
),
(
'/trigger_and_save',
self.trigger_and_save,
"Triggers the camera, and save the selected capture part"
),
(
'/get_trigger_and_save_progress',
self.get_trigger_and_save_progress,
"Returns the progress of the trigger and save process"
),
(
'/ensure_camera_ready',
self.ensure_camera_ready,
"Will check that the camera can save and has enough available space"
)
]
register_url_callback(self.pkg_name, self.pkg_version, urls)
def get_version(self):
return json.dumps(
{
"extensionVersion": AppExt.pkg_version
})
def get_time_offset(self):
timeOffset = time.time()
return json.dumps(
{
"timeOffset": timeOffset
})
def trigger_and_save(self):
request = {}
try:
request["id"] = str(self.get_arg('id'))
request["releaseOffsetTime"] = float(self.get_arg('releaseOffsetTime'))
request["preCaptureMs"] = self.get_int('preCaptureMs')
request["postCaptureMs"] = self.get_int('postCaptureMs')
request["singleFrameCaptureIntervalMs"] = self.get_int('singleFrameCaptureIntervalMs', True)
request["singleFrameCaptureEndMs"] = self.get_int('singleFrameCaptureEndMs', True)
captureFlow = CameraCaptureFlow(request["id"], self.cam, request)
timeStart = time.time()
captureFlow.run()
totalTime = int((time.time() - timeStart) * 1000)
ec = captureFlow.ExecutionContext
state = ec.get_state()
result = {
"id" : ec.Id,
"results" : ec.Results,
"logs" : ec.Logs,
"state" : state,
"fps" : captureFlow.Fps,
"release_frame" : captureFlow.ReleaseFrame,
"start_frame" : captureFlow.StartFrame,
"end_frame" : captureFlow.EndFrame,
"save_fps": captureFlow.SaveFps,
"trigger_offset" : captureFlow.TriggerInfo.TriggerTime,
"total_time" : totalTime
}
if ec.Error != None:
result["capture_error"] = ec.Error.AsObject()
captureFlow.save_logs()
return json.dumps(result)
except Exception as E:
request["error"] = str(E)
captureFlow.save_logs()
return json.dumps(request)
def get_arg(self, arg, isOptional = False):
req = flask.request.args
try:
val = req.get(arg)
return str(unquote(val))
except:
if isOptional:
return None
raise Exception("Could not find " + arg + " in the request")
def get_int(self, arg, isOptional = False):
try:
val = self.get_arg(arg)
return int(val)
except Exception as E:
if isOptional:
return None
raise E
def get_trigger_and_save_progress(self):
request = {}
try:
trigger_id = str(self.get_arg('id'))
exec_context = ExecutionContext(trigger_id, "/mnt/sdcard/DCIM/")
result = {}
result["id"] = trigger_id
state = None
timeBefore = time.time()
while state == None and time.time() - timeBefore < 1:
state = exec_context.get_state()
if state == None:
time.sleep(0.017)
result["state"] = state
return json.dumps(result)
except Exception as E:
request["error"] = str(E)
return json.dumps(request)
def ensure_camera_ready(self):
try:
camInfo = self.cam.get_storage_info()
if "available_space" not in camInfo:
raise CameraException(3, "StorageUnavailable")
if camInfo["available_space"] < 50000000:
raise CameraException(4, "StorageInsufficient")
self._validate_storage_writable()
except CameraException as camEx:
return json.dumps({ "Success": False, "Code": camEx.Code, "Message": camEx.Message })
except Exception as ex:
return json.dumps({ "Success": False, "Code": -1, "Message": str(ex) })
return json.dumps({ "Success": True, "Code": 0, "Message": None})
def _validate_storage_writable(self):
try:
timestamp = str(time.time())
fname = "/mnt/sdcard/DCIM/timestamp.txt"
storageFile = open(fname, "w")
storageFile.write(timestamp)
storageFile.close()
storageContent = open(fname, "r").readlines()[0]
if (storageContent != timestamp):
raise "could not write file"
except:
raise CameraException(2, "StorageReadonly")
The device is a radar unit and only allows for one camera to be synced at a given time. It reads the object it's tracking, tells the camera when to trigger and will save the file to ipad I am running the radar on. I would like to have a second camera trigger which would save the video on the second cameras interal memory. Doing this I can upload and merge with the other video file later. This would save me from manually having to trigger the second camera each time and trim the video lengths to match up. This would also allow me to connect the cameras wirelessly using travel routers. I was wondering how I could add the app_ext_multicast_trigger and multicast-trigger.conf to the app_ext_b1 python script so when the radar unit runs the app_ext_b1 python script on the camera it will also send out a multicast network packet to trigger camera two?

VTK textactor not showing

I'm using VTK to show textactor with info 'ID' added to the actors. When my mouse is over an actor, the MouseEvent will call an 'add_text' function. The function was called and printed the correct 'ID' but there's no textactor adding to the window, is there any problem with my program?
class MouseInteractorHighLightActor(vtk.vtkInteractorStyleTrackballCamera):
def __init__(self, parent=None):
self.AddObserver("MouseMoveEvent", self.MouseMove)
self.LastPickedActor = None
self.LastPickedProperty = vtk.vtkProperty()
self.new = vtkTextActor()
self.old = vtkTextActor()
self.on_actor = False
def add_text(self,renderer,ID):
self.new.SetInput(ID)
txtprop = self.new.GetTextProperty()
txtprop.SetFontSize(36)
self.new.SetDisplayPosition(0,0)
# renderer.RemoveActor(self.old)
self.old = self.new
if self.on_actor:
renderer.AddActor(self.new)
print("add_text called , ID : ",ID)
else:
pass
# renderer.RemoveActor(self.old)
# renderer.RemoveActor(self.new)
def MouseMove(self,obj,event):
Mousepos = self.GetInteractor().GetEventPosition()
picker = vtk.vtkPropPicker()
picker.Pick(Mousepos[0], Mousepos[1], 0, self.GetDefaultRenderer())
self.NewPickedActor = picker.GetActor()
if self.NewPickedActor:
if not self.on_actor:
self.on_actor = True
print("on actor")
info = self.NewPickedActor.GetProperty().GetInformation()
info = str(info)
pattern_1 = re.compile(r"ID.*\d+")
pattern_2 = re.compile(r"\d+")
string = pattern_1.findall(info)[0]
ID = pattern_2.findall(string)[0]
# print("ID : ",ID)
self.add_text(self.GetDefaultRenderer() , ID)
if self.LastPickedActor:
self.LastPickedActor.GetProperty().DeepCopy(self.LastPickedProperty)
self.LastPickedProperty.DeepCopy(self.NewPickedActor.GetProperty())
self.NewPickedActor.GetProperty().SetDiffuse(1.0)
self.NewPickedActor.GetProperty().SetSpecular(0.0)
self.LastPickedActor = self.NewPickedActor
else:
pass
else:
print("not on actor")
self.on_actor = False
Update , the problem is solved, source code :
class MouseInteractorHighLightActor(vtk.vtkInteractorStyleTrackballCamera):
def __init__(self, parent=None):
self.AddObserver("LeftButtonPressEvent", self.leftButtonPressEvent)
self.AddObserver("LeftButtonReleaseEvent", self.leftButtonReleaseEvent)
self.AddObserver("MouseMoveEvent", self.MouseMove)
self.LastPickedActor = None
self.LastPickedProperty = vtk.vtkProperty()
self.new = vtkTextActor()
self.old = vtkTextActor()
self.on_actor = False
self.picker = vtk.vtkPropPicker()
def add_text(self,renderer,ID):
self.new.SetInput(ID)
txtprop = self.new.GetTextProperty()
txtprop.SetFontSize(72)
self.new.SetDisplayPosition(0,0)
self.old = self.new
if self.on_actor:
renderer.AddActor(self.new)
# print("ID : ",ID)
def MouseMove(self,obj,event):
Mousepos = self.GetInteractor().GetEventPosition()
picker = vtk.vtkPropPicker()
picker.Pick(Mousepos[0], Mousepos[1], 0, self.GetDefaultRenderer())
self.NewPickedActor = picker.GetActor()
if self.NewPickedActor:
self.on_actor = True
# print("on actor")
info = self.NewPickedActor.GetProperty().GetInformation()
info = str(info)
pattern_1 = re.compile(r"ID.*\d+")
pattern_2 = re.compile(r"\d+")
string = pattern_1.findall(info)[0]
ID = pattern_2.findall(string)[0]
# print("ID : ",ID)
self.add_text(self.GetDefaultRenderer() , ID)
if self.LastPickedActor:
self.LastPickedActor.GetProperty().DeepCopy(self.LastPickedProperty)
self.LastPickedProperty.DeepCopy(self.NewPickedActor.GetProperty())
self.NewPickedActor.GetProperty().SetDiffuse(1.0)
self.NewPickedActor.GetProperty().SetSpecular(0.0)
self.LastPickedActor = self.NewPickedActor
self.OnLeftButtonDown()
self.OnLeftButtonUp()
else:
if self.LastPickedActor:
self.LastPickedActor.GetProperty().DeepCopy(self.LastPickedProperty)
self.on_actor = False
self.GetDefaultRenderer().RemoveActor(self.new)
self.GetDefaultRenderer().RemoveActor(self.old)
self.OnLeftButtonDown()
self.OnLeftButtonUp()
def leftButtonPressEvent(self, obj, event):
self.RemoveObservers("MouseMoveEvent")
self.OnLeftButtonDown()
def leftButtonReleaseEvent(self, obj, event):
self.AddObserver("MouseMoveEvent",self.MouseMove)
self.OnLeftButtonUp()

About python control motor program error?

I use python to write the program to control the motor, and the error is shown as follows after running:"message": "No value for argument 'speed_a' in function call pylint(no-value-for-parameter)[93,21]' Below is the code I am using:
import serial
import time
#import threading
import struct
from binascii import unhexlify
from crcmod import mkCrcFun
import binascii
import crcmod
def check_code(byte0, byte1, speed_vel, speed_ang):
'计算校验码时需要输入的字节'
read = byte0+byte1+speed_vel+speed_ang #解析校验码要输入的前几位
read=(str(binascii.b2a_hex(read))[2:-1])
print (read)
return (read)
def crc16_modbus(read):
'输出的控制电机指令字节码'
crc16 =crcmod.mkCrcFun(0x18005,rev=True,initCrc=0xFFFF,xorOut=0x0000)
data = read.replace(" ","")
#print (data)
readcrcout=hex(crc16(unhexlify(data))).upper()
str_list = list(readcrcout)
if len(str_list) < 6:
str_list.insert(2, '0'*(6-len(str_list))) # 位数不足补0
crc_data = "".join(str_list)
#print(crc_data)
read = read.strip()+crc_data[4:]+crc_data[2:4]
read = read.encode('UTF-8')
return read
def motor_speed_vel(speed_v,speed_a):
'计算小车线速度speed_v'
DEC1 = speed_v
DEC2 = speed_a
byte2 =(struct.pack("i",DEC1)[-4:-3])#线速度
byte3 =(struct.pack("i",DEC1)[-3:-2])#线速度
speed_vel = byte2 + byte3
byte4 = (struct.pack("i",DEC2)[-4:-3]) #角速度两个字节
byte5 = (struct.pack("i",DEC2)[-3:-2])
speed_ang = byte4+byte5
print (speed_vel,speed_ang)
return (speed_vel,speed_ang)
motor_speed_vel(200,20)
'''
def motor_speed_ang(speed_a):
'角速度的speed_a的byte码'
DEC2 = speed_a
byte4 = (struct.pack("i",DEC2)[-4:-3]) #角速度两个字节
byte5 = (struct.pack("i",DEC2)[-3:-2])
speed_ang = byte4+byte5
print (speed_ang)
return (speed_ang)
motor_speed_ang(20)
#motor_speed_cal(200,20) #设定的 (线速度,角速度)
'''
motor_speed_mode = b'\x01\x2F\x60\x60\x00\x03\x00\x00\x00\x0D'
#motor_status = b'\x43\x50\x00\x51\x00\x68\x95'
motor_start = b'\x01\x44\x21\x00\x31\x00\x00\x01\x00\x01\x75\x34'
motor_stop = b'\x01\x44\x21\x00\x31\x00\x00\x00\x00\x00\xE5\x34' # AB轴失能
class SpeedMotor:
def __init__(self, device,speed_v,speed_a):
# 真实速度
self.rel_speed = 0
# 设置的速度
self.set_speed1 = speed_v
# 设置角速度
self.set_speed2 = speed_a
# 运行状态
self.run = False
# 故障状态
self.fault = None
# 电机电压
self.voltage = 0
# 电机电流
self.current = 0
# 设置串口通讯
self.serial = serial.Serial(device, 115200)
self.serial.timeout = 0
# 设置为速度模式
self.serial.write(motor_speed_mode)
time.sleep(0.1)
# 设置加减速度
# self.serial.write(b'\x0A\x14\x14\x32')
# time.sleep(0.1)
def motor_speed_set(self):
'速度设置'
byte0 = b'\x01'
byte1 = b'\xEA'
speed_vel = motor_speed_vel(self.set_speed1)
speed_ang = motor_speed_vel(self.set_speed2)
read = check_code(byte0, byte1, speed_vel, speed_ang)
speed_code = read
self.serial.write(speed_code)
def motor_start(self):
self.serial.write(motor_start)
self.run = True
def motor_stop(self):
self.run = False
self.serial.write(motor_stop)
m = SpeedMotor('COM5',200,20)
m.motor_start()
#for i in range(100):
# m.set_speed = i
time.sleep(15)
m.motor_stop()`
I don't know if it is because of the problem with my parameter call, or because of the structure of the code, and I am very uncertain about the correctness of the code structure, because I am a beginner.

How to sector align data in a buffer (win32file.FILE_FLAG_NO_BUFFERING)

Consider this program:
import win32file
src_file = win32file.CreateFile(
r'C:\test.rar',
win32file.GENERIC_READ,
win32file.FILE_SHARE_READ,
None,
win32file.OPEN_EXISTING,
win32file.FILE_FLAG_NO_BUFFERING,
None
)
dst_file = win32file.CreateFile(
r'D:\test.rar',
win32file.GENERIC_WRITE,
win32file.FILE_SHARE_WRITE,
None,
win32file.CREATE_ALWAYS,
win32file.FILE_FLAG_NO_BUFFERING,
None
)
while True:
rc, data = win32file.ReadFile(src_file, 4096)
if not data:
break
else:
win32file.WriteFile(dst_file, data)
src_file.close()
dst_file.close()
When writing the latest data file fails:
pywintypes.error: (87, 'WriteFile', 'The parameter is incorrect.')
This is the behavior expected with the FILE_FLAG_NO_BUFFERING flag, but I do not know how to solve it in python.
You can use ctypes. Note that FILE_FLAG_NO_BUFFERING requires writing in sector-size multiples, so unless you want the destination file to be larger than the source file, you probably want to use a different setting for writing. I used FILE_FLAG_WRITE_THROUGH:
import ctypes
import ctypes.wintypes
import sys
src_filename = sys.argv[0]
dst_filename = sys.argv[0] + ".test.backup"
CloseHandle = ctypes.windll.kernel32.CloseHandle
CreateFile = ctypes.windll.kernel32.CreateFileA
ReadFile = ctypes.windll.kernel32.ReadFile
WriteFile = ctypes.windll.kernel32.WriteFile
FILE_SHARE_READ = 1
FILE_SHARE_WRITE = 2
FILE_FLAG_NO_BUFFERING = 0x20000000
CREATE_ALWAYS = 2
OPEN_EXISTING = 3
OPEN_ALWAYS = 4
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
INVALID_HANDLE_VALUE = ctypes.wintypes.HANDLE(-1).value
INVALID_FILE_ATTRIBUTES = 0xFFFFFFFF
FILE_FLAG_WRITE_THROUGH = 0x80000000
hSrc = CreateFile(
src_filename,
GENERIC_READ,
FILE_SHARE_READ,
None,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING,
None
)
hDest = CreateFile(
dst_filename,
GENERIC_WRITE,
FILE_SHARE_WRITE,
None,
OPEN_ALWAYS,
FILE_FLAG_WRITE_THROUGH,
None
)
def ctypes_alloc_aligned(size, alignment):
"""
http://stackoverflow.com/questions/8658813/control-memory-alignment-in-python-ctypes
"""
bufSize = size+(alignment-1)
raw_memory = bytearray(bufSize)
ctypes_raw_type = (ctypes.c_char * bufSize)
ctypes_raw_memory = ctypes_raw_type.from_buffer(raw_memory)
raw_address = ctypes.addressof(ctypes_raw_memory)
offset = raw_address % alignment
offset_to_aligned = (alignment - offset) % alignment
ctypes_aligned_type = (ctypes.c_char * (bufSize-offset_to_aligned))
ctypes_aligned_memory = ctypes_aligned_type.from_buffer(raw_memory, offset_to_aligned)
return ctypes_aligned_memory
sectorSize = 4096
bufSize = 256*sectorSize # 1MB
lpBuffer = ctypes_alloc_aligned(bufSize, sectorSize)
numBytes = ctypes.wintypes.DWORD()
while True:
bSuccess = ctypes.windll.kernel32.ReadFile(
hSrc, lpBuffer, bufSize, ctypes.byref(numBytes), None)
if not bSuccess:
print "ReadFile FAILED:", hSrc, numBytes
raise ctypes.WinError()
if numBytes.value == 0:
break
bSuccess = ctypes.windll.kernel32.WriteFile(
hDest, lpBuffer, numBytes, ctypes.byref(numBytes), None)
if not bSuccess:
print "WriteFile FAILED:", hDest, numBytes
raise ctypes.WinError()
CloseHandle(hSrc)
CloseHandle(hDest)

"WindowsError: access violation 000001" on DispatchMessageW in EventLoop

I research Python internals and write GUI Generic windows use Windows API.
# -*- coding: utf-8 -*-
import time
import threading
import logging
import uuid
import ctypes
import ctypes.wintypes
import const
INT = ctypes.wintypes.c_int
LPVOID = ctypes.wintypes.c_void_p
HCURSOR = ctypes.wintypes.HANDLE
LRESULT = ctypes.wintypes.LPARAM
COLORREF = ctypes.wintypes.DWORD
PVOID = ctypes.wintypes.c_void_p
WCHAR = ctypes.wintypes.c_wchar
BCHAR = ctypes.wintypes.c_wchar
LPRECT = ctypes.wintypes.POINTER(ctypes.wintypes.RECT)
LPPOINT = ctypes.wintypes.POINTER(ctypes.wintypes.POINT)
LPMSG = ctypes.wintypes.POINTER(ctypes.wintypes.MSG)
UINT_PTR = ctypes.wintypes.HANDLE
LONG_PTR = ctypes.wintypes.HANDLE
#WNDPROC = ctypes.wintypes.WINFUNCTYPE(ctypes.c_long, ctypes.wintypes.HWND, ctypes.wintypes.UINT, ctypes.wintypes.WPARAM, ctypes.wintypes.LPARAM)
WNDPROC = ctypes.wintypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int)
SW_SHOWNORMAL = 1
SW_SHOW = 5
CS_HREDRAW = 2
CS_VREDRAW = 1
CW_USEDEFAULT = 0x80000000
WM_DESTROY = 2
class WNDCLASSEX(ctypes.wintypes.Structure):
_fields_ = [("cbSize", ctypes.wintypes.UINT),
("style", ctypes.wintypes.UINT),
("lpfnWndProc", WNDPROC),
("cbClsExtra", ctypes.wintypes.INT),
("cbWndExtra", ctypes.wintypes.INT),
("hInstance", ctypes.wintypes.HANDLE),
("hIcon", ctypes.wintypes.HANDLE),
("hCursor", ctypes.wintypes.HANDLE),
("hBrush", ctypes.wintypes.HANDLE),
("lpszMenuName", ctypes.wintypes.LPCWSTR),
("lpszClassName", ctypes.wintypes.LPCWSTR),
("hIconSm", ctypes.wintypes.HANDLE)]
class Window(object):
def __init__(self, app, wclassName=None, wname=u"Custom Title"):
self.__app = app
#
self.__log = logging.getLogger("win_ui.window")
#
self.__hInst = app.getInstance()
self.__hWnd = None
#
if wclassName is None:
wclassName = u"NewWindowClass-{uid}".format(uid=uuid.uuid4().hex)
#
self.__wclassName = wclassName
self.__wname = wname
#
#self.__event_dispatcher = EventDispatcher(app=app)
#self.__event_dispatcher.start()
#
self.__has_exit = threading.Condition()
#
self._create()
def wnd_proc(self, hWnd, Msg, wParam, lParam):
self.__log.debug("WndProc: hWnd={hWnd!r}, Msg={Msg!r}, wParam={wParam!r}, lParam={lParam!r}".format(hWnd=hWnd, Msg=Msg, wParam=wParam, lParam=lParam))
#self.__event_dispatcher.push((hWnd, Msg, wParam, lParam))
#
result = None
#
self.__has_exit.acquire()
self.__has_exit.wait(0.1)
#
if Msg == WM_DESTROY:
self.__app.loadLibrary("user32").PostQuitMessage(0)
result = 0
#
if result is None:
result = self.__app.loadLibrary("user32").DefWindowProcW(hWnd, Msg, wParam, lParam)
#
self.__has_exit.release()
#
return result
def _create(self):
WndProc = WNDPROC(self.wnd_proc)
hBrush = self.__app.loadLibrary("gdi32").GetStockObject(const.LTGRAY_BRUSH)
print hBrush
wndClass = WNDCLASSEX()
wndClass.cbSize = ctypes.sizeof(WNDCLASSEX)
wndClass.style = CS_HREDRAW | CS_VREDRAW
wndClass.lpfnWndProc = WndProc
wndClass.cbClsExtra = 0
wndClass.cbWndExtra = 0
wndClass.hInstance = self.__hInst
wndClass.hIcon = 0 #self.__app.loadIcon()
wndClass.hCursor = 0 #self.__app.loadCursor()
wndClass.hBrush = hBrush
wndClass.lpszMenuName = None
wndClass.lpszClassName = ctypes.c_wchar_p(self.__wclassName)
wndClass.hIconSm = 0 #self.__app.loadCursor()
self.__log.debug("wndClass.cbSize = {cbSize!r}".format(cbSize=wndClass.cbSize))
self.__log.debug("wndClass.lpfnWndProc = {lpfnWndProc!r}".format(lpfnWndProc=wndClass.lpfnWndProc))
self.__log.debug("wndClass.hInstance = {hInst!r}".format(hInst=wndClass.hInstance))
self.__log.debug("wndClass.lpszClassName = {lpszClassName!r}".format(lpszClassName=wndClass.lpszClassName))
result = self.__app.loadLibrary("user32").RegisterClassExW(ctypes.byref(wndClass))
self.__log.debug("0x0{result:x} = RegisterClassExW(...)".format(result=result))
#
self.__x = CW_USEDEFAULT
self.__y = CW_USEDEFAULT
self.__width = 300
self.__height = 300
#
exStyle = 0
#exStyle = const.WS_EX_APPWINDOW
style = const.WS_OVERLAPPEDWINDOW
#style = const.WS_OVERLAPPEDWINDOW | const.WS_CAPTION | const.WS_VISIBLE
wclassName = ctypes.c_wchar_p(self.__wclassName)
wname = ctypes.c_wchar_p(self.__wname)
print wname
#
self.__app.loadLibrary("user32").CreateWindowExW.restype = ctypes.wintypes.HWND
self.__app.loadLibrary("user32").CreateWindowExW.argtypes = [ctypes.wintypes.DWORD, ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.wintypes.DWORD, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.wintypes.HWND, ctypes.wintypes.HMENU, ctypes.wintypes.HINSTANCE, ctypes.wintypes.LPVOID]
#
self.__hWnd = self.__app.loadLibrary("user32").CreateWindowExW(exStyle, wclassName, wname, style, self.__x, self.__y, self.__width, self.__height, 0, None, self.__hInst, 0)
self.__log.debug("0x0{hWnd!r} = CreateWindowExW(...)".format(hWnd=self.__hWnd))
if not self.__hWnd:
print self.__app.getLastError()
raise WindowsError("Failed to create window")
self.__log.debug("ShowWindow(hWnd=0x{hWnd:x})".format(hWnd=self.__hWnd))
result = self.__app.loadLibrary("user32").ShowWindow(self.__hWnd, SW_SHOW)
self.__log.debug('0x0{result:x} = ShowWindow(...)'.format(result=result))
self.__log.debug('UpdateWindow(hWnd=0x{hWnd:x})'.format(hWnd=self.__hWnd))
result = self.__app.loadLibrary("user32").UpdateWindow(self.__hWnd)
self.__log.debug('0x0{result:x} = UpdateWindow(...)'.format(result=result))
GUI generic window create but cause exception "WidnowsError: access violation 000001" on DispatchMessageW in EventLoop.
# -*- coding: utf-8 -*-
import logging
import uuid
import ctypes
import ctypes.wintypes
import const
class Application(object):
def __init__(self):
self.__log = logging.getLogger("win_ui.application")
self.__libs = {}
#
self._event_thread = self.loadLibrary("kernel32").GetCurrentThreadId()
def loadLibrary(self, name):
if name in self.__libs:
result = self.__libs[name]
else:
module = getattr(ctypes.windll, name)
result = self.__libs[name] = module
return result
def getInstance(self, hModule=None):
self.__log.debug('GetModuleHandleW(hModule={hModule!r})'.format(hModule=hModule))
result = self.loadLibrary("kernel32").GetModuleHandleW(None)
self.__log.debug('0x0{result:x} = GetModuleHandleW(...)'.format(result=result))
return result
def loadIcon(self, iconName=None):
if iconName is None:
iconName = const.IDI_APPLICATION
hInst = self.getInstance()
result = self.loadLibrary("user32").LoadIconW(hInst, iconName)
return result
def loadCursor(self, v=None):
if v is None:
v = const.IDI_APPLICATION
hInst = self.getInstance()
result = self.loadLibrary("user32").LoadCursorW(hInst, v)
return result
def getLastError(self):
self.__log.debug('GetLastError()')
result = self.loadLibrary("kernel32").GetLastError()
#print result
#rs = self.loadLibrary("kernel32").FormatMessageW(result)
#print rs
self.__log.debug('0x0{result:x} = GetLastError()'.format(result=result))
return result
def check(self):
if self._event_thread != self.loadLibrary("kernel32").GetCurrentThreadId():
raise RuntimeError("Thread?")
def run(self):
self.check()
msg = ctypes.wintypes.MSG()
lpmsg = ctypes.pointer(msg)
self.__log.debug('Entering message loop')
#
user32 = self.loadLibrary("user32")
while user32.GetMessageW(lpmsg, 0, 0, 0) != 0:
#while self.loadLibrary("user32").PeekMessageW(ctypes.byref(msg), 0, 0, 0, const.PM_REMOVE):
user32.TranslateMessage(lpmsg)
print lpmsg
user32.DispatchMessageW(lpmsg)
#
self.__log.debug('done.')
When I refactoring and calls RegisterWindowEx and CreateWindowEx on separate Python method CreateWindowEx start return 0x0 and GetLastError retrun 0x0. What problem there?

Categories

Resources