Uploaded Test files
This commit is contained in:
parent
f584ad9d97
commit
2e81cb7d99
16627 changed files with 2065359 additions and 102444 deletions
102
venv/Lib/site-packages/win32comext/adsi/__init__.py
Normal file
102
venv/Lib/site-packages/win32comext/adsi/__init__.py
Normal file
|
@ -0,0 +1,102 @@
|
|||
import win32com
|
||||
import win32com.client
|
||||
|
||||
if type(__path__)==type(''):
|
||||
# For freeze to work!
|
||||
import sys
|
||||
try:
|
||||
from . import adsi
|
||||
sys.modules['win32com.adsi.adsi'] = adsi
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
# See if we have a special directory for the binaries (for developers)
|
||||
win32com.__PackageSupportBuildPath__(__path__)
|
||||
|
||||
|
||||
# Some helpers
|
||||
# We want to _look_ like the ADSI module, but provide some additional
|
||||
# helpers.
|
||||
|
||||
# Of specific note - most of the interfaces supported by ADSI
|
||||
# derive from IDispatch - thus, you get the custome methods from the
|
||||
# interface, as well as via IDispatch.
|
||||
import pythoncom
|
||||
from .adsi import *
|
||||
|
||||
LCID = 0
|
||||
|
||||
IDispatchType = pythoncom.TypeIIDs[pythoncom.IID_IDispatch]
|
||||
IADsContainerType = pythoncom.TypeIIDs[adsi.IID_IADsContainer]
|
||||
|
||||
def _get_good_ret(ob,
|
||||
# Named arguments used internally
|
||||
resultCLSID = None):
|
||||
assert resultCLSID is None, "Now have type info for ADSI objects - fix me!"
|
||||
# See if the object supports IDispatch
|
||||
if hasattr(ob, "Invoke"):
|
||||
import win32com.client.dynamic
|
||||
name = "Dispatch wrapper around %r" % ob
|
||||
return win32com.client.dynamic.Dispatch(ob, name, ADSIDispatch)
|
||||
return ob
|
||||
|
||||
|
||||
class ADSIEnumerator:
|
||||
def __init__(self, ob):
|
||||
# Query the object for the container interface.
|
||||
self._cont_ = ob.QueryInterface(IID_IADsContainer)
|
||||
self._oleobj_ = ADsBuildEnumerator(self._cont_) # a PyIADsEnumVARIANT
|
||||
self.index = -1
|
||||
def __getitem__(self, index):
|
||||
return self.__GetIndex(index)
|
||||
def __call__(self, index):
|
||||
return self.__GetIndex(index)
|
||||
def __GetIndex(self, index):
|
||||
if type(index)!=type(0): raise TypeError("Only integer indexes are supported for enumerators")
|
||||
if index != self.index + 1:
|
||||
# Index requested out of sequence.
|
||||
raise ValueError("You must index this object sequentially")
|
||||
self.index = index
|
||||
result = ADsEnumerateNext(self._oleobj_, 1)
|
||||
if len(result):
|
||||
return _get_good_ret(result[0])
|
||||
# Failed - reset for next time around.
|
||||
self.index = -1
|
||||
self._oleobj_ = ADsBuildEnumerator(self._cont_) # a PyIADsEnumVARIANT
|
||||
raise IndexError("list index out of range")
|
||||
|
||||
class ADSIDispatch(win32com.client.CDispatch):
|
||||
def _wrap_dispatch_(self, ob, userName = None, returnCLSID = None, UnicodeToString=None):
|
||||
assert UnicodeToString is None, "this is deprectated and will be removed"
|
||||
if not userName:
|
||||
userName = "ADSI-object"
|
||||
olerepr = win32com.client.dynamic.MakeOleRepr(ob, None, None)
|
||||
return ADSIDispatch(ob, olerepr, userName)
|
||||
|
||||
def _NewEnum(self):
|
||||
try:
|
||||
return ADSIEnumerator(self)
|
||||
except pythoncom.com_error:
|
||||
# doesnt support it - let our base try!
|
||||
return win32com.client.CDispatch._NewEnum(self)
|
||||
|
||||
def __getattr__(self, attr):
|
||||
try:
|
||||
return getattr(self._oleobj_, attr)
|
||||
except AttributeError:
|
||||
return win32com.client.CDispatch.__getattr__(self, attr)
|
||||
|
||||
def QueryInterface(self, iid):
|
||||
ret = self._oleobj_.QueryInterface(iid)
|
||||
return _get_good_ret(ret)
|
||||
|
||||
# We override the global methods to do the right thing.
|
||||
_ADsGetObject = ADsGetObject # The one in the .pyd
|
||||
def ADsGetObject(path, iid = pythoncom.IID_IDispatch):
|
||||
ret = _ADsGetObject(path, iid)
|
||||
return _get_good_ret(ret)
|
||||
|
||||
_ADsOpenObject = ADsOpenObject
|
||||
def ADsOpenObject(path, username, password, reserved = 0, iid = pythoncom.IID_IDispatch):
|
||||
ret = _ADsOpenObject(path, username, password, reserved, iid)
|
||||
return _get_good_ret(ret)
|
Binary file not shown.
Binary file not shown.
BIN
venv/Lib/site-packages/win32comext/adsi/adsi.pyd
Normal file
BIN
venv/Lib/site-packages/win32comext/adsi/adsi.pyd
Normal file
Binary file not shown.
336
venv/Lib/site-packages/win32comext/adsi/adsicon.py
Normal file
336
venv/Lib/site-packages/win32comext/adsi/adsicon.py
Normal file
|
@ -0,0 +1,336 @@
|
|||
ADS_ATTR_CLEAR = ( 1 )
|
||||
ADS_ATTR_UPDATE = ( 2 )
|
||||
ADS_ATTR_APPEND = ( 3 )
|
||||
ADS_ATTR_DELETE = ( 4 )
|
||||
ADS_EXT_MINEXTDISPID = ( 1 )
|
||||
ADS_EXT_MAXEXTDISPID = ( 16777215 )
|
||||
ADS_EXT_INITCREDENTIALS = ( 1 )
|
||||
ADS_EXT_INITIALIZE_COMPLETE = ( 2 )
|
||||
|
||||
ADS_SEARCHPREF_ASYNCHRONOUS = 0
|
||||
ADS_SEARCHPREF_DEREF_ALIASES = 1
|
||||
ADS_SEARCHPREF_SIZE_LIMIT = 2
|
||||
ADS_SEARCHPREF_TIME_LIMIT = 3
|
||||
ADS_SEARCHPREF_ATTRIBTYPES_ONLY = 4
|
||||
ADS_SEARCHPREF_SEARCH_SCOPE = 5
|
||||
ADS_SEARCHPREF_TIMEOUT = 6
|
||||
ADS_SEARCHPREF_PAGESIZE = 7
|
||||
ADS_SEARCHPREF_PAGED_TIME_LIMIT = 8
|
||||
ADS_SEARCHPREF_CHASE_REFERRALS = 9
|
||||
ADS_SEARCHPREF_SORT_ON = 10
|
||||
ADS_SEARCHPREF_CACHE_RESULTS = 11
|
||||
ADS_SEARCHPREF_DIRSYNC = 12
|
||||
ADS_SEARCHPREF_TOMBSTONE = 13
|
||||
|
||||
ADS_SCOPE_BASE = 0
|
||||
ADS_SCOPE_ONELEVEL = 1
|
||||
ADS_SCOPE_SUBTREE = 2
|
||||
|
||||
ADS_SECURE_AUTHENTICATION = 0x1
|
||||
ADS_USE_ENCRYPTION = 0x2
|
||||
ADS_USE_SSL = 0x2
|
||||
ADS_READONLY_SERVER = 0x4
|
||||
ADS_PROMPT_CREDENTIALS = 0x8
|
||||
ADS_NO_AUTHENTICATION = 0x10
|
||||
ADS_FAST_BIND = 0x20
|
||||
ADS_USE_SIGNING = 0x40
|
||||
ADS_USE_SEALING = 0x80
|
||||
ADS_USE_DELEGATION = 0x100
|
||||
ADS_SERVER_BIND = 0x200
|
||||
|
||||
ADSTYPE_INVALID = 0
|
||||
ADSTYPE_DN_STRING = ADSTYPE_INVALID + 1
|
||||
ADSTYPE_CASE_EXACT_STRING = ADSTYPE_DN_STRING + 1
|
||||
ADSTYPE_CASE_IGNORE_STRING = ADSTYPE_CASE_EXACT_STRING + 1
|
||||
ADSTYPE_PRINTABLE_STRING = ADSTYPE_CASE_IGNORE_STRING + 1
|
||||
ADSTYPE_NUMERIC_STRING = ADSTYPE_PRINTABLE_STRING + 1
|
||||
ADSTYPE_BOOLEAN = ADSTYPE_NUMERIC_STRING + 1
|
||||
ADSTYPE_INTEGER = ADSTYPE_BOOLEAN + 1
|
||||
ADSTYPE_OCTET_STRING = ADSTYPE_INTEGER + 1
|
||||
ADSTYPE_UTC_TIME = ADSTYPE_OCTET_STRING + 1
|
||||
ADSTYPE_LARGE_INTEGER = ADSTYPE_UTC_TIME + 1
|
||||
ADSTYPE_PROV_SPECIFIC = ADSTYPE_LARGE_INTEGER + 1
|
||||
ADSTYPE_OBJECT_CLASS = ADSTYPE_PROV_SPECIFIC + 1
|
||||
ADSTYPE_CASEIGNORE_LIST = ADSTYPE_OBJECT_CLASS + 1
|
||||
ADSTYPE_OCTET_LIST = ADSTYPE_CASEIGNORE_LIST + 1
|
||||
ADSTYPE_PATH = ADSTYPE_OCTET_LIST + 1
|
||||
ADSTYPE_POSTALADDRESS = ADSTYPE_PATH + 1
|
||||
ADSTYPE_TIMESTAMP = ADSTYPE_POSTALADDRESS + 1
|
||||
ADSTYPE_BACKLINK = ADSTYPE_TIMESTAMP + 1
|
||||
ADSTYPE_TYPEDNAME = ADSTYPE_BACKLINK + 1
|
||||
ADSTYPE_HOLD = ADSTYPE_TYPEDNAME + 1
|
||||
ADSTYPE_NETADDRESS = ADSTYPE_HOLD + 1
|
||||
ADSTYPE_REPLICAPOINTER = ADSTYPE_NETADDRESS + 1
|
||||
ADSTYPE_FAXNUMBER = ADSTYPE_REPLICAPOINTER + 1
|
||||
ADSTYPE_EMAIL = ADSTYPE_FAXNUMBER + 1
|
||||
ADSTYPE_NT_SECURITY_DESCRIPTOR = ADSTYPE_EMAIL + 1
|
||||
ADSTYPE_UNKNOWN = ADSTYPE_NT_SECURITY_DESCRIPTOR + 1
|
||||
ADSTYPE_DN_WITH_BINARY = ADSTYPE_UNKNOWN + 1
|
||||
ADSTYPE_DN_WITH_STRING = ADSTYPE_DN_WITH_BINARY + 1
|
||||
|
||||
ADS_PROPERTY_CLEAR = 1
|
||||
ADS_PROPERTY_UPDATE = 2
|
||||
ADS_PROPERTY_APPEND = 3
|
||||
ADS_PROPERTY_DELETE = 4
|
||||
ADS_SYSTEMFLAG_DISALLOW_DELETE = -2147483648
|
||||
ADS_SYSTEMFLAG_CONFIG_ALLOW_RENAME = 0x40000000
|
||||
ADS_SYSTEMFLAG_CONFIG_ALLOW_MOVE = 0x20000000
|
||||
ADS_SYSTEMFLAG_CONFIG_ALLOW_LIMITED_MOVE = 0x10000000
|
||||
ADS_SYSTEMFLAG_DOMAIN_DISALLOW_RENAME = -2147483648
|
||||
ADS_SYSTEMFLAG_DOMAIN_DISALLOW_MOVE = 0x4000000
|
||||
ADS_SYSTEMFLAG_CR_NTDS_NC = 0x1
|
||||
ADS_SYSTEMFLAG_CR_NTDS_DOMAIN = 0x2
|
||||
ADS_SYSTEMFLAG_ATTR_NOT_REPLICATED = 0x1
|
||||
ADS_SYSTEMFLAG_ATTR_IS_CONSTRUCTED = 0x4
|
||||
ADS_GROUP_TYPE_GLOBAL_GROUP = 0x2
|
||||
ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP = 0x4
|
||||
ADS_GROUP_TYPE_LOCAL_GROUP = 0x4
|
||||
ADS_GROUP_TYPE_UNIVERSAL_GROUP = 0x8
|
||||
ADS_GROUP_TYPE_SECURITY_ENABLED = -2147483648
|
||||
ADS_UF_SCRIPT = 0x1
|
||||
ADS_UF_ACCOUNTDISABLE = 0x2
|
||||
ADS_UF_HOMEDIR_REQUIRED = 0x8
|
||||
ADS_UF_LOCKOUT = 0x10
|
||||
ADS_UF_PASSWD_NOTREQD = 0x20
|
||||
ADS_UF_PASSWD_CANT_CHANGE = 0x40
|
||||
ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED = 0x80
|
||||
ADS_UF_TEMP_DUPLICATE_ACCOUNT = 0x100
|
||||
ADS_UF_NORMAL_ACCOUNT = 0x200
|
||||
ADS_UF_INTERDOMAIN_TRUST_ACCOUNT = 0x800
|
||||
ADS_UF_WORKSTATION_TRUST_ACCOUNT = 0x1000
|
||||
ADS_UF_SERVER_TRUST_ACCOUNT = 0x2000
|
||||
ADS_UF_DONT_EXPIRE_PASSWD = 0x10000
|
||||
ADS_UF_MNS_LOGON_ACCOUNT = 0x20000
|
||||
ADS_UF_SMARTCARD_REQUIRED = 0x40000
|
||||
ADS_UF_TRUSTED_FOR_DELEGATION = 0x80000
|
||||
ADS_UF_NOT_DELEGATED = 0x100000
|
||||
ADS_UF_USE_DES_KEY_ONLY = 0x200000
|
||||
ADS_UF_DONT_REQUIRE_PREAUTH = 0x400000
|
||||
ADS_UF_PASSWORD_EXPIRED = 0x800000
|
||||
ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0x1000000
|
||||
ADS_RIGHT_DELETE = 0x10000
|
||||
ADS_RIGHT_READ_CONTROL = 0x20000
|
||||
ADS_RIGHT_WRITE_DAC = 0x40000
|
||||
ADS_RIGHT_WRITE_OWNER = 0x80000
|
||||
ADS_RIGHT_SYNCHRONIZE = 0x100000
|
||||
ADS_RIGHT_ACCESS_SYSTEM_SECURITY = 0x1000000
|
||||
ADS_RIGHT_GENERIC_READ = -2147483648
|
||||
ADS_RIGHT_GENERIC_WRITE = 0x40000000
|
||||
ADS_RIGHT_GENERIC_EXECUTE = 0x20000000
|
||||
ADS_RIGHT_GENERIC_ALL = 0x10000000
|
||||
ADS_RIGHT_DS_CREATE_CHILD = 0x1
|
||||
ADS_RIGHT_DS_DELETE_CHILD = 0x2
|
||||
ADS_RIGHT_ACTRL_DS_LIST = 0x4
|
||||
ADS_RIGHT_DS_SELF = 0x8
|
||||
ADS_RIGHT_DS_READ_PROP = 0x10
|
||||
ADS_RIGHT_DS_WRITE_PROP = 0x20
|
||||
ADS_RIGHT_DS_DELETE_TREE = 0x40
|
||||
ADS_RIGHT_DS_LIST_OBJECT = 0x80
|
||||
ADS_RIGHT_DS_CONTROL_ACCESS = 0x100
|
||||
ADS_ACETYPE_ACCESS_ALLOWED = 0
|
||||
ADS_ACETYPE_ACCESS_DENIED = 0x1
|
||||
ADS_ACETYPE_SYSTEM_AUDIT = 0x2
|
||||
ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = 0x5
|
||||
ADS_ACETYPE_ACCESS_DENIED_OBJECT = 0x6
|
||||
ADS_ACETYPE_SYSTEM_AUDIT_OBJECT = 0x7
|
||||
ADS_ACETYPE_SYSTEM_ALARM_OBJECT = 0x8
|
||||
ADS_ACETYPE_ACCESS_ALLOWED_CALLBACK = 0x9
|
||||
ADS_ACETYPE_ACCESS_DENIED_CALLBACK = 0xa
|
||||
ADS_ACETYPE_ACCESS_ALLOWED_CALLBACK_OBJECT = 0xb
|
||||
ADS_ACETYPE_ACCESS_DENIED_CALLBACK_OBJECT = 0xc
|
||||
ADS_ACETYPE_SYSTEM_AUDIT_CALLBACK = 0xd
|
||||
ADS_ACETYPE_SYSTEM_ALARM_CALLBACK = 0xe
|
||||
ADS_ACETYPE_SYSTEM_AUDIT_CALLBACK_OBJECT = 0xf
|
||||
ADS_ACETYPE_SYSTEM_ALARM_CALLBACK_OBJECT = 0x10
|
||||
ADS_ACEFLAG_INHERIT_ACE = 0x2
|
||||
ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE = 0x4
|
||||
ADS_ACEFLAG_INHERIT_ONLY_ACE = 0x8
|
||||
ADS_ACEFLAG_INHERITED_ACE = 0x10
|
||||
ADS_ACEFLAG_VALID_INHERIT_FLAGS = 0x1f
|
||||
ADS_ACEFLAG_SUCCESSFUL_ACCESS = 0x40
|
||||
ADS_ACEFLAG_FAILED_ACCESS = 0x80
|
||||
ADS_FLAG_OBJECT_TYPE_PRESENT = 0x1
|
||||
ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT = 0x2
|
||||
ADS_SD_CONTROL_SE_OWNER_DEFAULTED = 0x1
|
||||
ADS_SD_CONTROL_SE_GROUP_DEFAULTED = 0x2
|
||||
ADS_SD_CONTROL_SE_DACL_PRESENT = 0x4
|
||||
ADS_SD_CONTROL_SE_DACL_DEFAULTED = 0x8
|
||||
ADS_SD_CONTROL_SE_SACL_PRESENT = 0x10
|
||||
ADS_SD_CONTROL_SE_SACL_DEFAULTED = 0x20
|
||||
ADS_SD_CONTROL_SE_DACL_AUTO_INHERIT_REQ = 0x100
|
||||
ADS_SD_CONTROL_SE_SACL_AUTO_INHERIT_REQ = 0x200
|
||||
ADS_SD_CONTROL_SE_DACL_AUTO_INHERITED = 0x400
|
||||
ADS_SD_CONTROL_SE_SACL_AUTO_INHERITED = 0x800
|
||||
ADS_SD_CONTROL_SE_DACL_PROTECTED = 0x1000
|
||||
ADS_SD_CONTROL_SE_SACL_PROTECTED = 0x2000
|
||||
ADS_SD_CONTROL_SE_SELF_RELATIVE = 0x8000
|
||||
ADS_SD_REVISION_DS = 4
|
||||
ADS_NAME_TYPE_1779 = 1
|
||||
ADS_NAME_TYPE_CANONICAL = 2
|
||||
ADS_NAME_TYPE_NT4 = 3
|
||||
ADS_NAME_TYPE_DISPLAY = 4
|
||||
ADS_NAME_TYPE_DOMAIN_SIMPLE = 5
|
||||
ADS_NAME_TYPE_ENTERPRISE_SIMPLE = 6
|
||||
ADS_NAME_TYPE_GUID = 7
|
||||
ADS_NAME_TYPE_UNKNOWN = 8
|
||||
ADS_NAME_TYPE_USER_PRINCIPAL_NAME = 9
|
||||
ADS_NAME_TYPE_CANONICAL_EX = 10
|
||||
ADS_NAME_TYPE_SERVICE_PRINCIPAL_NAME = 11
|
||||
ADS_NAME_TYPE_SID_OR_SID_HISTORY_NAME = 12
|
||||
ADS_NAME_INITTYPE_DOMAIN = 1
|
||||
ADS_NAME_INITTYPE_SERVER = 2
|
||||
ADS_NAME_INITTYPE_GC = 3
|
||||
ADS_OPTION_SERVERNAME = 0
|
||||
ADS_OPTION_REFERRALS = ADS_OPTION_SERVERNAME + 1
|
||||
ADS_OPTION_PAGE_SIZE = ADS_OPTION_REFERRALS + 1
|
||||
ADS_OPTION_SECURITY_MASK = ADS_OPTION_PAGE_SIZE + 1
|
||||
ADS_OPTION_MUTUAL_AUTH_STATUS = ADS_OPTION_SECURITY_MASK + 1
|
||||
ADS_OPTION_QUOTA = ADS_OPTION_MUTUAL_AUTH_STATUS + 1
|
||||
ADS_OPTION_PASSWORD_PORTNUMBER = ADS_OPTION_QUOTA + 1
|
||||
ADS_OPTION_PASSWORD_METHOD = ADS_OPTION_PASSWORD_PORTNUMBER + 1
|
||||
ADS_SECURITY_INFO_OWNER = 0x1
|
||||
ADS_SECURITY_INFO_GROUP = 0x2
|
||||
ADS_SECURITY_INFO_DACL = 0x4
|
||||
ADS_SECURITY_INFO_SACL = 0x8
|
||||
ADS_SETTYPE_FULL = 1
|
||||
ADS_SETTYPE_PROVIDER = 2
|
||||
ADS_SETTYPE_SERVER = 3
|
||||
ADS_SETTYPE_DN = 4
|
||||
ADS_FORMAT_WINDOWS = 1
|
||||
ADS_FORMAT_WINDOWS_NO_SERVER = 2
|
||||
ADS_FORMAT_WINDOWS_DN = 3
|
||||
ADS_FORMAT_WINDOWS_PARENT = 4
|
||||
ADS_FORMAT_X500 = 5
|
||||
ADS_FORMAT_X500_NO_SERVER = 6
|
||||
ADS_FORMAT_X500_DN = 7
|
||||
ADS_FORMAT_X500_PARENT = 8
|
||||
ADS_FORMAT_SERVER = 9
|
||||
ADS_FORMAT_PROVIDER = 10
|
||||
ADS_FORMAT_LEAF = 11
|
||||
ADS_DISPLAY_FULL = 1
|
||||
ADS_DISPLAY_VALUE_ONLY = 2
|
||||
ADS_ESCAPEDMODE_DEFAULT = 1
|
||||
ADS_ESCAPEDMODE_ON = 2
|
||||
ADS_ESCAPEDMODE_OFF = 3
|
||||
ADS_ESCAPEDMODE_OFF_EX = 4
|
||||
ADS_PATH_FILE = 1
|
||||
ADS_PATH_FILESHARE = 2
|
||||
ADS_PATH_REGISTRY = 3
|
||||
ADS_SD_FORMAT_IID = 1
|
||||
ADS_SD_FORMAT_RAW = 2
|
||||
ADS_SD_FORMAT_HEXSTRING = 3
|
||||
|
||||
|
||||
# Generated by h2py from AdsErr.h
|
||||
def _HRESULT_TYPEDEF_(_sc): return _sc
|
||||
|
||||
E_ADS_BAD_PATHNAME = _HRESULT_TYPEDEF_((-2147463168))
|
||||
E_ADS_INVALID_DOMAIN_OBJECT = _HRESULT_TYPEDEF_((-2147463167))
|
||||
E_ADS_INVALID_USER_OBJECT = _HRESULT_TYPEDEF_((-2147463166))
|
||||
E_ADS_INVALID_COMPUTER_OBJECT = _HRESULT_TYPEDEF_((-2147463165))
|
||||
E_ADS_UNKNOWN_OBJECT = _HRESULT_TYPEDEF_((-2147463164))
|
||||
E_ADS_PROPERTY_NOT_SET = _HRESULT_TYPEDEF_((-2147463163))
|
||||
E_ADS_PROPERTY_NOT_SUPPORTED = _HRESULT_TYPEDEF_((-2147463162))
|
||||
E_ADS_PROPERTY_INVALID = _HRESULT_TYPEDEF_((-2147463161))
|
||||
E_ADS_BAD_PARAMETER = _HRESULT_TYPEDEF_((-2147463160))
|
||||
E_ADS_OBJECT_UNBOUND = _HRESULT_TYPEDEF_((-2147463159))
|
||||
E_ADS_PROPERTY_NOT_MODIFIED = _HRESULT_TYPEDEF_((-2147463158))
|
||||
E_ADS_PROPERTY_MODIFIED = _HRESULT_TYPEDEF_((-2147463157))
|
||||
E_ADS_CANT_CONVERT_DATATYPE = _HRESULT_TYPEDEF_((-2147463156))
|
||||
E_ADS_PROPERTY_NOT_FOUND = _HRESULT_TYPEDEF_((-2147463155))
|
||||
E_ADS_OBJECT_EXISTS = _HRESULT_TYPEDEF_((-2147463154))
|
||||
E_ADS_SCHEMA_VIOLATION = _HRESULT_TYPEDEF_((-2147463153))
|
||||
E_ADS_COLUMN_NOT_SET = _HRESULT_TYPEDEF_((-2147463152))
|
||||
S_ADS_ERRORSOCCURRED = _HRESULT_TYPEDEF_(0x00005011)
|
||||
S_ADS_NOMORE_ROWS = _HRESULT_TYPEDEF_(0x00005012)
|
||||
S_ADS_NOMORE_COLUMNS = _HRESULT_TYPEDEF_(0x00005013)
|
||||
E_ADS_INVALID_FILTER = _HRESULT_TYPEDEF_((-2147463148))
|
||||
|
||||
# ADS_DEREFENUM enum
|
||||
ADS_DEREF_NEVER = 0
|
||||
ADS_DEREF_SEARCHING = 1
|
||||
ADS_DEREF_FINDING = 2
|
||||
ADS_DEREF_ALWAYS = 3
|
||||
|
||||
# ADS_PREFERENCES_ENUM
|
||||
ADSIPROP_ASYNCHRONOUS = 0
|
||||
ADSIPROP_DEREF_ALIASES = 0x1
|
||||
ADSIPROP_SIZE_LIMIT = 0x2
|
||||
ADSIPROP_TIME_LIMIT = 0x3
|
||||
ADSIPROP_ATTRIBTYPES_ONLY = 0x4
|
||||
ADSIPROP_SEARCH_SCOPE = 0x5
|
||||
ADSIPROP_TIMEOUT = 0x6
|
||||
ADSIPROP_PAGESIZE = 0x7
|
||||
ADSIPROP_PAGED_TIME_LIMIT = 0x8
|
||||
ADSIPROP_CHASE_REFERRALS = 0x9
|
||||
ADSIPROP_SORT_ON = 0xa
|
||||
ADSIPROP_CACHE_RESULTS = 0xb
|
||||
ADSIPROP_ADSIFLAG = 0xc
|
||||
|
||||
# ADSI_DIALECT_ENUM
|
||||
ADSI_DIALECT_LDAP = 0
|
||||
ADSI_DIALECT_SQL = 0x1
|
||||
|
||||
# ADS_CHASE_REFERRALS_ENUM
|
||||
ADS_CHASE_REFERRALS_NEVER = 0
|
||||
ADS_CHASE_REFERRALS_SUBORDINATE = 0x20
|
||||
ADS_CHASE_REFERRALS_EXTERNAL = 0x40
|
||||
ADS_CHASE_REFERRALS_ALWAYS = ADS_CHASE_REFERRALS_SUBORDINATE | ADS_CHASE_REFERRALS_EXTERNAL
|
||||
|
||||
# Generated by h2py from ObjSel.h
|
||||
DSOP_SCOPE_TYPE_TARGET_COMPUTER = 0x00000001
|
||||
DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN = 0x00000002
|
||||
DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN = 0x00000004
|
||||
DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN = 0x00000008
|
||||
DSOP_SCOPE_TYPE_GLOBAL_CATALOG = 0x00000010
|
||||
DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN = 0x00000020
|
||||
DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN = 0x00000040
|
||||
DSOP_SCOPE_TYPE_WORKGROUP = 0x00000080
|
||||
DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE = 0x00000100
|
||||
DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE = 0x00000200
|
||||
DSOP_SCOPE_FLAG_STARTING_SCOPE = 0x00000001
|
||||
DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT = 0x00000002
|
||||
DSOP_SCOPE_FLAG_WANT_PROVIDER_LDAP = 0x00000004
|
||||
DSOP_SCOPE_FLAG_WANT_PROVIDER_GC = 0x00000008
|
||||
DSOP_SCOPE_FLAG_WANT_SID_PATH = 0x00000010
|
||||
DSOP_SCOPE_FLAG_WANT_DOWNLEVEL_BUILTIN_PATH = 0x00000020
|
||||
DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS = 0x00000040
|
||||
DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS = 0x00000080
|
||||
DSOP_SCOPE_FLAG_DEFAULT_FILTER_COMPUTERS = 0x00000100
|
||||
DSOP_SCOPE_FLAG_DEFAULT_FILTER_CONTACTS = 0x00000200
|
||||
DSOP_FILTER_INCLUDE_ADVANCED_VIEW = 0x00000001
|
||||
DSOP_FILTER_USERS = 0x00000002
|
||||
DSOP_FILTER_BUILTIN_GROUPS = 0x00000004
|
||||
DSOP_FILTER_WELL_KNOWN_PRINCIPALS = 0x00000008
|
||||
DSOP_FILTER_UNIVERSAL_GROUPS_DL = 0x00000010
|
||||
DSOP_FILTER_UNIVERSAL_GROUPS_SE = 0x00000020
|
||||
DSOP_FILTER_GLOBAL_GROUPS_DL = 0x00000040
|
||||
DSOP_FILTER_GLOBAL_GROUPS_SE = 0x00000080
|
||||
DSOP_FILTER_DOMAIN_LOCAL_GROUPS_DL = 0x00000100
|
||||
DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE = 0x00000200
|
||||
DSOP_FILTER_CONTACTS = 0x00000400
|
||||
DSOP_FILTER_COMPUTERS = 0x00000800
|
||||
DSOP_DOWNLEVEL_FILTER_USERS = (-2147483647)
|
||||
DSOP_DOWNLEVEL_FILTER_LOCAL_GROUPS = (-2147483646)
|
||||
DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS = (-2147483644)
|
||||
DSOP_DOWNLEVEL_FILTER_COMPUTERS = (-2147483640)
|
||||
DSOP_DOWNLEVEL_FILTER_WORLD = (-2147483632)
|
||||
DSOP_DOWNLEVEL_FILTER_AUTHENTICATED_USER = (-2147483616)
|
||||
DSOP_DOWNLEVEL_FILTER_ANONYMOUS = (-2147483584)
|
||||
DSOP_DOWNLEVEL_FILTER_BATCH = (-2147483520)
|
||||
DSOP_DOWNLEVEL_FILTER_CREATOR_OWNER = (-2147483392)
|
||||
DSOP_DOWNLEVEL_FILTER_CREATOR_GROUP = (-2147483136)
|
||||
DSOP_DOWNLEVEL_FILTER_DIALUP = (-2147482624)
|
||||
DSOP_DOWNLEVEL_FILTER_INTERACTIVE = (-2147481600)
|
||||
DSOP_DOWNLEVEL_FILTER_NETWORK = (-2147479552)
|
||||
DSOP_DOWNLEVEL_FILTER_SERVICE = (-2147475456)
|
||||
DSOP_DOWNLEVEL_FILTER_SYSTEM = (-2147467264)
|
||||
DSOP_DOWNLEVEL_FILTER_EXCLUDE_BUILTIN_GROUPS = (-2147450880)
|
||||
DSOP_DOWNLEVEL_FILTER_TERMINAL_SERVER = (-2147418112)
|
||||
DSOP_DOWNLEVEL_FILTER_ALL_WELLKNOWN_SIDS = (-2147352576)
|
||||
DSOP_DOWNLEVEL_FILTER_LOCAL_SERVICE = (-2147221504)
|
||||
DSOP_DOWNLEVEL_FILTER_NETWORK_SERVICE = (-2146959360)
|
||||
DSOP_DOWNLEVEL_FILTER_REMOTE_LOGON = (-2146435072)
|
||||
DSOP_FLAG_MULTISELECT = 0x00000001
|
||||
DSOP_FLAG_SKIP_TARGET_COMPUTER_DC_CHECK = 0x00000002
|
||||
CFSTR_DSOP_DS_SELECTION_LIST = "CFSTR_DSOP_DS_SELECTION_LIST"
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,58 @@
|
|||
# A demo for the IDsObjectPicker interface.
|
||||
import win32clipboard
|
||||
import pythoncom
|
||||
from win32com.adsi import adsi
|
||||
from win32com.adsi.adsicon import *
|
||||
|
||||
cf_objectpicker = win32clipboard.RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST)
|
||||
|
||||
def main():
|
||||
hwnd = 0
|
||||
|
||||
# Create an instance of the object picker.
|
||||
picker = pythoncom.CoCreateInstance(adsi.CLSID_DsObjectPicker,
|
||||
None,
|
||||
pythoncom.CLSCTX_INPROC_SERVER,
|
||||
adsi.IID_IDsObjectPicker)
|
||||
|
||||
# Create our scope init info.
|
||||
siis = adsi.DSOP_SCOPE_INIT_INFOs(1)
|
||||
sii = siis[0]
|
||||
|
||||
# Combine multiple scope types in a single array entry.
|
||||
|
||||
sii.type = DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN | \
|
||||
DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN
|
||||
|
||||
# Set uplevel and downlevel filters to include only computer objects.
|
||||
# Uplevel filters apply to both mixed and native modes.
|
||||
# Notice that the uplevel and downlevel flags are different.
|
||||
|
||||
sii.filterFlags.uplevel.bothModes = DSOP_FILTER_COMPUTERS
|
||||
sii.filterFlags.downlevel = DSOP_DOWNLEVEL_FILTER_COMPUTERS
|
||||
|
||||
# Initialize the interface.
|
||||
picker.Initialize(
|
||||
None, # Target is the local computer.
|
||||
siis, # scope infos
|
||||
DSOP_FLAG_MULTISELECT, # options
|
||||
('objectGUID','displayName') ) # attributes to fetch
|
||||
|
||||
do = picker.InvokeDialog(hwnd)
|
||||
# Extract the data from the IDataObject.
|
||||
format_etc = (cf_objectpicker, None,
|
||||
pythoncom.DVASPECT_CONTENT, -1,
|
||||
pythoncom.TYMED_HGLOBAL)
|
||||
medium = do.GetData(format_etc)
|
||||
data = adsi.StringAsDS_SELECTION_LIST(medium.data)
|
||||
for item in data:
|
||||
name, klass, adspath, upn, attrs, flags = item
|
||||
print("Item", name)
|
||||
print(" Class:", klass)
|
||||
print(" AdsPath:", adspath)
|
||||
print(" UPN:", upn)
|
||||
print(" Attrs:", attrs)
|
||||
print(" Flags:", flags)
|
||||
|
||||
if __name__=='__main__':
|
||||
main()
|
492
venv/Lib/site-packages/win32comext/adsi/demos/scp.py
Normal file
492
venv/Lib/site-packages/win32comext/adsi/demos/scp.py
Normal file
|
@ -0,0 +1,492 @@
|
|||
"""A re-implementation of the MS DirectoryService samples related to services.
|
||||
|
||||
* Adds and removes an ActiveDirectory "Service Connection Point",
|
||||
including managing the security on the object.
|
||||
* Creates and registers Service Principal Names.
|
||||
* Changes the username for a domain user.
|
||||
|
||||
Some of these functions are likely to become move to a module - but there
|
||||
is also a little command-line-interface to try these functions out.
|
||||
|
||||
For example:
|
||||
|
||||
scp.py --account-name=domain\\user --service-class=PythonScpTest \\
|
||||
--keyword=foo --keyword=bar --binding-string=bind_info \\
|
||||
ScpCreate SpnCreate SpnRegister
|
||||
|
||||
would:
|
||||
* Attempt to delete a Service Connection Point for the service class
|
||||
'PythonScpTest'
|
||||
* Attempt to create a Service Connection Point for that class, with 2
|
||||
keywords and a binding string of 'bind_info'
|
||||
* Create a Service Principal Name for the service and register it
|
||||
|
||||
to undo those changes, you could execute:
|
||||
|
||||
scp.py --account-name=domain\\user --service-class=PythonScpTest \\
|
||||
SpnCreate SpnUnregister ScpDelete
|
||||
|
||||
which will:
|
||||
* Create a SPN
|
||||
* Unregister that SPN from the Active Directory.
|
||||
* Delete the Service Connection Point
|
||||
|
||||
Executing with --test will create and remove one of everything.
|
||||
"""
|
||||
|
||||
from win32com.adsi.adsicon import *
|
||||
from win32com.adsi import adsi
|
||||
import win32api, win32con, winerror
|
||||
from win32com.client import Dispatch
|
||||
import ntsecuritycon as dscon
|
||||
import win32security
|
||||
import optparse, textwrap
|
||||
import traceback
|
||||
|
||||
verbose = 1
|
||||
g_createdSCP = None
|
||||
g_createdSPNs = []
|
||||
g_createdSPNLast = None
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging # use logging module global methods for now.
|
||||
|
||||
# still a bit confused about log(n, ...) vs logger.info/debug()
|
||||
|
||||
# Returns distinguished name of SCP.
|
||||
def ScpCreate(
|
||||
service_binding_info,
|
||||
service_class_name, # Service class string to store in SCP.
|
||||
account_name = None, # Logon account that needs access to SCP.
|
||||
container_name = None,
|
||||
keywords = None,
|
||||
object_class = "serviceConnectionPoint",
|
||||
dns_name_type = "A",
|
||||
dn = None,
|
||||
dns_name = None,
|
||||
):
|
||||
container_name = container_name or service_class_name
|
||||
if not dns_name:
|
||||
# Get the DNS name of the local computer
|
||||
dns_name = win32api.GetComputerNameEx(win32con.ComputerNameDnsFullyQualified)
|
||||
# Get the distinguished name of the computer object for the local computer
|
||||
if dn is None:
|
||||
dn = win32api.GetComputerObjectName(win32con.NameFullyQualifiedDN)
|
||||
|
||||
# Compose the ADSpath and bind to the computer object for the local computer
|
||||
comp = adsi.ADsGetObject("LDAP://" + dn, adsi.IID_IDirectoryObject)
|
||||
|
||||
# Publish the SCP as a child of the computer object
|
||||
keywords = keywords or []
|
||||
# Fill in the attribute values to be stored in the SCP.
|
||||
attrs = [
|
||||
("cn", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, (container_name,)),
|
||||
("objectClass", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, (object_class,)),
|
||||
("keywords", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, keywords),
|
||||
("serviceDnsName", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, (dns_name,)),
|
||||
("serviceDnsNameType", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, (dns_name_type,)),
|
||||
("serviceClassName", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, (service_class_name,)),
|
||||
("serviceBindingInformation", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, (service_binding_info,)),
|
||||
]
|
||||
new = comp.CreateDSObject("cn=" + container_name, attrs)
|
||||
logger.info("New connection point is at %s", container_name)
|
||||
# Wrap in a usable IDispatch object.
|
||||
new = Dispatch(new)
|
||||
# And allow access to the SCP for the specified account name
|
||||
AllowAccessToScpProperties(account_name, new)
|
||||
return new
|
||||
|
||||
def ScpDelete(container_name, dn = None):
|
||||
if dn is None:
|
||||
dn = win32api.GetComputerObjectName(win32con.NameFullyQualifiedDN)
|
||||
logger.debug("Removing connection point '%s' from %s", container_name, dn)
|
||||
|
||||
# Compose the ADSpath and bind to the computer object for the local computer
|
||||
comp = adsi.ADsGetObject("LDAP://" + dn, adsi.IID_IDirectoryObject)
|
||||
comp.DeleteDSObject("cn=" + container_name)
|
||||
logger.info("Deleted service connection point '%s'", container_name)
|
||||
|
||||
# This function is described in detail in the MSDN article titled
|
||||
# "Enabling Service Account to Access SCP Properties"
|
||||
# From that article:
|
||||
# The following sample code sets a pair of ACEs on a service connection point
|
||||
# (SCP) object. The ACEs grant read/write access to the user or computer account
|
||||
# under which the service instance will be running. Your service installation
|
||||
# program calls this code to ensure that the service will be allowed to update
|
||||
# its properties at run time. If you don't set ACEs like these, your service
|
||||
# will get access-denied errors if it tries to modify the SCP's properties.
|
||||
#
|
||||
# The code uses the IADsSecurityDescriptor, IADsAccessControlList, and
|
||||
# IADsAccessControlEntry interfaces to do the following:
|
||||
# * Get the SCP object's security descriptor.
|
||||
# * Set ACEs in the DACL of the security descriptor.
|
||||
# * Set the security descriptor back on the SCP object.
|
||||
|
||||
def AllowAccessToScpProperties(
|
||||
accountSAM, #Service account to allow access.
|
||||
scpObject, # The IADs SCP object.
|
||||
schemaIDGUIDs = # Attributes to allow write-access to.
|
||||
("{28630eb8-41d5-11d1-a9c1-0000f80367c1}", # serviceDNSName
|
||||
"{b7b1311c-b82e-11d0-afee-0000f80367c1}", # serviceBindingInformation
|
||||
)
|
||||
):
|
||||
|
||||
# If no service account is specified, service runs under LocalSystem.
|
||||
# So allow access to the computer account of the service's host.
|
||||
if accountSAM:
|
||||
trustee = accountSAM
|
||||
else:
|
||||
# Get the SAM account name of the computer object for the server.
|
||||
trustee = win32api.GetComputerObjectName(win32con.NameSamCompatible)
|
||||
|
||||
# Get the nTSecurityDescriptor attribute
|
||||
attribute = "nTSecurityDescriptor"
|
||||
sd = getattr(scpObject, attribute)
|
||||
acl = sd.DiscretionaryAcl
|
||||
|
||||
for sguid in schemaIDGUIDs:
|
||||
ace = Dispatch(adsi.CLSID_AccessControlEntry)
|
||||
|
||||
# Set the properties of the ACE.
|
||||
# Allow read and write access to the property.
|
||||
ace.AccessMask = ADS_RIGHT_DS_READ_PROP | ADS_RIGHT_DS_WRITE_PROP
|
||||
|
||||
# Set the trustee, which is either the service account or the
|
||||
# host computer account.
|
||||
ace.Trustee = trustee
|
||||
|
||||
# Set the ACE type.
|
||||
ace.AceType = ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
|
||||
|
||||
# Set AceFlags to zero because ACE is not inheritable.
|
||||
ace.AceFlags = 0
|
||||
|
||||
# Set Flags to indicate an ACE that protects a specified object.
|
||||
ace.Flags = ADS_FLAG_OBJECT_TYPE_PRESENT
|
||||
|
||||
# Set ObjectType to the schemaIDGUID of the attribute.
|
||||
ace.ObjectType = sguid
|
||||
|
||||
# Add the ACEs to the DACL.
|
||||
acl.AddAce(ace)
|
||||
|
||||
# Write the modified DACL back to the security descriptor.
|
||||
sd.DiscretionaryAcl = acl
|
||||
# Write the ntSecurityDescriptor property to the property cache.
|
||||
setattr(scpObject, attribute, sd)
|
||||
# SetInfo updates the SCP object in the directory.
|
||||
scpObject.SetInfo()
|
||||
logger.info("Set security on object for account '%s'" % (trustee,))
|
||||
|
||||
# Service Principal Names functions from the same sample.
|
||||
# The example calls the DsWriteAccountSpn function, which stores the SPNs in
|
||||
# Microsoft Active Directory under the servicePrincipalName attribute of the
|
||||
# account object specified by the serviceAcctDN parameter. The account object
|
||||
# corresponds to the logon account specified in the CreateService call for this
|
||||
# service instance. If the logon account is a domain user account,
|
||||
# serviceAcctDN must be the distinguished name of the account object in
|
||||
# Active Directory for that user account. If the service's logon account is the
|
||||
# LocalSystem account, serviceAcctDN must be the distinguished name of the
|
||||
# computer account object for the host computer on which the service is
|
||||
# installed. win32api.TranslateNames and win32security.DsCrackNames can
|
||||
# be used to convert a domain\account format name to a distinguished name.
|
||||
def SpnRegister(
|
||||
serviceAcctDN, # DN of the service's logon account
|
||||
spns, # List of SPNs to register
|
||||
operation, # Add, replace, or delete SPNs
|
||||
):
|
||||
assert type(spns) not in [str, str] and hasattr(spns, "__iter__"), \
|
||||
"spns must be a sequence of strings (got %r)" % spns
|
||||
# Bind to a domain controller.
|
||||
# Get the domain for the current user.
|
||||
samName = win32api.GetUserNameEx(win32api.NameSamCompatible)
|
||||
samName = samName.split('\\', 1)[0]
|
||||
|
||||
if not serviceAcctDN:
|
||||
# Get the SAM account name of the computer object for the server.
|
||||
serviceAcctDN = win32api.GetComputerObjectName(win32con.NameFullyQualifiedDN)
|
||||
logger.debug("SpnRegister using DN '%s'", serviceAcctDN)
|
||||
|
||||
# Get the name of a domain controller in that domain.
|
||||
info = win32security.DsGetDcName(
|
||||
domainName=samName,
|
||||
flags=dscon.DS_IS_FLAT_NAME |
|
||||
dscon.DS_RETURN_DNS_NAME |
|
||||
dscon.DS_DIRECTORY_SERVICE_REQUIRED)
|
||||
# Bind to the domain controller.
|
||||
handle = win32security.DsBind( info['DomainControllerName'] )
|
||||
|
||||
# Write the SPNs to the service account or computer account.
|
||||
logger.debug("DsWriteAccountSpn with spns %s")
|
||||
win32security.DsWriteAccountSpn(
|
||||
handle, # handle to the directory
|
||||
operation, # Add or remove SPN from account's existing SPNs
|
||||
serviceAcctDN, # DN of service account or computer account
|
||||
spns) # names
|
||||
|
||||
# Unbind the DS in any case (but Python would do it anyway)
|
||||
handle.Close()
|
||||
|
||||
def UserChangePassword(username_dn, new_password):
|
||||
# set the password on the account.
|
||||
# Use the distinguished name to bind to the account object.
|
||||
accountPath = "LDAP://" + username_dn
|
||||
user = adsi.ADsGetObject(accountPath, adsi.IID_IADsUser)
|
||||
|
||||
# Set the password on the account.
|
||||
user.SetPassword(new_password)
|
||||
|
||||
# functions related to the command-line interface
|
||||
def log(level, msg, *args):
|
||||
if verbose >= level:
|
||||
print(msg % args)
|
||||
|
||||
class _NoDefault: pass
|
||||
|
||||
def _get_option(po, opt_name, default = _NoDefault):
|
||||
parser, options = po
|
||||
ret = getattr(options, opt_name, default)
|
||||
if not ret and default is _NoDefault:
|
||||
parser.error("The '%s' option must be specified for this operation" % opt_name)
|
||||
if not ret:
|
||||
ret = default
|
||||
return ret
|
||||
|
||||
def _option_error(po, why):
|
||||
parser = po[0]
|
||||
parser.error(why)
|
||||
|
||||
def do_ScpCreate(po):
|
||||
"""Create a Service Connection Point"""
|
||||
global g_createdSCP
|
||||
scp = ScpCreate(_get_option(po, "binding_string"),
|
||||
_get_option(po, "service_class"),
|
||||
_get_option(po, "account_name_sam", None),
|
||||
keywords=_get_option(po, "keywords", None))
|
||||
g_createdSCP = scp
|
||||
return scp.distinguishedName
|
||||
|
||||
def do_ScpDelete(po):
|
||||
"""Delete a Service Connection Point"""
|
||||
sc = _get_option(po, "service_class")
|
||||
try:
|
||||
ScpDelete(sc)
|
||||
except adsi.error as details:
|
||||
if details[0] != winerror.ERROR_DS_OBJ_NOT_FOUND:
|
||||
raise
|
||||
log(2, "ScpDelete ignoring ERROR_DS_OBJ_NOT_FOUND for service-class '%s'",
|
||||
sc)
|
||||
return sc
|
||||
|
||||
def do_SpnCreate(po):
|
||||
"""Create a Service Principal Name"""
|
||||
# The 'service name' is the dn of our scp.
|
||||
if g_createdSCP is None:
|
||||
# Could accept an arg to avoid this?
|
||||
_option_error(po, "ScpCreate must have been specified before SpnCreate")
|
||||
# Create a Service Principal Name"
|
||||
spns = win32security.DsGetSpn(dscon.DS_SPN_SERVICE,
|
||||
_get_option(po, "service_class"),
|
||||
g_createdSCP.distinguishedName,
|
||||
_get_option(po, "port", 0),
|
||||
None, None)
|
||||
spn = spns[0]
|
||||
log(2, "Created SPN: %s", spn)
|
||||
global g_createdSPNLast
|
||||
g_createdSPNLast = spn
|
||||
g_createdSPNs.append(spn)
|
||||
return spn
|
||||
|
||||
def do_SpnRegister(po):
|
||||
"""Register a previously created Service Principal Name"""
|
||||
if not g_createdSPNLast:
|
||||
_option_error(po, "SpnCreate must appear before SpnRegister")
|
||||
|
||||
SpnRegister(_get_option(po, "account_name_dn", None),
|
||||
(g_createdSPNLast,),
|
||||
dscon.DS_SPN_ADD_SPN_OP)
|
||||
return g_createdSPNLast
|
||||
|
||||
def do_SpnUnregister(po):
|
||||
"""Unregister a previously created Service Principal Name"""
|
||||
if not g_createdSPNLast:
|
||||
_option_error(po, "SpnCreate must appear before SpnUnregister")
|
||||
SpnRegister(_get_option(po, "account_name_dn", None),
|
||||
(g_createdSPNLast,),
|
||||
dscon.DS_SPN_DELETE_SPN_OP)
|
||||
return g_createdSPNLast
|
||||
|
||||
def do_UserChangePassword(po):
|
||||
"""Change the password for a specified user"""
|
||||
UserChangePassword(_get_option(po, "account_name_dn"),
|
||||
_get_option(po, "password"))
|
||||
return "Password changed OK"
|
||||
|
||||
handlers = (
|
||||
('ScpCreate', do_ScpCreate),
|
||||
('ScpDelete', do_ScpDelete),
|
||||
('SpnCreate', do_SpnCreate),
|
||||
('SpnRegister', do_SpnRegister),
|
||||
('SpnUnregister', do_SpnUnregister),
|
||||
('UserChangePassword', do_UserChangePassword),
|
||||
)
|
||||
|
||||
class HelpFormatter(optparse.IndentedHelpFormatter):
|
||||
def format_description(self, description):
|
||||
return description
|
||||
|
||||
def main():
|
||||
global verbose
|
||||
_handlers_dict = {}
|
||||
|
||||
arg_descs = []
|
||||
for arg, func in handlers:
|
||||
this_desc = "\n".join(textwrap.wrap(func.__doc__,
|
||||
subsequent_indent = " " * 8))
|
||||
arg_descs.append(" %s: %s" % (arg, this_desc))
|
||||
_handlers_dict[arg.lower()] = func
|
||||
|
||||
description = __doc__ + "\ncommands:\n" + "\n".join(arg_descs) + "\n"
|
||||
|
||||
parser = optparse.OptionParser(usage = "%prog [options] command ...",
|
||||
description=description,
|
||||
formatter=HelpFormatter())
|
||||
|
||||
parser.add_option("-v", action="count",
|
||||
dest="verbose", default=1,
|
||||
help="increase the verbosity of status messages")
|
||||
|
||||
parser.add_option("-q", "--quiet", action="store_true",
|
||||
help="Don't print any status messages")
|
||||
|
||||
parser.add_option("-t", "--test", action="store_true",
|
||||
help="Execute a mini-test suite, providing defaults for most options and args"),
|
||||
|
||||
parser.add_option("", "--show-tracebacks", action="store_true",
|
||||
help="Show the tracebacks for any exceptions")
|
||||
|
||||
parser.add_option("", "--service-class",
|
||||
help="The service class name to use")
|
||||
|
||||
parser.add_option("", "--port", default=0,
|
||||
help="The port number to associate with the SPN")
|
||||
|
||||
parser.add_option("", "--binding-string",
|
||||
help="The binding string to use for SCP creation")
|
||||
|
||||
parser.add_option("", "--account-name",
|
||||
help="The account name to use (default is LocalSystem)")
|
||||
|
||||
parser.add_option("", "--password",
|
||||
help="The password to set.")
|
||||
|
||||
parser.add_option("", "--keyword", action="append", dest="keywords",
|
||||
help="""A keyword to add to the SCP. May be specified
|
||||
multiple times""")
|
||||
|
||||
parser.add_option("", "--log-level",
|
||||
help="""The log-level to use - may be a number or a logging
|
||||
module constant""", default=str(logging.WARNING))
|
||||
|
||||
options, args = parser.parse_args()
|
||||
po = (parser, options)
|
||||
# fixup misc
|
||||
try:
|
||||
options.port = int(options.port)
|
||||
except (TypeError, ValueError):
|
||||
parser.error("--port must be numeric")
|
||||
# fixup log-level
|
||||
try:
|
||||
log_level = int(options.log_level)
|
||||
except (TypeError, ValueError):
|
||||
try:
|
||||
log_level = int(getattr(logging, options.log_level.upper()))
|
||||
except (ValueError, TypeError, AttributeError):
|
||||
parser.error("Invalid --log-level value")
|
||||
try:
|
||||
sl = logger.setLevel
|
||||
# logger is a real logger
|
||||
except AttributeError:
|
||||
# logger is logging module
|
||||
sl = logging.getLogger().setLevel
|
||||
sl(log_level)
|
||||
# Check -q/-v
|
||||
if options.quiet and options.verbose:
|
||||
parser.error("Can't specify --quiet and --verbose")
|
||||
if options.quiet:
|
||||
options.verbose -= 1
|
||||
verbose = options.verbose
|
||||
# --test
|
||||
if options.test:
|
||||
if args:
|
||||
parser.error("Can't specify args with --test")
|
||||
|
||||
args = "ScpDelete ScpCreate SpnCreate SpnRegister SpnUnregister ScpDelete"
|
||||
log(1, "--test - pretending args are:\n %s", args)
|
||||
args = args.split()
|
||||
if not options.service_class:
|
||||
options.service_class = "PythonScpTest"
|
||||
log(2, "--test: --service-class=%s", options.service_class)
|
||||
if not options.keywords:
|
||||
options.keywords = "Python Powered".split()
|
||||
log(2, "--test: --keyword=%s", options.keywords)
|
||||
if not options.binding_string:
|
||||
options.binding_string = "test binding string"
|
||||
log(2, "--test: --binding-string=%s", options.binding_string)
|
||||
|
||||
# check args
|
||||
if not args:
|
||||
parser.error("No command specified (use --help for valid commands)")
|
||||
for arg in args:
|
||||
if arg.lower() not in _handlers_dict:
|
||||
parser.error("Invalid command '%s' (use --help for valid commands)" % arg)
|
||||
|
||||
# Patch up account-name.
|
||||
if options.account_name:
|
||||
log(2, "Translating account name '%s'", options.account_name)
|
||||
options.account_name_sam = win32security.TranslateName(options.account_name,
|
||||
win32api.NameUnknown,
|
||||
win32api.NameSamCompatible)
|
||||
log(2, "NameSamCompatible is '%s'",options.account_name_sam)
|
||||
options.account_name_dn = win32security.TranslateName(options.account_name,
|
||||
win32api.NameUnknown,
|
||||
win32api.NameFullyQualifiedDN)
|
||||
log(2, "NameFullyQualifiedDNis '%s'",options.account_name_dn)
|
||||
|
||||
# do it.
|
||||
for arg in args:
|
||||
handler = _handlers_dict[arg.lower()] # already been validated
|
||||
if handler is None:
|
||||
parser.error("Invalid command '%s'" % arg)
|
||||
err_msg = None
|
||||
try:
|
||||
try:
|
||||
log(2, "Executing '%s'...", arg)
|
||||
result = handler(po)
|
||||
log(1, "%s: %s", arg, result)
|
||||
except:
|
||||
if options.show_tracebacks:
|
||||
print("--show-tracebacks specified - dumping exception")
|
||||
traceback.print_exc()
|
||||
raise
|
||||
except adsi.error as xxx_todo_changeme:
|
||||
(hr, desc, exc, argerr) = xxx_todo_changeme.args
|
||||
if exc:
|
||||
extra_desc = exc[2]
|
||||
else:
|
||||
extra_desc = ""
|
||||
err_msg = desc
|
||||
if extra_desc:
|
||||
err_msg += "\n\t" + extra_desc
|
||||
except win32api.error as xxx_todo_changeme1:
|
||||
(hr, func, msg) = xxx_todo_changeme1.args
|
||||
err_msg = msg
|
||||
if err_msg:
|
||||
log(1, "Command '%s' failed: %s", arg, err_msg)
|
||||
|
||||
if __name__=='__main__':
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
print("*** Interrupted")
|
132
venv/Lib/site-packages/win32comext/adsi/demos/search.py
Normal file
132
venv/Lib/site-packages/win32comext/adsi/demos/search.py
Normal file
|
@ -0,0 +1,132 @@
|
|||
from win32com.adsi import adsi
|
||||
from win32com.adsi.adsicon import *
|
||||
from win32com.adsi import adsicon
|
||||
import pythoncom, pywintypes, win32security
|
||||
|
||||
options = None # set to optparse options object
|
||||
|
||||
ADsTypeNameMap = {}
|
||||
|
||||
def getADsTypeName(type_val):
|
||||
# convert integer type to the 'typename' as known in the headerfiles.
|
||||
if not ADsTypeNameMap:
|
||||
for n, v in adsicon.__dict__.items():
|
||||
if n.startswith("ADSTYPE_"):
|
||||
ADsTypeNameMap[v] = n
|
||||
return ADsTypeNameMap.get(type_val, hex(type_val))
|
||||
|
||||
def _guid_from_buffer(b):
|
||||
return pywintypes.IID(b, True)
|
||||
|
||||
def _sid_from_buffer(b):
|
||||
return str(pywintypes.SID(b))
|
||||
|
||||
_null_converter = lambda x: x
|
||||
|
||||
converters = {
|
||||
'objectGUID' : _guid_from_buffer,
|
||||
'objectSid' : _sid_from_buffer,
|
||||
'instanceType' : getADsTypeName,
|
||||
}
|
||||
|
||||
def log(level, msg, *args):
|
||||
if options.verbose >= level:
|
||||
print("log:", msg % args)
|
||||
|
||||
def getGC():
|
||||
cont = adsi.ADsOpenObject("GC:", options.user, options.password, 0, adsi.IID_IADsContainer)
|
||||
enum = adsi.ADsBuildEnumerator(cont)
|
||||
# Only 1 child of the global catalog.
|
||||
for e in enum:
|
||||
gc = e.QueryInterface(adsi.IID_IDirectorySearch)
|
||||
return gc
|
||||
return None
|
||||
|
||||
def print_attribute(col_data):
|
||||
prop_name, prop_type, values = col_data
|
||||
if values is not None:
|
||||
log(2, "property '%s' has type '%s'", prop_name, getADsTypeName(prop_type))
|
||||
value = [converters.get(prop_name, _null_converter)(v[0]) for v in values]
|
||||
if len(value) == 1:
|
||||
value = value[0]
|
||||
print(" %s=%r" % (prop_name, value))
|
||||
else:
|
||||
print(" %s is None" % (prop_name,))
|
||||
|
||||
def search():
|
||||
gc = getGC()
|
||||
if gc is None:
|
||||
log(0, "Can't find the global catalog")
|
||||
return
|
||||
|
||||
prefs = [(ADS_SEARCHPREF_SEARCH_SCOPE, (ADS_SCOPE_SUBTREE,))]
|
||||
hr, statuses = gc.SetSearchPreference(prefs)
|
||||
log(3, "SetSearchPreference returned %d/%r", hr, statuses)
|
||||
|
||||
if options.attributes:
|
||||
attributes = options.attributes.split(",")
|
||||
else:
|
||||
attributes = None
|
||||
|
||||
h = gc.ExecuteSearch(options.filter, attributes)
|
||||
hr = gc.GetNextRow(h)
|
||||
while hr != S_ADS_NOMORE_ROWS:
|
||||
print("-- new row --")
|
||||
if attributes is None:
|
||||
# Loop over all columns returned
|
||||
while 1:
|
||||
col_name = gc.GetNextColumnName(h)
|
||||
if col_name is None:
|
||||
break
|
||||
data = gc.GetColumn(h, col_name)
|
||||
print_attribute(data)
|
||||
else:
|
||||
# loop over attributes specified.
|
||||
for a in attributes:
|
||||
try:
|
||||
data = gc.GetColumn(h, a)
|
||||
print_attribute(data)
|
||||
except adsi.error as details:
|
||||
if details[0] != E_ADS_COLUMN_NOT_SET:
|
||||
raise
|
||||
print_attribute( (a, None, None) )
|
||||
hr = gc.GetNextRow(h)
|
||||
gc.CloseSearchHandle(h)
|
||||
|
||||
def main():
|
||||
global options
|
||||
from optparse import OptionParser
|
||||
|
||||
parser = OptionParser()
|
||||
parser.add_option("-f", "--file", dest="filename",
|
||||
help="write report to FILE", metavar="FILE")
|
||||
parser.add_option("-v", "--verbose",
|
||||
action="count", default=1,
|
||||
help="increase verbosity of output")
|
||||
parser.add_option("-q", "--quiet",
|
||||
action="store_true",
|
||||
help="suppress output messages")
|
||||
|
||||
parser.add_option("-U", "--user",
|
||||
help="specify the username used to connect")
|
||||
parser.add_option("-P", "--password",
|
||||
help="specify the password used to connect")
|
||||
parser.add_option("", "--filter",
|
||||
default = "(&(objectCategory=person)(objectClass=User))",
|
||||
help="specify the search filter")
|
||||
parser.add_option("", "--attributes",
|
||||
help="comma sep'd list of attribute names to print")
|
||||
|
||||
options, args = parser.parse_args()
|
||||
if options.quiet:
|
||||
if options.verbose != 1:
|
||||
parser.error("Can not use '--verbose' and '--quiet'")
|
||||
options.verbose = 0
|
||||
|
||||
if args:
|
||||
parser.error("You need not specify args")
|
||||
|
||||
search()
|
||||
|
||||
if __name__=='__main__':
|
||||
main()
|
247
venv/Lib/site-packages/win32comext/adsi/demos/test.py
Normal file
247
venv/Lib/site-packages/win32comext/adsi/demos/test.py
Normal file
|
@ -0,0 +1,247 @@
|
|||
import sys, string
|
||||
import pythoncom
|
||||
|
||||
import win32api
|
||||
from win32com.adsi import *
|
||||
|
||||
verbose_level = 0
|
||||
|
||||
server = '' # Must have trailing /
|
||||
local_name = win32api.GetComputerName()
|
||||
|
||||
def DumpRoot():
|
||||
"Dumps the root DSE"
|
||||
path = "LDAP://%srootDSE" % server
|
||||
rootdse = ADsGetObject(path)
|
||||
|
||||
for item in rootdse.Get("SupportedLDAPVersion"):
|
||||
print("%s supports ldap version %s" % (path, item))
|
||||
|
||||
attributes = ["CurrentTime", "defaultNamingContext"]
|
||||
for attr in attributes:
|
||||
val = rootdse.Get(attr)
|
||||
print(" %s=%s" % (attr, val))
|
||||
|
||||
###############################################
|
||||
#
|
||||
# Code taken from article titled:
|
||||
# Reading attributeSchema and classSchema Objects
|
||||
def _DumpClass(child):
|
||||
attrs = "Abstract lDAPDisplayName schemaIDGUID schemaNamingContext attributeSyntax oMSyntax"
|
||||
_DumpTheseAttributes(child, string.split(attrs))
|
||||
|
||||
def _DumpAttribute(child):
|
||||
attrs = "lDAPDisplayName schemaIDGUID adminDescription adminDisplayName rDNAttID defaultHidingValue defaultObjectCategory systemOnly defaultSecurityDescriptor"
|
||||
_DumpTheseAttributes(child, string.split(attrs))
|
||||
|
||||
def _DumpTheseAttributes(child, attrs):
|
||||
for attr in attrs:
|
||||
try:
|
||||
val = child.Get(attr)
|
||||
except pythoncom.com_error as details:
|
||||
continue
|
||||
# ###
|
||||
(hr, msg, exc, arg) = details
|
||||
if exc and exc[2]: msg = exc[2]
|
||||
val = "<Error: %s>" % (msg,)
|
||||
if verbose_level >= 2:
|
||||
print(" %s: %s=%s" % (child.Class, attr, val))
|
||||
|
||||
def DumpSchema():
|
||||
"Dumps the default DSE schema"
|
||||
# Bind to rootDSE to get the schemaNamingContext property.
|
||||
path = "LDAP://%srootDSE" % server
|
||||
rootdse = ADsGetObject(path)
|
||||
name = rootdse.Get("schemaNamingContext")
|
||||
|
||||
# Bind to the actual schema container.
|
||||
path= "LDAP://" + server + name
|
||||
print("Binding to", path)
|
||||
ob = ADsGetObject(path)
|
||||
nclasses = nattr = nsub = nunk = 0
|
||||
|
||||
# Enumerate the attribute and class objects in the schema container.
|
||||
for child in ob:
|
||||
# Find out if this is a class, attribute, or subSchema object.
|
||||
class_name = child.Class
|
||||
if class_name == "classSchema":
|
||||
_DumpClass(child)
|
||||
nclasses = nclasses + 1
|
||||
elif class_name == "attributeSchema":
|
||||
_DumpAttribute(child)
|
||||
nattr = nattr + 1
|
||||
elif class_name == "subSchema":
|
||||
nsub = nsub + 1
|
||||
else:
|
||||
print("Unknown class:", class_name)
|
||||
nunk = nunk + 1
|
||||
if verbose_level:
|
||||
print("Processed", nclasses, "classes")
|
||||
print("Processed", nattr, "attributes")
|
||||
print("Processed", nsub, "sub-schema's")
|
||||
print("Processed", nunk, "unknown types")
|
||||
|
||||
def _DumpObject(ob, level = 0):
|
||||
prefix = " " * level
|
||||
print("%s%s object: %s" % (prefix, ob.Class, ob.Name))
|
||||
# Do the directory object thing
|
||||
try:
|
||||
dir_ob = ADsGetObject(ob.ADsPath, IID_IDirectoryObject)
|
||||
except pythoncom.com_error:
|
||||
dir_ob = None
|
||||
if dir_ob is not None:
|
||||
info = dir_ob.GetObjectInformation()
|
||||
print("%s RDN='%s', ObjectDN='%s'" % (prefix, info.RDN, info.ObjectDN))
|
||||
# Create a list of names to fetch
|
||||
names = ["distinguishedName"]
|
||||
attrs = dir_ob.GetObjectAttributes(names)
|
||||
for attr in attrs:
|
||||
for val, typ in attr.Values:
|
||||
print("%s Attribute '%s' = %s" % (prefix, attr.AttrName, val))
|
||||
|
||||
for child in ob:
|
||||
_DumpObject(child, level+1)
|
||||
|
||||
def DumpAllObjects():
|
||||
"Recursively dump the entire directory!"
|
||||
path = "LDAP://%srootDSE" % server
|
||||
rootdse = ADsGetObject(path)
|
||||
name = rootdse.Get("defaultNamingContext")
|
||||
|
||||
# Bind to the actual schema container.
|
||||
path= "LDAP://" + server + name
|
||||
print("Binding to", path)
|
||||
ob = ADsGetObject(path)
|
||||
|
||||
# Enumerate the attribute and class objects in the schema container.
|
||||
_DumpObject(ob)
|
||||
|
||||
##########################################################
|
||||
#
|
||||
# Code taken from article:
|
||||
# Example Code for Enumerating Schema Classes, Attributes, and Syntaxes
|
||||
|
||||
# Fill a map with VT_ datatypes, to give us better names:
|
||||
vt_map = {}
|
||||
for name, val in pythoncom.__dict__.items():
|
||||
if name[:3] == "VT_":
|
||||
vt_map[val] = name
|
||||
|
||||
def DumpSchema2():
|
||||
"Dumps the schema using an alternative technique"
|
||||
path = "LDAP://%sschema" % (server,)
|
||||
schema = ADsGetObject(path, IID_IADsContainer)
|
||||
nclass = nprop = nsyntax = 0
|
||||
for item in schema:
|
||||
item_class = string.lower(item.Class)
|
||||
if item_class == "class":
|
||||
items = []
|
||||
if item.Abstract: items.append("Abstract")
|
||||
if item.Auxiliary: items.append("Auxiliary")
|
||||
# if item.Structural: items.append("Structural")
|
||||
desc = string.join(items, ", ")
|
||||
import win32com.util
|
||||
iid_name = win32com.util.IIDToInterfaceName(item.PrimaryInterface)
|
||||
if verbose_level >= 2:
|
||||
print("Class: Name=%s, Flags=%s, Primary Interface=%s" % (item.Name, desc, iid_name))
|
||||
nclass = nclass + 1
|
||||
elif item_class == "property":
|
||||
if item.MultiValued:
|
||||
val_type = "Multi-Valued"
|
||||
else:
|
||||
val_type = "Single-Valued"
|
||||
if verbose_level >= 2:
|
||||
print("Property: Name=%s, %s" % (item.Name, val_type))
|
||||
nprop = nprop + 1
|
||||
elif item_class == "syntax":
|
||||
data_type = vt_map.get(item.OleAutoDataType, "<unknown type>")
|
||||
if verbose_level >= 2:
|
||||
print("Syntax: Name=%s, Datatype = %s" % (item.Name, data_type))
|
||||
nsyntax = nsyntax + 1
|
||||
if verbose_level >= 1:
|
||||
print("Processed", nclass, "classes")
|
||||
print("Processed", nprop, "properties")
|
||||
print("Processed", nsyntax, "syntax items")
|
||||
|
||||
def DumpGC():
|
||||
"Dumps the GC: object (whatever that is!)"
|
||||
ob = ADsGetObject("GC:", IID_IADsContainer)
|
||||
for sub_ob in ob:
|
||||
print("GC ob: %s (%s)" % (sub_ob.Name, sub_ob.ADsPath))
|
||||
|
||||
def DumpLocalUsers():
|
||||
"Dumps the local machine users"
|
||||
path = "WinNT://%s,computer" % (local_name,)
|
||||
ob = ADsGetObject(path, IID_IADsContainer)
|
||||
ob.put_Filter(["User", "Group"])
|
||||
for sub_ob in ob:
|
||||
print("User/Group: %s (%s)" % (sub_ob.Name, sub_ob.ADsPath))
|
||||
|
||||
def DumpLocalGroups():
|
||||
"Dumps the local machine groups"
|
||||
path = "WinNT://%s,computer" % (local_name,)
|
||||
ob = ADsGetObject(path, IID_IADsContainer)
|
||||
|
||||
ob.put_Filter(["Group"])
|
||||
for sub_ob in ob:
|
||||
print("Group: %s (%s)" % (sub_ob.Name, sub_ob.ADsPath))
|
||||
# get the members
|
||||
members = sub_ob.Members()
|
||||
for member in members:
|
||||
print(" Group member: %s (%s)" % (member.Name, member.ADsPath))
|
||||
|
||||
def usage(tests):
|
||||
import os
|
||||
print("Usage: %s [-s server ] [-v] [Test ...]" % os.path.basename(sys.argv[0]))
|
||||
print(" -v : Verbose - print more information")
|
||||
print(" -s : server - execute the tests against the named server")
|
||||
print("where Test is one of:")
|
||||
for t in tests:
|
||||
print(t.__name__,":", t.__doc__)
|
||||
print()
|
||||
print("If not tests are specified, all tests are run")
|
||||
sys.exit(1)
|
||||
|
||||
def main():
|
||||
import getopt, traceback
|
||||
tests = []
|
||||
for ob in globals().values():
|
||||
if type(ob)==type(main) and ob.__doc__:
|
||||
tests.append(ob)
|
||||
opts, args = getopt.getopt(sys.argv[1:], "s:hv")
|
||||
for opt, val in opts:
|
||||
if opt=="-s":
|
||||
if val[-1] not in "\\/":
|
||||
val = val + "/"
|
||||
global server
|
||||
server = val
|
||||
if opt=="-h":
|
||||
usage(tests)
|
||||
if opt=="-v":
|
||||
global verbose_level
|
||||
verbose_level = verbose_level + 1
|
||||
|
||||
if len(args)==0:
|
||||
print("Running all tests - use '-h' to see command-line options...")
|
||||
dotests = tests
|
||||
else:
|
||||
dotests = []
|
||||
for arg in args:
|
||||
for t in tests:
|
||||
if t.__name__==arg:
|
||||
dotests.append(t)
|
||||
break
|
||||
else:
|
||||
print("Test '%s' unknown - skipping" % arg)
|
||||
if not len(dotests):
|
||||
print("Nothing to do!")
|
||||
usage(tests)
|
||||
for test in dotests:
|
||||
try:
|
||||
test()
|
||||
except:
|
||||
print("Test %s failed" % test.__name__)
|
||||
traceback.print_exc()
|
||||
|
||||
if __name__=='__main__':
|
||||
main()
|
|
@ -0,0 +1,6 @@
|
|||
# This is a python package
|
||||
# __PackageSupportBuildPath__ not needed for distutil based builds,
|
||||
# but not everyone is there yet.
|
||||
import win32com
|
||||
win32com.__PackageSupportBuildPath__(__path__)
|
||||
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,140 @@
|
|||
import os
|
||||
import win32com.server.policy
|
||||
import win32security, ntsecuritycon, win32con
|
||||
import pythoncom, win32api
|
||||
from win32com.authorization import authorization
|
||||
|
||||
from ntsecuritycon import FILE_READ_ATTRIBUTES, FILE_READ_DATA, FILE_READ_EA, SYNCHRONIZE,\
|
||||
STANDARD_RIGHTS_READ, STANDARD_RIGHTS_WRITE, STANDARD_RIGHTS_EXECUTE, FILE_APPEND_DATA, \
|
||||
FILE_WRITE_ATTRIBUTES, FILE_WRITE_DATA, FILE_WRITE_EA, WRITE_OWNER, WRITE_DAC, READ_CONTROL, \
|
||||
SI_ADVANCED, SI_EDIT_AUDITS, SI_EDIT_PROPERTIES, SI_EDIT_ALL, SI_PAGE_TITLE, SI_RESET, \
|
||||
SI_ACCESS_SPECIFIC, SI_ACCESS_GENERAL, SI_ACCESS_CONTAINER, SI_ACCESS_PROPERTY, \
|
||||
FILE_ALL_ACCESS, FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, \
|
||||
OBJECT_INHERIT_ACE, CONTAINER_INHERIT_ACE, INHERIT_ONLY_ACE, \
|
||||
SI_PAGE_PERM, SI_PAGE_ADVPERM, SI_PAGE_AUDIT, SI_PAGE_OWNER, PSPCB_SI_INITDIALOG, \
|
||||
SI_CONTAINER
|
||||
from win32security import OBJECT_INHERIT_ACE, CONTAINER_INHERIT_ACE, INHERIT_ONLY_ACE
|
||||
from win32com.shell.shellcon import PSPCB_RELEASE, PSPCB_CREATE ## Msg parameter to PropertySheetPageCallback
|
||||
from pythoncom import IID_NULL
|
||||
|
||||
|
||||
class SecurityInformation(win32com.server.policy.DesignatedWrapPolicy):
|
||||
_com_interfaces_=[authorization.IID_ISecurityInformation]
|
||||
_public_methods_=['GetObjectInformation','GetSecurity','SetSecurity','GetAccessRights',
|
||||
'GetInheritTypes','MapGeneric','PropertySheetPageCallback']
|
||||
|
||||
def __init__(self, FileName):
|
||||
self.FileName=FileName
|
||||
self._wrap_(self)
|
||||
|
||||
def GetObjectInformation(self):
|
||||
"""Identifies object whose security will be modified, and determines options available
|
||||
to the end user"""
|
||||
flags=SI_ADVANCED|SI_EDIT_ALL|SI_PAGE_TITLE|SI_RESET
|
||||
if os.path.isdir(self.FileName):
|
||||
flags|=SI_CONTAINER
|
||||
hinstance=0 ## handle to module containing string resources
|
||||
servername='' ## name of authenticating server if not local machine
|
||||
objectname=os.path.split(self.FileName)[1]
|
||||
pagetitle='Python ACL Editor'
|
||||
if os.path.isdir(self.FileName):
|
||||
pagetitle+=' (dir)'
|
||||
else:
|
||||
pagetitle+=' (file)'
|
||||
objecttype=IID_NULL
|
||||
return flags, hinstance, servername, objectname, pagetitle, objecttype
|
||||
|
||||
def GetSecurity(self, requestedinfo, bdefault):
|
||||
"""Requests the existing permissions for object"""
|
||||
if bdefault:
|
||||
## This is invoked if the 'Default' button is pressed (only present if SI_RESET is passed
|
||||
## with the flags in GetObjectInfo). Passing an empty SD with a NULL Dacl
|
||||
## should cause inherited ACL from parent dir or default dacl from user's token to be used
|
||||
return win32security.SECURITY_DESCRIPTOR()
|
||||
else:
|
||||
## GetFileSecurity sometimes fails to return flags indicating that an ACE is inherited
|
||||
return win32security.GetNamedSecurityInfo(self.FileName, win32security.SE_FILE_OBJECT, requestedinfo)
|
||||
|
||||
def SetSecurity(self, requestedinfo, sd):
|
||||
"""Applies permissions to the object"""
|
||||
owner=sd.GetSecurityDescriptorOwner()
|
||||
group=sd.GetSecurityDescriptorGroup()
|
||||
dacl=sd.GetSecurityDescriptorDacl()
|
||||
sacl=sd.GetSecurityDescriptorSacl()
|
||||
win32security.SetNamedSecurityInfo(self.FileName, win32security.SE_FILE_OBJECT, requestedinfo,
|
||||
owner, group, dacl, sacl)
|
||||
## should also handle recursive operations here
|
||||
|
||||
def GetAccessRights(self, objecttype, flags):
|
||||
"""Returns a tuple of (AccessRights, DefaultAccess), where AccessRights is a sequence of tuples representing
|
||||
SI_ACCESS structs, containing (guid, access mask, Name, flags). DefaultAccess indicates which of the
|
||||
AccessRights will be used initially when a new ACE is added (zero based).
|
||||
Flags can contain SI_ACCESS_SPECIFIC,SI_ACCESS_GENERAL,SI_ACCESS_CONTAINER,SI_ACCESS_PROPERTY,
|
||||
CONTAINER_INHERIT_ACE,INHERIT_ONLY_ACE,OBJECT_INHERIT_ACE
|
||||
"""
|
||||
## input flags: SI_ADVANCED,SI_EDIT_AUDITS,SI_EDIT_PROPERTIES indicating which property sheet is requesting the rights
|
||||
if (objecttype is not None) and (objecttype!=IID_NULL):
|
||||
## Should not be true for file objects. Usually only used with DS objects that support security for
|
||||
## their properties
|
||||
raise NotImplementedError("Object type is not supported")
|
||||
|
||||
if os.path.isdir(self.FileName):
|
||||
file_append_data_desc='Create subfolders'
|
||||
file_write_data_desc='Create Files'
|
||||
else:
|
||||
file_append_data_desc='Append data'
|
||||
file_write_data_desc='Write data'
|
||||
|
||||
accessrights=[(IID_NULL, FILE_GENERIC_READ, 'Generic read', SI_ACCESS_GENERAL|SI_ACCESS_SPECIFIC|OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
|
||||
(IID_NULL, FILE_GENERIC_WRITE, 'Generic write', SI_ACCESS_GENERAL|SI_ACCESS_SPECIFIC|OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
|
||||
(IID_NULL, win32con.DELETE, 'Delete', SI_ACCESS_SPECIFIC|OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
|
||||
(IID_NULL, WRITE_OWNER, 'Change owner', SI_ACCESS_SPECIFIC|OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
|
||||
(IID_NULL, READ_CONTROL,'Read Permissions', SI_ACCESS_SPECIFIC|OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
|
||||
(IID_NULL, WRITE_DAC, 'Change permissions', SI_ACCESS_SPECIFIC|OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
|
||||
(IID_NULL, FILE_APPEND_DATA, file_append_data_desc, SI_ACCESS_SPECIFIC|OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
|
||||
(IID_NULL, FILE_WRITE_DATA, file_write_data_desc, SI_ACCESS_SPECIFIC|OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)
|
||||
]
|
||||
return (accessrights, 0)
|
||||
|
||||
def MapGeneric(self, guid, aceflags, mask):
|
||||
""" Converts generic access rights to specific rights. This implementation uses standard file system rights,
|
||||
but you can map them any way that suits your application.
|
||||
"""
|
||||
return win32security.MapGenericMask(mask, (FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS))
|
||||
|
||||
def GetInheritTypes(self):
|
||||
"""Specifies which types of ACE inheritance are supported.
|
||||
Returns a sequence of tuples representing SI_INHERIT_TYPE structs, containing
|
||||
(object type guid, inheritance flags, display name). Guid is usually only used with
|
||||
Directory Service objects.
|
||||
"""
|
||||
return ((IID_NULL, 0, 'Only current object'),
|
||||
(IID_NULL, OBJECT_INHERIT_ACE, 'Files inherit permissions'),
|
||||
(IID_NULL, CONTAINER_INHERIT_ACE, 'Sub Folders inherit permissions'),
|
||||
(IID_NULL, CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE, 'Files and subfolders'),
|
||||
)
|
||||
|
||||
def PropertySheetPageCallback(self, hwnd, msg, pagetype):
|
||||
"""Invoked each time a property sheet page is created or destroyed."""
|
||||
## page types from SI_PAGE_TYPE enum: SI_PAGE_PERM SI_PAGE_ADVPERM SI_PAGE_AUDIT SI_PAGE_OWNER
|
||||
## msg: PSPCB_CREATE, PSPCB_RELEASE, PSPCB_SI_INITDIALOG
|
||||
return None
|
||||
|
||||
def EditSecurity(self, owner_hwnd=0):
|
||||
"""Creates an ACL editor dialog based on parameters returned by interface methods"""
|
||||
isi=pythoncom.WrapObject(self, authorization.IID_ISecurityInformation, pythoncom.IID_IUnknown)
|
||||
authorization.EditSecurity(owner_hwnd, isi)
|
||||
|
||||
## folder permissions
|
||||
temp_dir=win32api.GetTempPath()
|
||||
dir_name=win32api.GetTempFileName(temp_dir,'isi')[0]
|
||||
print(dir_name)
|
||||
os.remove(dir_name)
|
||||
os.mkdir(dir_name)
|
||||
si=SecurityInformation(dir_name)
|
||||
si.EditSecurity()
|
||||
|
||||
## file permissions
|
||||
fname=win32api.GetTempFileName(dir_name,'isi')[0]
|
||||
si=SecurityInformation(fname)
|
||||
si.EditSecurity()
|
|
@ -0,0 +1,134 @@
|
|||
"""
|
||||
Implements a permissions editor for services.
|
||||
Service can be specified as plain name for local machine,
|
||||
or as a remote service of the form \\machinename\service
|
||||
"""
|
||||
|
||||
import os
|
||||
import win32com.server.policy
|
||||
import win32security, ntsecuritycon, win32con
|
||||
import pythoncom, win32api, win32service
|
||||
from win32com.authorization import authorization
|
||||
|
||||
SERVICE_GENERIC_EXECUTE=win32service.SERVICE_START|win32service.SERVICE_STOP|win32service.SERVICE_PAUSE_CONTINUE|win32service.SERVICE_USER_DEFINED_CONTROL
|
||||
SERVICE_GENERIC_READ=win32service.SERVICE_QUERY_CONFIG|win32service.SERVICE_QUERY_STATUS|win32service.SERVICE_INTERROGATE|win32service.SERVICE_ENUMERATE_DEPENDENTS
|
||||
SERVICE_GENERIC_WRITE=win32service.SERVICE_CHANGE_CONFIG
|
||||
|
||||
from ntsecuritycon import STANDARD_RIGHTS_READ, STANDARD_RIGHTS_WRITE, STANDARD_RIGHTS_EXECUTE, \
|
||||
WRITE_OWNER, WRITE_DAC, READ_CONTROL, \
|
||||
SI_ADVANCED, SI_EDIT_AUDITS, SI_EDIT_PROPERTIES, SI_EDIT_ALL, SI_PAGE_TITLE, SI_RESET, \
|
||||
SI_ACCESS_SPECIFIC, SI_ACCESS_GENERAL, SI_ACCESS_CONTAINER, SI_ACCESS_PROPERTY, \
|
||||
OBJECT_INHERIT_ACE, CONTAINER_INHERIT_ACE, INHERIT_ONLY_ACE, \
|
||||
SI_PAGE_PERM, SI_PAGE_ADVPERM, SI_PAGE_AUDIT, SI_PAGE_OWNER, PSPCB_SI_INITDIALOG, \
|
||||
SI_CONTAINER
|
||||
from win32security import OBJECT_INHERIT_ACE, CONTAINER_INHERIT_ACE, INHERIT_ONLY_ACE
|
||||
from win32com.shell.shellcon import PSPCB_RELEASE, PSPCB_CREATE ## Msg parameter to PropertySheetPageCallback
|
||||
from pythoncom import IID_NULL
|
||||
|
||||
|
||||
class ServiceSecurity(win32com.server.policy.DesignatedWrapPolicy):
|
||||
_com_interfaces_=[authorization.IID_ISecurityInformation]
|
||||
_public_methods_=['GetObjectInformation','GetSecurity','SetSecurity','GetAccessRights',
|
||||
'GetInheritTypes','MapGeneric','PropertySheetPageCallback']
|
||||
|
||||
def __init__(self, ServiceName):
|
||||
self.ServiceName=ServiceName
|
||||
self._wrap_(self)
|
||||
|
||||
def GetObjectInformation(self):
|
||||
"""Identifies object whose security will be modified, and determines options available
|
||||
to the end user"""
|
||||
flags=SI_ADVANCED|SI_EDIT_ALL|SI_PAGE_TITLE|SI_RESET
|
||||
hinstance=0 ## handle to module containing string resources
|
||||
servername='' ## name of authenticating server if not local machine
|
||||
|
||||
## service name can contain remote machine name of the form \\Server\ServiceName
|
||||
objectname=os.path.split(self.ServiceName)[1]
|
||||
pagetitle='Service Permissions for '+self.ServiceName
|
||||
objecttype=IID_NULL
|
||||
return flags, hinstance, servername, objectname, pagetitle, objecttype
|
||||
|
||||
def GetSecurity(self, requestedinfo, bdefault):
|
||||
"""Requests the existing permissions for object"""
|
||||
if bdefault:
|
||||
return win32security.SECURITY_DESCRIPTOR()
|
||||
else:
|
||||
return win32security.GetNamedSecurityInfo(self.ServiceName, win32security.SE_SERVICE, requestedinfo)
|
||||
|
||||
def SetSecurity(self, requestedinfo, sd):
|
||||
"""Applies permissions to the object"""
|
||||
owner=sd.GetSecurityDescriptorOwner()
|
||||
group=sd.GetSecurityDescriptorGroup()
|
||||
dacl=sd.GetSecurityDescriptorDacl()
|
||||
sacl=sd.GetSecurityDescriptorSacl()
|
||||
win32security.SetNamedSecurityInfo(self.ServiceName, win32security.SE_SERVICE, requestedinfo,
|
||||
owner, group, dacl, sacl)
|
||||
|
||||
def GetAccessRights(self, objecttype, flags):
|
||||
"""Returns a tuple of (AccessRights, DefaultAccess), where AccessRights is a sequence of tuples representing
|
||||
SI_ACCESS structs, containing (guid, access mask, Name, flags). DefaultAccess indicates which of the
|
||||
AccessRights will be used initially when a new ACE is added (zero based).
|
||||
Flags can contain SI_ACCESS_SPECIFIC,SI_ACCESS_GENERAL,SI_ACCESS_CONTAINER,SI_ACCESS_PROPERTY,
|
||||
CONTAINER_INHERIT_ACE,INHERIT_ONLY_ACE,OBJECT_INHERIT_ACE
|
||||
"""
|
||||
## input flags: SI_ADVANCED,SI_EDIT_AUDITS,SI_EDIT_PROPERTIES indicating which property sheet is requesting the rights
|
||||
if (objecttype is not None) and (objecttype!=IID_NULL):
|
||||
## Not relevent for services
|
||||
raise NotImplementedError("Object type is not supported")
|
||||
|
||||
## ???? for some reason, the DACL for a service will not retain ACCESS_SYSTEM_SECURITY in an ACE ????
|
||||
## (IID_NULL, win32con.ACCESS_SYSTEM_SECURITY, 'View/change audit settings', SI_ACCESS_SPECIFIC),
|
||||
|
||||
accessrights=[
|
||||
(IID_NULL, win32service.SERVICE_ALL_ACCESS, 'Full control', SI_ACCESS_GENERAL),
|
||||
(IID_NULL, SERVICE_GENERIC_READ, 'Generic read', SI_ACCESS_GENERAL),
|
||||
(IID_NULL, SERVICE_GENERIC_WRITE, 'Generic write', SI_ACCESS_GENERAL),
|
||||
(IID_NULL, SERVICE_GENERIC_EXECUTE, 'Start/Stop/Pause service', SI_ACCESS_GENERAL),
|
||||
(IID_NULL, READ_CONTROL, 'Read Permissions', SI_ACCESS_GENERAL),
|
||||
(IID_NULL, WRITE_DAC, 'Change permissions', SI_ACCESS_GENERAL),
|
||||
(IID_NULL, WRITE_OWNER, 'Change owner', SI_ACCESS_GENERAL),
|
||||
(IID_NULL, win32con.DELETE, 'Delete service', SI_ACCESS_GENERAL),
|
||||
(IID_NULL, win32service.SERVICE_START, 'Start service', SI_ACCESS_SPECIFIC),
|
||||
(IID_NULL, win32service.SERVICE_STOP, 'Stop service', SI_ACCESS_SPECIFIC),
|
||||
(IID_NULL, win32service.SERVICE_PAUSE_CONTINUE, 'Pause/unpause service', SI_ACCESS_SPECIFIC),
|
||||
(IID_NULL, win32service.SERVICE_USER_DEFINED_CONTROL, 'Execute user defined operations', SI_ACCESS_SPECIFIC),
|
||||
(IID_NULL, win32service.SERVICE_QUERY_CONFIG, 'Read configuration', SI_ACCESS_SPECIFIC),
|
||||
(IID_NULL, win32service.SERVICE_CHANGE_CONFIG, 'Change configuration', SI_ACCESS_SPECIFIC),
|
||||
(IID_NULL, win32service.SERVICE_ENUMERATE_DEPENDENTS, 'List dependent services', SI_ACCESS_SPECIFIC),
|
||||
(IID_NULL, win32service.SERVICE_QUERY_STATUS, 'Query status', SI_ACCESS_SPECIFIC),
|
||||
(IID_NULL, win32service.SERVICE_INTERROGATE, 'Query status (immediate)', SI_ACCESS_SPECIFIC),
|
||||
]
|
||||
return (accessrights, 0)
|
||||
|
||||
def MapGeneric(self, guid, aceflags, mask):
|
||||
""" Converts generic access rights to specific rights.
|
||||
"""
|
||||
return win32security.MapGenericMask(mask,
|
||||
(SERVICE_GENERIC_READ, SERVICE_GENERIC_WRITE, SERVICE_GENERIC_EXECUTE, win32service.SERVICE_ALL_ACCESS))
|
||||
|
||||
def GetInheritTypes(self):
|
||||
"""Specifies which types of ACE inheritance are supported.
|
||||
Services don't use any inheritance
|
||||
"""
|
||||
return ((IID_NULL, 0, 'Only current object'),)
|
||||
|
||||
def PropertySheetPageCallback(self, hwnd, msg, pagetype):
|
||||
"""Invoked each time a property sheet page is created or destroyed."""
|
||||
## page types from SI_PAGE_TYPE enum: SI_PAGE_PERM SI_PAGE_ADVPERM SI_PAGE_AUDIT SI_PAGE_OWNER
|
||||
## msg: PSPCB_CREATE, PSPCB_RELEASE, PSPCB_SI_INITDIALOG
|
||||
return None
|
||||
|
||||
def EditSecurity(self, owner_hwnd=0):
|
||||
"""Creates an ACL editor dialog based on parameters returned by interface methods"""
|
||||
isi=pythoncom.WrapObject(self, authorization.IID_ISecurityInformation, pythoncom.IID_IUnknown)
|
||||
authorization.EditSecurity(owner_hwnd, isi)
|
||||
|
||||
if __name__=='__main__':
|
||||
# Find the first service on local machine and edit its permissions
|
||||
scm = win32service.OpenSCManager(None, None, win32service.SC_MANAGER_ENUMERATE_SERVICE)
|
||||
svcs=win32service.EnumServicesStatus(scm)
|
||||
win32service.CloseServiceHandle(scm)
|
||||
si=ServiceSecurity(svcs[0][0])
|
||||
si.EditSecurity()
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
4
venv/Lib/site-packages/win32comext/axcontrol/__init__.py
Normal file
4
venv/Lib/site-packages/win32comext/axcontrol/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
|||
# See if we have a special directory for the binaries (for developers)
|
||||
import win32com
|
||||
win32com.__PackageSupportBuildPath__(__path__)
|
||||
|
Binary file not shown.
BIN
venv/Lib/site-packages/win32comext/axcontrol/axcontrol.pyd
Normal file
BIN
venv/Lib/site-packages/win32comext/axcontrol/axcontrol.pyd
Normal file
Binary file not shown.
3
venv/Lib/site-packages/win32comext/axdebug/__init__.py
Normal file
3
venv/Lib/site-packages/win32comext/axdebug/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
# See if we have a special directory for the binaries (for developers)
|
||||
import win32com
|
||||
win32com.__PackageSupportBuildPath__(__path__)
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
416
venv/Lib/site-packages/win32comext/axdebug/adb.py
Normal file
416
venv/Lib/site-packages/win32comext/axdebug/adb.py
Normal file
|
@ -0,0 +1,416 @@
|
|||
"""The glue between the Python debugger interface and the Active Debugger interface
|
||||
"""
|
||||
from win32com.axdebug.util import trace, _wrap, _wrap_remove
|
||||
from win32com.server.util import unwrap
|
||||
import win32com.client.connect
|
||||
from . import gateways
|
||||
import sys, bdb, traceback
|
||||
from . import axdebug, stackframe
|
||||
import win32api, pythoncom
|
||||
import _thread, os
|
||||
|
||||
def fnull(*args):
|
||||
pass
|
||||
|
||||
try:
|
||||
os.environ["DEBUG_AXDEBUG"]
|
||||
debugging = 1
|
||||
except KeyError:
|
||||
debugging = 0
|
||||
|
||||
traceenter = fnull # trace enter of functions
|
||||
tracev = fnull # verbose trace
|
||||
|
||||
if debugging:
|
||||
traceenter = trace # trace enter of functions
|
||||
tracev = trace # verbose trace
|
||||
|
||||
class OutputReflector:
|
||||
def __init__(self, file, writefunc):
|
||||
self.writefunc = writefunc
|
||||
self.file = file
|
||||
def __getattr__(self,name):
|
||||
return getattr(self.file, name)
|
||||
def write(self,message):
|
||||
self.writefunc(message)
|
||||
self.file.write(message)
|
||||
|
||||
def _dumpf(frame):
|
||||
if frame is None:
|
||||
return "<None>"
|
||||
else:
|
||||
addn = "(with trace!)"
|
||||
if frame.f_trace is None:
|
||||
addn = " **No Trace Set **"
|
||||
return "Frame at %d, file %s, line: %d%s" % (id(frame), frame.f_code.co_filename, frame.f_lineno, addn)
|
||||
|
||||
g_adb = None
|
||||
|
||||
def OnSetBreakPoint(codeContext, breakPointState, lineNo):
|
||||
try:
|
||||
fileName = codeContext.codeContainer.GetFileName()
|
||||
# inject the code into linecache.
|
||||
import linecache
|
||||
linecache.cache[fileName] = 0, 0, codeContext.codeContainer.GetText(), fileName
|
||||
g_adb._OnSetBreakPoint(fileName, codeContext, breakPointState, lineNo+1)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
class Adb(bdb.Bdb,gateways.RemoteDebugApplicationEvents):
|
||||
def __init__(self):
|
||||
self.debugApplication = None
|
||||
self.debuggingThread = None
|
||||
self.debuggingThreadStateHandle = None
|
||||
self.stackSnifferCookie = self.stackSniffer = None
|
||||
self.codeContainerProvider = None
|
||||
self.debuggingThread = None
|
||||
self.breakFlags = None
|
||||
self.breakReason = None
|
||||
self.appDebugger = None
|
||||
self.appEventConnection = None
|
||||
self.logicalbotframe = None # Anything at this level or below does not exist!
|
||||
self.currentframe = None # The frame we are currently in.
|
||||
self.recursiveData = [] # Data saved for each reentery on this thread.
|
||||
bdb.Bdb.__init__(self)
|
||||
self._threadprotectlock = _thread.allocate_lock()
|
||||
self.reset()
|
||||
|
||||
def canonic(self, fname):
|
||||
if fname[0]=='<':
|
||||
return fname
|
||||
return bdb.Bdb.canonic(self, fname)
|
||||
|
||||
def reset(self):
|
||||
traceenter("adb.reset")
|
||||
bdb.Bdb.reset(self)
|
||||
|
||||
def __xxxxx__set_break(self, filename, lineno, cond = None):
|
||||
# As per standard one, except no linecache checking!
|
||||
if filename not in self.breaks:
|
||||
self.breaks[filename] = []
|
||||
list = self.breaks[filename]
|
||||
if lineno in list:
|
||||
return 'There is already a breakpoint there!'
|
||||
list.append(lineno)
|
||||
if cond is not None: self.cbreaks[filename, lineno]=cond
|
||||
|
||||
def stop_here(self, frame):
|
||||
traceenter("stop_here", _dumpf(frame), _dumpf(self.stopframe))
|
||||
# As per bdb.stop_here, except for logicalbotframe
|
||||
## if self.stopframe is None:
|
||||
## return 1
|
||||
if frame is self.stopframe:
|
||||
return 1
|
||||
|
||||
tracev("stop_here said 'No'!")
|
||||
return 0
|
||||
|
||||
def break_here(self, frame):
|
||||
traceenter("break_here", self.breakFlags, _dumpf(frame))
|
||||
self.breakReason = None
|
||||
if self.breakFlags==axdebug.APPBREAKFLAG_DEBUGGER_HALT:
|
||||
self.breakReason = axdebug.BREAKREASON_DEBUGGER_HALT
|
||||
elif self.breakFlags==axdebug.APPBREAKFLAG_DEBUGGER_BLOCK:
|
||||
self.breakReason = axdebug.BREAKREASON_DEBUGGER_BLOCK
|
||||
elif self.breakFlags==axdebug.APPBREAKFLAG_STEP:
|
||||
self.breakReason = axdebug.BREAKREASON_STEP
|
||||
else:
|
||||
print("Calling base 'break_here' with", self.breaks)
|
||||
if bdb.Bdb.break_here(self, frame):
|
||||
self.breakReason = axdebug.BREAKREASON_BREAKPOINT
|
||||
return self.breakReason is not None
|
||||
|
||||
def break_anywhere(self, frame):
|
||||
traceenter("break_anywhere", _dumpf(frame))
|
||||
if self.breakFlags==axdebug.APPBREAKFLAG_DEBUGGER_HALT:
|
||||
self.breakReason = axdebug.BREAKREASON_DEBUGGER_HALT
|
||||
return 1
|
||||
rc = bdb.Bdb.break_anywhere(self, frame)
|
||||
tracev("break_anywhere",_dumpf(frame),"returning",rc)
|
||||
return rc
|
||||
|
||||
def dispatch_return(self, frame, arg):
|
||||
traceenter("dispatch_return", _dumpf(frame), arg)
|
||||
if self.logicalbotframe is frame:
|
||||
# We dont want to debug parent frames.
|
||||
tracev("dispatch_return resetting sys.trace")
|
||||
sys.settrace(None)
|
||||
return
|
||||
# self.bSetTrace = 0
|
||||
self.currentframe = frame.f_back
|
||||
return bdb.Bdb.dispatch_return(self, frame, arg)
|
||||
|
||||
def dispatch_line(self, frame):
|
||||
traceenter("dispatch_line", _dumpf(frame), _dumpf(self.botframe))
|
||||
# trace("logbotframe is", _dumpf(self.logicalbotframe), "botframe is", self.botframe)
|
||||
if frame is self.logicalbotframe:
|
||||
trace("dispatch_line", _dumpf(frame), "for bottom frame returing tracer")
|
||||
# The next code executed in the frame above may be a builtin (eg, apply())
|
||||
# in which sys.trace needs to be set.
|
||||
sys.settrace(self.trace_dispatch)
|
||||
# And return the tracer incase we are about to execute Python code,
|
||||
# in which case sys tracer is ignored!
|
||||
return self.trace_dispatch
|
||||
|
||||
if self.codeContainerProvider.FromFileName(frame.f_code.co_filename) is None:
|
||||
trace("dispatch_line has no document for", _dumpf(frame), "- skipping trace!")
|
||||
return None
|
||||
self.currentframe = frame # So the stack sniffer knows our most recent, debuggable code.
|
||||
return bdb.Bdb.dispatch_line(self, frame)
|
||||
|
||||
def dispatch_call(self, frame, arg):
|
||||
traceenter("dispatch_call",_dumpf(frame))
|
||||
frame.f_locals['__axstack_address__'] = axdebug.GetStackAddress()
|
||||
if frame is self.botframe:
|
||||
trace("dispatch_call is self.botframe - returning tracer")
|
||||
return self.trace_dispatch
|
||||
# Not our bottom frame. If we have a document for it,
|
||||
# then trace it, otherwise run at full speed.
|
||||
if self.codeContainerProvider.FromFileName(frame.f_code.co_filename) is None:
|
||||
trace("dispatch_call has no document for", _dumpf(frame), "- skipping trace!")
|
||||
## sys.settrace(None)
|
||||
return None
|
||||
return self.trace_dispatch
|
||||
|
||||
# rc = bdb.Bdb.dispatch_call(self, frame, arg)
|
||||
# trace("dispatch_call", _dumpf(frame),"returned",rc)
|
||||
# return rc
|
||||
|
||||
def trace_dispatch(self, frame, event, arg):
|
||||
traceenter("trace_dispatch", _dumpf(frame), event, arg)
|
||||
if self.debugApplication is None:
|
||||
trace("trace_dispatch has no application!")
|
||||
return # None
|
||||
return bdb.Bdb.trace_dispatch(self, frame, event, arg)
|
||||
|
||||
|
||||
#
|
||||
# The user functions do bugger all!
|
||||
#
|
||||
# def user_call(self, frame, argument_list):
|
||||
# traceenter("user_call",_dumpf(frame))
|
||||
|
||||
def user_line(self, frame):
|
||||
traceenter("user_line",_dumpf(frame))
|
||||
# Traces at line zero
|
||||
if frame.f_lineno!=0:
|
||||
breakReason = self.breakReason
|
||||
if breakReason is None:
|
||||
breakReason = axdebug.BREAKREASON_STEP
|
||||
self._HandleBreakPoint(frame, None, breakReason)
|
||||
|
||||
def user_return(self, frame, return_value):
|
||||
# traceenter("user_return",_dumpf(frame),return_value)
|
||||
bdb.Bdb.user_return(self, frame, return_value)
|
||||
|
||||
def user_exception(self, frame, exc_info):
|
||||
# traceenter("user_exception")
|
||||
bdb.Bdb.user_exception(self, frame, exc_info)
|
||||
|
||||
|
||||
def _HandleBreakPoint(self, frame, tb, reason):
|
||||
traceenter("Calling HandleBreakPoint with reason", reason,"at frame", _dumpf(frame))
|
||||
traceenter(" Current frame is", _dumpf(self.currentframe))
|
||||
try:
|
||||
resumeAction = self.debugApplication.HandleBreakPoint(reason)
|
||||
tracev("HandleBreakPoint returned with ", resumeAction)
|
||||
except pythoncom.com_error as details:
|
||||
# Eeek - the debugger is dead, or something serious is happening.
|
||||
# Assume we should continue
|
||||
resumeAction = axdebug.BREAKRESUMEACTION_CONTINUE
|
||||
trace("HandleBreakPoint FAILED with", details)
|
||||
|
||||
self.stack = []
|
||||
self.curindex = 0
|
||||
if resumeAction == axdebug.BREAKRESUMEACTION_ABORT:
|
||||
self.set_quit()
|
||||
elif resumeAction == axdebug.BREAKRESUMEACTION_CONTINUE:
|
||||
tracev("resume action is continue")
|
||||
self.set_continue()
|
||||
elif resumeAction == axdebug.BREAKRESUMEACTION_STEP_INTO:
|
||||
tracev("resume action is step")
|
||||
self.set_step()
|
||||
elif resumeAction == axdebug.BREAKRESUMEACTION_STEP_OVER:
|
||||
tracev("resume action is next")
|
||||
self.set_next(frame)
|
||||
elif resumeAction == axdebug.BREAKRESUMEACTION_STEP_OUT:
|
||||
tracev("resume action is stop out")
|
||||
self.set_return(frame)
|
||||
else:
|
||||
raise ValueError("unknown resume action flags")
|
||||
self.breakReason = None
|
||||
|
||||
def set_trace(self):
|
||||
self.breakReason = axdebug.BREAKREASON_LANGUAGE_INITIATED
|
||||
bdb.Bdb.set_trace(self)
|
||||
|
||||
def CloseApp(self):
|
||||
traceenter("ClosingApp")
|
||||
self.reset()
|
||||
self.logicalbotframe = None
|
||||
if self.stackSnifferCookie is not None:
|
||||
try:
|
||||
self.debugApplication.RemoveStackFrameSniffer(self.stackSnifferCookie)
|
||||
|
||||
except pythoncom.com_error:
|
||||
trace("*** Could not RemoveStackFrameSniffer %d" % (self.stackSnifferCookie))
|
||||
if self.stackSniffer:
|
||||
_wrap_remove(self.stackSniffer)
|
||||
self.stackSnifferCookie = self.stackSniffer = None
|
||||
|
||||
if self.appEventConnection is not None:
|
||||
self.appEventConnection.Disconnect()
|
||||
self.appEventConnection = None
|
||||
self.debugApplication = None
|
||||
self.appDebugger = None
|
||||
if self.codeContainerProvider is not None:
|
||||
self.codeContainerProvider.Close()
|
||||
self.codeContainerProvider = None
|
||||
|
||||
def AttachApp(self, debugApplication, codeContainerProvider):
|
||||
# traceenter("AttachApp", debugApplication, codeContainerProvider)
|
||||
self.codeContainerProvider = codeContainerProvider
|
||||
self.debugApplication = debugApplication
|
||||
self.stackSniffer = _wrap(stackframe.DebugStackFrameSniffer(self), axdebug.IID_IDebugStackFrameSniffer)
|
||||
self.stackSnifferCookie = debugApplication.AddStackFrameSniffer(self.stackSniffer)
|
||||
# trace("StackFrameSniffer added (%d)" % self.stackSnifferCookie)
|
||||
|
||||
# Connect to the application events.
|
||||
self.appEventConnection = win32com.client.connect.SimpleConnection(self.debugApplication, self, axdebug.IID_IRemoteDebugApplicationEvents)
|
||||
|
||||
def ResetAXDebugging(self):
|
||||
traceenter("ResetAXDebugging", self, "with refcount", len(self.recursiveData))
|
||||
if win32api.GetCurrentThreadId()!=self.debuggingThread:
|
||||
trace("ResetAXDebugging called on other thread")
|
||||
return
|
||||
|
||||
if len(self.recursiveData)==0:
|
||||
# print "ResetAXDebugging called for final time."
|
||||
self.logicalbotframe = None
|
||||
self.debuggingThread = None
|
||||
self.currentframe = None
|
||||
self.debuggingThreadStateHandle = None
|
||||
return
|
||||
|
||||
self.logbotframe, self.stopframe, self.currentframe, self.debuggingThreadStateHandle = self.recursiveData[0]
|
||||
self.recursiveData = self.recursiveData[1:]
|
||||
|
||||
def SetupAXDebugging(self, baseFrame = None, userFrame = None):
|
||||
"""Get ready for potential debugging. Must be called on the thread
|
||||
that is being debugged.
|
||||
"""
|
||||
# userFrame is for non AXScript debugging. This is the first frame of the
|
||||
# users code.
|
||||
if userFrame is None:
|
||||
userFrame = baseFrame
|
||||
else:
|
||||
# We have missed the "dispatch_call" function, so set this up now!
|
||||
userFrame.f_locals['__axstack_address__'] = axdebug.GetStackAddress()
|
||||
|
||||
traceenter("SetupAXDebugging", self)
|
||||
self._threadprotectlock.acquire()
|
||||
try:
|
||||
thisThread = win32api.GetCurrentThreadId()
|
||||
if self.debuggingThread is None:
|
||||
self.debuggingThread = thisThread
|
||||
else:
|
||||
if self.debuggingThread!=thisThread:
|
||||
trace("SetupAXDebugging called on other thread - ignored!")
|
||||
return
|
||||
# push our context.
|
||||
self.recursiveData.insert(0, (self.logicalbotframe,self.stopframe, self.currentframe,self.debuggingThreadStateHandle))
|
||||
finally:
|
||||
self._threadprotectlock.release()
|
||||
|
||||
trace("SetupAXDebugging has base frame as", _dumpf(baseFrame))
|
||||
self.botframe = baseFrame
|
||||
self.stopframe = userFrame
|
||||
self.logicalbotframe = baseFrame
|
||||
self.currentframe = None
|
||||
self.debuggingThreadStateHandle = axdebug.GetThreadStateHandle()
|
||||
|
||||
self._BreakFlagsChanged()
|
||||
|
||||
# RemoteDebugApplicationEvents
|
||||
def OnConnectDebugger(self, appDebugger):
|
||||
traceenter("OnConnectDebugger", appDebugger)
|
||||
self.appDebugger = appDebugger
|
||||
# Reflect output to appDebugger
|
||||
writefunc = lambda s: appDebugger.onDebugOutput(s)
|
||||
sys.stdout = OutputReflector(sys.stdout, writefunc)
|
||||
sys.stderr = OutputReflector(sys.stderr, writefunc)
|
||||
|
||||
def OnDisconnectDebugger(self):
|
||||
traceenter("OnDisconnectDebugger")
|
||||
# Stop reflecting output
|
||||
if isinstance(sys.stdout, OutputReflector):
|
||||
sys.stdout = sys.stdout.file
|
||||
if isinstance(sys.stderr, OutputReflector):
|
||||
sys.stderr = sys.stderr.file
|
||||
self.appDebugger = None
|
||||
self.set_quit()
|
||||
|
||||
def OnSetName(self, name):
|
||||
traceenter("OnSetName", name)
|
||||
def OnDebugOutput(self, string):
|
||||
traceenter("OnDebugOutput", string)
|
||||
def OnClose(self):
|
||||
traceenter("OnClose")
|
||||
def OnEnterBreakPoint(self, rdat):
|
||||
traceenter("OnEnterBreakPoint", rdat)
|
||||
def OnLeaveBreakPoint(self, rdat):
|
||||
traceenter("OnLeaveBreakPoint", rdat)
|
||||
def OnCreateThread(self, rdat):
|
||||
traceenter("OnCreateThread", rdat)
|
||||
def OnDestroyThread(self, rdat):
|
||||
traceenter("OnDestroyThread", rdat)
|
||||
def OnBreakFlagChange(self, abf, rdat):
|
||||
traceenter("Debugger OnBreakFlagChange", abf, rdat)
|
||||
self.breakFlags = abf
|
||||
self._BreakFlagsChanged()
|
||||
|
||||
def _BreakFlagsChanged(self):
|
||||
traceenter("_BreakFlagsChanged to %s with our thread = %s, and debugging thread = %s" % (self.breakFlags, self.debuggingThread, win32api.GetCurrentThreadId()))
|
||||
trace("_BreakFlagsChanged has breaks", self.breaks)
|
||||
# If a request comes on our debugging thread, then do it now!
|
||||
# if self.debuggingThread!=win32api.GetCurrentThreadId():
|
||||
# return
|
||||
|
||||
if len(self.breaks) or self.breakFlags:
|
||||
|
||||
if self.logicalbotframe:
|
||||
trace("BreakFlagsChange with bot frame", _dumpf(self.logicalbotframe))
|
||||
# We have frames not to be debugged (eg, Scripting engine frames
|
||||
# (sys.settrace will be set when out logicalbotframe is hit -
|
||||
# this may not be the right thing to do, as it may not cause the
|
||||
# immediate break we desire.)
|
||||
self.logicalbotframe.f_trace = self.trace_dispatch
|
||||
else:
|
||||
trace("BreakFlagsChanged, but no bottom frame")
|
||||
if self.stopframe is not None:
|
||||
self.stopframe.f_trace = self.trace_dispatch
|
||||
# If we have the thread-state for the thread being debugged, then
|
||||
# we dynamically set its trace function - it is possible that the thread
|
||||
# being debugged is in a blocked call (eg, a message box) and we
|
||||
# want to hit the debugger the instant we return
|
||||
if self.debuggingThreadStateHandle is not None and \
|
||||
self.breakFlags and \
|
||||
self.debuggingThread != win32api.GetCurrentThreadId():
|
||||
axdebug.SetThreadStateTrace(self.debuggingThreadStateHandle, self.trace_dispatch)
|
||||
def _OnSetBreakPoint(self, key, codeContext, bps, lineNo):
|
||||
traceenter("_OnSetBreakPoint", self, key, codeContext, bps, lineNo)
|
||||
if bps==axdebug.BREAKPOINT_ENABLED:
|
||||
problem = self.set_break(key, lineNo)
|
||||
if problem:
|
||||
print("*** set_break failed -", problem)
|
||||
trace("_OnSetBreakPoint just set BP and has breaks", self.breaks)
|
||||
else:
|
||||
self.clear_break(key, lineNo)
|
||||
self._BreakFlagsChanged()
|
||||
trace("_OnSetBreakPoint leaving with breaks", self.breaks)
|
||||
|
||||
def Debugger():
|
||||
global g_adb
|
||||
if g_adb is None:
|
||||
g_adb = Adb()
|
||||
return g_adb
|
BIN
venv/Lib/site-packages/win32comext/axdebug/axdebug.pyd
Normal file
BIN
venv/Lib/site-packages/win32comext/axdebug/axdebug.pyd
Normal file
Binary file not shown.
254
venv/Lib/site-packages/win32comext/axdebug/codecontainer.py
Normal file
254
venv/Lib/site-packages/win32comext/axdebug/codecontainer.py
Normal file
|
@ -0,0 +1,254 @@
|
|||
"""A utility class for a code container.
|
||||
|
||||
A code container is a class which holds source code for a debugger. It knows how
|
||||
to color the text, and also how to translate lines into offsets, and back.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from win32com.axdebug import axdebug
|
||||
import tokenize
|
||||
from .util import RaiseNotImpl, _wrap
|
||||
|
||||
from win32com.server.exception import Exception
|
||||
import win32api, winerror
|
||||
from . import contexts
|
||||
|
||||
_keywords = {} # set of Python keywords
|
||||
for name in """
|
||||
and assert break class continue def del elif else except exec
|
||||
finally for from global if import in is lambda not
|
||||
or pass print raise return try while
|
||||
""".split():
|
||||
_keywords[name] = 1
|
||||
|
||||
class SourceCodeContainer:
|
||||
def __init__(self, text, fileName = "<Remove Me!>", sourceContext = 0, startLineNumber = 0, site = None, debugDocument = None):
|
||||
self.sourceContext = sourceContext # The source context added by a smart host.
|
||||
self.text = text
|
||||
if text:
|
||||
self._buildlines()
|
||||
self.nextLineNo = 0
|
||||
self.fileName = fileName
|
||||
self.codeContexts = {}
|
||||
self.site = site
|
||||
self.startLineNumber = startLineNumber
|
||||
self.debugDocument = None
|
||||
def _Close(self):
|
||||
self.text = self.lines = self.lineOffsets = None
|
||||
self.codeContexts = None
|
||||
self.debugDocument = None
|
||||
self.site = None
|
||||
self.sourceContext = None
|
||||
|
||||
def GetText(self):
|
||||
return self.text
|
||||
def GetName(self, dnt):
|
||||
assert 0, "You must subclass this"
|
||||
def GetFileName(self):
|
||||
return self.fileName
|
||||
|
||||
def GetPositionOfLine(self, cLineNumber):
|
||||
self.GetText() # Prime us.
|
||||
try:
|
||||
return self.lineOffsets[cLineNumber]
|
||||
except IndexError:
|
||||
raise Exception(scode=winerror.S_FALSE)
|
||||
def GetLineOfPosition(self, charPos):
|
||||
self.GetText() # Prime us.
|
||||
lastOffset = 0
|
||||
lineNo = 0
|
||||
for lineOffset in self.lineOffsets[1:]:
|
||||
if lineOffset > charPos:
|
||||
break
|
||||
lastOffset = lineOffset
|
||||
lineNo = lineNo + 1
|
||||
else: # for not broken.
|
||||
# print "Cant find", charPos, "in", self.lineOffsets
|
||||
raise Exception(scode=winerror.S_FALSE)
|
||||
# print "GLOP ret=",lineNo, (charPos-lastOffset)
|
||||
return lineNo, (charPos-lastOffset)
|
||||
|
||||
def GetNextLine(self):
|
||||
if self.nextLineNo>=len(self.lines):
|
||||
self.nextLineNo = 0 # auto-reset.
|
||||
return ""
|
||||
rc = self.lines[self.nextLineNo]
|
||||
self.nextLineNo = self.nextLineNo + 1
|
||||
return rc
|
||||
|
||||
def GetLine(self, num):
|
||||
self.GetText() # Prime us.
|
||||
return self.lines[num]
|
||||
|
||||
def GetNumChars(self):
|
||||
return len(self.GetText())
|
||||
|
||||
def GetNumLines(self):
|
||||
self.GetText() # Prime us.
|
||||
return len(self.lines)
|
||||
|
||||
def _buildline(self, pos):
|
||||
i = self.text.find('\n', pos)
|
||||
if i < 0:
|
||||
newpos = len(self.text)
|
||||
else:
|
||||
newpos = i+1
|
||||
r = self.text[pos:newpos]
|
||||
return r, newpos
|
||||
|
||||
def _buildlines(self):
|
||||
self.lines = []
|
||||
self.lineOffsets = [0]
|
||||
line, pos = self._buildline(0)
|
||||
while line:
|
||||
self.lines.append(line)
|
||||
self.lineOffsets.append(pos)
|
||||
line, pos = self._buildline(pos)
|
||||
|
||||
def _ProcessToken(self, type, token, spos, epos, line):
|
||||
srow, scol = spos
|
||||
erow, ecol = epos
|
||||
self.GetText() # Prime us.
|
||||
linenum = srow - 1 # Lines zero based for us too.
|
||||
realCharPos = self.lineOffsets[linenum] + scol
|
||||
numskipped = realCharPos - self.lastPos
|
||||
if numskipped==0:
|
||||
pass
|
||||
elif numskipped==1:
|
||||
self.attrs.append(axdebug.SOURCETEXT_ATTR_COMMENT)
|
||||
else:
|
||||
self.attrs.append((axdebug.SOURCETEXT_ATTR_COMMENT, numskipped))
|
||||
kwSize = len(token)
|
||||
self.lastPos = realCharPos + kwSize
|
||||
attr = 0
|
||||
|
||||
if type==tokenize.NAME:
|
||||
if token in _keywords:
|
||||
attr = axdebug.SOURCETEXT_ATTR_KEYWORD
|
||||
elif type==tokenize.STRING:
|
||||
attr = axdebug.SOURCETEXT_ATTR_STRING
|
||||
elif type==tokenize.NUMBER:
|
||||
attr = axdebug.SOURCETEXT_ATTR_NUMBER
|
||||
elif type==tokenize.OP:
|
||||
attr = axdebug.SOURCETEXT_ATTR_OPERATOR
|
||||
elif type==tokenize.COMMENT:
|
||||
attr = axdebug.SOURCETEXT_ATTR_COMMENT
|
||||
# else attr remains zero...
|
||||
if kwSize==0:
|
||||
pass
|
||||
elif kwSize==1:
|
||||
self.attrs.append(attr)
|
||||
else:
|
||||
self.attrs.append((attr, kwSize))
|
||||
|
||||
def GetSyntaxColorAttributes(self):
|
||||
self.lastPos = 0
|
||||
self.attrs = []
|
||||
try:
|
||||
tokenize.tokenize(self.GetNextLine, self._ProcessToken)
|
||||
except tokenize.TokenError:
|
||||
pass # Ignore - will cause all subsequent text to be commented.
|
||||
numAtEnd = len(self.GetText()) - self.lastPos
|
||||
if numAtEnd:
|
||||
self.attrs.append((axdebug.SOURCETEXT_ATTR_COMMENT, numAtEnd))
|
||||
return self.attrs
|
||||
|
||||
# We also provide and manage DebugDocumentContext objects
|
||||
def _MakeDebugCodeContext(self, lineNo, charPos, len):
|
||||
return _wrap(contexts.DebugCodeContext(lineNo, charPos, len, self, self.site), axdebug.IID_IDebugCodeContext)
|
||||
# Make a context at the given position. It should take up the entire context.
|
||||
def _MakeContextAtPosition(self, charPos):
|
||||
lineNo, offset = self.GetLineOfPosition(charPos)
|
||||
try:
|
||||
endPos = self.GetPositionOfLine(lineNo+1)
|
||||
except:
|
||||
endPos = charPos
|
||||
codecontext = self._MakeDebugCodeContext(lineNo, charPos, endPos-charPos)
|
||||
return codecontext
|
||||
|
||||
# Returns a DebugCodeContext. debugDocument can be None for smart hosts.
|
||||
def GetCodeContextAtPosition(self, charPos):
|
||||
# trace("GetContextOfPos", charPos, maxChars)
|
||||
# Convert to line number.
|
||||
lineNo, offset = self.GetLineOfPosition(charPos)
|
||||
charPos = self.GetPositionOfLine(lineNo)
|
||||
try:
|
||||
cc = self.codeContexts[charPos]
|
||||
# trace(" GetContextOfPos using existing")
|
||||
except KeyError:
|
||||
cc = self._MakeContextAtPosition(charPos)
|
||||
self.codeContexts[charPos] = cc
|
||||
return cc
|
||||
|
||||
class SourceModuleContainer(SourceCodeContainer):
|
||||
def __init__(self, module):
|
||||
self.module = module
|
||||
if hasattr(module, '__file__'):
|
||||
fname = self.module.__file__
|
||||
# Check for .pyc or .pyo or even .pys!
|
||||
if fname[-1] in ['O','o','C','c', 'S', 's']: fname = fname[:-1]
|
||||
try:
|
||||
fname = win32api.GetFullPathName(fname)
|
||||
except win32api.error:
|
||||
pass
|
||||
else:
|
||||
if module.__name__=='__main__' and len(sys.argv)>0:
|
||||
fname = sys.argv[0]
|
||||
else:
|
||||
fname = "<Unknown!>"
|
||||
SourceCodeContainer.__init__(self, None, fname)
|
||||
|
||||
def GetText(self):
|
||||
if self.text is None:
|
||||
fname = self.GetFileName()
|
||||
if fname:
|
||||
try:
|
||||
self.text = open(fname, "r").read()
|
||||
except IOError as details:
|
||||
self.text = "# Exception opening file\n# %s" % (repr(details))
|
||||
else:
|
||||
self.text = "# No file available for module '%s'" % (self.module)
|
||||
self._buildlines()
|
||||
return self.text
|
||||
|
||||
def GetName(self, dnt):
|
||||
name = self.module.__name__
|
||||
try:
|
||||
fname = win32api.GetFullPathName(self.module.__file__)
|
||||
except win32api.error:
|
||||
fname = self.module.__file__
|
||||
except AttributeError:
|
||||
fname = name
|
||||
if dnt==axdebug.DOCUMENTNAMETYPE_APPNODE:
|
||||
return name.split(".")[-1]
|
||||
elif dnt==axdebug.DOCUMENTNAMETYPE_TITLE:
|
||||
return fname
|
||||
elif dnt==axdebug.DOCUMENTNAMETYPE_FILE_TAIL:
|
||||
return os.path.split(fname)[1]
|
||||
elif dnt==axdebug.DOCUMENTNAMETYPE_URL:
|
||||
return "file:%s" % fname
|
||||
else:
|
||||
raise Exception(scode=winerror.E_UNEXPECTED)
|
||||
|
||||
if __name__=='__main__':
|
||||
import sys
|
||||
sys.path.append(".")
|
||||
import ttest
|
||||
sc = SourceModuleContainer(ttest)
|
||||
# sc = SourceCodeContainer(open(sys.argv[1], "rb").read(), sys.argv[1])
|
||||
attrs = sc.GetSyntaxColorAttributes()
|
||||
attrlen = 0
|
||||
for attr in attrs:
|
||||
if type(attr)==type(()):
|
||||
attrlen = attrlen + attr[1]
|
||||
else:
|
||||
attrlen = attrlen + 1
|
||||
text = sc.GetText()
|
||||
if attrlen!=len(text):
|
||||
print("Lengths dont match!!! (%d/%d)" % (attrlen, len(text)))
|
||||
|
||||
# print "Attributes:"
|
||||
# print attrs
|
||||
print("GetLineOfPos=", sc.GetLineOfPosition(0))
|
||||
print("GetLineOfPos=", sc.GetLineOfPosition(4))
|
||||
print("GetLineOfPos=", sc.GetLineOfPosition(10))
|
56
venv/Lib/site-packages/win32comext/axdebug/contexts.py
Normal file
56
venv/Lib/site-packages/win32comext/axdebug/contexts.py
Normal file
|
@ -0,0 +1,56 @@
|
|||
""" A module for managing the AXDebug I*Contexts
|
||||
|
||||
"""
|
||||
from . import gateways, axdebug
|
||||
import pythoncom, win32com.server.util
|
||||
|
||||
# Utility function for wrapping object created by this module.
|
||||
from .util import _wrap, _wrap_remove, trace
|
||||
from . import adb
|
||||
|
||||
class DebugCodeContext(gateways.DebugCodeContext, gateways.DebugDocumentContext):
|
||||
# NOTE: We also implement the IDebugDocumentContext interface for Simple Hosts.
|
||||
# Thus, debugDocument may be NULL when we have smart hosts - but in that case, we
|
||||
# wont be called upon to provide it.
|
||||
_public_methods_ = gateways.DebugCodeContext._public_methods_ + \
|
||||
gateways.DebugDocumentContext._public_methods_
|
||||
_com_interfaces_ = gateways.DebugCodeContext._com_interfaces_ + \
|
||||
gateways.DebugDocumentContext._com_interfaces_
|
||||
|
||||
def __init__(self, lineNo, charPos, len, codeContainer, debugSite):
|
||||
self.debugSite = debugSite
|
||||
self.offset = charPos
|
||||
self.length = len
|
||||
self.breakPointState = 0
|
||||
self.lineno = lineNo
|
||||
gateways.DebugCodeContext.__init__(self)
|
||||
self.codeContainer = codeContainer
|
||||
|
||||
def _Close(self):
|
||||
self.debugSite = None
|
||||
|
||||
def GetDocumentContext(self):
|
||||
if self.debugSite is not None:
|
||||
# We have a smart host - let him give it to us.
|
||||
return self.debugSite.GetDocumentContextFromPosition(
|
||||
self.codeContainer.sourceContext,
|
||||
self.offset,
|
||||
self.length)
|
||||
else:
|
||||
# Simple host - Fine - Ill do it myself!
|
||||
return _wrap(self, axdebug.IID_IDebugDocumentContext)
|
||||
|
||||
def SetBreakPoint(self, bps):
|
||||
self.breakPointState = bps
|
||||
adb.OnSetBreakPoint(self, bps, self.lineno)
|
||||
|
||||
# The DebugDocumentContext methods for simple hosts.
|
||||
def GetDocument(self):
|
||||
return self.codeContainer.debugDocument
|
||||
|
||||
def EnumCodeContexts(self):
|
||||
return _wrap(EnumDebugCodeContexts([self]), axdebug.IID_IEnumDebugCodeContexts)
|
||||
|
||||
class EnumDebugCodeContexts(gateways.EnumDebugCodeContexts):
|
||||
def _wrap(self, obj):
|
||||
return _wrap(obj, axdebug.IID_IDebugCodeContext)
|
203
venv/Lib/site-packages/win32comext/axdebug/debugger.py
Normal file
203
venv/Lib/site-packages/win32comext/axdebug/debugger.py
Normal file
|
@ -0,0 +1,203 @@
|
|||
import sys, traceback, string
|
||||
|
||||
from win32com.axscript import axscript
|
||||
from win32com.axdebug import codecontainer, axdebug, gateways, documents, contexts, adb, expressions
|
||||
from win32com.axdebug.util import trace, _wrap, _wrap_remove
|
||||
|
||||
import pythoncom
|
||||
import win32api, winerror
|
||||
import os
|
||||
|
||||
currentDebugger = None
|
||||
|
||||
class ModuleTreeNode:
|
||||
"""Helper class for building a module tree
|
||||
"""
|
||||
def __init__(self, module):
|
||||
modName = module.__name__
|
||||
self.moduleName = modName
|
||||
self.module = module
|
||||
self.realNode = None
|
||||
self.cont = codecontainer.SourceModuleContainer(module)
|
||||
def __repr__(self):
|
||||
return "<ModuleTreeNode wrapping %s>" % (self.module)
|
||||
def Attach(self, parentRealNode):
|
||||
self.realNode.Attach(parentRealNode)
|
||||
|
||||
def Close(self):
|
||||
self.module = None
|
||||
self.cont = None
|
||||
self.realNode = None
|
||||
|
||||
def BuildModule(module, built_nodes, rootNode, create_node_fn, create_node_args ):
|
||||
if module:
|
||||
keep = module.__name__
|
||||
keep = keep and (built_nodes.get(module) is None)
|
||||
if keep and hasattr(module, '__file__'):
|
||||
keep = string.lower(os.path.splitext(module.__file__)[1]) not in [".pyd", ".dll"]
|
||||
# keep = keep and module.__name__=='__main__'
|
||||
if module and keep:
|
||||
# print "keeping", module.__name__
|
||||
node = ModuleTreeNode(module)
|
||||
built_nodes[module] = node
|
||||
realNode = create_node_fn(*(node,)+create_node_args)
|
||||
node.realNode = realNode
|
||||
|
||||
# Split into parent nodes.
|
||||
parts = string.split(module.__name__, '.')
|
||||
if parts[-1][:8]=='__init__': parts = parts[:-1]
|
||||
parent = string.join(parts[:-1], '.')
|
||||
parentNode = rootNode
|
||||
if parent:
|
||||
parentModule = sys.modules[parent]
|
||||
BuildModule(parentModule, built_nodes, rootNode, create_node_fn, create_node_args)
|
||||
if parentModule in built_nodes:
|
||||
parentNode = built_nodes[parentModule].realNode
|
||||
node.Attach(parentNode)
|
||||
|
||||
def RefreshAllModules(builtItems, rootNode, create_node, create_node_args):
|
||||
for module in list(sys.modules.values()):
|
||||
BuildModule(module, builtItems, rootNode, create_node, create_node_args)
|
||||
|
||||
# realNode = pdm.CreateDebugDocumentHelper(None) # DebugDocumentHelper node?
|
||||
# app.CreateApplicationNode() # doc provider node.
|
||||
|
||||
class CodeContainerProvider(documents.CodeContainerProvider):
|
||||
def __init__(self, axdebugger):
|
||||
self.axdebugger = axdebugger
|
||||
documents.CodeContainerProvider.__init__(self)
|
||||
self.currentNumModules = len(sys.modules)
|
||||
self.nodes = {}
|
||||
self.axdebugger.RefreshAllModules(self.nodes, self)
|
||||
|
||||
def FromFileName(self, fname):
|
||||
### It appears we cant add modules during a debug session!
|
||||
# if self.currentNumModules != len(sys.modules):
|
||||
# self.axdebugger.RefreshAllModules(self.nodes, self)
|
||||
# self.currentNumModules = len(sys.modules)
|
||||
# for key in self.ccsAndNodes.keys():
|
||||
# print "File:", key
|
||||
return documents.CodeContainerProvider.FromFileName(self, fname)
|
||||
|
||||
def Close(self):
|
||||
documents.CodeContainerProvider.Close(self)
|
||||
self.axdebugger = None
|
||||
print("Closing %d nodes" % (len(self.nodes)))
|
||||
for node in self.nodes.values():
|
||||
node.Close()
|
||||
self.nodes = {}
|
||||
|
||||
class OriginalInterfaceMaker:
|
||||
def MakeInterfaces(self, pdm):
|
||||
app = self.pdm.CreateApplication()
|
||||
self.cookie = pdm.AddApplication(app)
|
||||
root = app.GetRootNode()
|
||||
return app, root
|
||||
|
||||
def CloseInterfaces(self, pdm):
|
||||
pdm.RemoveApplication(self.cookie)
|
||||
|
||||
class SimpleHostStyleInterfaceMaker:
|
||||
def MakeInterfaces(self, pdm):
|
||||
app = pdm.GetDefaultApplication()
|
||||
root = app.GetRootNode()
|
||||
return app, root
|
||||
|
||||
def CloseInterfaces(self, pdm):
|
||||
pass
|
||||
|
||||
|
||||
class AXDebugger:
|
||||
def __init__(self, interfaceMaker = None, processName = None):
|
||||
if processName is None: processName = "Python Process"
|
||||
if interfaceMaker is None: interfaceMaker = SimpleHostStyleInterfaceMaker()
|
||||
|
||||
self.pydebugger = adb.Debugger()
|
||||
|
||||
self.pdm=pythoncom.CoCreateInstance(axdebug.CLSID_ProcessDebugManager,None,pythoncom.CLSCTX_ALL, axdebug.IID_IProcessDebugManager)
|
||||
|
||||
self.app, self.root = interfaceMaker.MakeInterfaces(self.pdm)
|
||||
self.app.SetName(processName)
|
||||
self.interfaceMaker = interfaceMaker
|
||||
|
||||
expressionProvider = _wrap(expressions.ProvideExpressionContexts(), axdebug.IID_IProvideExpressionContexts)
|
||||
self.expressionCookie = self.app.AddGlobalExpressionContextProvider(expressionProvider)
|
||||
|
||||
contProvider = CodeContainerProvider(self)
|
||||
self.pydebugger.AttachApp(self.app, contProvider)
|
||||
|
||||
def Break(self):
|
||||
# Get the frame we start debugging from - this is the frame 1 level up
|
||||
try:
|
||||
1 + ''
|
||||
except:
|
||||
frame = sys.exc_info()[2].tb_frame.f_back
|
||||
|
||||
# Get/create the debugger, and tell it to break.
|
||||
self.app.StartDebugSession()
|
||||
# self.app.CauseBreak()
|
||||
|
||||
self.pydebugger.SetupAXDebugging(None, frame)
|
||||
self.pydebugger.set_trace()
|
||||
|
||||
def Close(self):
|
||||
self.pydebugger.ResetAXDebugging()
|
||||
self.interfaceMaker.CloseInterfaces(self.pdm)
|
||||
self.pydebugger.CloseApp()
|
||||
self.app.RemoveGlobalExpressionContextProvider(self.expressionCookie)
|
||||
self.expressionCookie = None
|
||||
|
||||
self.pdm = None
|
||||
self.app = None
|
||||
self.pydebugger = None
|
||||
self.root = None
|
||||
|
||||
def RefreshAllModules(self, nodes, containerProvider):
|
||||
RefreshAllModules(nodes, self.root, self.CreateApplicationNode, (containerProvider,))
|
||||
|
||||
def CreateApplicationNode(self, node, containerProvider):
|
||||
realNode = self.app.CreateApplicationNode()
|
||||
|
||||
document = documents.DebugDocumentText(node.cont)
|
||||
document = _wrap(document, axdebug.IID_IDebugDocument)
|
||||
|
||||
node.cont.debugDocument = document
|
||||
|
||||
provider = documents.DebugDocumentProvider(document)
|
||||
provider = _wrap(provider, axdebug.IID_IDebugDocumentProvider)
|
||||
realNode.SetDocumentProvider(provider)
|
||||
|
||||
containerProvider.AddCodeContainer(node.cont, realNode)
|
||||
return realNode
|
||||
|
||||
def _GetCurrentDebugger():
|
||||
global currentDebugger
|
||||
if currentDebugger is None:
|
||||
currentDebugger = AXDebugger()
|
||||
return currentDebugger
|
||||
|
||||
def Break():
|
||||
_GetCurrentDebugger().Break()
|
||||
|
||||
brk = Break
|
||||
set_trace = Break
|
||||
|
||||
def dosomethingelse():
|
||||
a=2
|
||||
b = "Hi there"
|
||||
|
||||
def dosomething():
|
||||
a=1
|
||||
b=2
|
||||
dosomethingelse()
|
||||
|
||||
def test():
|
||||
Break()
|
||||
input("Waiting...")
|
||||
dosomething()
|
||||
print("Done")
|
||||
|
||||
if __name__=='__main__':
|
||||
print("About to test the debugging interfaces!")
|
||||
test()
|
||||
print(" %d/%d com objects still alive" % (pythoncom._GetInterfaceCount(), pythoncom._GetGatewayCount()))
|
124
venv/Lib/site-packages/win32comext/axdebug/documents.py
Normal file
124
venv/Lib/site-packages/win32comext/axdebug/documents.py
Normal file
|
@ -0,0 +1,124 @@
|
|||
""" Management of documents for AXDebugging.
|
||||
"""
|
||||
|
||||
from . import axdebug, gateways
|
||||
import pythoncom
|
||||
from .util import _wrap, _wrap_remove, RaiseNotImpl, trace
|
||||
from win32com.server.util import unwrap
|
||||
from . import codecontainer
|
||||
from . import contexts
|
||||
from win32com.server.exception import Exception
|
||||
import win32api, winerror, os, string, sys
|
||||
|
||||
#def trace(*args):
|
||||
# pass
|
||||
|
||||
def GetGoodFileName(fname):
|
||||
if fname[0] != "<":
|
||||
return win32api.GetFullPathName(fname)
|
||||
return fname
|
||||
|
||||
class DebugDocumentProvider(gateways.DebugDocumentProvider):
|
||||
def __init__(self, doc):
|
||||
self.doc = doc
|
||||
|
||||
def GetName(self, dnt):
|
||||
return self.doc.GetName(dnt)
|
||||
|
||||
def GetDocumentClassId(self):
|
||||
return self.doc.GetDocumentClassId()
|
||||
|
||||
def GetDocument(self):
|
||||
return self.doc
|
||||
|
||||
class DebugDocumentText(gateways.DebugDocumentInfo, gateways.DebugDocumentText, gateways.DebugDocument):
|
||||
_com_interfaces_ = gateways.DebugDocumentInfo._com_interfaces_ + \
|
||||
gateways.DebugDocumentText._com_interfaces_ + \
|
||||
gateways.DebugDocument._com_interfaces_
|
||||
_public_methods_ = gateways.DebugDocumentInfo._public_methods_ + \
|
||||
gateways.DebugDocumentText._public_methods_ + \
|
||||
gateways.DebugDocument._public_methods_
|
||||
# A class which implements a DebugDocumentText, using the functionality
|
||||
# provided by a codeContainer
|
||||
def __init__(self, codeContainer):
|
||||
gateways.DebugDocumentText.__init__(self)
|
||||
gateways.DebugDocumentInfo.__init__(self)
|
||||
gateways.DebugDocument.__init__(self)
|
||||
self.codeContainer = codeContainer
|
||||
|
||||
def _Close(self):
|
||||
self.docContexts = None
|
||||
# self.codeContainer._Close()
|
||||
self.codeContainer = None
|
||||
# IDebugDocumentInfo
|
||||
def GetName(self, dnt):
|
||||
return self.codeContainer.GetName(dnt)
|
||||
|
||||
def GetDocumentClassId(self):
|
||||
return "{DF630910-1C1D-11d0-AE36-8C0F5E000000}"
|
||||
|
||||
# IDebugDocument has no methods!
|
||||
#
|
||||
|
||||
# IDebugDocumentText methods.
|
||||
# def GetDocumentAttributes
|
||||
def GetSize(self):
|
||||
# trace("GetSize")
|
||||
return self.codeContainer.GetNumLines(), self.codeContainer.GetNumChars()
|
||||
def GetPositionOfLine(self, cLineNumber):
|
||||
return self.codeContainer.GetPositionOfLine(cLineNumber)
|
||||
def GetLineOfPosition(self, charPos):
|
||||
return self.codeContainer.GetLineOfPosition(charPos)
|
||||
def GetText(self, charPos, maxChars, wantAttr):
|
||||
# Get all the attributes, else the tokenizer will get upset.
|
||||
# XXX - not yet!
|
||||
# trace("GetText", charPos, maxChars, wantAttr)
|
||||
cont = self.codeContainer
|
||||
attr = cont.GetSyntaxColorAttributes()
|
||||
return cont.GetText(), attr
|
||||
|
||||
def GetPositionOfContext(self, context):
|
||||
trace("GetPositionOfContext", context)
|
||||
context = unwrap(context)
|
||||
return context.offset, context.length
|
||||
|
||||
# Return a DebugDocumentContext.
|
||||
def GetContextOfPosition(self, charPos, maxChars):
|
||||
# Make one
|
||||
doc = _wrap(self, axdebug.IID_IDebugDocument)
|
||||
rc = self.codeContainer.GetCodeContextAtPosition(charPos)
|
||||
return rc.QueryInterface(axdebug.IID_IDebugDocumentContext)
|
||||
|
||||
class CodeContainerProvider:
|
||||
"""An abstract Python class which provides code containers!
|
||||
|
||||
Given a Python file name (as the debugger knows it by) this will
|
||||
return a CodeContainer interface suitable for use.
|
||||
|
||||
This provides a simple base imlpementation that simply supports
|
||||
a dictionary of nodes and providers.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.ccsAndNodes = {}
|
||||
|
||||
def AddCodeContainer(self, cc, node = None):
|
||||
fname = GetGoodFileName(cc.fileName)
|
||||
self.ccsAndNodes[fname] = cc, node
|
||||
|
||||
def FromFileName(self, fname):
|
||||
cc, node = self.ccsAndNodes.get(GetGoodFileName(fname), (None, None))
|
||||
# if cc is None:
|
||||
# print "FromFileName for %s returning None" % fname
|
||||
return cc
|
||||
|
||||
def Close(self):
|
||||
for cc, node in self.ccsAndNodes.values():
|
||||
try:
|
||||
# Must close the node before closing the provider
|
||||
# as node may make calls on provider (eg Reset breakpoints etc)
|
||||
if node is not None:
|
||||
node.Close()
|
||||
cc._Close()
|
||||
except pythoncom.com_error:
|
||||
pass
|
||||
self.ccsAndNodes = {}
|
48
venv/Lib/site-packages/win32comext/axdebug/dump.py
Normal file
48
venv/Lib/site-packages/win32comext/axdebug/dump.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
import sys, string
|
||||
import traceback
|
||||
from win32com.axdebug import axdebug
|
||||
from win32com.client.util import Enumerator
|
||||
import pythoncom
|
||||
|
||||
def DumpDebugApplicationNode(node, level = 0):
|
||||
# Recursive dump of a DebugApplicationNode
|
||||
spacer = " " * level
|
||||
for desc, attr in [("Node Name", axdebug.DOCUMENTNAMETYPE_APPNODE),
|
||||
("Title", axdebug.DOCUMENTNAMETYPE_TITLE),
|
||||
("Filename", axdebug.DOCUMENTNAMETYPE_FILE_TAIL),
|
||||
("URL", axdebug.DOCUMENTNAMETYPE_URL),
|
||||
]:
|
||||
try:
|
||||
info = node.GetName(attr)
|
||||
except pythoncom.com_error:
|
||||
info = "<N/A>"
|
||||
print("%s%s: %s" % (spacer, desc, info))
|
||||
try:
|
||||
doc = node.GetDocument()
|
||||
except pythoncom.com_error:
|
||||
doc = None
|
||||
if doc:
|
||||
doctext = doc.QueryInterface(axdebug.IID_IDebugDocumentText)
|
||||
numLines, numChars = doctext.GetSize()
|
||||
# text, attr = doctext.GetText(0, 20, 1)
|
||||
text, attr = doctext.GetText(0, numChars, 1)
|
||||
print("%sText is %s, %d bytes long" % (spacer, repr(text[:40]+"..."), len(text)))
|
||||
else:
|
||||
print("%s%s" % (spacer, "<No document available>"))
|
||||
|
||||
for child in Enumerator(node.EnumChildren()):
|
||||
DumpDebugApplicationNode(child, level+1)
|
||||
|
||||
def dumpall():
|
||||
dm=pythoncom.CoCreateInstance(axdebug.CLSID_MachineDebugManager,None,pythoncom.CLSCTX_ALL, axdebug.IID_IMachineDebugManager)
|
||||
e=Enumerator(dm.EnumApplications())
|
||||
for app in e:
|
||||
print("Application: %s" % app.GetName())
|
||||
node = app.GetRootNode() # of type PyIDebugApplicationNode->PyIDebugDocumentProvider->PyIDebugDocumentInfo
|
||||
DumpDebugApplicationNode(node)
|
||||
|
||||
if __name__=='__main__':
|
||||
try:
|
||||
dumpall()
|
||||
except:
|
||||
traceback.print_exc()
|
156
venv/Lib/site-packages/win32comext/axdebug/expressions.py
Normal file
156
venv/Lib/site-packages/win32comext/axdebug/expressions.py
Normal file
|
@ -0,0 +1,156 @@
|
|||
from . import axdebug, gateways
|
||||
from .util import _wrap, _wrap_remove, RaiseNotImpl
|
||||
import io, traceback
|
||||
from pprint import pprint
|
||||
from win32com.server.exception import COMException
|
||||
import winerror
|
||||
import string
|
||||
import sys
|
||||
|
||||
# Given an object, return a nice string
|
||||
def MakeNiceString(ob):
|
||||
stream = io.StringIO()
|
||||
pprint(ob, stream)
|
||||
return string.strip(stream.getvalue())
|
||||
|
||||
class ProvideExpressionContexts(gateways.ProvideExpressionContexts):
|
||||
pass
|
||||
|
||||
class ExpressionContext(gateways.DebugExpressionContext):
|
||||
def __init__(self, frame):
|
||||
self.frame = frame
|
||||
def ParseLanguageText(self, code, radix, delim, flags):
|
||||
return _wrap(Expression(self.frame, code, radix, delim, flags), axdebug.IID_IDebugExpression)
|
||||
def GetLanguageInfo(self):
|
||||
# print "GetLanguageInfo"
|
||||
return "Python", "{DF630910-1C1D-11d0-AE36-8C0F5E000000}"
|
||||
|
||||
class Expression(gateways.DebugExpression):
|
||||
def __init__(self, frame, code, radix, delim, flags):
|
||||
self.callback = None
|
||||
self.frame = frame
|
||||
self.code = code
|
||||
self.radix = radix
|
||||
self.delim = delim
|
||||
self.flags = flags
|
||||
self.isComplete = 0
|
||||
self.result=None
|
||||
self.hresult = winerror.E_UNEXPECTED
|
||||
def Start(self, callback):
|
||||
try:
|
||||
try:
|
||||
try:
|
||||
self.result = eval(self.code, self.frame.f_globals, self.frame.f_locals)
|
||||
except SyntaxError:
|
||||
exec(self.code, self.frame.f_globals, self.frame.f_locals)
|
||||
self.result = ""
|
||||
self.hresult = 0
|
||||
except:
|
||||
l = traceback.format_exception_only(sys.exc_info()[0], sys.exc_info()[1])
|
||||
# l is a list of strings with trailing "\n"
|
||||
self.result = string.join(map(lambda s:s[:-1], l), "\n")
|
||||
self.hresult = winerror.E_FAIL
|
||||
finally:
|
||||
self.isComplete = 1
|
||||
callback.onComplete()
|
||||
def Abort(self):
|
||||
print("** ABORT **")
|
||||
|
||||
def QueryIsComplete(self):
|
||||
return self.isComplete
|
||||
|
||||
def GetResultAsString(self):
|
||||
# print "GetStrAsResult returning", self.result
|
||||
return self.hresult, MakeNiceString(self.result)
|
||||
|
||||
def GetResultAsDebugProperty(self):
|
||||
result = _wrap(DebugProperty(self.code, self.result, None, self.hresult), axdebug.IID_IDebugProperty)
|
||||
return self.hresult, result
|
||||
|
||||
def MakeEnumDebugProperty(object, dwFieldSpec, nRadix, iid, stackFrame = None):
|
||||
name_vals = []
|
||||
if hasattr(object, "items") and hasattr(object, "keys"): # If it is a dict.
|
||||
name_vals = iter(object.items())
|
||||
dictionary = object
|
||||
elif hasattr(object, "__dict__"): #object with dictionary, module
|
||||
name_vals = iter(object.__dict__.items())
|
||||
dictionary = object.__dict__
|
||||
infos = []
|
||||
for name, val in name_vals:
|
||||
infos.append(GetPropertyInfo(name, val, dwFieldSpec, nRadix, 0, dictionary, stackFrame))
|
||||
return _wrap(EnumDebugPropertyInfo(infos), axdebug.IID_IEnumDebugPropertyInfo)
|
||||
|
||||
def GetPropertyInfo(obname, obvalue, dwFieldSpec, nRadix, hresult=0, dictionary = None, stackFrame = None):
|
||||
# returns a tuple
|
||||
name = typ = value = fullname = attrib = dbgprop = None
|
||||
if dwFieldSpec & axdebug.DBGPROP_INFO_VALUE:
|
||||
value = MakeNiceString(obvalue)
|
||||
if dwFieldSpec & axdebug.DBGPROP_INFO_NAME:
|
||||
name = obname
|
||||
if dwFieldSpec & axdebug.DBGPROP_INFO_TYPE:
|
||||
if hresult:
|
||||
typ = "Error"
|
||||
else:
|
||||
try:
|
||||
typ = type(obvalue).__name__
|
||||
except AttributeError:
|
||||
typ = str(type(obvalue))
|
||||
if dwFieldSpec & axdebug.DBGPROP_INFO_FULLNAME:
|
||||
fullname = obname
|
||||
if dwFieldSpec & axdebug.DBGPROP_INFO_ATTRIBUTES:
|
||||
if hasattr(obvalue, "has_key") or hasattr(obvalue, "__dict__"): # If it is a dict or object
|
||||
attrib = axdebug.DBGPROP_ATTRIB_VALUE_IS_EXPANDABLE
|
||||
else:
|
||||
attrib = 0
|
||||
if dwFieldSpec & axdebug.DBGPROP_INFO_DEBUGPROP:
|
||||
dbgprop = _wrap(DebugProperty(name, obvalue, None, hresult, dictionary, stackFrame), axdebug.IID_IDebugProperty)
|
||||
return name, typ, value, fullname, attrib, dbgprop
|
||||
|
||||
from win32com.server.util import ListEnumeratorGateway
|
||||
class EnumDebugPropertyInfo(ListEnumeratorGateway):
|
||||
"""A class to expose a Python sequence as an EnumDebugCodeContexts
|
||||
|
||||
Create an instance of this class passing a sequence (list, tuple, or
|
||||
any sequence protocol supporting object) and it will automatically
|
||||
support the EnumDebugCodeContexts interface for the object.
|
||||
|
||||
"""
|
||||
_public_methods_ = ListEnumeratorGateway._public_methods_ + ["GetCount"]
|
||||
_com_interfaces_ = [ axdebug.IID_IEnumDebugPropertyInfo]
|
||||
def GetCount(self):
|
||||
return len(self._list_)
|
||||
def _wrap(self, ob):
|
||||
return ob
|
||||
|
||||
class DebugProperty:
|
||||
_com_interfaces_ = [axdebug.IID_IDebugProperty]
|
||||
_public_methods_ = ['GetPropertyInfo', 'GetExtendedInfo', 'SetValueAsString',
|
||||
'EnumMembers', 'GetParent'
|
||||
]
|
||||
def __init__(self, name, value, parent = None, hresult = 0, dictionary = None, stackFrame = None):
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.parent = parent
|
||||
self.hresult = hresult
|
||||
self.dictionary = dictionary
|
||||
self.stackFrame = stackFrame
|
||||
|
||||
def GetPropertyInfo(self, dwFieldSpec, nRadix):
|
||||
return GetPropertyInfo(self.name, self.value, dwFieldSpec, nRadix, self.hresult, dictionary, stackFrame)
|
||||
|
||||
def GetExtendedInfo(self): ### Note - not in the framework.
|
||||
RaiseNotImpl("DebugProperty::GetExtendedInfo")
|
||||
|
||||
def SetValueAsString(self, value, radix):
|
||||
if self.stackFrame and self.dictionary:
|
||||
self.dictionary[self.name]= eval(value,self.stackFrame.f_globals, self.stackFrame.f_locals)
|
||||
else:
|
||||
RaiseNotImpl("DebugProperty::SetValueAsString")
|
||||
|
||||
def EnumMembers(self, dwFieldSpec, nRadix, iid):
|
||||
# Returns IEnumDebugPropertyInfo
|
||||
return MakeEnumDebugProperty(self.value, dwFieldSpec, nRadix, iid, self.stackFrame)
|
||||
|
||||
def GetParent(self):
|
||||
# return IDebugProperty
|
||||
RaiseNotImpl("DebugProperty::GetParent")
|
452
venv/Lib/site-packages/win32comext/axdebug/gateways.py
Normal file
452
venv/Lib/site-packages/win32comext/axdebug/gateways.py
Normal file
|
@ -0,0 +1,452 @@
|
|||
# Classes which describe interfaces.
|
||||
|
||||
from win32com.server.exception import Exception
|
||||
from win32com.server.util import ListEnumeratorGateway
|
||||
from win32com.axdebug import axdebug
|
||||
from win32com.axdebug.util import RaiseNotImpl, _wrap
|
||||
import pythoncom
|
||||
import win32com.server.connect
|
||||
import winerror
|
||||
|
||||
class EnumDebugCodeContexts(ListEnumeratorGateway):
|
||||
"""A class to expose a Python sequence as an EnumDebugCodeContexts
|
||||
|
||||
Create an instance of this class passing a sequence (list, tuple, or
|
||||
any sequence protocol supporting object) and it will automatically
|
||||
support the EnumDebugCodeContexts interface for the object.
|
||||
|
||||
"""
|
||||
_com_interfaces_ = [ axdebug.IID_IEnumDebugCodeContexts ]
|
||||
|
||||
class EnumDebugStackFrames(ListEnumeratorGateway):
|
||||
"""A class to expose a Python sequence as an EnumDebugStackFrames
|
||||
|
||||
Create an instance of this class passing a sequence (list, tuple, or
|
||||
any sequence protocol supporting object) and it will automatically
|
||||
support the EnumDebugStackFrames interface for the object.
|
||||
|
||||
"""
|
||||
_com_interfaces_ = [ axdebug.IID_IEnumDebugStackFrames ]
|
||||
|
||||
class EnumDebugApplicationNodes(ListEnumeratorGateway):
|
||||
"""A class to expose a Python sequence as an EnumDebugStackFrames
|
||||
|
||||
Create an instance of this class passing a sequence (list, tuple, or
|
||||
any sequence protocol supporting object) and it will automatically
|
||||
support the EnumDebugApplicationNodes interface for the object.
|
||||
|
||||
"""
|
||||
_com_interfaces_ = [ axdebug.IID_IEnumDebugApplicationNodes ]
|
||||
|
||||
class EnumRemoteDebugApplications(ListEnumeratorGateway):
|
||||
_com_interfaces_ = [ axdebug.IID_IEnumRemoteDebugApplications ]
|
||||
|
||||
class EnumRemoteDebugApplicationThreads(ListEnumeratorGateway):
|
||||
_com_interfaces_ = [ axdebug.IID_IEnumRemoteDebugApplicationThreads ]
|
||||
|
||||
class DebugDocumentInfo:
|
||||
_public_methods_ = ["GetName", "GetDocumentClassId"]
|
||||
_com_interfaces_ = [axdebug.IID_IDebugDocumentInfo]
|
||||
def __init__(self):
|
||||
pass
|
||||
def GetName(self, dnt):
|
||||
""" Get the one of the name of the document
|
||||
dnt -- int DOCUMENTNAMETYPE
|
||||
"""
|
||||
RaiseNotImpl("GetName")
|
||||
def GetDocumentClassId(self):
|
||||
"""
|
||||
Result must be an IID object (or string representing one).
|
||||
"""
|
||||
RaiseNotImpl("GetDocumentClassId")
|
||||
|
||||
class DebugDocumentProvider(DebugDocumentInfo):
|
||||
_public_methods_ = DebugDocumentInfo._public_methods_ + ["GetDocument"]
|
||||
_com_interfaces_ = DebugDocumentInfo._com_interfaces_ + [axdebug.IID_IDebugDocumentProvider]
|
||||
def GetDocument(self):
|
||||
RaiseNotImpl("GetDocument")
|
||||
|
||||
class DebugApplicationNode(DebugDocumentProvider):
|
||||
"""Provides the functionality of IDebugDocumentProvider, plus a context within a project tree.
|
||||
"""
|
||||
_public_methods_ = """EnumChildren GetParent SetDocumentProvider
|
||||
Close Attach Detach""".split() + \
|
||||
DebugDocumentProvider._public_methods_
|
||||
_com_interfaces_ = [axdebug.IID_IDebugDocumentProvider] + \
|
||||
DebugDocumentProvider._com_interfaces_
|
||||
def __init__(self):
|
||||
DebugDocumentProvider.__init__(self)
|
||||
def EnumChildren(self):
|
||||
# Result is type PyIEnumDebugApplicationNodes
|
||||
RaiseNotImpl("EnumChildren")
|
||||
def GetParent(self):
|
||||
# result is type PyIDebugApplicationNode
|
||||
RaiseNotImpl("GetParent")
|
||||
def SetDocumentProvider(self, pddp): # PyIDebugDocumentProvider pddp
|
||||
# void result.
|
||||
RaiseNotImpl("SetDocumentProvider")
|
||||
def Close(self):
|
||||
# void result.
|
||||
RaiseNotImpl("Close")
|
||||
def Attach(self, parent): # PyIDebugApplicationNode
|
||||
# void result.
|
||||
RaiseNotImpl("Attach")
|
||||
def Detach(self):
|
||||
# void result.
|
||||
RaiseNotImpl("Detach")
|
||||
|
||||
class DebugApplicationNodeEvents:
|
||||
"""Event interface for DebugApplicationNode object.
|
||||
"""
|
||||
_public_methods_ = "onAddChild onRemoveChild onDetach".split()
|
||||
_com_interfaces_ = [axdebug.IID_IDebugApplicationNodeEvents]
|
||||
def __init__(self):
|
||||
pass
|
||||
def onAddChild(self, child): # PyIDebugApplicationNode
|
||||
# void result.
|
||||
RaiseNotImpl("onAddChild")
|
||||
def onRemoveChild(self, child): # PyIDebugApplicationNode
|
||||
# void result.
|
||||
RaiseNotImpl("onRemoveChild")
|
||||
def onDetach(self):
|
||||
# void result.
|
||||
RaiseNotImpl("onDetach")
|
||||
def onAttach(self, parent): # PyIDebugApplicationNode
|
||||
# void result.
|
||||
RaiseNotImpl("onAttach")
|
||||
|
||||
class DebugDocument(DebugDocumentInfo):
|
||||
"""The base interface to all debug documents.
|
||||
"""
|
||||
_public_methods_ = DebugDocumentInfo._public_methods_
|
||||
_com_interfaces_ = [axdebug.IID_IDebugDocument] + DebugDocumentInfo._com_interfaces_
|
||||
|
||||
class DebugDocumentText(DebugDocument):
|
||||
"""The interface to a text only debug document.
|
||||
"""
|
||||
_com_interfaces_ = [axdebug.IID_IDebugDocumentText] + \
|
||||
DebugDocument._com_interfaces_
|
||||
_public_methods_ = ["GetDocumentAttributes", "GetSize",
|
||||
"GetPositionOfLine", "GetLineOfPosition", "GetText",
|
||||
"GetPositionOfContext", "GetContextOfPosition"] + \
|
||||
DebugDocument._public_methods_
|
||||
def __init__(self):
|
||||
pass
|
||||
# IDebugDocumentText
|
||||
def GetDocumentAttributes(self):
|
||||
# Result is int (TEXT_DOC_ATTR)
|
||||
RaiseNotImpl("GetDocumentAttributes")
|
||||
def GetSize(self):
|
||||
# Result is (numLines, numChars)
|
||||
RaiseNotImpl("GetSize")
|
||||
def GetPositionOfLine(self, cLineNumber):
|
||||
# Result is int char position
|
||||
RaiseNotImpl("GetPositionOfLine")
|
||||
def GetLineOfPosition(self, charPos):
|
||||
# Result is int, int (lineNo, offset)
|
||||
RaiseNotImpl("GetLineOfPosition")
|
||||
def GetText(self, charPos, maxChars, wantAttr):
|
||||
"""Params
|
||||
charPos -- integer
|
||||
maxChars -- integer
|
||||
wantAttr -- Should the function compute attributes.
|
||||
|
||||
Return value must be (string, attribtues). attributes may be
|
||||
None if(not wantAttr)
|
||||
"""
|
||||
RaiseNotImpl("GetText")
|
||||
def GetPositionOfContext(self, debugDocumentContext):
|
||||
"""Params
|
||||
debugDocumentContext -- a PyIDebugDocumentContext object.
|
||||
|
||||
Return value must be (charPos, numChars)
|
||||
"""
|
||||
RaiseNotImpl("GetPositionOfContext")
|
||||
def GetContextOfPosition(self, charPos, maxChars):
|
||||
"""Params are integers.
|
||||
Return value must be PyIDebugDocumentContext object
|
||||
"""
|
||||
print(self)
|
||||
RaiseNotImpl("GetContextOfPosition")
|
||||
|
||||
class DebugDocumentTextExternalAuthor:
|
||||
"""Allow external editors to edit file-based debugger documents, and to notify the document when the source file has been changed.
|
||||
"""
|
||||
_public_methods_ = ["GetPathName", "GetFileName", "NotifyChanged"]
|
||||
_com_interfaces_ = [axdebug.IID_IDebugDocumentTextExternalAuthor]
|
||||
def __init__(self):
|
||||
pass
|
||||
def GetPathName(self):
|
||||
"""Return the full path (including file name) to the document's source file.
|
||||
|
||||
Result must be (filename, fIsOriginal), where
|
||||
- if fIsOriginalPath is TRUE if the path refers to the original file for the document.
|
||||
- if fIsOriginalPath is FALSE if the path refers to a newly created temporary file.
|
||||
|
||||
raise Exception(winerror.E_FAIL) if no source file can be created/determined.
|
||||
"""
|
||||
RaiseNotImpl("GetPathName")
|
||||
|
||||
def GetFileName(self):
|
||||
"""Return just the name of the document, with no path information. (Used for "Save As...")
|
||||
|
||||
Result is a string
|
||||
"""
|
||||
RaiseNotImpl("GetFileName")
|
||||
|
||||
def NotifyChanged(self):
|
||||
""" Notify the host that the document's source file has been saved and
|
||||
that its contents should be refreshed.
|
||||
"""
|
||||
RaiseNotImpl("NotifyChanged")
|
||||
|
||||
|
||||
class DebugDocumentTextEvents:
|
||||
_public_methods_ = """onDestroy onInsertText onRemoveText
|
||||
onReplaceText onUpdateTextAttributes
|
||||
onUpdateDocumentAttributes""".split()
|
||||
_com_interfaces_ = [ axdebug.IID_IDebugDocumentTextEvents ]
|
||||
def __init__(self):
|
||||
pass
|
||||
def onDestroy(self):
|
||||
# Result is void.
|
||||
RaiseNotImpl("onDestroy")
|
||||
def onInsertText(self, cCharacterPosition, cNumToInsert):
|
||||
# Result is void.
|
||||
RaiseNotImpl("onInsertText")
|
||||
def onRemoveText(self, cCharacterPosition, cNumToRemove):
|
||||
# Result is void.
|
||||
RaiseNotImpl("onRemoveText")
|
||||
def onReplaceText(self, cCharacterPosition, cNumToReplace):
|
||||
# Result is void.
|
||||
RaiseNotImpl("onReplaceText")
|
||||
def onUpdateTextAttributes(self, cCharacterPosition, cNumToUpdate):
|
||||
# Result is void.
|
||||
RaiseNotImpl("onUpdateTextAttributes")
|
||||
def onUpdateDocumentAttributes(self,textdocattr): # TEXT_DOC_ATTR
|
||||
# Result is void.
|
||||
RaiseNotImpl("onUpdateDocumentAttributes")
|
||||
|
||||
class DebugDocumentContext:
|
||||
_public_methods_ = [ 'GetDocument', 'EnumCodeContexts']
|
||||
_com_interfaces_ = [ axdebug.IID_IDebugDocumentContext ]
|
||||
def __init__(self):
|
||||
pass
|
||||
def GetDocument(self):
|
||||
"""Return value must be a PyIDebugDocument object
|
||||
"""
|
||||
RaiseNotImpl("GetDocument")
|
||||
|
||||
def EnumCodeContexts(self):
|
||||
"""Return value must be a PyIEnumDebugCodeContexts object
|
||||
"""
|
||||
RaiseNotImpl("EnumCodeContexts")
|
||||
|
||||
|
||||
class DebugCodeContext:
|
||||
_public_methods_ = [ 'GetDocumentContext', 'SetBreakPoint']
|
||||
_com_interfaces_ = [ axdebug.IID_IDebugCodeContext ]
|
||||
def __init__(self):
|
||||
pass
|
||||
def GetDocumentContext(self):
|
||||
"""Return value must be a PyIDebugDocumentContext object
|
||||
"""
|
||||
RaiseNotImpl("GetDocumentContext")
|
||||
def SetBreakPoint(self, bps):
|
||||
"""bps -- an integer with flags.
|
||||
"""
|
||||
RaiseNotImpl("SetBreakPoint")
|
||||
|
||||
|
||||
class DebugStackFrame:
|
||||
"""Abstraction representing a logical stack frame on the stack of a thread."""
|
||||
_public_methods_ = [ 'GetCodeContext', 'GetDescriptionString', 'GetLanguageString', 'GetThread', 'GetDebugProperty']
|
||||
_com_interfaces_ = [ axdebug.IID_IDebugStackFrame ]
|
||||
def __init__(self):
|
||||
pass
|
||||
def GetCodeContext(self):
|
||||
"""Returns the current code context associated with the stack frame.
|
||||
|
||||
Return value must be a IDebugCodeContext object
|
||||
"""
|
||||
RaiseNotImpl("GetCodeContext")
|
||||
def GetDescriptionString(self, fLong):
|
||||
"""Returns a textual description of the stack frame.
|
||||
|
||||
fLong -- A flag indicating if the long name is requested.
|
||||
"""
|
||||
RaiseNotImpl("GetDescriptionString")
|
||||
def GetLanguageString(self):
|
||||
"""Returns a short or long textual description of the language.
|
||||
|
||||
fLong -- A flag indicating if the long name is requested.
|
||||
"""
|
||||
RaiseNotImpl("GetLanguageString")
|
||||
def GetThread(self):
|
||||
""" Returns the thread associated with this stack frame.
|
||||
|
||||
Result must be a IDebugApplicationThread
|
||||
"""
|
||||
RaiseNotImpl("GetThread")
|
||||
def GetDebugProperty(self):
|
||||
RaiseNotImpl("GetDebugProperty")
|
||||
|
||||
|
||||
class DebugDocumentHost:
|
||||
"""The interface from the IDebugDocumentHelper back to
|
||||
the smart host or language engine. This interface
|
||||
exposes host specific functionality such as syntax coloring.
|
||||
"""
|
||||
_public_methods_ = [ 'GetDeferredText', 'GetScriptTextAttributes', 'OnCreateDocumentContext', 'GetPathName', 'GetFileName', 'NotifyChanged']
|
||||
_com_interfaces_ = [ axdebug.IID_IDebugDocumentHost ]
|
||||
def __init__(self):
|
||||
pass
|
||||
def GetDeferredText(self, dwTextStartCookie, maxChars, bWantAttr):
|
||||
RaiseNotImpl("GetDeferredText")
|
||||
|
||||
def GetScriptTextAttributes(self, codeText, delimterText, flags):
|
||||
# Result must be an attribute sequence of same "length" as the code.
|
||||
RaiseNotImpl("GetScriptTextAttributes")
|
||||
|
||||
def OnCreateDocumentContext(self):
|
||||
# Result must be a PyIUnknown
|
||||
RaiseNotImpl("OnCreateDocumentContext")
|
||||
|
||||
def GetPathName(self):
|
||||
# Result must be (string, int) where the int is a BOOL
|
||||
# - TRUE if the path refers to the original file for the document.
|
||||
# - FALSE if the path refers to a newly created temporary file.
|
||||
# - raise Exception(scode=E_FAIL) if no source file can be created/determined.
|
||||
RaiseNotImpl("GetPathName")
|
||||
|
||||
def GetFileName(self):
|
||||
# Result is a string with just the name of the document, no path information.
|
||||
RaiseNotImpl("GetFileName")
|
||||
|
||||
def NotifyChanged(self):
|
||||
RaiseNotImpl("NotifyChanged")
|
||||
|
||||
# Additional gateway related functions.
|
||||
|
||||
class DebugDocumentTextConnectServer:
|
||||
_public_methods_ = win32com.server.connect.IConnectionPointContainer_methods + win32com.server.connect.IConnectionPoint_methods
|
||||
_com_interfaces_ = [pythoncom.IID_IConnectionPoint, pythoncom.IID_IConnectionPointContainer]
|
||||
# IConnectionPoint interfaces
|
||||
def __init__(self):
|
||||
self.cookieNo = -1
|
||||
self.connections = {}
|
||||
def EnumConnections(self):
|
||||
RaiseNotImpl("EnumConnections")
|
||||
def GetConnectionInterface(self):
|
||||
RaiseNotImpl("GetConnectionInterface")
|
||||
def GetConnectionPointContainer(self):
|
||||
return _wrap(self)
|
||||
def Advise(self, pUnk):
|
||||
# Creates a connection to the client. Simply allocate a new cookie,
|
||||
# find the clients interface, and store it in a dictionary.
|
||||
interface = pUnk.QueryInterface(axdebug.IID_IDebugDocumentTextEvents,1)
|
||||
self.cookieNo = self.cookieNo + 1
|
||||
self.connections[self.cookieNo] = interface
|
||||
return self.cookieNo
|
||||
def Unadvise(self, cookie):
|
||||
# Destroy a connection - simply delete interface from the map.
|
||||
try:
|
||||
del self.connections[cookie]
|
||||
except KeyError:
|
||||
return Exception(scode=winerror.E_UNEXPECTED)
|
||||
# IConnectionPointContainer interfaces
|
||||
def EnumConnectionPoints(self):
|
||||
RaiseNotImpl("EnumConnectionPoints")
|
||||
def FindConnectionPoint(self, iid):
|
||||
# Find a connection we support. Only support the single event interface.
|
||||
if iid==axdebug.IID_IDebugDocumentTextEvents:
|
||||
return _wrap(self)
|
||||
raise Exception(scode=winerror.E_NOINTERFACE) # ??
|
||||
|
||||
class RemoteDebugApplicationEvents:
|
||||
_public_methods_ = ["OnConnectDebugger","OnDisconnectDebugger","OnSetName","OnDebugOutput","OnClose","OnEnterBreakPoint","OnLeaveBreakPoint","OnCreateThread","OnDestroyThread","OnBreakFlagChange"]
|
||||
_com_interfaces_ = [axdebug.IID_IRemoteDebugApplicationEvents]
|
||||
def OnConnectDebugger(self, appDebugger):
|
||||
"""appDebugger -- a PyIApplicationDebugger
|
||||
"""
|
||||
RaiseNotImpl("OnConnectDebugger")
|
||||
def OnDisconnectDebugger(self):
|
||||
RaiseNotImpl("OnDisconnectDebugger")
|
||||
def OnSetName(self, name):
|
||||
RaiseNotImpl("OnSetName")
|
||||
def OnDebugOutput(self, string):
|
||||
RaiseNotImpl("OnDebugOutput")
|
||||
def OnClose(self):
|
||||
RaiseNotImpl("OnClose")
|
||||
def OnEnterBreakPoint(self, rdat):
|
||||
"""rdat -- PyIRemoteDebugApplicationThread
|
||||
"""
|
||||
RaiseNotImpl("OnEnterBreakPoint")
|
||||
def OnLeaveBreakPoint(self, rdat):
|
||||
"""rdat -- PyIRemoteDebugApplicationThread
|
||||
"""
|
||||
RaiseNotImpl("OnLeaveBreakPoint")
|
||||
def OnCreateThread(self, rdat):
|
||||
"""rdat -- PyIRemoteDebugApplicationThread
|
||||
"""
|
||||
RaiseNotImpl("OnCreateThread")
|
||||
def OnDestroyThread(self, rdat):
|
||||
"""rdat -- PyIRemoteDebugApplicationThread
|
||||
"""
|
||||
RaiseNotImpl("OnDestroyThread")
|
||||
def OnBreakFlagChange(self, abf, rdat):
|
||||
"""abf -- int - one of the axdebug.APPBREAKFLAGS constants
|
||||
rdat -- PyIRemoteDebugApplicationThread
|
||||
RaiseNotImpl("OnBreakFlagChange")
|
||||
"""
|
||||
class DebugExpressionContext:
|
||||
_public_methods_ = ["ParseLanguageText", "GetLanguageInfo"]
|
||||
_com_interfaces_ = [axdebug.IID_IDebugExpressionContext]
|
||||
def __init__(self):
|
||||
pass
|
||||
def ParseLanguageText(self, code, radix, delim, flags):
|
||||
"""
|
||||
result is IDebugExpression
|
||||
"""
|
||||
RaiseNotImpl("ParseLanguageText")
|
||||
def GetLanguageInfo(self):
|
||||
"""
|
||||
result is (string langName, iid langId)
|
||||
"""
|
||||
RaiseNotImpl("GetLanguageInfo")
|
||||
|
||||
class DebugExpression:
|
||||
_public_methods_ = ["Start", "Abort", "QueryIsComplete", "GetResultAsString", "GetResultAsDebugProperty"]
|
||||
_com_interfaces_ = [axdebug.IID_IDebugExpression]
|
||||
def Start(self, callback):
|
||||
"""
|
||||
callback -- an IDebugExpressionCallback
|
||||
|
||||
result - void
|
||||
"""
|
||||
RaiseNotImpl("Start")
|
||||
def Abort(self):
|
||||
"""
|
||||
no params
|
||||
result -- void
|
||||
"""
|
||||
RaiseNotImpl("Abort")
|
||||
|
||||
def QueryIsComplete(self):
|
||||
"""
|
||||
no params
|
||||
result -- void
|
||||
"""
|
||||
RaiseNotImpl("QueryIsComplete")
|
||||
|
||||
def GetResultAsString(self):
|
||||
RaiseNotImpl("GetResultAsString")
|
||||
|
||||
def GetResultAsDebugProperty(self):
|
||||
RaiseNotImpl("GetResultAsDebugProperty")
|
||||
|
||||
class ProvideExpressionContexts:
|
||||
_public_methods_ = ["EnumExpressionContexts"]
|
||||
_com_interfaces_ = [axdebug.IID_IProvideExpressionContexts]
|
||||
def EnumExpressionContexts(self):
|
||||
RaiseNotImpl("EnumExpressionContexts")
|
146
venv/Lib/site-packages/win32comext/axdebug/stackframe.py
Normal file
146
venv/Lib/site-packages/win32comext/axdebug/stackframe.py
Normal file
|
@ -0,0 +1,146 @@
|
|||
"""Support for stack-frames.
|
||||
|
||||
Provides Implements a nearly complete wrapper for a stack frame.
|
||||
"""
|
||||
import sys
|
||||
from .util import _wrap, RaiseNotImpl
|
||||
import expressions, gateways, axdebug, winerror
|
||||
import pythoncom
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
from .util import trace
|
||||
#def trace(*args):
|
||||
# pass
|
||||
|
||||
class EnumDebugStackFrames(gateways.EnumDebugStackFrames):
|
||||
"""A class that given a debugger object, can return an enumerator
|
||||
of DebugStackFrame objects.
|
||||
"""
|
||||
def __init__(self, debugger):
|
||||
infos = []
|
||||
frame = debugger.currentframe
|
||||
# print "Stack check"
|
||||
while frame:
|
||||
# print " Checking frame", frame.f_code.co_filename, frame.f_lineno-1, frame.f_trace,
|
||||
# Get a DebugCodeContext for the stack frame. If we fail, then it
|
||||
# is not debuggable, and therefore not worth displaying.
|
||||
cc = debugger.codeContainerProvider.FromFileName(frame.f_code.co_filename)
|
||||
if cc is not None:
|
||||
try:
|
||||
address = frame.f_locals['__axstack_address__']
|
||||
except KeyError:
|
||||
# print "Couldnt find stack address for",frame.f_code.co_filename, frame.f_lineno-1
|
||||
# Use this one, even tho it is wrong :-(
|
||||
address = axdebug.GetStackAddress()
|
||||
frameInfo = DebugStackFrame(frame, frame.f_lineno-1, cc), address, address+1, 0, None
|
||||
infos.append(frameInfo)
|
||||
# print "- Kept!"
|
||||
# else:
|
||||
# print "- rejected"
|
||||
frame = frame.f_back
|
||||
|
||||
gateways.EnumDebugStackFrames.__init__(self, infos, 0)
|
||||
# def __del__(self):
|
||||
# print "EnumDebugStackFrames dieing"
|
||||
|
||||
def Next(self, count):
|
||||
return gateways.EnumDebugStackFrames.Next(self, count)
|
||||
|
||||
# def _query_interface_(self, iid):
|
||||
# from win32com.util import IIDToInterfaceName
|
||||
# print "EnumDebugStackFrames QI with %s (%s)" % (IIDToInterfaceName(iid), str(iid))
|
||||
# return 0
|
||||
def _wrap(self, obj):
|
||||
# This enum returns a tuple, with 2 com objects in it.
|
||||
obFrame, min, lim, fFinal, obFinal = obj
|
||||
obFrame = _wrap(obFrame, axdebug.IID_IDebugStackFrame)
|
||||
if obFinal:
|
||||
obFinal = _wrap(obFinal, pythoncom.IID_IUnknown)
|
||||
return obFrame, min, lim, fFinal, obFinal
|
||||
|
||||
class DebugStackFrame(gateways.DebugStackFrame):
|
||||
def __init__(self, frame, lineno, codeContainer):
|
||||
self.frame = frame
|
||||
self.lineno = lineno
|
||||
self.codeContainer = codeContainer
|
||||
self.expressionContext = None
|
||||
# def __del__(self):
|
||||
# print "DSF dieing"
|
||||
def _query_interface_(self, iid):
|
||||
if iid==axdebug.IID_IDebugExpressionContext:
|
||||
if self.expressionContext is None:
|
||||
self.expressionContext = _wrap(expressions.ExpressionContext(self.frame), axdebug.IID_IDebugExpressionContext)
|
||||
return self.expressionContext
|
||||
# from win32com.util import IIDToInterfaceName
|
||||
# print "DebugStackFrame QI with %s (%s)" % (IIDToInterfaceName(iid), str(iid))
|
||||
return 0
|
||||
#
|
||||
# The following need implementation
|
||||
def GetThread(self):
|
||||
""" Returns the thread associated with this stack frame.
|
||||
|
||||
Result must be a IDebugApplicationThread
|
||||
"""
|
||||
RaiseNotImpl("GetThread")
|
||||
|
||||
def GetCodeContext(self):
|
||||
offset = self.codeContainer.GetPositionOfLine(self.lineno)
|
||||
return self.codeContainer.GetCodeContextAtPosition(offset)
|
||||
#
|
||||
# The following are usefully implemented
|
||||
def GetDescriptionString(self, fLong):
|
||||
filename = self.frame.f_code.co_filename
|
||||
s = ""
|
||||
if 0: #fLong:
|
||||
s = s + filename
|
||||
if self.frame.f_code.co_name:
|
||||
s = s + self.frame.f_code.co_name
|
||||
else:
|
||||
s = s + "<lambda>"
|
||||
return s
|
||||
def GetLanguageString(self, fLong):
|
||||
if fLong:
|
||||
return "Python ActiveX Scripting Engine"
|
||||
else:
|
||||
return "Python"
|
||||
def GetDebugProperty(self):
|
||||
return _wrap(StackFrameDebugProperty(self.frame), axdebug.IID_IDebugProperty)
|
||||
|
||||
class DebugStackFrameSniffer:
|
||||
_public_methods_ = ["EnumStackFrames"]
|
||||
_com_interfaces_ = [axdebug.IID_IDebugStackFrameSniffer]
|
||||
def __init__(self, debugger):
|
||||
self.debugger = debugger
|
||||
trace("DebugStackFrameSniffer instantiated")
|
||||
# def __del__(self):
|
||||
# print "DSFS dieing"
|
||||
def EnumStackFrames(self):
|
||||
trace("DebugStackFrameSniffer.EnumStackFrames called")
|
||||
return _wrap(EnumDebugStackFrames(self.debugger), axdebug.IID_IEnumDebugStackFrames)
|
||||
|
||||
# A DebugProperty for a stack frame.
|
||||
class StackFrameDebugProperty:
|
||||
_com_interfaces_ = [axdebug.IID_IDebugProperty]
|
||||
_public_methods_ = ['GetPropertyInfo', 'GetExtendedInfo', 'SetValueAsString',
|
||||
'EnumMembers', 'GetParent'
|
||||
]
|
||||
def __init__(self, frame):
|
||||
self.frame = frame
|
||||
|
||||
def GetPropertyInfo(self, dwFieldSpec, nRadix):
|
||||
RaiseNotImpl("StackFrameDebugProperty::GetPropertyInfo")
|
||||
def GetExtendedInfo(self): ### Note - not in the framework.
|
||||
RaiseNotImpl("StackFrameDebugProperty::GetExtendedInfo")
|
||||
|
||||
def SetValueAsString(self, value, radix):
|
||||
#
|
||||
RaiseNotImpl("DebugProperty::SetValueAsString")
|
||||
|
||||
def EnumMembers(self, dwFieldSpec, nRadix, iid):
|
||||
print("EnumMembers", dwFieldSpec, nRadix, iid)
|
||||
from . import expressions
|
||||
return expressions.MakeEnumDebugProperty(self.frame.f_locals, dwFieldSpec, nRadix, iid, self.frame)
|
||||
|
||||
def GetParent(self):
|
||||
# return IDebugProperty
|
||||
RaiseNotImpl("DebugProperty::GetParent")
|
114
venv/Lib/site-packages/win32comext/axdebug/util.py
Normal file
114
venv/Lib/site-packages/win32comext/axdebug/util.py
Normal file
|
@ -0,0 +1,114 @@
|
|||
# Utility function for wrapping objects. Centralising allows me to turn
|
||||
# debugging on and off for the entire package in a single spot.
|
||||
|
||||
import sys
|
||||
import win32com.server.util
|
||||
from win32com.server.exception import Exception
|
||||
import winerror
|
||||
import win32api
|
||||
import os
|
||||
|
||||
try:
|
||||
os.environ["DEBUG_AXDEBUG"]
|
||||
debugging = 1
|
||||
except KeyError:
|
||||
debugging = 0
|
||||
|
||||
def trace(*args):
|
||||
if not debugging: return
|
||||
print(str(win32api.GetCurrentThreadId()) + ":", end=' ')
|
||||
for arg in args:
|
||||
print(arg, end=' ')
|
||||
print()
|
||||
|
||||
# The AXDebugging implementation assumes that the returned COM pointers are in
|
||||
# some cases identical. Eg, from a C++ perspective:
|
||||
# p->GetSomeInterface( &p1 );
|
||||
# p->GetSomeInterface( &p2 );
|
||||
# p1==p2
|
||||
# By default, this is _not_ true for Python.
|
||||
# (Now this is only true for Document objects, and Python
|
||||
# now does ensure this.
|
||||
|
||||
all_wrapped = {}
|
||||
|
||||
def _wrap_nodebug(object, iid):
|
||||
return win32com.server.util.wrap(object, iid)
|
||||
|
||||
def _wrap_debug(object, iid):
|
||||
import win32com.server.policy
|
||||
dispatcher = win32com.server.policy.DispatcherWin32trace
|
||||
return win32com.server.util.wrap(object, iid, useDispatcher = dispatcher)
|
||||
|
||||
if debugging:
|
||||
_wrap = _wrap_debug
|
||||
else:
|
||||
_wrap = _wrap_nodebug
|
||||
|
||||
def _wrap_remove(object, iid = None):
|
||||
# Old - no longer used or necessary!
|
||||
return
|
||||
|
||||
def _dump_wrapped():
|
||||
from win32com.server.util import unwrap
|
||||
print("Wrapped items:")
|
||||
for key, items in all_wrapped.items():
|
||||
print(key, end=' ')
|
||||
try:
|
||||
ob = unwrap(key)
|
||||
print(ob, sys.getrefcount(ob))
|
||||
except:
|
||||
print("<error>")
|
||||
|
||||
|
||||
def RaiseNotImpl(who = None):
|
||||
if who is not None:
|
||||
print("********* Function %s Raising E_NOTIMPL ************" % (who))
|
||||
|
||||
# Print a sort-of "traceback", dumping all the frames leading to here.
|
||||
try:
|
||||
1/0
|
||||
except:
|
||||
frame = sys.exc_info()[2].tb_frame
|
||||
while frame:
|
||||
print("File: %s, Line: %d" % (frame.f_code.co_filename, frame.f_lineno))
|
||||
frame = frame.f_back
|
||||
|
||||
# and raise the exception for COM
|
||||
raise Exception(scode=winerror.E_NOTIMPL)
|
||||
|
||||
|
||||
import win32com.server.policy
|
||||
class Dispatcher(win32com.server.policy.DispatcherWin32trace):
|
||||
def __init__(self, policyClass, object):
|
||||
win32com.server.policy.DispatcherTrace.__init__(self, policyClass, object)
|
||||
import win32traceutil # Sets up everything.
|
||||
# print "Object with win32trace dispatcher created (object=%s)" % `object`
|
||||
|
||||
def _QueryInterface_(self, iid):
|
||||
rc = win32com.server.policy.DispatcherBase._QueryInterface_(self, iid)
|
||||
# if not rc:
|
||||
# self._trace_("in _QueryInterface_ with unsupported IID %s (%s)\n" % (IIDToInterfaceName(iid),iid))
|
||||
return rc
|
||||
|
||||
def _Invoke_(self, dispid, lcid, wFlags, args):
|
||||
print("In Invoke with", dispid, lcid, wFlags, args, "with object",self.policy._obj_)
|
||||
try:
|
||||
rc = win32com.server.policy.DispatcherBase._Invoke_(self, dispid, lcid, wFlags, args)
|
||||
# print "Invoke of", dispid, "returning", rc
|
||||
return rc
|
||||
except Exception:
|
||||
t, v, tb = sys.exc_info()
|
||||
tb = None # A cycle
|
||||
scode = v.scode
|
||||
try:
|
||||
desc = " (" + str(v.description) + ")"
|
||||
except AttributeError:
|
||||
desc = ""
|
||||
print("*** Invoke of %s raised COM exception 0x%x%s" % (dispid, scode, desc))
|
||||
except:
|
||||
print("*** Invoke of %s failed:" % dispid)
|
||||
typ, val, tb = sys.exc_info()
|
||||
import traceback
|
||||
traceback.print_exception(typ, val, tb)
|
||||
raise
|
|
@ -0,0 +1,19 @@
|
|||
<HTML>
|
||||
|
||||
<SCRIPT Language="Python" RUNAT=Server>
|
||||
|
||||
# Just for the sake of the demo, our Python script engine
|
||||
# will create a Python.Interpreter COM object, and call that.
|
||||
|
||||
# This is completely useless, as the Python Script Engine is
|
||||
# completely normal Python, and ASP does not impose retrictions, so
|
||||
# there is nothing the COM object can do that we can not do natively.
|
||||
|
||||
o = Server.CreateObject("Python.Interpreter")
|
||||
|
||||
Response.Write("Python says 1+1=" + str(o.Eval("1+1")))
|
||||
|
||||
</SCRIPT>
|
||||
|
||||
</HTML>
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<%@ Language=Python %>
|
||||
<HTML>
|
||||
|
||||
<HEAD>
|
||||
|
||||
<BODY BACKGROUND="/samples/images/backgrnd.gif">
|
||||
|
||||
<TITLE>Python test</TITLE>
|
||||
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="FFFFFF">
|
||||
|
||||
<SCRIPT Language="Python" RUNAT=Server>
|
||||
# NOTE that the <% tags below execute _before_ these tags!
|
||||
Response.Write("Hello from Python<P>")
|
||||
Response.Write("Browser is "+bc.browser)
|
||||
import win32api # Should be no problem using win32api in ASP pages.
|
||||
Response.Write("<p>Win32 username is "+win32api.GetUserName())
|
||||
</SCRIPT>
|
||||
|
||||
<BODY BGCOLOR="FFFFFF">
|
||||
|
||||
<%
|
||||
import sys
|
||||
print sys.path
|
||||
from win32com.axscript.asputil import *
|
||||
print "Hello"
|
||||
print "There"
|
||||
print "How are you"
|
||||
%>
|
||||
|
||||
<%bc = Server.CreateObject("MSWC.BrowserType")%>
|
||||
<BODY BGCOLOR="FFFFFF">
|
||||
<table border=1>
|
||||
<tr><td>Browser</td><td> <%=bc.browser %>
|
||||
<tr><td>Version</td><td> <%=bc.version %> </td></TR>
|
||||
<tr><td>Frames</td><td>
|
||||
<%Response.Write( iif(bc.frames, "TRUE", "FALSE")) %></td></TR>
|
||||
<tr><td>Tables</td><td>
|
||||
<%Response.Write( iif (bc.tables, "TRUE", "FALSE")) %></td></TR>
|
||||
<tr><td>BackgroundSounds</td><td>
|
||||
<%Response.Write( iif(bc.BackgroundSounds, "TRUE", "FALSE"))%></td></TR>
|
||||
<tr><td>VBScript</td><td>
|
||||
<%Response.Write( iif(bc.vbscript, "TRUE", "FALSE"))%></td></TR>
|
||||
<tr><td>JavaScript</td><td>
|
||||
<%Response.Write( iif(bc.javascript, "TRUE", "FALSE"))%></td></TR>
|
||||
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,4 @@
|
|||
<%@ language=python%>
|
||||
<html>
|
||||
<%Response.Redirect("test1.html")%>
|
||||
</html>
|
|
@ -0,0 +1,10 @@
|
|||
<html>
|
||||
<head>
|
||||
<body>
|
||||
GOT There
|
||||
<script language=javascript>
|
||||
location.href ="http://192.168.0.1/Python/interrupt/test.asp"
|
||||
</script>
|
||||
</body>
|
||||
</head>
|
||||
</html>
|
|
@ -0,0 +1,6 @@
|
|||
<%@ language =Python%>
|
||||
<html>
|
||||
<head>
|
||||
<%Response.Redirect("test.html")%>
|
||||
</head>
|
||||
</html>
|
|
@ -0,0 +1,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<body>
|
||||
GOT HERE
|
||||
<script language=javascript>
|
||||
location.href ="http://192.168.0.1/Python/interrupt/test1.asp"
|
||||
</script>
|
||||
</body>
|
||||
</head>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<HTML>
|
||||
|
||||
<SCRIPT Language="Python" RUNAT=Server>
|
||||
|
||||
for i in range(3,8):
|
||||
Response.Write("<FONT SIZE=%d>Hello World!!<BR>" % i)
|
||||
|
||||
</SCRIPT>
|
||||
|
||||
</HTML>
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<base target="text">
|
||||
<TITLE> Internet Workshop </TITLE>
|
||||
</HEAD>
|
||||
<BODY leftmargin=8 bgcolor="#FFFFFF" VLINK="#666666" LINK="#FF0000">
|
||||
<FONT FACE="ARIAL,HELVETICA" SIZE="2">
|
||||
|
||||
<P>
|
||||
<BR>
|
||||
<P><FONT FACE="ARIAL,HELVETICA" SIZE="5"><B>Python AX Script Engine</B></FONT>
|
||||
<BR>Demo using the Marquee Control
|
||||
<BR>Mark Hammond.
|
||||
|
||||
<P>This is really quite a boring demo, as the Marquee control does everything. However, there is Python code behind the buttons that change the speed. This code is all of 2 lines per button!!!
|
||||
|
||||
<P>For more information on Python as an ActiveX scripting language, see
|
||||
|
||||
<P><B>Python</B>
|
||||
<BR><A HREF="http://www.python.org">http://www.python.org</A>
|
||||
|
||||
</FONT>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
<HTML>
|
||||
<HEAD><TITLE>Python Script sample: Calculator</TITLE></HEAD>
|
||||
<BODY><FONT FACE=ARIAL SIZE=3> <!-- global default -->
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
# globals
|
||||
Accum = 0.0 # Previous number (operand) awaiting operation
|
||||
FlagNewNum = 1 # Flag to indicate a new number (operand) is being entered
|
||||
NullOp = lambda x,y: y
|
||||
PendingOp = NullOp# Pending operation waiting for completion of second operand
|
||||
numberButNames = ['Zero','One','Two','Three','Four','Five','Six','Seven','Eight','Nine']
|
||||
|
||||
def NumPressed(Num):
|
||||
print "NumPressed", Num
|
||||
global FlagNewNum
|
||||
if FlagNewNum:
|
||||
ax.document.Keypad.ReadOut.Value = Num
|
||||
FlagNewNum = None
|
||||
else:
|
||||
if ax.document.Keypad.ReadOut.Value == "0":
|
||||
ax.document.Keypad.ReadOut.Value = str(Num)
|
||||
else:
|
||||
ax.document.Keypad.ReadOut.Value= ax.document.Keypad.ReadOut.Value + str(Num)
|
||||
|
||||
# Dynamically create handlers for all the decimal buttons.
|
||||
# (ie, this will dynamically create "One_OnClick()"... etc handlers
|
||||
for i in range(len(numberButNames)):
|
||||
exec "def %s_OnClick():\tNumPressed(%d)\n" % (numberButNames[i],i)
|
||||
|
||||
def Decimal_OnClick():
|
||||
global curReadOut, FlagNewNum
|
||||
curReadOut = ax.document.Keypad.ReadOut.Value
|
||||
if FlagNewNum:
|
||||
curReadOut = "0."
|
||||
FlagNewNum = None
|
||||
else:
|
||||
if not ("." in curReadOut):
|
||||
curReadOut = curReadOut + "."
|
||||
ax.document.Keypad.ReadOut.Value = curReadOut
|
||||
|
||||
import sys, string
|
||||
|
||||
def Operation(Op, fn):
|
||||
global FlagNewNum, PendingOp, Accum
|
||||
ReadOut = ax.document.Keypad.ReadOut.Value
|
||||
print "Operation", Op, ReadOut, PendingOp, Accum
|
||||
if FlagNewNum:
|
||||
# User is hitting op keys repeatedly, so don't do anything
|
||||
PendingOp = NullOp
|
||||
else:
|
||||
FlagNewNum = 1
|
||||
Accum = PendingOp( Accum, string.atof(ReadOut) )
|
||||
ax.document.Keypad.ReadOut.Value = str(Accum)
|
||||
PendingOp = fn
|
||||
|
||||
def ClearEntry_OnClick():
|
||||
# Remove current number and reset state
|
||||
global FlagNewNum
|
||||
ax.document.Keypad.ReadOut.Value = "0"
|
||||
FlagNewNum = 1
|
||||
|
||||
def Clear_OnClick():
|
||||
global Accum, PendingOp
|
||||
Accum = 0
|
||||
PendingOp = NullOp
|
||||
ClearEntry_OnClick()
|
||||
|
||||
def Neg_OnClick():
|
||||
ax.document.Keypad.ReadOut.Value = str(-string.atof(ax.document.Keypad.ReadOut.Value))
|
||||
</SCRIPT>
|
||||
|
||||
|
||||
<form action="" Name="Keypad">
|
||||
<TABLE>
|
||||
<B>
|
||||
<TABLE BORDER=2 WIDTH=50 HEIGHT=60 CELLPADDING=1 CELLSPACING=5>
|
||||
<CAPTION ALIGN=top> <b>Calculator</b><p> </CAPTION>
|
||||
<TR>
|
||||
<TD COLSPAN=3 ALIGN=MIDDLE><INPUT NAME="ReadOut" TYPE="Text" SIZE=24 VALUE="0" WIDTH=100%></TD>
|
||||
<TD></TD>
|
||||
<TD><INPUT NAME="Clear" TYPE="Button" VALUE=" C " ></TD>
|
||||
<TD><INPUT NAME="ClearEntry" TYPE="Button" VALUE=" CE " ></TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><INPUT NAME="Seven" TYPE="Button" VALUE=" 7 " ></TD>
|
||||
<TD><INPUT NAME="Eight" TYPE="Button" VALUE=" 8 " ></TD>
|
||||
<TD><INPUT NAME="Nine" TYPE="Button" VALUE=" 9 " ></TD>
|
||||
<TD></TD>
|
||||
<TD><INPUT NAME="Neg" TYPE="Button" VALUE=" +/- " ></TD>
|
||||
<TD><INPUT NAME="Percent" TYPE="Button" VALUE=" % " OnClick="Operation('%', lambda x,y: x*y/100.0)"></TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><INPUT NAME="Four" TYPE="Button" VALUE=" 4 " ></TD>
|
||||
<TD><INPUT NAME="Five" TYPE="Button" VALUE=" 5 " ></TD>
|
||||
<TD><INPUT NAME="Six" TYPE="Button" VALUE=" 6 " ></TD>
|
||||
<TD></TD>
|
||||
<TD ALIGN=MIDDLE><INPUT NAME="Plus" TYPE="Button" VALUE=" + " OnClick="Operation('+', lambda x,y: x+y)"></TD>
|
||||
<TD ALIGN=MIDDLE><INPUT NAME="Minus" TYPE="Button" VALUE=" - " OnClick="Operation('-', lambda x,y: x-y)"></TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><INPUT NAME="One" TYPE="Button" VALUE=" 1 " ></TD>
|
||||
<TD><INPUT NAME="Two" TYPE="Button" VALUE=" 2 " ></TD>
|
||||
<TD><INPUT NAME="Three" TYPE="Button" VALUE=" 3 " ></TD>
|
||||
<TD></TD>
|
||||
<TD ALIGN=MIDDLE><INPUT NAME="Multiply" TYPE="Button" VALUE=" * " OnClick="Operation('*', lambda x,y: x*y)" ></TD>
|
||||
<TD ALIGN=MIDDLE><INPUT NAME="Divide" TYPE="Button" VALUE=" / " OnClick="Operation('/', lambda x,y: x/y)" ></TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD><INPUT NAME="Zero" TYPE="Button" VALUE=" 0 " ></TD>
|
||||
<TD><INPUT NAME="Decimal" TYPE="Button" VALUE=" . " ></TD>
|
||||
<TD COLSPAN=3></TD>
|
||||
<TD><INPUT NAME="Equals" TYPE="Button" VALUE=" = " OnClick="Operation('=', lambda x,y: x)"></TD>
|
||||
</TR></TABLE></TABLE></B>
|
||||
</FORM>
|
||||
</FONT></BODY></HTML>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<HTML>
|
||||
<BODY>
|
||||
|
||||
<SCRIPT>
|
||||
b="Hello There, how are you"
|
||||
</SCRIPT>
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
print "Hello"
|
||||
a="Hi there"
|
||||
document.write("Hello<P>")
|
||||
alert("Hi there")
|
||||
</SCRIPT>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -0,0 +1,26 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Python AXScript Demos</TITLE>
|
||||
</HEAD>
|
||||
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
def Window_OnLoad():
|
||||
pass
|
||||
# import win32traceutil
|
||||
# print "Frames are", ax.window.frames._print_details_()
|
||||
# print "Frame 0 href = ", ax.frames.Item(0).location.href
|
||||
|
||||
def Name_OnLoad():
|
||||
print "Frame loading"
|
||||
|
||||
</SCRIPT>
|
||||
|
||||
<FRAMESET FRAMEBORDER=1 COLS = "250, *">
|
||||
<FRAME SRC="demo_menu.htm">
|
||||
<FRAME SRC="demo_check.htm" NAME="Body">
|
||||
</FRAMESET>
|
||||
|
||||
|
||||
</HTML>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<HTML>
|
||||
<H1>Engine Registration</H1>
|
||||
|
||||
<BODY>
|
||||
|
||||
<p>The Python ActiveX Scripting Engine is not currently registered.<p>
|
||||
|
||||
<p>Due to a <a href="http://starship.python.net/crew/mhammond/win32/PrivacyProblem.html">privacy
|
||||
concern</a> discovered in the engine, the use of Python inside IE has been disabled.</p>
|
||||
|
||||
Before any of the supplied demos will work, the engine must be successfully registered.
|
||||
|
||||
<P>To install a version of the engine, that does work with IE, you can execute the Python program
|
||||
<CODE>win32com\axscript\client\pyscript_rexec.py</CODE> must be run. You can either do this manually, or follow the instructions below.</p>
|
||||
|
||||
<H2>Register the engine now!</H2>
|
||||
|
||||
<p>If you have read about the <a href="http://starship.python.net/crew/mhammond/win32/PrivacyProblem.html">privacy
|
||||
concern</a> and still wish to register the engine, just follow the process outlined below:</p>
|
||||
<OL>
|
||||
<LI>Click on the link below
|
||||
<LI><B>A dialog will be presented asking if the file should be opened or saved to disk. Select "Open it".</B>
|
||||
<LI>A Console program will briefly open, while the server is registered.
|
||||
</OL>
|
||||
|
||||
<P><A HREF="..\..\..\client\pyscript_rexec.py">Register the engine now</A>
|
||||
|
||||
<H2>Checking the registration</H2>
|
||||
After the registration is complete, simply hit the Reload button. If the
|
||||
registration was successful, the page will change to the Python/AvtiveX Demo Page.
|
||||
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
try:
|
||||
window.open("demo_intro.htm", "Body")
|
||||
except:
|
||||
history.back()
|
||||
</SCRIPT>
|
||||
</BODY></HTML>
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<HTML>
|
||||
<BODY>
|
||||
|
||||
<H1>
|
||||
<MARQUEE NAME="Marquee1" DIRECTION=LEFT BEHAVIOR=SCROLL SCROLLAMOUNT=10 SCROLLDELAY=200
|
||||
>Python ActiveX Scripting Demonstation
|
||||
</MARQUEE>
|
||||
</H1>
|
||||
|
||||
<p>Congratulations on installing the Python ActiveX Scripting Engine</p>
|
||||
|
||||
<p>Be warned that there is a <a href="http://starship.python.net/crew/mhammond/win32/PrivacyProblem.html">privacy
|
||||
concern</a> with this engine. Please read this information, including how to disable the feature.</p>
|
||||
|
||||
|
||||
<H3>Object model</H3>
|
||||
<P>Except as described below, the object module exposed should be similar to that exposed
|
||||
by Visual Basic, etc. Due to the nature of ActiveX Scripting, the details for each
|
||||
host are different, but Python should work "correctly".
|
||||
|
||||
<P>The object model exposed via Python for MSIE is not as seamless as VB. The biggest limitation is
|
||||
the concept of a "local" namespace. For example, in VB, you can
|
||||
code <code>text="Hi there"</code>, but in Python, you must code
|
||||
<code>MyForm.ThisButton.Text="Hi There"</code>. See the <A HREF="foo2.htm">foo2</A> sample
|
||||
for futher details.
|
||||
|
||||
<H3>Known bugs and problems</H3>
|
||||
<UL>
|
||||
<LI><P>This release seems to have broken Aaron's mouse-trace sample. No idea why, and Im supposed to be looking into it.
|
||||
<LI><P>Builtin objects such as MARQUEE are giving me grief. Objects accessed via forms are generally
|
||||
no problem.
|
||||
<LI><P>If you are trying to use Python with the Windows Scripting Host, note that
|
||||
.pys files are not correct registered - you will need to explicitely
|
||||
specify either cscript.exe or wscript.exe on the command line.
|
||||
</UL>
|
||||
|
||||
</BODY></HTML>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<HTML>
|
||||
<BODY>
|
||||
<H1>Scripting Demos</H1>
|
||||
<P>An <A HREF="demo_check.htm" TARGET=Body>Introduction</A> to the
|
||||
scripting engine.
|
||||
|
||||
<P>The <A HREF="calc.htm" TARGET=Body>Calculator Demo</A> is a very
|
||||
cool sample written by Aaron Watters.
|
||||
|
||||
<P><A HREF="mouseTrack.htm" TARGET=Body>Mouse track</A> is another of
|
||||
Aaron's samples, and shows how fast the Python engine is!
|
||||
|
||||
<P>The <A HREF="foo2.htm" TARGET=Body>foo2 sample</A> is mainly used
|
||||
for debugging and testing, but does show some forms in action.
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<HTML>
|
||||
<BODY>
|
||||
A page generated by Python
|
||||
|
||||
<SCRIPT LANGUAGE="XXXVBScript">
|
||||
document.open()
|
||||
document.writeLn "<P>Hello from VBScript"
|
||||
document.close()
|
||||
</SCRIPT>
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
ax.document.write("<P>Hello from Python")
|
||||
ax.document.close()
|
||||
ax.document.open()
|
||||
ax.document.write("<P>Hello again from Python")
|
||||
ax.document.close()
|
||||
|
||||
def Window_OnLoad():
|
||||
pass
|
||||
# ax.document.write("<P>Hello from Load from Python")
|
||||
# ax.document.close()
|
||||
</SCRIPT>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -0,0 +1,105 @@
|
|||
<HTML>
|
||||
<BODY>
|
||||
|
||||
<SCRIPT>
|
||||
b="Hello"
|
||||
</SCRIPT>
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
import win32traceutil
|
||||
import sys
|
||||
print "Hello"
|
||||
a="Hi there"
|
||||
print "Location is", document.location
|
||||
document.write("Hello", " from version ", 2, " of the Python AXScript Engine","<P>")
|
||||
document.writeln("This is Python", sys.version)
|
||||
|
||||
</SCRIPT>
|
||||
|
||||
<P>The caption on the first button is set by the Window Load code. Clicking
|
||||
that button changes the text in the first edit box.
|
||||
|
||||
<P>The second button changes its own text when clicked.
|
||||
|
||||
<P>The fourth button calls a global function, defined in the global 'script' scope,
|
||||
rather than the 'MyForm' scope.
|
||||
|
||||
<FORM NAME="MyForm" METHOD="GET">
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
print "Hello from in the form"
|
||||
</SCRIPT>
|
||||
<INPUT NAME="Button1" TYPE="Button" OnClick="MyForm.Text1.value='Hi'" LANGUAGE="Python">
|
||||
<INPUT TYPE="TEXT" SIZE=25 NAME="Text1">
|
||||
<INPUT NAME="Button2" TYPE="Button" VALUE="Click for 'Hi'" OnClick="a='Howdy'; MyForm.Button2.value='Hi'" LANGUAGE="Python">
|
||||
<INPUT NAME="Button3" TYPE="Button" VALUE="Click for URL" OnClick="MyForm.Text2.value=document.location" LANGUAGE="Python">
|
||||
<INPUT TYPE="TEXT" SIZE=25 NAME="Text2">
|
||||
<INPUT NAME="Button4" TYPE="Button" VALUE="Call global fn" OnClick="foo1()" LANGUAGE="Python">
|
||||
<INPUT NAME="Button5" TYPE="Button" VALUE="Script for... Test">
|
||||
<script for="Button5" event="onClick" language="Python">
|
||||
print "HelloThere";
|
||||
window.alert("Hello")
|
||||
def ATest():
|
||||
print "Hello from ATEst"
|
||||
|
||||
ATest()
|
||||
</script>
|
||||
<INPUT NAME="Button6" TYPE="Button" VALUE="Set Other" OnClick="Form2.Text1.Value='Hi from other'" LANGUAGE="Python">
|
||||
|
||||
</FORM><BR>
|
||||
<P>
|
||||
And here is a second form
|
||||
<P>
|
||||
<FORM NAME="Form2" METHOD="GET">
|
||||
<INPUT NAME="Button1" TYPE="Button" OnClick="Form2.Text1.Value='Hi'" LANGUAGE="Python">
|
||||
<INPUT NAME="Button2" TYPE="Button" VALUE="Set Other" OnClick="MyForm.Text1.Value='Hi from other'" LANGUAGE="Python">
|
||||
<INPUT TYPE="TEXT" SIZE=25 NAME="Text1">
|
||||
<INPUT NAME="ButRExec" TYPE="Button" VALUE="RExec fail" OnClick="import win32api;win32api.MessageBox(0,'Oops')" LANGUAGE="Python">
|
||||
<INPUT NAME="ButRExec2" TYPE="Button" VALUE="RExec fail 2" OnClick="import sys,win32traceutil;print sys.modules;from win32com.client import dynamic;import win32com.client.dynamic, pythoncom, win32com.client;o=win32com.client.Dispatch('Word.Application')" LANGUAGE="Python">
|
||||
<INPUT NAME="ButVB" TYPE="Button" VALUE="VBScript Button" OnClick='alert("Hi from VBScript")'>
|
||||
<INPUT NAME="ButCallChain" TYPE="Button" VALUE="Multi-Language call" OnClick='CallPython()'>
|
||||
</FORM><BR>
|
||||
|
||||
<SCRIPT LANGUAGE="VBScript">
|
||||
function CallPython()
|
||||
alert("Hello from VB - Im about to call Python!")
|
||||
PythonGlobalFunction()
|
||||
end function
|
||||
</SCRIPT>
|
||||
|
||||
<SCRIPT LANGUAGE="JScript">
|
||||
function JScriptFunction()
|
||||
{
|
||||
alert("Hello from JScript");
|
||||
}
|
||||
</SCRIPT>
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
x=13
|
||||
|
||||
def foo1():
|
||||
y = 14
|
||||
for name, item in globals().items():
|
||||
print name, `item`
|
||||
alert ("Hello from AXCode")
|
||||
print "Y is ",y
|
||||
|
||||
def PythonGlobalFunction():
|
||||
window.alert("Hello from Python - Im about to call JScript!")
|
||||
window.JScriptFunction()
|
||||
|
||||
def Window_OnLoad():
|
||||
print "X is", x
|
||||
print "a is", a
|
||||
# print "------ GLOBALS ----------"
|
||||
# for n,v in globals().items():
|
||||
# print n,'=',v
|
||||
print "MyForm is", MyForm
|
||||
print "MyForm is repr", `MyForm`
|
||||
print "MyForm.Button1 is", `MyForm.Button1`
|
||||
MyForm.Button1.Value = "Python Rules!"
|
||||
Form2.Button1.value = "Form2!"
|
||||
MyForm.Text1.value = document.location
|
||||
</SCRIPT>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -0,0 +1,25 @@
|
|||
<HTML>
|
||||
<BODY>
|
||||
|
||||
<FORM NAME="TestForm" METHOD="POST" >
|
||||
<INPUT TYPE="TEXT" SIZE=25 NAME="Name">Name<br>
|
||||
<INPUT TYPE="TEXT" SIZE=25 NAME="Address">Address<br>
|
||||
<INPUT TYPE=SUBMIT
|
||||
</FORM>
|
||||
|
||||
<SCRIPT LANGUAGE="Python" for="TestForm" Event="onSubmit">
|
||||
return Validate()
|
||||
</SCRIPT>
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
|
||||
def Validate():
|
||||
if not TestForm.Name.Value or not TestForm.Address.Value:
|
||||
ax.alert("You must enter a name and address.")
|
||||
return 1
|
||||
return 0
|
||||
|
||||
</SCRIPT>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -0,0 +1,60 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<base target="text">
|
||||
<TITLE> Internet Workshop </TITLE>
|
||||
</HEAD>
|
||||
<BODY leftmargin=8 bgcolor="#FFFFFF" VLINK="#666666" LINK="#FF0000">
|
||||
<FONT FACE="ARIAL,HELVETICA" SIZE="2">
|
||||
|
||||
<P>
|
||||
<BR>
|
||||
<P><FONT FACE="ARIAL,HELVETICA" SIZE="5"><B>Marquee Demo</B></FONT>
|
||||
|
||||
<P>
|
||||
|
||||
|
||||
<OBJECT
|
||||
ID="Marquee1"
|
||||
CLASSID="CLSID:1A4DA620-6217-11CF-BE62-0080C72EDD2D"
|
||||
CODEBASE="/workshop/activex/gallery/ms/marquee/other/marquee.ocx#Version=4,70,0,1112"
|
||||
TYPE="application/x-oleobject"
|
||||
WIDTH=100%
|
||||
HEIGHT=80
|
||||
>
|
||||
<PARAM NAME="szURL" VALUE="marqueeText1.htm">
|
||||
<PARAM NAME="ScrollPixelsX" VALUE="0">
|
||||
<PARAM NAME="ScrollPixelsY" VALUE="-5">
|
||||
<PARAM NAME="ScrollDelay" VALUE="100">
|
||||
<PARAM NAME="Whitespace" VALUE="0">
|
||||
</OBJECT>
|
||||
|
||||
<br> <br>
|
||||
|
||||
<INPUT TYPE="Button" NAME="btnFaster" VALUE="Faster">
|
||||
<INPUT TYPE="Button" NAME="btnNormal" VALUE="Normal">
|
||||
<INPUT TYPE="Button" NAME="btnSlower" VALUE="Slower">
|
||||
|
||||
<SCRIPT Language="Python">
|
||||
|
||||
def btnFaster_Onclick():
|
||||
ax.Marquee1.ScrollDelay = 0
|
||||
|
||||
def btnNormal_Onclick():
|
||||
ax.Marquee1.ScrollDelay = 50
|
||||
|
||||
def btnSlower_Onclick():
|
||||
ax.Marquee1.ScrollDelay = 300
|
||||
|
||||
</SCRIPT>
|
||||
|
||||
|
||||
<P>
|
||||
<HR>
|
||||
<B>Notes:</B>
|
||||
<P>
|
||||
|
||||
|
||||
</FONT>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<HTML>
|
||||
|
||||
<HEAD><TITLE>Python Scripting sample: Mouse tracking</TITLE></HEAD>
|
||||
<BODY BGCOLOR="#FFFFFF" TOPMARGIN=8>
|
||||
<FONT SIZE=5>
|
||||
<TABLE Border=0><TR VALIGN=MIDDLE><TD>
|
||||
<A ID="Image"> <IMG
|
||||
SRC="file:..\..\..\..\..\win32com\html\image\pycom_blowing.gif"
|
||||
ALT="Clickable Map Image" HEIGHT=113 WIDTH=624 BORDER=0></A>
|
||||
|
||||
</TD></TR>
|
||||
<TR><TD> </TD></TR>
|
||||
<TR VALIGN=MIDDLE><TD VALIGN=MIDDLE ALIGN=CENTER><FONT SIZE=5><INPUT
|
||||
TYPE="text" NAME="TxtLinkDescription" SIZE=50></FONT></TD></TR></TABLE>
|
||||
</FONT>
|
||||
|
||||
<P>
|
||||
A mouse tracking demo. Move the mouse over the image above...
|
||||
|
||||
<SCRIPT Language="Python">
|
||||
<!--
|
||||
# Remember the last location clicked
|
||||
#print "here we go", 1
|
||||
mx = my = 0
|
||||
|
||||
# class for rectangle testing
|
||||
class rect:
|
||||
def __init__(self, lowx, lowy, upx, upy, desc, url):
|
||||
self.lowx, self.lowy, self.upx, self.upy, self.desc, self.url = \
|
||||
lowx, lowy, upx, upy, desc, url
|
||||
def inside(self, x, y):
|
||||
# print (x,y), "inside", self.desc,
|
||||
result = self.lowx <= x <= self.upx and self.lowy <= y <= self.upy
|
||||
# print result
|
||||
return result
|
||||
def mouse_move(self):
|
||||
# print "move", self.desc
|
||||
ax.TxtLinkDescription.Value = coords + " - " + self.desc
|
||||
def onclick(self):
|
||||
# print "click", self.desc
|
||||
ax.TxtLinkDescription.Value = coords +" click! " + `self.url`
|
||||
if self.url: ax.location = self.url
|
||||
|
||||
blows = "Blows away "
|
||||
rects =[rect(12,48,59,101,blows+"Visual Basic", ""),
|
||||
rect(107,0,172,58,blows+"Internet Explorer", ""),
|
||||
rect(193,0,261,56,blows+"Microsoft Access", ""),
|
||||
rect(332,43,392,93,blows+"Microsoft Word", ""),
|
||||
rect(457,52,521,99,blows+"Microsoft Excel", ""),
|
||||
rect(537,12,613,85,"Python blows them all away!", "http://www.python.org"),
|
||||
]
|
||||
|
||||
default = rect(0,0,0,0,"Click on an icon","")
|
||||
|
||||
def Image_MouseMove(s, b, x, y):
|
||||
global mx, my, coords
|
||||
coords =`(x,y)`
|
||||
# print coords,
|
||||
mx, my = x, y
|
||||
for r in rects:
|
||||
if r.inside(x,y):
|
||||
# print r.desc
|
||||
r.mouse_move()
|
||||
break
|
||||
else:
|
||||
# print default.desc
|
||||
default.mouse_move()
|
||||
|
||||
def Image_OnClick():
|
||||
for r in rects:
|
||||
if r.inside(mx,my):
|
||||
r.onclick()
|
||||
break
|
||||
-->
|
||||
</SCRIPT>
|
||||
|
||||
<P>
|
||||
|
||||
</FONT>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
|
@ -0,0 +1,34 @@
|
|||
#app=WScript.Application
|
||||
#app._print_details_() # Use this to see what Python knows about a COM object.
|
||||
|
||||
g_index = 1
|
||||
# A procedure, using a global.
|
||||
def Show(desc, value = None):
|
||||
global g_index # Need global for g_index, as I locally assign.
|
||||
# No global needed to "xl" object, as only referenced.
|
||||
# Also note "xl" is assigned later in the script - ie, Python is very late bound.
|
||||
xl.Cells(g_index, 1).Value = desc
|
||||
if value: xl.Cells(g_index, 2).Value = value
|
||||
g_index = g_index + 1
|
||||
|
||||
xl = WScript.CreateObject("Excel.Application")
|
||||
import sys
|
||||
|
||||
xl.Visible = 1
|
||||
#xl.Workbooks().Add() # Excel versions before 98
|
||||
xl.Workbooks.Add()
|
||||
|
||||
# Show the WScript properties.
|
||||
Show("Application Friendly Name", WScript.Name)
|
||||
Show("Application Version", WScript.Version)
|
||||
Show("Application Context: Fully Qualified Name", WScript.FullName)
|
||||
Show("Application Context: Path Only", WScript.Path)
|
||||
Show("State of Interactive Mode", WScript.Interactive)
|
||||
|
||||
Show("All script arguments:")
|
||||
args = WScript.Arguments
|
||||
|
||||
for i in range(0,args.Count()):
|
||||
Show("Arg %d" % i, args(i))
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
""" Windows Script Host Sample Script
|
||||
' Ported to Python
|
||||
'
|
||||
' ------------------------------------------------------------------------
|
||||
' Copyright (C) 1996 Microsoft Corporation
|
||||
'
|
||||
' You have a royalty-free right to use, modify, reproduce and distribute
|
||||
' the Sample Application Files (and/or any modified version) in any way
|
||||
' you find useful, provided that you agree that Microsoft has no warranty,
|
||||
' obligations or liability for any Sample Application Files.
|
||||
' ------------------------------------------------------------------------
|
||||
'
|
||||
' This sample demonstrates how to write/delete from the registry.
|
||||
"""
|
||||
|
||||
WshShell = WScript.CreateObject("WScript.Shell")
|
||||
|
||||
WshShell.Popup("This script shows how to use registry related methods.", 2)
|
||||
|
||||
WshShell.Popup("Create key HKCU\\Foo with value 'Top level key'")
|
||||
WshShell.RegWrite("HKCU\\Foo\\", "Top level key")
|
||||
|
||||
WshShell.Popup("Create key HKCU\\Foo\\Bar with value 'Second level key'")
|
||||
WshShell.RegWrite( "HKCU\\Foo\\Bar\\", "Second level key")
|
||||
|
||||
WshShell.Popup ("Set value HKCU\\Foo\\Value to REG_SZ 1")
|
||||
WshShell.RegWrite( "HKCU\\Foo\\Value", 1)
|
||||
|
||||
WshShell.Popup ("Set value HKCU\\Foo\\Bar to REG_DWORD 2")
|
||||
WshShell.RegWrite ("HKCU\\Foo\\Bar", 2, "REG_DWORD")
|
||||
|
||||
WshShell.Popup ("Set value HKCU\\Foo\\Bar to REG_EXPAND_SZ '3'")
|
||||
WshShell.RegWrite ("HKCU\\Foo\\Bar\\Baz", "%SystemRoot%\\Foo")
|
||||
|
||||
WshShell.Popup ("Delete value HKCU\\Foo\\Bar\\Baz")
|
||||
WshShell.RegDelete ("HKCU\\Foo\\Bar\\Baz")
|
||||
|
||||
WshShell.Popup ("Delete key HKCU\\Foo\\Bar")
|
||||
WshShell.RegDelete ("HKCU\\Foo\\Bar\\")
|
||||
|
||||
WshShell.Popup ("Delete key HKCU\\Foo")
|
||||
WshShell.RegDelete ("HKCU\\Foo\\")
|
||||
|
||||
WScript.Echo ("Done")
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# Testall - test core AX support.
|
||||
|
||||
# Test "Restricted Execution" (ie, IObjectSafety).
|
||||
# This will fail if in a "restricted execution" environment, but
|
||||
# will silenty do nothing of not restricted. This same line in an MSIE
|
||||
# script would cause an exception.
|
||||
print("Importing win32api...")
|
||||
import win32api
|
||||
if 1==1:
|
||||
print("Hi")
|
||||
|
||||
WScript.Echo("Hello from WScript")
|
||||
|
||||
#fail
|
||||
|
4
venv/Lib/site-packages/win32comext/axscript/__init__.py
Normal file
4
venv/Lib/site-packages/win32comext/axscript/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
|||
# See if we have a special directory for the binaries (for developers)
|
||||
import win32com
|
||||
win32com.__PackageSupportBuildPath__(__path__)
|
||||
|
Binary file not shown.
Binary file not shown.
12
venv/Lib/site-packages/win32comext/axscript/asputil.py
Normal file
12
venv/Lib/site-packages/win32comext/axscript/asputil.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
"""A utility module for ASP (Active Server Pages on MS Internet Info Server.
|
||||
|
||||
Contains:
|
||||
iif -- A utility function to avoid using "if" statements in ASP <% tags
|
||||
|
||||
"""
|
||||
|
||||
def iif(cond, t, f):
|
||||
if cond:
|
||||
return t
|
||||
else:
|
||||
return f
|
BIN
venv/Lib/site-packages/win32comext/axscript/axscript.pyd
Normal file
BIN
venv/Lib/site-packages/win32comext/axscript/axscript.pyd
Normal file
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
# This is a Python package
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
209
venv/Lib/site-packages/win32comext/axscript/client/debug.py
Normal file
209
venv/Lib/site-packages/win32comext/axscript/client/debug.py
Normal file
|
@ -0,0 +1,209 @@
|
|||
import traceback, sys, string
|
||||
|
||||
import win32com.server.util
|
||||
from win32com.util import IIDToInterfaceName
|
||||
from win32com.client.util import Enumerator
|
||||
from win32com.server.exception import COMException
|
||||
import pythoncom
|
||||
from .framework import trace
|
||||
from win32com.axdebug import axdebug, gateways, contexts, stackframe, documents, adb
|
||||
from win32com.axdebug.codecontainer import SourceCodeContainer
|
||||
from win32com.axdebug.util import _wrap, _wrap_remove
|
||||
import win32com.client.connect
|
||||
import win32api, winerror
|
||||
import os
|
||||
|
||||
try:
|
||||
os.environ["DEBUG_AXDEBUG"]
|
||||
debuggingTrace = 1 # Should we print "trace" output?
|
||||
except KeyError:
|
||||
debuggingTrace = 0
|
||||
|
||||
def trace(*args):
|
||||
"""A function used instead of "print" for debugging output.
|
||||
"""
|
||||
if not debuggingTrace:
|
||||
return
|
||||
print(win32api.GetCurrentThreadId(), end=' ')
|
||||
for arg in args:
|
||||
print(arg, end=' ')
|
||||
print()
|
||||
|
||||
# Note that the DebugManager is not a COM gateway class for the
|
||||
# debugger - but it does create and manage them.
|
||||
class DebugManager:
|
||||
_debugger_interfaces_ = [axdebug.IID_IActiveScriptDebug]
|
||||
def __init__(self, scriptEngine):
|
||||
self.scriptEngine = scriptEngine
|
||||
self.adb = adb.Debugger()
|
||||
self.rootNode = None
|
||||
self.debugApplication = None
|
||||
self.ccProvider = documents.CodeContainerProvider()
|
||||
try:
|
||||
self.scriptSiteDebug = scriptEngine.GetScriptSite(axdebug.IID_IActiveScriptSiteDebug)
|
||||
except pythoncom.com_error:
|
||||
# No debugger interface (ie, dumb host). Do the extra work.
|
||||
trace("Scripting site has no debugger interface")
|
||||
self.scriptSiteDebug = None
|
||||
# Get the debug application object.
|
||||
self.debugApplication = None
|
||||
if self.scriptSiteDebug is not None:
|
||||
# Spec says that we should test for this, and if it fails revert to
|
||||
# PDM application.
|
||||
try:
|
||||
self.debugApplication = self.scriptSiteDebug.GetApplication()
|
||||
self.rootNode = self.scriptSiteDebug.GetRootApplicationNode()
|
||||
except pythoncom.com_error:
|
||||
self.debugApplication = None
|
||||
|
||||
if self.debugApplication is None:
|
||||
# Try to get/create the default one
|
||||
# NOTE - Dont catch exceptions here - let the parent do it,
|
||||
# so it knows debug support is available.
|
||||
pdm=pythoncom.CoCreateInstance(axdebug.CLSID_ProcessDebugManager,None,pythoncom.CLSCTX_ALL, axdebug.IID_IProcessDebugManager)
|
||||
self.debugApplication = pdm.GetDefaultApplication()
|
||||
self.rootNode = self.debugApplication.GetRootNode()
|
||||
|
||||
assert self.debugApplication is not None, "Need to have a DebugApplication object by now!"
|
||||
self.activeScriptDebug = None
|
||||
|
||||
if self.debugApplication is not None:
|
||||
self.adb.AttachApp(self.debugApplication, self.ccProvider)
|
||||
self.codeContainers = {}
|
||||
self.activeScriptDebug = _wrap(ActiveScriptDebug(self, self.codeContainers), axdebug.IID_IActiveScriptDebug)
|
||||
|
||||
def Close(self):
|
||||
# Called by the language engine when it receives a close request
|
||||
if self.activeScriptDebug is not None:
|
||||
_wrap_remove(self.activeScriptDebug)
|
||||
self.activeScriptDebug = None
|
||||
self.scriptEngine = None
|
||||
self.rootNode = None
|
||||
self.debugApplication = None
|
||||
self.scriptSiteDebug = None
|
||||
if self.ccProvider is not None:
|
||||
self.ccProvider.Close()
|
||||
self.ccProvider = None
|
||||
self.codeContainers = {}
|
||||
if self.adb:
|
||||
self.adb.CloseApp()
|
||||
self.adb = None
|
||||
# print "Close complete"
|
||||
|
||||
def IsAnyHost(self):
|
||||
"Do we have _any_ debugging interfaces installed?"
|
||||
return self.debugApplication is not None
|
||||
|
||||
def IsSimpleHost(self):
|
||||
return self.scriptSiteDebug is None
|
||||
|
||||
def HandleRuntimeError( self ):
|
||||
"""Called by the engine when a runtime error occurs. If we have a debugger,
|
||||
we let it know.
|
||||
|
||||
The result is a boolean which indicates if the error handler should call
|
||||
IActiveScriptSite::OnScriptError()
|
||||
"""
|
||||
# if self.IsAnyHost:
|
||||
# site = _wrap(self, axdebug.IID_IActiveScriptSite)
|
||||
# breakResume, errorResume, fCallOnError = self.debugApplication(activeScriptErrorDebug, site)
|
||||
# Do something with these!
|
||||
# else:
|
||||
trace("HandleRuntimeError")
|
||||
fCallOnError = 1
|
||||
return fCallOnError
|
||||
|
||||
def _query_interface_for_debugger_(self, iid):
|
||||
if iid in self._debugger_interfaces_:
|
||||
return self.activeScriptDebug
|
||||
trace("DebugManager QI - unknown IID", iid)
|
||||
return 0
|
||||
|
||||
|
||||
def OnEnterScript(self):
|
||||
trace("OnEnterScript")
|
||||
try:
|
||||
1/0
|
||||
except:
|
||||
# Bit of a hack - reach into engine.
|
||||
baseFrame = sys.exc_info()[2].tb_frame.f_back
|
||||
self.adb.SetupAXDebugging(baseFrame)
|
||||
|
||||
def OnLeaveScript(self):
|
||||
trace("OnLeaveScript")
|
||||
self.adb.ResetAXDebugging()
|
||||
|
||||
def AddScriptBlock(self, codeBlock):
|
||||
# If we dont have debugging support, dont bother.
|
||||
cc = DebugCodeBlockContainer(codeBlock, self.scriptSiteDebug)
|
||||
if self.IsSimpleHost():
|
||||
document = documents.DebugDocumentText(cc)
|
||||
document = _wrap(document, axdebug.IID_IDebugDocument)
|
||||
provider = documents.DebugDocumentProvider(document)
|
||||
provider = _wrap(provider, axdebug.IID_IDebugDocumentProvider)
|
||||
cc.debugDocument = document
|
||||
newNode = self.debugApplication.CreateApplicationNode()
|
||||
newNode.SetDocumentProvider(provider)
|
||||
newNode.Attach(self.rootNode)
|
||||
else:
|
||||
newNode = None # Managed by smart host.
|
||||
self.codeContainers[cc.sourceContext] = cc
|
||||
self.ccProvider.AddCodeContainer(cc, newNode)
|
||||
|
||||
class DebugCodeBlockContainer(SourceCodeContainer):
|
||||
def __init__(self, codeBlock, site):
|
||||
self.codeBlock = codeBlock
|
||||
SourceCodeContainer.__init__(self, codeBlock.codeText, codeBlock.GetFileName(), codeBlock.sourceContextCookie, codeBlock.startLineNumber, site)
|
||||
|
||||
def GetName(self, dnt):
|
||||
if dnt==axdebug.DOCUMENTNAMETYPE_APPNODE:
|
||||
return self.codeBlock.GetDisplayName()
|
||||
elif dnt==axdebug.DOCUMENTNAMETYPE_TITLE:
|
||||
return self.codeBlock.GetDisplayName()
|
||||
# elif dnt==axdebug.DOCUMENTNAMETYPE_FILE_TAIL:
|
||||
# elif dnt==axdebug.DOCUMENTNAMETYPE_URL:
|
||||
else:
|
||||
raise COMException(scode=winerror.S_FALSE)
|
||||
|
||||
|
||||
class EnumDebugCodeContexts(gateways.EnumDebugCodeContexts):
|
||||
def _wrap(self, ob):
|
||||
return ob
|
||||
|
||||
class ActiveScriptDebug:
|
||||
"""The class which implements the IActiveScriptDebug interface for the Active Script engine.
|
||||
|
||||
Only ever used by smart hosts.
|
||||
"""
|
||||
_public_methods_ = ["GetScriptTextAttributes", "GetScriptletTextAttributes", "EnumCodeContextsOfPosition"]
|
||||
_com_interfaces_ = [axdebug.IID_IActiveScriptDebug]
|
||||
def __init__(self, debugMgr, codeContainers):
|
||||
self.debugMgr = debugMgr
|
||||
self.scriptSiteDebug = debugMgr.scriptSiteDebug
|
||||
self.codeContainers = codeContainers
|
||||
|
||||
def _Close(self):
|
||||
self.debugMgr = None
|
||||
self.scriptSiteDebug = None
|
||||
self.codeContainers = {}
|
||||
|
||||
def _query_interface_(self, iid):
|
||||
trace("DebuggerQI with", iid)
|
||||
return _wrap(self.debugMgr.scriptEngine, iid)
|
||||
|
||||
def GetScriptTextAttributes(self, code, delim, flags):
|
||||
container = SourceCodeContainer(code, "<Temp Code Block>")
|
||||
return container.GetSyntaxColorAttributes()
|
||||
def GetScriptletTextAttributes(self, code, delim, flags):
|
||||
trace ("GetScriptletTextAttributes", code, delim, flags)
|
||||
container = SourceCodeContainer(code, "<Temp Code Block>")
|
||||
return container.GetSyntaxColorAttributes()
|
||||
|
||||
def EnumCodeContextsOfPosition(self, context, charOffset, numChars):
|
||||
trace("EnumCodeContextsOfPosition", context, charOffset, numChars)
|
||||
try:
|
||||
context = self.codeContainers[context].GetCodeContextAtPosition(charOffset)
|
||||
except KeyError:
|
||||
raise COMException(scode=winerror.E_UNEXPECTED)
|
||||
enum = EnumDebugCodeContexts([context])
|
||||
return _wrap(enum, axdebug.IID_IEnumDebugCodeContexts)
|
243
venv/Lib/site-packages/win32comext/axscript/client/error.py
Normal file
243
venv/Lib/site-packages/win32comext/axscript/client/error.py
Normal file
|
@ -0,0 +1,243 @@
|
|||
"""Exception and error handling.
|
||||
|
||||
This contains the core exceptions that the implementations should raise
|
||||
as well as the IActiveScriptError interface code.
|
||||
|
||||
"""
|
||||
|
||||
import sys, traceback
|
||||
from win32com.axscript import axscript
|
||||
import winerror
|
||||
import win32com.server.exception
|
||||
import win32com.server.util
|
||||
import pythoncom
|
||||
import re
|
||||
|
||||
debugging = 0
|
||||
|
||||
def FormatForAX(text):
|
||||
"""Format a string suitable for an AX Host
|
||||
"""
|
||||
# Replace all " with ', so it works OK in HTML (ie, ASP)
|
||||
return ExpandTabs(AddCR(text))
|
||||
|
||||
def ExpandTabs(text):
|
||||
return re.sub('\t',' ', text)
|
||||
|
||||
def AddCR(text):
|
||||
return re.sub('\n','\r\n',text)
|
||||
|
||||
class IActiveScriptError:
|
||||
"""An implementation of IActiveScriptError
|
||||
|
||||
The ActiveX Scripting host calls this client whenever we report
|
||||
an exception to it. This interface provides the exception details
|
||||
for the host to report to the user.
|
||||
"""
|
||||
_com_interfaces_ = [axscript.IID_IActiveScriptError]
|
||||
_public_methods_ = ["GetSourceLineText","GetSourcePosition","GetExceptionInfo"]
|
||||
def _query_interface_(self, iid):
|
||||
print("IActiveScriptError QI - unknown IID", iid)
|
||||
return 0
|
||||
def _SetExceptionInfo(self, exc):
|
||||
self.exception = exc
|
||||
def GetSourceLineText(self):
|
||||
return self.exception.linetext
|
||||
def GetSourcePosition(self):
|
||||
ctx = self.exception.sourceContext
|
||||
# Zero based in the debugger (but our columns are too!)
|
||||
return ctx, self.exception.lineno + self.exception.startLineNo-1, self.exception.colno
|
||||
def GetExceptionInfo(self):
|
||||
return self.exception
|
||||
|
||||
class AXScriptException(win32com.server.exception.COMException):
|
||||
"""A class used as a COM exception.
|
||||
|
||||
Note this has attributes which conform to the standard attributes
|
||||
for COM exceptions, plus a few others specific to our IActiveScriptError
|
||||
object.
|
||||
"""
|
||||
def __init__(self, site, codeBlock, exc_type, exc_value, exc_traceback):
|
||||
# set properties base class shares via base ctor...
|
||||
win32com.server.exception.COMException.__init__( self, \
|
||||
description = "Unknown Exception", \
|
||||
scode = winerror.DISP_E_EXCEPTION, \
|
||||
source = "Python ActiveX Scripting Engine",
|
||||
)
|
||||
|
||||
# And my other values...
|
||||
if codeBlock is None:
|
||||
self.sourceContext = 0
|
||||
self.startLineNo = 0
|
||||
else:
|
||||
self.sourceContext = codeBlock.sourceContextCookie
|
||||
self.startLineNo = codeBlock.startLineNumber
|
||||
self.linetext = ""
|
||||
|
||||
self.__BuildFromException(site, exc_type, exc_value, exc_traceback)
|
||||
|
||||
def __BuildFromException(self, site, type , value, tb):
|
||||
if debugging:
|
||||
import linecache
|
||||
linecache.clearcache()
|
||||
try:
|
||||
if issubclass(type, SyntaxError):
|
||||
self._BuildFromSyntaxError(site, value, tb)
|
||||
else:
|
||||
self._BuildFromOther(site, type, value, tb)
|
||||
except: # Error extracting traceback info!!!
|
||||
traceback.print_exc()
|
||||
# re-raise.
|
||||
raise
|
||||
|
||||
def _BuildFromSyntaxError(self, site, exc, tb):
|
||||
value = exc.args
|
||||
# All syntax errors should have a message as element 0
|
||||
try:
|
||||
msg = value[0]
|
||||
except:
|
||||
msg = "Unknown Error (%s)" % (value,)
|
||||
try:
|
||||
(filename, lineno, offset, line) = value[1]
|
||||
# Some of these may be None, which upsets us!
|
||||
if offset is None:
|
||||
offset = 0
|
||||
if line is None:
|
||||
line = ""
|
||||
except:
|
||||
msg = "Unknown"
|
||||
lineno = 0
|
||||
offset = 0
|
||||
line = "Unknown"
|
||||
self.description=FormatForAX(msg)
|
||||
self.lineno = lineno
|
||||
self.colno = offset - 1
|
||||
self.linetext = ExpandTabs(line.rstrip())
|
||||
|
||||
def _BuildFromOther(self, site, exc_type, value, tb):
|
||||
self.colno = -1
|
||||
self.lineno = 0
|
||||
if debugging: # Full traceback if debugging.
|
||||
list=traceback.format_exception(exc_type, value, tb)
|
||||
self.description = ExpandTabs(''.join(list))
|
||||
return
|
||||
# Run down the traceback list, looking for the first "<Script..>"
|
||||
# Hide traceback above this. In addition, keep going down
|
||||
# looking for a "_*_" attribute, and below hide these also.
|
||||
hide_names = ["r_import","r_reload","r_open"] # hide from these functions down in the traceback.
|
||||
depth = None
|
||||
tb_top = tb
|
||||
while tb_top:
|
||||
filename, lineno, name, line = self.ExtractTracebackInfo(tb_top, site)
|
||||
if filename[:7]=="<Script":
|
||||
break
|
||||
tb_top = tb_top.tb_next
|
||||
format_items = []
|
||||
if tb_top: # found one.
|
||||
depth = 0
|
||||
tb_look = tb_top
|
||||
# Look down for our bottom
|
||||
while tb_look:
|
||||
filename, lineno, name, line = self.ExtractTracebackInfo(tb_look, site)
|
||||
if name in hide_names:
|
||||
break
|
||||
# We can report a line-number, but not a filename. Therefore,
|
||||
# we return the last line-number we find in one of our script
|
||||
# blocks.
|
||||
if filename.startswith("<Script"):
|
||||
self.lineno = lineno
|
||||
self.linetext = line
|
||||
format_items.append((filename, lineno, name, line))
|
||||
depth = depth + 1
|
||||
tb_look = tb_look.tb_next
|
||||
else:
|
||||
depth = None
|
||||
tb_top = tb
|
||||
|
||||
bits = ['Traceback (most recent call last):\n']
|
||||
bits.extend(traceback.format_list(format_items))
|
||||
if exc_type==pythoncom.com_error:
|
||||
desc = "%s (0x%x)" % (value.strerror, value.hresult)
|
||||
if value.hresult==winerror.DISP_E_EXCEPTION and value.excepinfo and value.excepinfo[2]:
|
||||
desc = value.excepinfo[2]
|
||||
bits.append("COM Error: "+desc)
|
||||
else:
|
||||
bits.extend(traceback.format_exception_only(exc_type, value))
|
||||
|
||||
# XXX - this utf8 encoding seems bogus. From well before py3k,
|
||||
# we had the comment:
|
||||
# > all items in the list are utf8 courtesy of Python magically
|
||||
# > converting unicode to utf8 before compilation.
|
||||
# but that is likely just confusion from early unicode days;
|
||||
# Python isn't doing it, pywin32 probably was, so 'mbcs' would
|
||||
# be the default encoding. We should never hit this these days
|
||||
# anyway, but on py3k, we *never* will, and str objects there
|
||||
# don't have a decode method...
|
||||
if sys.version_info < (3,):
|
||||
for i in range(len(bits)):
|
||||
if type(bits[i]) is str:
|
||||
#assert type(bits[i]) is str, type(bits[i])
|
||||
bits[i] = bits[i].decode('utf8')
|
||||
|
||||
self.description = ExpandTabs(''.join(bits))
|
||||
# Clear tracebacks etc.
|
||||
tb = tb_top = tb_look = None
|
||||
|
||||
def ExtractTracebackInfo(self, tb, site):
|
||||
import linecache
|
||||
f = tb.tb_frame
|
||||
lineno = tb.tb_lineno
|
||||
co = f.f_code
|
||||
filename = co.co_filename
|
||||
name = co.co_name
|
||||
line = linecache.getline(filename, lineno)
|
||||
if not line:
|
||||
try:
|
||||
codeBlock = site.scriptCodeBlocks[filename]
|
||||
except KeyError:
|
||||
codeBlock = None
|
||||
if codeBlock:
|
||||
# Note: 'line' will now be unicode.
|
||||
line = codeBlock.GetLineNo(lineno)
|
||||
if line:
|
||||
line = line.strip()
|
||||
else:
|
||||
line = None
|
||||
return filename, lineno, name, line
|
||||
def __repr__(self):
|
||||
return "AXScriptException Object with description:" + self.description
|
||||
|
||||
def ProcessAXScriptException(scriptingSite, debugManager, exceptionInstance):
|
||||
"""General function to handle any exception in AX code
|
||||
|
||||
This function creates an instance of our IActiveScriptError interface, and
|
||||
gives it to the host, along with out exception class. The host will
|
||||
likely call back on the IActiveScriptError interface to get the source text
|
||||
and other information not normally in COM exceptions.
|
||||
"""
|
||||
# traceback.print_exc()
|
||||
instance = IActiveScriptError()
|
||||
instance._SetExceptionInfo(exceptionInstance)
|
||||
gateway = win32com.server.util.wrap(instance, axscript.IID_IActiveScriptError)
|
||||
if debugManager:
|
||||
fCallOnError = debugManager.HandleRuntimeError()
|
||||
if not fCallOnError:
|
||||
return None
|
||||
|
||||
try:
|
||||
result = scriptingSite.OnScriptError(gateway)
|
||||
except pythoncom.com_error as details:
|
||||
print("**OnScriptError failed:", details)
|
||||
print("Exception description:'%s'" % (repr(exceptionInstance.description)))
|
||||
print("Exception text:'%s'" % (repr(exceptionInstance.linetext)))
|
||||
result = winerror.S_FALSE
|
||||
|
||||
if result==winerror.S_OK:
|
||||
# If the above returns NOERROR, it is assumed the error has been
|
||||
# correctly registered and the value SCRIPT_E_REPORTED is returned.
|
||||
ret = win32com.server.exception.COMException(scode=axscript.SCRIPT_E_REPORTED)
|
||||
return ret
|
||||
else:
|
||||
# The error is taken to be unreported and is propagated up the call stack
|
||||
# via the IDispatch::Invoke's EXCEPINFO parameter (hr returned is DISP_E_EXCEPTION.
|
||||
return exceptionInstance
|
1019
venv/Lib/site-packages/win32comext/axscript/client/framework.py
Normal file
1019
venv/Lib/site-packages/win32comext/axscript/client/framework.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,70 @@
|
|||
# pydumper.py
|
||||
#
|
||||
# This is being worked on - it does not yet work at all, in ay way
|
||||
# shape or form :-)
|
||||
#
|
||||
# A new script engine, derived from the standard scripting engine,
|
||||
# which dumps information.
|
||||
|
||||
# This generally can be used to grab all sorts of useful details about
|
||||
# an engine - expose bugs in it or Python, dump the object model, etc.
|
||||
|
||||
# As it is derived from the standard engine, it fully supports Python
|
||||
# as a scripting language - meaning the dumps produced can be quite dynamic,
|
||||
# and based on the script code you execute.
|
||||
|
||||
from . import pyscript
|
||||
from win32com.axscript import axscript
|
||||
|
||||
from .pyscript import RaiseAssert, trace, Exception, SCRIPTTEXT_FORCEEXECUTION
|
||||
|
||||
PyDump_CLSID = '{ac527e60-c693-11d0-9c25-00aa00125a98}'
|
||||
|
||||
class AXScriptAttribute(pyscript.AXScriptAttribute):
|
||||
pass
|
||||
|
||||
class NamedScriptAttribute(pyscript.NamedScriptAttribute):
|
||||
pass
|
||||
|
||||
|
||||
class PyScript(pyscript.PyScript):
|
||||
pass
|
||||
|
||||
|
||||
def Register():
|
||||
import sys
|
||||
if '-d' in sys.argv:
|
||||
dispatcher = "DispatcherWin32trace"
|
||||
debug_desc = " ("+dispatcher+")"
|
||||
debug_option = "Yes"
|
||||
else:
|
||||
dispatcher = None
|
||||
debug_desc = ""
|
||||
debug_option = ""
|
||||
|
||||
categories = [axscript.CATID_ActiveScript,axscript.CATID_ActiveScriptParse]
|
||||
clsid = PyDump_CLSID
|
||||
lcid = 0x0409 # // english
|
||||
policy = None # "win32com.axscript.client.axspolicy.AXScriptPolicy"
|
||||
|
||||
print("Registering COM server%s..." % debug_desc)
|
||||
from win32com.server.register import RegisterServer
|
||||
|
||||
languageName = "PyDump"
|
||||
verProgId = "Python.Dumper.1"
|
||||
RegisterServer(clsid = clsid, pythonInstString = "win32com.axscript.client.pyscript.PyDumper",
|
||||
className = "Python Debugging/Dumping ActiveX Scripting Engine",
|
||||
progID = languageName, verProgID = verProgId,
|
||||
catids = categories,
|
||||
policy=policy, dispatcher = dispatcher)
|
||||
|
||||
CreateRegKey(languageName + "\\OLEScript")
|
||||
# Basic Registration for wsh.
|
||||
win32com.server.register._set_string(".pysDump", "pysDumpFile")
|
||||
win32com.server.register._set_string("pysDumpFile\\ScriptEngine", languageName)
|
||||
print("Dumping Server registered.")
|
||||
|
||||
if __name__=='__main__':
|
||||
Register()
|
||||
|
||||
|
372
venv/Lib/site-packages/win32comext/axscript/client/pyscript.py
Normal file
372
venv/Lib/site-packages/win32comext/axscript/client/pyscript.py
Normal file
|
@ -0,0 +1,372 @@
|
|||
"""Python ActiveX Scripting Implementation
|
||||
|
||||
This module implements the Python ActiveX Scripting client.
|
||||
|
||||
To register the implementation, simply "run" this Python program - ie
|
||||
either double-click on it, or run "python.exe pyscript.py" from the
|
||||
command line.
|
||||
"""
|
||||
|
||||
import winerror
|
||||
import win32com
|
||||
import win32api
|
||||
import pythoncom
|
||||
import sys
|
||||
import traceback
|
||||
import re
|
||||
import win32com.client.dynamic
|
||||
from win32com.axscript.client import framework, scriptdispatch
|
||||
from win32com.axscript import axscript
|
||||
import win32com.server.register
|
||||
|
||||
from win32com.axscript.client.framework import \
|
||||
RaiseAssert, trace, Exception, SCRIPTTEXT_FORCEEXECUTION, \
|
||||
SCRIPTTEXT_ISEXPRESSION, SCRIPTTEXT_ISPERSISTENT
|
||||
|
||||
PyScript_CLSID = "{DF630910-1C1D-11d0-AE36-8C0F5E000000}"
|
||||
|
||||
debugging_attr = 0
|
||||
|
||||
def debug_attr_print(*args):
|
||||
if debugging_attr:
|
||||
trace(*args)
|
||||
|
||||
def ExpandTabs(text):
|
||||
return re.sub('\t',' ', text)
|
||||
|
||||
def AddCR(text):
|
||||
return re.sub('\n','\r\n',text)
|
||||
|
||||
class AXScriptCodeBlock(framework.AXScriptCodeBlock):
|
||||
def GetDisplayName(self):
|
||||
return "PyScript - " + framework.AXScriptCodeBlock.GetDisplayName(self)
|
||||
|
||||
# There is only ever _one_ ax object - it exists in the global namespace
|
||||
# for all script items.
|
||||
# It performs a search from all global/visible objects
|
||||
# down.
|
||||
# This means that if 2 sub-objects of the same name are used
|
||||
# then only one is ever reachable using the ax shortcut.
|
||||
class AXScriptAttribute:
|
||||
"An attribute in a scripts namespace."
|
||||
def __init__(self, engine):
|
||||
self.__dict__['_scriptEngine_'] = engine
|
||||
def __getattr__(self, attr):
|
||||
if attr[1]=="_" and attr[:-1]=="_":
|
||||
raise AttributeError(attr)
|
||||
rc = self._FindAttribute_(attr)
|
||||
if rc is None:
|
||||
raise AttributeError(attr)
|
||||
return rc
|
||||
def _Close_(self):
|
||||
self.__dict__['_scriptEngine_'] = None
|
||||
|
||||
def _DoFindAttribute_(self, obj, attr):
|
||||
try:
|
||||
return obj.subItems[attr.lower()].attributeObject
|
||||
except KeyError:
|
||||
pass
|
||||
# Check out the sub-items
|
||||
for item in obj.subItems.values():
|
||||
try:
|
||||
return self._DoFindAttribute_(item, attr)
|
||||
except AttributeError:
|
||||
pass
|
||||
raise AttributeError(attr)
|
||||
|
||||
def _FindAttribute_(self, attr):
|
||||
for item in self._scriptEngine_.subItems.values():
|
||||
try:
|
||||
return self._DoFindAttribute_(item, attr)
|
||||
except AttributeError:
|
||||
pass
|
||||
# All else fails, see if it is a global
|
||||
# (mainly b/w compat)
|
||||
return getattr(self._scriptEngine_.globalNameSpaceModule, attr)
|
||||
# raise AttributeError(attr)
|
||||
|
||||
class NamedScriptAttribute:
|
||||
"An explicitely named object in an objects namespace"
|
||||
# Each named object holds a reference to one of these.
|
||||
# Whenever a sub-item appears in a namespace, it is really one of these
|
||||
# objects. Has a circular reference back to the item itself, which is
|
||||
# closed via _Close_()
|
||||
def __init__(self, scriptItem):
|
||||
self.__dict__['_scriptItem_'] = scriptItem
|
||||
def __repr__(self):
|
||||
return "<NamedItemAttribute" + repr(self._scriptItem_) + ">"
|
||||
def __getattr__(self, attr):
|
||||
# If a known subitem, return it.
|
||||
try:
|
||||
return self._scriptItem_.subItems[attr.lower()].attributeObject
|
||||
except KeyError:
|
||||
# Otherwise see if the dispatch can give it to us
|
||||
if self._scriptItem_.dispatchContainer:
|
||||
return getattr(self._scriptItem_.dispatchContainer,attr)
|
||||
raise AttributeError(attr)
|
||||
def __setattr__(self, attr, value):
|
||||
# XXX - todo - if a known item, then should call its default
|
||||
# dispatch method.
|
||||
attr=attr.lower()
|
||||
if self._scriptItem_.dispatchContainer:
|
||||
try:
|
||||
return setattr(self._scriptItem_.dispatchContainer,attr, value)
|
||||
except AttributeError:
|
||||
pass
|
||||
raise AttributeError(attr)
|
||||
def _Close_(self):
|
||||
self.__dict__['_scriptItem_'] = None
|
||||
|
||||
|
||||
class ScriptItem(framework.ScriptItem):
|
||||
def __init__(self, parentItem, name, dispatch, flags):
|
||||
framework.ScriptItem.__init__(self, parentItem, name, dispatch, flags)
|
||||
self.scriptlets = {}
|
||||
self.attributeObject = None
|
||||
def Reset(self):
|
||||
framework.ScriptItem.Reset(self)
|
||||
if self.attributeObject:
|
||||
self.attributeObject._Close_()
|
||||
self.attributeObject = None
|
||||
def Close(self):
|
||||
framework.ScriptItem.Close(self) # calls reset.
|
||||
self.dispatchContainer = None
|
||||
self.scriptlets = {}
|
||||
|
||||
def Register(self):
|
||||
framework.ScriptItem.Register(self)
|
||||
self.attributeObject = NamedScriptAttribute(self)
|
||||
if self.dispatch:
|
||||
# Need to avoid the new Python "lazy" dispatch behaviour.
|
||||
try:
|
||||
engine = self.GetEngine()
|
||||
olerepr = clsid = None
|
||||
typeinfo = self.dispatch.GetTypeInfo()
|
||||
clsid = typeinfo.GetTypeAttr()[0]
|
||||
try:
|
||||
olerepr = engine.mapKnownCOMTypes[clsid]
|
||||
except KeyError:
|
||||
pass
|
||||
except pythoncom.com_error:
|
||||
typeinfo = None
|
||||
if olerepr is None:
|
||||
olerepr = win32com.client.dynamic.MakeOleRepr(self.dispatch, typeinfo, None)
|
||||
if clsid is not None:
|
||||
engine.mapKnownCOMTypes[clsid] = olerepr
|
||||
self.dispatchContainer = win32com.client.dynamic.CDispatch(self.dispatch, olerepr, self.name)
|
||||
# self.dispatchContainer = win32com.client.dynamic.Dispatch(self.dispatch, userName = self.name)
|
||||
# self.dispatchContainer = win32com.client.dynamic.DumbDispatch(self.dispatch, userName = self.name)
|
||||
|
||||
# def Connect(self):
|
||||
# framework.ScriptItem.Connect(self)
|
||||
# def Disconnect(self):
|
||||
# framework.ScriptItem.Disconnect(self)
|
||||
|
||||
class PyScript(framework.COMScript):
|
||||
# Setup the auto-registration stuff...
|
||||
_reg_verprogid_ = "Python.AXScript.2"
|
||||
_reg_progid_ = "Python"
|
||||
# _reg_policy_spec_ = default
|
||||
_reg_catids_ = [axscript.CATID_ActiveScript,axscript.CATID_ActiveScriptParse]
|
||||
_reg_desc_ = "Python ActiveX Scripting Engine"
|
||||
_reg_clsid_ = PyScript_CLSID
|
||||
_reg_class_spec_ = "win32com.axscript.client.pyscript.PyScript"
|
||||
_reg_remove_keys_ = [(".pys",), ("pysFile",)]
|
||||
_reg_threading_ = "both"
|
||||
|
||||
def __init__(self):
|
||||
framework.COMScript.__init__(self)
|
||||
self.globalNameSpaceModule = None
|
||||
self.codeBlocks = []
|
||||
self.scriptDispatch = None
|
||||
|
||||
def InitNew(self):
|
||||
framework.COMScript.InitNew(self)
|
||||
import imp
|
||||
self.scriptDispatch = None
|
||||
self.globalNameSpaceModule = imp.new_module("__ax_main__")
|
||||
self.globalNameSpaceModule.__dict__['ax'] = AXScriptAttribute(self)
|
||||
|
||||
self.codeBlocks = []
|
||||
self.persistedCodeBlocks = []
|
||||
self.mapKnownCOMTypes = {} # Map of known CLSID to typereprs
|
||||
self.codeBlockCounter = 0
|
||||
|
||||
def Stop(self):
|
||||
# Flag every pending script as already done
|
||||
for b in self.codeBlocks:
|
||||
b.beenExecuted = 1
|
||||
return framework.COMScript.Stop(self)
|
||||
|
||||
def Reset(self):
|
||||
# Reset all code-blocks that are persistent, and discard the rest
|
||||
oldCodeBlocks = self.codeBlocks[:]
|
||||
self.codeBlocks = []
|
||||
for b in oldCodeBlocks:
|
||||
if b.flags & SCRIPTTEXT_ISPERSISTENT:
|
||||
b.beenExecuted = 0
|
||||
self.codeBlocks.append(b)
|
||||
return framework.COMScript.Reset(self)
|
||||
|
||||
def _GetNextCodeBlockNumber(self):
|
||||
self.codeBlockCounter = self.codeBlockCounter + 1
|
||||
return self.codeBlockCounter
|
||||
|
||||
def RegisterNamedItem(self, item):
|
||||
wasReg = item.isRegistered
|
||||
framework.COMScript.RegisterNamedItem(self, item)
|
||||
if not wasReg:
|
||||
# Insert into our namespace.
|
||||
# Add every item by name
|
||||
if item.IsVisible():
|
||||
self.globalNameSpaceModule.__dict__[item.name] = item.attributeObject
|
||||
if item.IsGlobal():
|
||||
# Global items means sub-items are also added...
|
||||
for subitem in item.subItems.values():
|
||||
self.globalNameSpaceModule.__dict__[subitem.name] = subitem.attributeObject
|
||||
# Also add all methods
|
||||
for name, entry in item.dispatchContainer._olerepr_.mapFuncs.items():
|
||||
if not entry.hidden:
|
||||
self.globalNameSpaceModule.__dict__[name] = getattr(item.dispatchContainer,name)
|
||||
|
||||
def DoExecutePendingScripts(self):
|
||||
try:
|
||||
globs = self.globalNameSpaceModule.__dict__
|
||||
for codeBlock in self.codeBlocks:
|
||||
if not codeBlock.beenExecuted:
|
||||
if self.CompileInScriptedSection(codeBlock, "exec"):
|
||||
self.ExecInScriptedSection(codeBlock, globs)
|
||||
finally:
|
||||
pass
|
||||
|
||||
def DoRun(self):
|
||||
pass
|
||||
|
||||
def Close(self):
|
||||
self.ResetNamespace()
|
||||
self.globalNameSpaceModule = None
|
||||
self.codeBlocks = []
|
||||
self.scriptDispatch = None
|
||||
framework.COMScript.Close(self)
|
||||
|
||||
def GetScriptDispatch(self, name):
|
||||
# trace("GetScriptDispatch with", name)
|
||||
# if name is not None: return None
|
||||
if self.scriptDispatch is None:
|
||||
self.scriptDispatch = scriptdispatch.MakeScriptDispatch(self, self.globalNameSpaceModule)
|
||||
return self.scriptDispatch
|
||||
|
||||
def MakeEventMethodName(self, subItemName, eventName):
|
||||
return subItemName[0].upper()+subItemName[1:] + "_" + eventName[0].upper()+eventName[1:]
|
||||
|
||||
def DoAddScriptlet(self, defaultName, code, itemName, subItemName, eventName, delimiter,sourceContextCookie, startLineNumber):
|
||||
# Just store the code away - compile when called. (JIT :-)
|
||||
item = self.GetNamedItem(itemName)
|
||||
if itemName==subItemName: # Explicit handlers - eg <SCRIPT LANGUAGE="Python" for="TestForm" Event="onSubmit">
|
||||
subItem = item
|
||||
else:
|
||||
subItem = item.GetCreateSubItem(item, subItemName, None, None)
|
||||
funcName = self.MakeEventMethodName(subItemName, eventName)
|
||||
|
||||
codeBlock = AXScriptCodeBlock("Script Event %s" %funcName, code, sourceContextCookie, startLineNumber, 0)
|
||||
self._AddScriptCodeBlock(codeBlock)
|
||||
subItem.scriptlets[funcName] = codeBlock
|
||||
|
||||
def DoProcessScriptItemEvent(self, item, event, lcid, wFlags, args):
|
||||
# trace("ScriptItemEvent", self, item, event, event.name, lcid, wFlags, args)
|
||||
funcName = self.MakeEventMethodName(item.name, event.name)
|
||||
codeBlock = function = None
|
||||
try:
|
||||
function = item.scriptlets[funcName]
|
||||
if type(function)==type(self): # ie, is a CodeBlock instance
|
||||
codeBlock = function
|
||||
function = None
|
||||
except KeyError:
|
||||
pass
|
||||
if codeBlock is not None:
|
||||
realCode = "def %s():\n" % funcName
|
||||
for line in framework.RemoveCR(codeBlock.codeText).split("\n"):
|
||||
realCode = realCode + '\t' + line + '\n'
|
||||
realCode = realCode + '\n'
|
||||
if not self.CompileInScriptedSection(codeBlock, "exec", realCode):
|
||||
return
|
||||
dict = {}
|
||||
self.ExecInScriptedSection(codeBlock, self.globalNameSpaceModule.__dict__, dict)
|
||||
function = dict[funcName]
|
||||
# cache back in scriptlets as a function.
|
||||
item.scriptlets[funcName] = function
|
||||
if function is None:
|
||||
# still no function - see if in the global namespace.
|
||||
try:
|
||||
function = self.globalNameSpaceModule.__dict__[funcName]
|
||||
except KeyError:
|
||||
# Not there _exactly_ - do case ins search.
|
||||
funcNameLook = funcName.lower()
|
||||
for attr in self.globalNameSpaceModule.__dict__.keys():
|
||||
if funcNameLook==attr.lower():
|
||||
function = self.globalNameSpaceModule.__dict__[attr]
|
||||
# cache back in scriptlets, to avoid this overhead next time
|
||||
item.scriptlets[funcName] = function
|
||||
|
||||
if function is None:
|
||||
raise Exception(scode=winerror.DISP_E_MEMBERNOTFOUND)
|
||||
return self.ApplyInScriptedSection(codeBlock, function, args)
|
||||
|
||||
def DoParseScriptText(self, code, sourceContextCookie, startLineNumber, bWantResult, flags):
|
||||
code = framework.RemoveCR(code) + "\n"
|
||||
if flags & SCRIPTTEXT_ISEXPRESSION:
|
||||
name = "Script Expression"
|
||||
exec_type = "eval"
|
||||
else:
|
||||
name = "Script Block"
|
||||
exec_type = "exec"
|
||||
num = self._GetNextCodeBlockNumber()
|
||||
if num==1: num=""
|
||||
name = "%s %s" % (name, num)
|
||||
codeBlock = AXScriptCodeBlock(name, code, sourceContextCookie, startLineNumber, flags)
|
||||
self._AddScriptCodeBlock(codeBlock)
|
||||
globs = self.globalNameSpaceModule.__dict__
|
||||
if bWantResult: # always immediate.
|
||||
if self.CompileInScriptedSection(codeBlock, exec_type):
|
||||
if flags & SCRIPTTEXT_ISEXPRESSION:
|
||||
return self.EvalInScriptedSection(codeBlock, globs)
|
||||
else:
|
||||
return self.ExecInScriptedSection(codeBlock, globs)
|
||||
|
||||
# else compile failed, but user chose to keep running...
|
||||
else:
|
||||
if flags & SCRIPTTEXT_FORCEEXECUTION:
|
||||
if self.CompileInScriptedSection(codeBlock, exec_type):
|
||||
self.ExecInScriptedSection(codeBlock, globs)
|
||||
else:
|
||||
self.codeBlocks.append(codeBlock)
|
||||
|
||||
def GetNamedItemClass(self):
|
||||
return ScriptItem
|
||||
|
||||
def ResetNamespace(self):
|
||||
if self.globalNameSpaceModule is not None:
|
||||
try:
|
||||
self.globalNameSpaceModule.ax._Reset_()
|
||||
except AttributeError:
|
||||
pass # ???
|
||||
globalNameSpaceModule = None
|
||||
|
||||
def DllRegisterServer():
|
||||
klass=PyScript
|
||||
win32com.server.register._set_subkeys(klass._reg_progid_ + "\\OLEScript", {}) # Just a CreateKey
|
||||
# Basic Registration for wsh.
|
||||
win32com.server.register._set_string(".pys", "pysFile")
|
||||
win32com.server.register._set_string("pysFile\\ScriptEngine", klass._reg_progid_)
|
||||
guid_wsh_shellex = "{60254CA5-953B-11CF-8C96-00AA00B8708C}"
|
||||
win32com.server.register._set_string("pysFile\\ShellEx\\DropHandler", guid_wsh_shellex)
|
||||
win32com.server.register._set_string("pysFile\\ShellEx\\PropertySheetHandlers\\WSHProps", guid_wsh_shellex)
|
||||
|
||||
def Register(klass=PyScript):
|
||||
import sys
|
||||
ret = win32com.server.register.UseCommandLine(klass,
|
||||
finalize_register=DllRegisterServer)
|
||||
return ret
|
||||
|
||||
if __name__=='__main__':
|
||||
Register()
|
|
@ -0,0 +1,43 @@
|
|||
# A version of the ActiveScripting engine that enables rexec support
|
||||
# This version supports hosting by IE - however, due to Python's
|
||||
# rexec module being neither completely trusted nor private, it is
|
||||
# *not* enabled by default.
|
||||
# As of Python 2.2, rexec is simply not available - thus, if you use this,
|
||||
# a HTML page can do almost *anything* at all on your machine.
|
||||
|
||||
# You almost certainly do NOT want to use thus!
|
||||
|
||||
import pythoncom
|
||||
from win32com.axscript import axscript
|
||||
import winerror
|
||||
from . import pyscript
|
||||
|
||||
INTERFACE_USES_DISPEX = 0x00000004 # Object knows to use IDispatchEx
|
||||
INTERFACE_USES_SECURITY_MANAGER = 0x00000008 # Object knows to use IInternetHostSecurityManager
|
||||
|
||||
class PyScriptRExec(pyscript.PyScript):
|
||||
# Setup the auto-registration stuff...
|
||||
_reg_verprogid_ = "Python.AXScript-rexec.2"
|
||||
_reg_progid_ = "Python" # Same ProgID as the standard engine.
|
||||
# _reg_policy_spec_ = default
|
||||
_reg_catids_ = [axscript.CATID_ActiveScript,axscript.CATID_ActiveScriptParse]
|
||||
_reg_desc_ = "Python ActiveX Scripting Engine (with rexec support)"
|
||||
_reg_clsid_ = "{69c2454b-efa2-455b-988c-c3651c4a2f69}"
|
||||
_reg_class_spec_ = "win32com.axscript.client.pyscript_rexec.PyScriptRExec"
|
||||
_reg_remove_keys_ = [(".pys",), ("pysFile",)]
|
||||
_reg_threading_ = "Apartment"
|
||||
|
||||
def _GetSupportedInterfaceSafetyOptions(self):
|
||||
# print "**** calling", pyscript.PyScript._GetSupportedInterfaceSafetyOptions, "**->", pyscript.PyScript._GetSupportedInterfaceSafetyOptions(self)
|
||||
return INTERFACE_USES_DISPEX | \
|
||||
INTERFACE_USES_SECURITY_MANAGER | \
|
||||
axscript.INTERFACESAFE_FOR_UNTRUSTED_DATA | \
|
||||
axscript.INTERFACESAFE_FOR_UNTRUSTED_CALLER
|
||||
|
||||
if __name__=='__main__':
|
||||
print("WARNING: By registering this engine, you are giving remote HTML code")
|
||||
print("the ability to execute *any* code on your system.")
|
||||
print()
|
||||
print("You almost certainly do NOT want to do this.")
|
||||
print("You have been warned, and are doing this at your own (significant) risk")
|
||||
pyscript.Register(PyScriptRExec)
|
|
@ -0,0 +1,105 @@
|
|||
"""dynamic dispatch objects for AX Script.
|
||||
|
||||
This is an IDispatch object that a scripting host may use to
|
||||
query and invoke methods on the main script. Not may hosts use
|
||||
this yet, so it is not well tested!
|
||||
"""
|
||||
|
||||
import winerror
|
||||
import types
|
||||
from win32com.server.exception import COMException
|
||||
import win32com.server.policy
|
||||
import win32com.server.util
|
||||
from win32com.client import Dispatch
|
||||
import pythoncom
|
||||
from win32com.axscript import axscript
|
||||
|
||||
debugging = 0
|
||||
|
||||
PyIDispatchType = pythoncom.TypeIIDs[pythoncom.IID_IDispatch]
|
||||
|
||||
def _is_callable(obj):
|
||||
return type(obj) in [types.FunctionType, types.MethodType]
|
||||
# ignore hasattr(obj, "__call__") as this means all COM objects!
|
||||
|
||||
class ScriptDispatch:
|
||||
_public_methods_ = []
|
||||
def __init__(self, engine, scriptNamespace):
|
||||
self.engine = engine
|
||||
self.scriptNamespace = scriptNamespace
|
||||
|
||||
def _dynamic_(self, name, lcid, wFlags, args):
|
||||
# Ensure any newly added items are available.
|
||||
self.engine.RegisterNewNamedItems()
|
||||
self.engine.ProcessNewNamedItemsConnections()
|
||||
if wFlags & pythoncom.INVOKE_FUNC:
|
||||
# attempt to call a function
|
||||
try:
|
||||
func = getattr(self.scriptNamespace, name)
|
||||
if not _is_callable(func):
|
||||
raise AttributeError(name) # Not a function.
|
||||
realArgs = []
|
||||
for arg in args:
|
||||
if type(arg)==PyIDispatchType:
|
||||
realArgs.append(Dispatch(arg))
|
||||
else:
|
||||
realArgs.append(arg)
|
||||
try:
|
||||
# xxx - todo - work out what code block to pass???
|
||||
return self.engine.ApplyInScriptedSection(None, func, tuple(realArgs))
|
||||
except COMException as xxx_todo_changeme:
|
||||
(hr, msg, exc, arg) = xxx_todo_changeme.args
|
||||
raise
|
||||
|
||||
except AttributeError:
|
||||
if not wFlags & pythoncom.DISPATCH_PROPERTYGET:
|
||||
raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
|
||||
if wFlags & pythoncom.DISPATCH_PROPERTYGET:
|
||||
# attempt to get a property
|
||||
try:
|
||||
ret = getattr(self.scriptNamespace, name)
|
||||
if _is_callable(ret):
|
||||
raise AttributeError(name) # Not a property.
|
||||
except AttributeError:
|
||||
raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
|
||||
except COMException as instance:
|
||||
raise
|
||||
except:
|
||||
ret = self.engine.HandleException()
|
||||
return ret
|
||||
|
||||
raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
|
||||
|
||||
class StrictDynamicPolicy(win32com.server.policy.DynamicPolicy):
|
||||
def _wrap_(self, object):
|
||||
win32com.server.policy.DynamicPolicy._wrap_(self, object)
|
||||
if hasattr(self._obj_, 'scriptNamespace'):
|
||||
for name in dir(self._obj_.scriptNamespace):
|
||||
self._dyn_dispid_to_name_[self._getdispid_(name,0)] = name
|
||||
|
||||
def _getmembername_(self, dispid):
|
||||
try:
|
||||
return str(self._dyn_dispid_to_name_[dispid])
|
||||
except KeyError:
|
||||
raise COMException(scode=winerror.DISP_E_UNKNOWNNAME, desc="Name not found")
|
||||
|
||||
def _getdispid_(self, name, fdex):
|
||||
try:
|
||||
func = getattr(self._obj_.scriptNamespace, str(name))
|
||||
except AttributeError:
|
||||
raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
|
||||
# if not _is_callable(func):
|
||||
return win32com.server.policy.DynamicPolicy._getdispid_(self, name, fdex)
|
||||
|
||||
def _wrap_debug(obj):
|
||||
return win32com.server.util.wrap(obj, usePolicy=StrictDynamicPolicy, useDispatcher=win32com.server.policy.DispatcherWin32trace)
|
||||
def _wrap_nodebug(obj):
|
||||
return win32com.server.util.wrap(obj, usePolicy=StrictDynamicPolicy)
|
||||
|
||||
if debugging:
|
||||
_wrap = _wrap_debug
|
||||
else:
|
||||
_wrap = _wrap_nodebug
|
||||
|
||||
def MakeScriptDispatch(engine, namespace):
|
||||
return _wrap(ScriptDispatch(engine, namespace))
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
126
venv/Lib/site-packages/win32comext/axscript/server/axsite.py
Normal file
126
venv/Lib/site-packages/win32comext/axscript/server/axsite.py
Normal file
|
@ -0,0 +1,126 @@
|
|||
import win32com.axscript.axscript
|
||||
import winerror
|
||||
from win32com.axscript import axscript
|
||||
from win32com.server import exception, util
|
||||
import pythoncom
|
||||
|
||||
class AXEngine:
|
||||
def __init__(self, site, engine):
|
||||
self.eScript = self.eParse = self.eSafety = None
|
||||
if type(engine) == type(''):
|
||||
engine = pythoncom.CoCreateInstance(engine,
|
||||
None,
|
||||
pythoncom.CLSCTX_SERVER,
|
||||
pythoncom.IID_IUnknown)
|
||||
|
||||
self.eScript = engine.QueryInterface(axscript.IID_IActiveScript)
|
||||
self.eParse = engine.QueryInterface(axscript.IID_IActiveScriptParse)
|
||||
self.eSafety = engine.QueryInterface(axscript.IID_IObjectSafety)
|
||||
|
||||
self.eScript.SetScriptSite(site)
|
||||
self.eParse.InitNew()
|
||||
def __del__(self):
|
||||
self.Close()
|
||||
def GetScriptDispatch(self, name = None):
|
||||
return self.eScript.GetScriptDispatch(name)
|
||||
def AddNamedItem(self, item, flags):
|
||||
return self.eScript.AddNamedItem(item, flags)
|
||||
# Some helpers.
|
||||
def AddCode(self, code, flags=0):
|
||||
self.eParse.ParseScriptText(code, None, None, None, 0, 0, flags)
|
||||
def EvalCode(self, code):
|
||||
return self.eParse.ParseScriptText(code, None, None, None, 0, 0, axscript.SCRIPTTEXT_ISEXPRESSION)
|
||||
def Start(self):
|
||||
# Should maybe check state?
|
||||
# Do I need to transition through?
|
||||
self.eScript.SetScriptState(axscript.SCRIPTSTATE_STARTED)
|
||||
# self.eScript.SetScriptState(axscript.SCRIPTSTATE_CONNECTED)
|
||||
|
||||
def Close(self):
|
||||
if self.eScript:
|
||||
self.eScript.Close()
|
||||
self.eScript = self.eParse = self.eSafety = None
|
||||
def SetScriptState(self, state):
|
||||
self.eScript.SetScriptState(state)
|
||||
|
||||
IActiveScriptSite_methods = [
|
||||
'GetLCID',
|
||||
'GetItemInfo',
|
||||
'GetDocVersionString',
|
||||
'OnScriptTerminate',
|
||||
'OnStateChange',
|
||||
'OnScriptError',
|
||||
'OnEnterScript',
|
||||
'OnLeaveScript',
|
||||
]
|
||||
|
||||
class AXSite:
|
||||
"""An Active Scripting site. A Site can have exactly one engine.
|
||||
"""
|
||||
_public_methods_ = IActiveScriptSite_methods
|
||||
_com_interfaces_ = [ axscript.IID_IActiveScriptSite ]
|
||||
|
||||
def __init__(self, objModel={}, engine = None, lcid=0):
|
||||
self.lcid = lcid
|
||||
self.objModel = { }
|
||||
for name, object in objModel.items():
|
||||
# Gregs code did string.lower this - I think that is callers job if he wants!
|
||||
self.objModel[name] = object
|
||||
|
||||
self.engine = None
|
||||
if engine:
|
||||
self._AddEngine(engine)
|
||||
|
||||
def AddEngine(self, engine):
|
||||
"""Adds a new engine to the site.
|
||||
engine can be a string, or a fully wrapped engine object.
|
||||
"""
|
||||
if type(engine)==type(''):
|
||||
newEngine = AXEngine(util.wrap(self), engine)
|
||||
else:
|
||||
newEngine = engine
|
||||
self.engine = newEngine
|
||||
flags = axscript.SCRIPTITEM_ISVISIBLE | axscript.SCRIPTITEM_NOCODE | axscript.SCRIPTITEM_GLOBALMEMBERS | axscript.SCRIPTITEM_ISPERSISTENT
|
||||
for name in self.objModel.keys():
|
||||
newEngine.AddNamedItem(name, flags)
|
||||
newEngine.SetScriptState(axscript.SCRIPTSTATE_INITIALIZED)
|
||||
return newEngine
|
||||
|
||||
# B/W compat
|
||||
_AddEngine = AddEngine
|
||||
|
||||
def _Close(self):
|
||||
self.engine.Close()
|
||||
self.objModel = {}
|
||||
|
||||
def GetLCID(self):
|
||||
return self.lcid
|
||||
|
||||
def GetItemInfo(self, name, returnMask):
|
||||
if name not in self.objModel:
|
||||
raise exception.Exception(scode=winerror.TYPE_E_ELEMENTNOTFOUND, desc='item not found')
|
||||
|
||||
### for now, we don't have any type information
|
||||
|
||||
if returnMask & axscript.SCRIPTINFO_IUNKNOWN:
|
||||
return (self.objModel[name], None)
|
||||
|
||||
return (None, None)
|
||||
|
||||
def GetDocVersionString(self):
|
||||
return 'Python AXHost version 1.0'
|
||||
|
||||
def OnScriptTerminate(self, result, excepInfo):
|
||||
pass
|
||||
|
||||
def OnStateChange(self, state):
|
||||
pass
|
||||
|
||||
def OnScriptError(self, errorInterface):
|
||||
return winerror.S_FALSE
|
||||
|
||||
def OnEnterScript(self):
|
||||
pass
|
||||
|
||||
def OnLeaveScript(self):
|
||||
pass
|
15
venv/Lib/site-packages/win32comext/axscript/server/error.py
Normal file
15
venv/Lib/site-packages/win32comext/axscript/server/error.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
"""Exception instance for AXScript servers.
|
||||
|
||||
This module implements an exception instance that is raised by the core
|
||||
server scripting support.
|
||||
|
||||
When a script error occurs, it wraps the COM object that describes the
|
||||
exception in a Python instance, which can then be raised and caught.
|
||||
"""
|
||||
|
||||
class Exception:
|
||||
def __init__(self, activeScriptError):
|
||||
self.activeScriptError = activeScriptError
|
||||
def __getattr__(self, attr):
|
||||
return getattr(self.activeScriptError, attr)
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue