Todo: 集成多平台 解决因SaiNiu线程抢占资源问题 本地提交测试环境打包 和 正式打包脚本与正式环境打包bat 提交Python32环境包 改进多日志文件生成情况修改打包日志细节
This commit is contained in:
113
Utils/PythonNew32/Lib/site-packages/win32comext/adsi/__init__.py
Normal file
113
Utils/PythonNew32/Lib/site-packages/win32comext/adsi/__init__.py
Normal file
@@ -0,0 +1,113 @@
|
||||
import win32com
|
||||
import win32com.client
|
||||
|
||||
if isinstance(__path__, str):
|
||||
# For freeze to work!
|
||||
import sys
|
||||
|
||||
try:
|
||||
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 * # nopycln: import # Re-export everything from win32comext/adsi/adsi.pyd
|
||||
|
||||
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(adsi.IID_IADsContainer)
|
||||
self._oleobj_ = adsi.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 not isinstance(index, int):
|
||||
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 = adsi.ADsEnumerateNext(self._oleobj_, 1)
|
||||
if len(result):
|
||||
return _get_good_ret(result[0])
|
||||
# Failed - reset for next time around.
|
||||
self.index = -1
|
||||
self._oleobj_ = adsi.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):
|
||||
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:
|
||||
# doesn't 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 adsi.pyd methods to do the right thing.
|
||||
def ADsGetObject(path, iid=pythoncom.IID_IDispatch):
|
||||
ret = adsi.ADsGetObject(path, iid)
|
||||
return _get_good_ret(ret)
|
||||
|
||||
|
||||
def ADsOpenObject(path, username, password, reserved=0, iid=pythoncom.IID_IDispatch):
|
||||
ret = adsi.ADsOpenObject(path, username, password, reserved, iid)
|
||||
return _get_good_ret(ret)
|
||||
BIN
Utils/PythonNew32/Lib/site-packages/win32comext/adsi/adsi.pyd
Normal file
BIN
Utils/PythonNew32/Lib/site-packages/win32comext/adsi/adsi.pyd
Normal file
Binary file not shown.
340
Utils/PythonNew32/Lib/site-packages/win32comext/adsi/adsicon.py
Normal file
340
Utils/PythonNew32/Lib/site-packages/win32comext/adsi/adsicon.py
Normal file
@@ -0,0 +1,340 @@
|
||||
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"
|
||||
@@ -0,0 +1,68 @@
|
||||
# A demo for the IDsObjectPicker interface.
|
||||
import pythoncom
|
||||
import win32clipboard
|
||||
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()
|
||||
@@ -0,0 +1,565 @@
|
||||
"""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.
|
||||
"""
|
||||
|
||||
import optparse
|
||||
import textwrap
|
||||
import traceback
|
||||
|
||||
import ntsecuritycon as dscon
|
||||
import win32api
|
||||
import win32con
|
||||
import win32security
|
||||
import winerror
|
||||
from win32com.adsi import adsi
|
||||
from win32com.adsi.adsicon import *
|
||||
from win32com.client import Dispatch
|
||||
|
||||
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 %r", 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 not isinstance(spns, 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(f" {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")
|
||||
@@ -0,0 +1,151 @@
|
||||
import pythoncom
|
||||
import pywintypes
|
||||
from win32com.adsi import adsi, adsicon
|
||||
from win32com.adsi.adsicon import *
|
||||
|
||||
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(f" {prop_name}={value!r}")
|
||||
else:
|
||||
print(f" {prop_name} is None")
|
||||
|
||||
|
||||
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()
|
||||
@@ -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.
@@ -0,0 +1,229 @@
|
||||
import os
|
||||
|
||||
import pythoncom
|
||||
import win32api
|
||||
import win32com.server.policy
|
||||
import win32con
|
||||
import win32security
|
||||
from ntsecuritycon import (
|
||||
FILE_ALL_ACCESS,
|
||||
FILE_APPEND_DATA,
|
||||
FILE_GENERIC_EXECUTE,
|
||||
FILE_GENERIC_READ,
|
||||
FILE_GENERIC_WRITE,
|
||||
FILE_WRITE_DATA,
|
||||
READ_CONTROL,
|
||||
SI_ACCESS_GENERAL,
|
||||
SI_ACCESS_SPECIFIC,
|
||||
SI_ADVANCED,
|
||||
SI_CONTAINER,
|
||||
SI_EDIT_ALL,
|
||||
SI_PAGE_TITLE,
|
||||
SI_RESET,
|
||||
WRITE_DAC,
|
||||
WRITE_OWNER,
|
||||
)
|
||||
from pythoncom import IID_NULL
|
||||
from win32com.authorization import authorization
|
||||
from win32security import CONTAINER_INHERIT_ACE, OBJECT_INHERIT_ACE
|
||||
|
||||
|
||||
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,219 @@
|
||||
r"""
|
||||
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 pythoncom
|
||||
import win32com.server.policy
|
||||
import win32con
|
||||
import win32security
|
||||
import 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 (
|
||||
READ_CONTROL,
|
||||
SI_ACCESS_GENERAL,
|
||||
SI_ACCESS_SPECIFIC,
|
||||
SI_ADVANCED,
|
||||
SI_EDIT_ALL,
|
||||
SI_PAGE_TITLE,
|
||||
SI_RESET,
|
||||
WRITE_DAC,
|
||||
WRITE_OWNER,
|
||||
)
|
||||
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()
|
||||
@@ -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.
@@ -0,0 +1,4 @@
|
||||
# See if we have a special directory for the binaries (for developers)
|
||||
import win32com
|
||||
|
||||
win32com.__PackageSupportBuildPath__(__path__)
|
||||
467
Utils/PythonNew32/Lib/site-packages/win32comext/axdebug/adb.py
Normal file
467
Utils/PythonNew32/Lib/site-packages/win32comext/axdebug/adb.py
Normal file
@@ -0,0 +1,467 @@
|
||||
"""The glue between the Python debugger interface and the Active Debugger interface"""
|
||||
|
||||
import _thread
|
||||
import bdb
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
import pythoncom
|
||||
import win32api
|
||||
import win32com.client.connect
|
||||
from win32com.axdebug.util import _wrap, trace
|
||||
|
||||
from . import axdebug, gateways, stackframe
|
||||
|
||||
|
||||
def fnull(*args):
|
||||
pass
|
||||
|
||||
|
||||
debugging = "DEBUG_AXDEBUG" in os.environ
|
||||
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 f"Frame at {id(frame)}, file {frame.f_code.co_filename}, line: {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 don't 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(
|
||||
f"*** Could not RemoveStackFrameSniffer {self.stackSnifferCookie}"
|
||||
)
|
||||
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(f"StackFrameSniffer added ({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(
|
||||
f"_BreakFlagsChanged to {self.breakFlags} "
|
||||
+ f"with our thread = {self.debuggingThread}, "
|
||||
+ f"and debugging thread = {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
|
||||
@@ -0,0 +1,279 @@
|
||||
"""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.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
import tokenize
|
||||
from keyword import kwlist
|
||||
from typing import Any
|
||||
|
||||
import win32api
|
||||
import winerror
|
||||
from win32com.axdebug import axdebug, contexts
|
||||
from win32com.axdebug.util import _wrap
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
_keywords = {
|
||||
_keyword
|
||||
for _keyword in kwlist
|
||||
# Avoids including True/False/None
|
||||
if _keyword.islower()
|
||||
}
|
||||
"""set of Python keywords"""
|
||||
|
||||
|
||||
class SourceCodeContainer:
|
||||
def __init__(
|
||||
self,
|
||||
text: str | None,
|
||||
fileName="<Remove Me!>",
|
||||
sourceContext=0,
|
||||
startLineNumber=0,
|
||||
site=None,
|
||||
debugDocument=None,
|
||||
):
|
||||
self.sourceContext = sourceContext # The source context added by a smart host.
|
||||
self.text: str | None = text
|
||||
if text:
|
||||
self._buildlines()
|
||||
self.nextLineNo = 0
|
||||
self.fileName = fileName
|
||||
# Any: PyIDispatch type is not statically exposed
|
||||
self.codeContexts: dict[int, Any] = {}
|
||||
self.site = site
|
||||
self.startLineNumber = startLineNumber
|
||||
self.debugDocument = debugDocument
|
||||
|
||||
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):
|
||||
raise NotImplementedError("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 COMException(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 += 1
|
||||
else: # for not broken.
|
||||
# print("Can't find", charPos, "in", self.lineOffsets)
|
||||
raise COMException(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 += 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:
|
||||
for tokens in tokenize.tokenize(self.GetNextLine):
|
||||
self._ProcessToken(*tokens)
|
||||
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]
|
||||
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 OSError as details:
|
||||
self.text = f"# COMException opening file\n# {details!r}"
|
||||
else:
|
||||
self.text = f"# No file available for module '{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 f"file:{fname}"
|
||||
else:
|
||||
raise COMException(scode=winerror.E_UNEXPECTED)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from Test 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 isinstance(attr, tuple):
|
||||
attrlen += attr[1]
|
||||
else:
|
||||
attrlen += 1
|
||||
text = sc.GetText()
|
||||
if attrlen != len(text):
|
||||
print(f"Lengths don't match!!! ({attrlen}/{len(text)})")
|
||||
|
||||
# print("Attributes:")
|
||||
# print(attrs)
|
||||
print("GetLineOfPos=", sc.GetLineOfPosition(0))
|
||||
print("GetLineOfPos=", sc.GetLineOfPosition(4))
|
||||
print("GetLineOfPos=", sc.GetLineOfPosition(10))
|
||||
@@ -0,0 +1,58 @@
|
||||
"""A module for managing the AXDebug I*Contexts"""
|
||||
|
||||
from . import adb, axdebug, gateways
|
||||
|
||||
# Utility function for wrapping object created by this module.
|
||||
from .util import _wrap
|
||||
|
||||
|
||||
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
|
||||
# won't 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 - I'll 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)
|
||||
@@ -0,0 +1,238 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pythoncom
|
||||
from win32com.axdebug import adb, axdebug, codecontainer, documents, expressions
|
||||
from win32com.axdebug.util import _wrap
|
||||
|
||||
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 f"<ModuleTreeNode wrapping {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 = os.path.splitext(module.__file__)[1].lower() 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 = module.__name__.split(".")
|
||||
if parts[-1][:8] == "__init__":
|
||||
parts = parts[:-1]
|
||||
parent = ".".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 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 can't 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:
|
||||
# print("File:", key)
|
||||
return documents.CodeContainerProvider.FromFileName(self, fname)
|
||||
|
||||
def Close(self):
|
||||
documents.CodeContainerProvider.Close(self)
|
||||
self.axdebugger = None
|
||||
print(f"Closing {len(self.nodes)} 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(
|
||||
f" {pythoncom._GetInterfaceCount()}/{pythoncom._GetGatewayCount()} com objects still alive"
|
||||
)
|
||||
@@ -0,0 +1,135 @@
|
||||
"""Management of documents for AXDebugging."""
|
||||
|
||||
import pythoncom
|
||||
import win32api
|
||||
from win32com.server.util import unwrap
|
||||
|
||||
from . import axdebug, gateways
|
||||
from .util import _wrap, trace
|
||||
|
||||
# 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.DebugDocumentText):
|
||||
_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 implementation 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(f"FromFileName for {fname} returning None")
|
||||
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 = {}
|
||||
@@ -0,0 +1,57 @@
|
||||
import traceback
|
||||
|
||||
import pythoncom
|
||||
from win32com.axdebug import axdebug
|
||||
from win32com.client.util import Enumerator
|
||||
|
||||
|
||||
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(f"{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(f"{spacer}Text is '{text[:40] + '...'}', {len(text)} bytes long")
|
||||
else:
|
||||
print(f"{spacer*2}<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(f"Application: {app.GetName()}")
|
||||
node = app.GetRootNode() # of type PyIDebugApplicationNode->PyIDebugDocumentProvider->PyIDebugDocumentInfo
|
||||
DumpDebugApplicationNode(node)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
dumpall()
|
||||
except:
|
||||
traceback.print_exc()
|
||||
@@ -0,0 +1,212 @@
|
||||
import io
|
||||
import sys
|
||||
import traceback
|
||||
from pprint import pprint
|
||||
|
||||
import winerror
|
||||
|
||||
from . import axdebug, gateways
|
||||
from .util import RaiseNotImpl, _wrap
|
||||
|
||||
|
||||
# Given an object, return a nice string
|
||||
def MakeNiceString(ob):
|
||||
stream = io.StringIO()
|
||||
pprint(ob, stream)
|
||||
return stream.getvalue().strip()
|
||||
|
||||
|
||||
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 = "\n".join(s[:-1] for s in l)
|
||||
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 = object.items()
|
||||
dictionary = object
|
||||
elif hasattr(object, "__dict__"): # object with dictionary, module
|
||||
name_vals = 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,
|
||||
self.dictionary,
|
||||
self.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")
|
||||
@@ -0,0 +1,583 @@
|
||||
# Classes which describe interfaces.
|
||||
|
||||
import pythoncom
|
||||
import win32com.server.connect
|
||||
import winerror
|
||||
from win32com.axdebug import axdebug
|
||||
from win32com.axdebug.util import RaiseNotImpl, _wrap
|
||||
from win32com.server.exception import COMException
|
||||
from win32com.server.util import ListEnumeratorGateway
|
||||
|
||||
|
||||
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 COMException(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 COMException(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 += 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 COMException(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 COMException(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")
|
||||
@@ -0,0 +1,178 @@
|
||||
"""Support for stack-frames.
|
||||
|
||||
Provides Implements a nearly complete wrapper for a stack frame.
|
||||
"""
|
||||
|
||||
import pythoncom
|
||||
|
||||
from . import axdebug, expressions, gateways
|
||||
from .util import RaiseNotImpl, _wrap, 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("Couldn't 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(f"EnumDebugStackFrames QI with {IIDToInterfaceName(iid)} ({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(f"DebugStackFrame QI with {IIDToInterfaceName(iid)} ({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 += filename
|
||||
if self.frame.f_code.co_name:
|
||||
s += self.frame.f_code.co_name
|
||||
else:
|
||||
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")
|
||||
@@ -0,0 +1,98 @@
|
||||
# Utility function for wrapping objects. Centralising allows me to turn
|
||||
# debugging on and off for the entire package in a single spot.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
import win32api
|
||||
import win32com.server.dispatcher
|
||||
import win32com.server.policy
|
||||
import win32com.server.util
|
||||
import winerror
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
debugging = "DEBUG_AXDEBUG" in os.environ
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
||||
def _wrap(object, iid):
|
||||
useDispatcher = win32com.server.policy.DispatcherWin32trace if debugging else None
|
||||
return win32com.server.util.wrap(object, iid, useDispatcher=useDispatcher)
|
||||
|
||||
|
||||
def RaiseNotImpl(who=None):
|
||||
if who is not None:
|
||||
print(f"********* Function {who} Raising E_NOTIMPL ************")
|
||||
|
||||
# Print a sort-of "traceback", dumping all the frames leading to here.
|
||||
for frame, i in traceback.walk_stack(sys._getframe()):
|
||||
print(f"File: {frame.f_code.co_filename}, Line: {frame.f_lineno}")
|
||||
|
||||
# and raise the exception for COM
|
||||
raise COMException(scode=winerror.E_NOTIMPL)
|
||||
|
||||
|
||||
class Dispatcher(win32com.server.dispatcher.DispatcherWin32trace):
|
||||
def __init__(self, policyClass, object):
|
||||
win32com.server.dispatcher.DispatcherTrace.__init__(self, policyClass, object)
|
||||
import win32traceutil # Sets up everything.
|
||||
|
||||
# print(f"Object with win32trace dispatcher created ({object})")
|
||||
|
||||
def _QueryInterface_(self, iid):
|
||||
rc = win32com.server.policy.DispatcherBase._QueryInterface_(self, iid)
|
||||
# if not rc:
|
||||
# self._trace_(f"in _QueryInterface_ with unsupported IID {IIDToInterfaceName(iid)} ({iid})\n")
|
||||
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 COMException:
|
||||
t, v, tb = sys.exc_info()
|
||||
tb = None # A cycle
|
||||
scode = v.scode
|
||||
try:
|
||||
desc = f" ({v.description})"
|
||||
except AttributeError:
|
||||
desc = ""
|
||||
print(f"*** Invoke of {dispid} raised COM exception 0x{scode:x}{desc}")
|
||||
except:
|
||||
print(f"*** Invoke of {dispid} failed:")
|
||||
typ, val, tb = sys.exc_info()
|
||||
import traceback
|
||||
|
||||
traceback.print_exception(typ, val, tb)
|
||||
raise
|
||||
@@ -0,0 +1,18 @@
|
||||
<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,10 @@
|
||||
<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,10 @@
|
||||
<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,179 @@
|
||||
<!--
|
||||
original Author: Bill Rollins
|
||||
adapted for python by aaron watters
|
||||
Purpose: This HTML example shows how to use Microsoft's ActiveX Chart control.
|
||||
Properties of the control are changed using sub procedures called
|
||||
by radio buttons and check boxes. The AboutBox method is called from
|
||||
a command button.
|
||||
Created: 3/16/96
|
||||
Edited: 3/19/96 - VBScript code edited so there is only one procedure for each property.
|
||||
3/23/96 - Font sizes changed in title. Added text to the Notes section.
|
||||
6/01/96 - Change OBJECT tag to match E3 Beta requirements
|
||||
-->
|
||||
|
||||
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>ActiveX / VBScript Chart Example</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR=#FFFFCC TEXT=#000000>
|
||||
|
||||
<B><FONT SIZE=6>Chart Example</FONT></B><BR>
|
||||
<FONT SIZE=2>You must be running Microsoft Internet Explorer 3.0 and have the Microsoft ActiveX Chart Control installed to view this page.</FONT><BR>
|
||||
<P>
|
||||
The chart control enables you to draw charts. The chart's types and styles are properties of the control. The chart has one method, AboutBox. The chart generates no events.
|
||||
|
||||
<HR>
|
||||
|
||||
<OBJECT
|
||||
classid="clsid:FC25B780-75BE-11CF-8B01-444553540000"
|
||||
CODEBASE="http://activex.microsoft.com/controls/iexplorer/iechart.ocx#Version=4,70,0,1161"
|
||||
TYPE="application/x-oleobject"
|
||||
id=Chart1
|
||||
width=200
|
||||
height=200
|
||||
align=left
|
||||
hspace=0
|
||||
vspace=0
|
||||
>
|
||||
|
||||
<param name="_extentX" value="300">
|
||||
<param name="_extentY" value="150">
|
||||
<param name="ChartStyle" value="0">
|
||||
<param name="ChartType" value="4">
|
||||
<param name="hgridStyle" value="0">
|
||||
<param name="vgridStyle" value="0">
|
||||
<param name="colorscheme" value="0">
|
||||
<param name="rows" value="2">
|
||||
<param name="columns" value="4">
|
||||
<param name="data[0][0]" value="30">
|
||||
<param name="data[0][1]" value="2">
|
||||
<param name="data[0][2]" value="20">
|
||||
<param name="data[0][3]" value="40">
|
||||
<param name="data[1][0]" value="15">
|
||||
<param name="data[1][1]" value="33">
|
||||
<param name="data[1][2]" value="21">
|
||||
<param name="data[1][3]" value="45">
|
||||
<param name="BackStyle" value="1">
|
||||
|
||||
|
||||
</object>
|
||||
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
|
||||
|
||||
# Calls the AboutBox Method. This displays the Chart Object About Box
|
||||
def DoChartAboutBox():
|
||||
ax.Chart1.AboutBox()
|
||||
|
||||
# Changes the type of chart. WhatType is passed as a value (0-5) when one of the Chart Type radio buttons is selected
|
||||
def DoChartType(WhatType):
|
||||
ax.Chart1.ChartType = WhatType
|
||||
|
||||
# Turns horizontal gridlines on or off depending on value of chkHorizontal checkbox
|
||||
def DoHorizontalGrid():
|
||||
print(ax.chkHorizontal.Checked)
|
||||
if ax.chkHorizontal.Checked:
|
||||
ax.Chart1.HGridStyle = 1
|
||||
else:
|
||||
ax.Chart1.HGridStyle = 0
|
||||
|
||||
# Sets the background of the chart to Opaque or Transparent
|
||||
def DoBackground(intBackGround):
|
||||
ax.Chart1.BackStyle = intBackGround
|
||||
|
||||
# Turns vertical gridlines on or off depending on value of chkVertical checkbox
|
||||
def DoVerticalGrid():
|
||||
if ax.chkVertical.Checked:
|
||||
ax.Chart1.VGridStyle = 1
|
||||
else:
|
||||
ax.Chart1.VGridStyle = 0
|
||||
|
||||
</SCRIPT>
|
||||
|
||||
|
||||
|
||||
<TABLE BORDER = 0 XBORDER=5 BGCOLOR="#FFFFCC" WIDTH=300 ALIGN=LEFT>
|
||||
<TR><TD colspan=2 BGCOLOR=NAVY ALIGN=CENTER><FONT COLOR=FFFFCC>Chart Type</TR>
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(0)"> Simple Pie </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(11)"> Simple Column </TD></TR>
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(1)"> Pie with Wedge Out </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(12)"> Stacked Column </TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(2)"> Simple Point </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(13)"> Full Column </TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(3)"> Stacked Point </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(14)"> Simple Bar </TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(4)"> Full Point </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(15)"> Stacked Bar </TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(5)"> Simple Line </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(16)"> Full Bar </TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(6)"> Stacked Line </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(17)"> HLC Stock </TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(7)"> Full Line </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(18)"> HLC Stock WSJ</TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(8)"> Simple Area </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(19)"> OHLC Stock </TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(9)"> Stack Area </TD>
|
||||
<TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(20)"> OHLC Stock WSJ </TD></TR>
|
||||
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=ChartType onClick="DoChartType(10)"> Full Area </TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<TABLE XBORDER=5 WIDTH=125 BGCOLOR="#FFFFCC" ALIGN=LEFT>
|
||||
<TR><TD BGCOLOR=NAVY ALIGN=CENTER><FONT COLOR=FFFFCC>Gridlines</TR>
|
||||
<TR><TD><INPUT TYPE=CHECKBOX NAME="chkHorizontal" onClick="DoHorizontalGrid()">Horizontal</TD></TR>
|
||||
<TR><TD><INPUT TYPE=CHECKBOX NAME="chkVertical" onClick="DoVerticalGrid()">Vertical</TD></TR>
|
||||
<TR><TD BGCOLOR=NAVY ALIGN=CENTER><FONT COLOR=FFFFCC>Background</TR>
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=BackStyle onClick="DoBackground(1)">Opaque</TD></TR>
|
||||
<TR><TD><INPUT TYPE=RADIO NAME=BackStyle onClick="DoBackground(0)">Transparent</TD></TR>
|
||||
|
||||
</TABLE>
|
||||
|
||||
<BR CLEAR=ALL>
|
||||
<BR>
|
||||
|
||||
<INPUT TYPE=BUTTON VALUE="About Chart Control" NAME="cdmChartAboutBox" onClick="DoChartAboutBox()">
|
||||
|
||||
<BR CLEAR=ALL>
|
||||
<BR><BR>
|
||||
|
||||
<HR>
|
||||
<B><FONT SIZE=4>Notes</FONT></B><BR>
|
||||
The chart's properties on this page are changed by selecting the various radio buttons and check boxes. The OnClick event of these intrinsic controls calls VBScript procedures that change the chart properties.<BR>
|
||||
<P>
|
||||
The About Chart Control command button calls the chart's AboutBox method.<BR>
|
||||
<P>
|
||||
To view the source code for this page, select <SAMP>Source</SAMP> from the <SAMP>View</SAMP> menu.<BR>
|
||||
<P>
|
||||
If you have any questions or comments about this example, please send them to <A HREF ="mailto:billr@smart.net">billr@smart.net</A>. We would appreciate feedback and would like to hear about other developers' experiences with these new tools.<BR>
|
||||
|
||||
|
||||
<HR>
|
||||
|
||||
</BODY>
|
||||
|
||||
|
||||
|
||||
<ADDRESS>
|
||||
<FONT SIZE=2>
|
||||
© 1996 Rollins & Associates, Inc.<BR>
|
||||
Page last updated 08/28/96<BR>
|
||||
Please send comments to <A HREF ="mailto:billr@smart.net">billr@smart.net</A><BR>
|
||||
</FONT>
|
||||
</ADDRESS>
|
||||
|
||||
</HTML>
|
||||
@@ -0,0 +1,46 @@
|
||||
<HTML>
|
||||
<BODY>
|
||||
Let's try this out:
|
||||
|
||||
<FORM>
|
||||
<INPUT NAME="Button1" TYPE="Button" OnClick="foo1" LANGUAGE="VBScript">
|
||||
<FORM METHOD="GET" NAME="MyForm">
|
||||
<INPUT TYPE="TEXT" NAME="Text1" SIZE=25>
|
||||
<INPUT TYPE="SUBMIT">
|
||||
<INPUT NAME="Button2" TYPE="Button" VALUE="Hi" OnClick="text2.value=window.document.location" LANGUAGE="VBScript">
|
||||
<INPUT TYPE="TEXT" SIZE=25 NAME="Text2">
|
||||
</FORM>
|
||||
And here is a second form
|
||||
<P>
|
||||
<FORM NAME="Form2" METHOD="GET">
|
||||
<INPUT NAME="Button2" TYPE="Button" VALUE="Hi" OnClick="button2.value=window.document.location" LANGUAGE="VBScript">
|
||||
</FORM><BR>
|
||||
|
||||
<SCRIPT LANGUAGE="JScript">
|
||||
y=15
|
||||
</SCRIPT>
|
||||
|
||||
<SCRIPT LANGUAGE="VBScript">
|
||||
x = 13
|
||||
Sub foo1
|
||||
Dim y
|
||||
y = 14
|
||||
alert "Hello"
|
||||
End Sub
|
||||
|
||||
Sub Window_OnLoad
|
||||
foo1
|
||||
MyForm.button2.value = "Loaded"
|
||||
Form2.button2.value = "Loaded"
|
||||
End Sub
|
||||
Sub Link_MouseMove(b, s, x, y)
|
||||
MsgBox b
|
||||
End Sub
|
||||
</SCRIPT>
|
||||
|
||||
<SCRIPT LANGUAGE="Python">
|
||||
print("Python loaded")
|
||||
</SCRIPT>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
@@ -0,0 +1,24 @@
|
||||
<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="https://www.python.org">https://www.python.org</A>
|
||||
|
||||
</FONT>
|
||||
</BODY>
|
||||
</HTML>
|
||||
@@ -0,0 +1,115 @@
|
||||
<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, float(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(-float(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,25 @@
|
||||
<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,39 @@
|
||||
<HTML>
|
||||
<H1>Engine Registration</H1>
|
||||
|
||||
<BODY>
|
||||
|
||||
<p>The Python ActiveX Scripting Engine is not currently registered.<p>
|
||||
|
||||
<p>Due to a <a href="https://web.archive.org/web/20080305234321/http://starship.python.net:80/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="https://web.archive.org/web/20080305234321/http://starship.python.net:80/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,37 @@
|
||||
<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="https://web.archive.org/web/20080305234321/http://starship.python.net:80/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 I'm 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 explicitly
|
||||
specify either cscript.exe or wscript.exe on the command line.
|
||||
</UL>
|
||||
|
||||
</BODY></HTML>
|
||||
@@ -0,0 +1,14 @@
|
||||
<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 - I'm 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 - I'm 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,59 @@
|
||||
<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,82 @@
|
||||
<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!", "https://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,31 @@
|
||||
#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()
|
||||
|
||||
# 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,44 @@
|
||||
""" 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,14 @@
|
||||
# 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
|
||||
@@ -0,0 +1,4 @@
|
||||
# See if we have a special directory for the binaries (for developers)
|
||||
import win32com
|
||||
|
||||
win32com.__PackageSupportBuildPath__(__path__)
|
||||
@@ -0,0 +1,13 @@
|
||||
"""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
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
# This is a Python package
|
||||
@@ -0,0 +1,223 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pythoncom
|
||||
import win32api
|
||||
import winerror
|
||||
from win32com.axdebug import adb, axdebug, documents, gateways
|
||||
from win32com.axdebug.codecontainer import SourceCodeContainer
|
||||
from win32com.axdebug.util import _wrap
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
debuggingTrace = "DEBUG_AXDEBUG" in os.environ # Should we print "trace" output?
|
||||
|
||||
|
||||
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 - Don't 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
|
||||
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")
|
||||
self.adb.SetupAXDebugging(sys._getframe().f_back)
|
||||
|
||||
def OnLeaveScript(self):
|
||||
trace("OnLeaveScript")
|
||||
self.adb.ResetAXDebugging()
|
||||
|
||||
def AddScriptBlock(self, codeBlock):
|
||||
# If we don't have debugging support, don't 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)
|
||||
@@ -0,0 +1,262 @@
|
||||
"""Exception and error handling.
|
||||
|
||||
This contains the core exceptions that the implementations should raise
|
||||
as well as the IActiveScriptError interface code.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import traceback
|
||||
import warnings
|
||||
from types import TracebackType
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import pythoncom
|
||||
import win32com.server.util
|
||||
import winerror
|
||||
from win32com.axscript import axscript
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from win32comext.axscript.client.debug import DebugManager
|
||||
from win32comext.axscript.client.framework import AXScriptCodeBlock, COMScript
|
||||
from win32comext.axscript.server.axsite import AXSite
|
||||
|
||||
debugging = 0
|
||||
|
||||
|
||||
def FormatForAX(text: str):
|
||||
"""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: str):
|
||||
return re.sub(r"\t", " ", text)
|
||||
|
||||
|
||||
def AddCR(text: str):
|
||||
return re.sub(r"\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: AXScriptException):
|
||||
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(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: COMScript,
|
||||
codeBlock: AXScriptCodeBlock | None,
|
||||
exc_type: None = None,
|
||||
exc_value: BaseException | None = None,
|
||||
exc_traceback: None = None,
|
||||
):
|
||||
# set properties base class shares via base ctor...
|
||||
super().__init__(
|
||||
description="Unknown Exception",
|
||||
scode=winerror.DISP_E_EXCEPTION,
|
||||
source="Python ActiveX Scripting Engine",
|
||||
)
|
||||
|
||||
if exc_type is not None or exc_traceback is not None:
|
||||
warnings.warn(
|
||||
"`exc_type` and `exc_traceback` were redundant and are now unused.",
|
||||
category=DeprecationWarning,
|
||||
)
|
||||
|
||||
# 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_value)
|
||||
|
||||
def __BuildFromException(self, site: COMScript, value: BaseException | None):
|
||||
if debugging:
|
||||
import linecache
|
||||
|
||||
linecache.clearcache()
|
||||
try:
|
||||
if isinstance(value, SyntaxError):
|
||||
self._BuildFromSyntaxError(value)
|
||||
else:
|
||||
self._BuildFromOther(site, value)
|
||||
except: # Error extracting traceback info!!!
|
||||
traceback.print_exc()
|
||||
# re-raise.
|
||||
raise
|
||||
|
||||
def _BuildFromSyntaxError(self, exc: SyntaxError):
|
||||
# Some of these may be None, which upsets us!
|
||||
msg = exc.msg or "Unknown Error"
|
||||
offset = exc.offset or 0
|
||||
line = exc.text or ""
|
||||
lineno = exc.lineno or 0
|
||||
|
||||
self.description = FormatForAX(msg)
|
||||
self.lineno = lineno
|
||||
self.colno = offset - 1
|
||||
self.linetext = ExpandTabs(line.rstrip())
|
||||
|
||||
def _BuildFromOther(self, site: COMScript, value: BaseException | None):
|
||||
tb = value.__traceback__ if value else None
|
||||
exc_type = type(value) if value else None
|
||||
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.
|
||||
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.
|
||||
tb_look: TracebackType | None = 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))
|
||||
tb_look = tb_look.tb_next
|
||||
else:
|
||||
tb_top = tb
|
||||
|
||||
bits = ["Traceback (most recent call last):\n"]
|
||||
bits.extend(traceback.format_list(format_items))
|
||||
if isinstance(value, pythoncom.com_error):
|
||||
desc = f"{value.strerror} (0x{value.hresult:x})"
|
||||
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))
|
||||
|
||||
self.description = ExpandTabs("".join(bits))
|
||||
|
||||
def ExtractTracebackInfo(self, tb: TracebackType, site: COMScript):
|
||||
import linecache
|
||||
|
||||
lineno = tb.tb_lineno
|
||||
co = tb.tb_frame.f_code
|
||||
filename = co.co_filename
|
||||
name = co.co_name
|
||||
line: str | None = linecache.getline(filename, lineno)
|
||||
if not line:
|
||||
codeBlock = site.scriptCodeBlocks.get(filename)
|
||||
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: AXSite,
|
||||
debugManager: DebugManager,
|
||||
exceptionInstance: AXScriptException,
|
||||
):
|
||||
"""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(f"Exception description: '{exceptionInstance.description!r}'")
|
||||
print(f"Exception text: '{exceptionInstance.linetext!r}'")
|
||||
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 = 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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,78 @@
|
||||
# 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.
|
||||
|
||||
import sys
|
||||
|
||||
import win32api
|
||||
import win32con
|
||||
from win32com.axscript import axscript
|
||||
|
||||
from . import pyscript
|
||||
|
||||
PyDump_CLSID = "{ac527e60-c693-11d0-9c25-00aa00125a98}"
|
||||
|
||||
|
||||
class AXScriptAttribute(pyscript.AXScriptAttribute):
|
||||
pass
|
||||
|
||||
|
||||
class NamedScriptAttribute(pyscript.NamedScriptAttribute):
|
||||
pass
|
||||
|
||||
|
||||
class PyScript(pyscript.PyScript):
|
||||
pass
|
||||
|
||||
|
||||
def Register():
|
||||
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, _set_string
|
||||
|
||||
languageName = "PyDump"
|
||||
verProgId = "Python.Dumper.1"
|
||||
RegisterServer(
|
||||
clsid=clsid,
|
||||
pythonInstString="win32com.axscript.client.pyscript.PyDumper",
|
||||
desc="Python Debugging/Dumping ActiveX Scripting Engine",
|
||||
progID=languageName,
|
||||
verProgID=verProgId,
|
||||
policy=policy,
|
||||
catids=categories,
|
||||
dispatcher=dispatcher,
|
||||
)
|
||||
|
||||
win32api.RegCreateKey(win32con.HKEY_CLASSES_ROOT, languageName + "\\OLEScript")
|
||||
# Basic Registration for wsh.
|
||||
_set_string(".pysDump", "pysDumpFile")
|
||||
_set_string("pysDumpFile\\ScriptEngine", languageName)
|
||||
print("Dumping Server registered.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
Register()
|
||||
@@ -0,0 +1,438 @@
|
||||
"""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 re
|
||||
import types
|
||||
|
||||
import pythoncom
|
||||
import win32com
|
||||
import win32com.client.dynamic
|
||||
import win32com.server.register
|
||||
import winerror
|
||||
from win32com.axscript import axscript
|
||||
from win32com.axscript.client import framework, scriptdispatch
|
||||
from win32com.axscript.client.framework import (
|
||||
SCRIPTTEXT_FORCEEXECUTION,
|
||||
SCRIPTTEXT_ISEXPRESSION,
|
||||
SCRIPTTEXT_ISPERSISTENT,
|
||||
trace,
|
||||
)
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
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(r"\t", " ", text)
|
||||
|
||||
|
||||
def AddCR(text):
|
||||
return re.sub(r"\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 explicitly 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 f"<NamedItemAttribute{self._scriptItem_!r}>"
|
||||
|
||||
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.
|
||||
olerepr, clsid = None
|
||||
try:
|
||||
engine = self.GetEngine()
|
||||
typeinfo = self.dispatch.GetTypeInfo()
|
||||
clsid = typeinfo.GetTypeAttr()[0]
|
||||
olerepr = engine.mapKnownCOMTypes.get(clsid)
|
||||
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)
|
||||
|
||||
self.scriptDispatch = None
|
||||
self.globalNameSpaceModule = types.ModuleType("__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 += 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 isinstance(function, PyScript): # 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 += "\t" + line + "\n"
|
||||
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__:
|
||||
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 COMException(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 += f" {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):
|
||||
ret = win32com.server.register.UseCommandLine(
|
||||
klass, finalize_register=DllRegisterServer
|
||||
)
|
||||
return ret
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
Register()
|
||||
@@ -0,0 +1,54 @@
|
||||
# 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
|
||||
|
||||
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,103 @@
|
||||
"""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!
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import types
|
||||
|
||||
import pythoncom
|
||||
import win32com.server.policy
|
||||
import win32com.server.util
|
||||
import winerror
|
||||
from win32com.client import Dispatch
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
debugging = 0
|
||||
|
||||
PyIDispatchType = pythoncom.TypeIIDs[pythoncom.IID_IDispatch]
|
||||
|
||||
# ignore hasattr(obj, "__call__") as this means all COM objects!
|
||||
_CallableTypes = (types.FunctionType, types.MethodType)
|
||||
|
||||
|
||||
class ScriptDispatch:
|
||||
_public_methods_: list[str] = []
|
||||
|
||||
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 isinstance(func, _CallableTypes):
|
||||
raise AttributeError(name) # Not a function.
|
||||
realArgs = []
|
||||
for arg in args:
|
||||
if isinstance(arg, PyIDispatchType):
|
||||
realArgs.append(Dispatch(arg))
|
||||
else:
|
||||
realArgs.append(arg)
|
||||
# xxx - todo - work out what code block to pass???
|
||||
return self.engine.ApplyInScriptedSection(None, func, tuple(realArgs))
|
||||
|
||||
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 isinstance(ret, _CallableTypes):
|
||||
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 isinstance(func, _CallableTypes):
|
||||
return win32com.server.policy.DynamicPolicy._getdispid_(self, name, fdex)
|
||||
|
||||
|
||||
def _wrap(obj):
|
||||
useDispatcher = win32com.server.policy.DispatcherWin32trace if debugging else None
|
||||
return win32com.server.util.wrap(
|
||||
obj, usePolicy=StrictDynamicPolicy, useDispatcher=useDispatcher
|
||||
)
|
||||
|
||||
|
||||
def MakeScriptDispatch(engine, namespace):
|
||||
return _wrap(ScriptDispatch(engine, namespace))
|
||||
@@ -0,0 +1,145 @@
|
||||
import pythoncom
|
||||
import winerror
|
||||
from win32com.axscript import axscript
|
||||
from win32com.server import util
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
|
||||
class AXEngine:
|
||||
def __init__(self, site, engine):
|
||||
self.eScript = self.eParse = self.eSafety = None
|
||||
if isinstance(engine, str):
|
||||
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 str.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 isinstance(engine, str):
|
||||
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:
|
||||
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 COMException(
|
||||
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
|
||||
@@ -0,0 +1,16 @@
|
||||
def Function(i):
|
||||
Test.Echo(i)
|
||||
|
||||
print(dir())
|
||||
|
||||
a=1
|
||||
b=a
|
||||
c=b # And here is a comment
|
||||
d="A string"
|
||||
print(a)
|
||||
Test.echo("Hello from Python")
|
||||
for i in range(2):
|
||||
Function(i)
|
||||
a = """\
|
||||
A multi-line string!
|
||||
"""
|
||||
@@ -0,0 +1,7 @@
|
||||
a=1
|
||||
b=a
|
||||
Test.Echo "Hello from VBScript"
|
||||
' Here is a comment
|
||||
for i = 1 to 10
|
||||
|
||||
next
|
||||
@@ -0,0 +1,185 @@
|
||||
import sys
|
||||
|
||||
import pythoncom
|
||||
from win32com.axscript import axscript
|
||||
from win32com.axscript.server import axsite
|
||||
from win32com.server import connect, util
|
||||
|
||||
|
||||
class MySite(axsite.AXSite):
|
||||
def OnScriptError(self, error):
|
||||
exc = error.GetExceptionInfo()
|
||||
context, line, char = error.GetSourcePosition()
|
||||
print(" >Exception:", exc[1])
|
||||
try:
|
||||
st = error.GetSourceLineText()
|
||||
except pythoncom.com_error:
|
||||
st = None
|
||||
if st is None:
|
||||
st = ""
|
||||
text = st + "\n" + (" " * (char - 1)) + "^" + "\n" + exc[2]
|
||||
for line in text.splitlines():
|
||||
print(" >" + line)
|
||||
|
||||
|
||||
class MyCollection(util.Collection):
|
||||
def _NewEnum(self):
|
||||
print("Making new Enumerator")
|
||||
return util.Collection._NewEnum(self)
|
||||
|
||||
|
||||
class Test:
|
||||
_public_methods_ = ["echo"]
|
||||
_public_attrs_ = ["collection", "verbose"]
|
||||
|
||||
def __init__(self):
|
||||
self.verbose = 0
|
||||
self.collection = util.wrap(MyCollection([1, "Two", 3]))
|
||||
self.last = ""
|
||||
|
||||
# self._connect_server_ = TestConnectServer(self)
|
||||
|
||||
def echo(self, *args):
|
||||
self.last = "".join(map(str, args))
|
||||
if self.verbose:
|
||||
for arg in args:
|
||||
print(arg, end=" ")
|
||||
print()
|
||||
|
||||
|
||||
# self._connect_server_.Broadcast(last)
|
||||
|
||||
|
||||
#### Connections currently won't work, as there is no way for the engine to
|
||||
#### know what events we support. We need typeinfo support.
|
||||
|
||||
IID_ITestEvents = pythoncom.MakeIID("{8EB72F90-0D44-11d1-9C4B-00AA00125A98}")
|
||||
|
||||
|
||||
class TestConnectServer(connect.ConnectableServer):
|
||||
_connect_interfaces_ = [IID_ITestEvents]
|
||||
|
||||
# The single public method that the client can call on us
|
||||
# (ie, as a normal COM server, this exposes just this single method.
|
||||
def __init__(self, object):
|
||||
self.object = object
|
||||
|
||||
def Broadcast(self, arg):
|
||||
# Simply broadcast a notification.
|
||||
self._BroadcastNotify(self.NotifyDoneIt, (arg,))
|
||||
|
||||
def NotifyDoneIt(self, interface, arg):
|
||||
interface.Invoke(1000, 0, pythoncom.DISPATCH_METHOD, 1, arg)
|
||||
|
||||
|
||||
VBScript = """\
|
||||
prop = "Property Value"
|
||||
|
||||
sub hello(arg1)
|
||||
test.echo arg1
|
||||
end sub
|
||||
|
||||
sub testcollection
|
||||
test.verbose = 1
|
||||
for each item in test.collection
|
||||
test.echo "Collection item is", item
|
||||
next
|
||||
end sub
|
||||
"""
|
||||
|
||||
PyScript = """\
|
||||
print("PyScript is being parsed...")\n
|
||||
|
||||
prop = "Property Value"
|
||||
def hello(arg1):
|
||||
test.echo(arg1)
|
||||
pass
|
||||
|
||||
def testcollection():
|
||||
test.verbose = 1
|
||||
# test.collection[1] = "New one"
|
||||
for item in test.collection:
|
||||
test.echo("Collection item is", item)
|
||||
pass
|
||||
"""
|
||||
|
||||
ErrScript = """\
|
||||
bad code for everyone!
|
||||
"""
|
||||
|
||||
|
||||
def TestEngine(engineName, code, bShouldWork=1):
|
||||
echoer = Test()
|
||||
model = {
|
||||
"test": util.wrap(echoer),
|
||||
}
|
||||
|
||||
site = MySite(model)
|
||||
engine = site._AddEngine(engineName)
|
||||
engine.AddCode(code, axscript.SCRIPTTEXT_ISPERSISTENT)
|
||||
try:
|
||||
engine.Start()
|
||||
finally:
|
||||
if not bShouldWork:
|
||||
engine.Close()
|
||||
return
|
||||
doTestEngine(engine, echoer)
|
||||
# re-transition the engine back to the UNINITIALIZED state, a-la ASP.
|
||||
engine.eScript.SetScriptState(axscript.SCRIPTSTATE_UNINITIALIZED)
|
||||
engine.eScript.SetScriptSite(util.wrap(site))
|
||||
print("restarting")
|
||||
engine.Start()
|
||||
# all done!
|
||||
engine.Close()
|
||||
|
||||
|
||||
def doTestEngine(engine, echoer):
|
||||
# Now call into the scripts IDispatch
|
||||
from win32com.client.dynamic import Dispatch
|
||||
|
||||
ob = Dispatch(engine.GetScriptDispatch())
|
||||
try:
|
||||
ob.hello("Goober")
|
||||
except pythoncom.com_error as exc:
|
||||
print("***** Calling 'hello' failed", exc)
|
||||
return
|
||||
if echoer.last != "Goober":
|
||||
print(f"***** Function call didnt set value correctly {echoer.last!r}")
|
||||
|
||||
if str(ob.prop) != "Property Value":
|
||||
print(f"***** Property Value not correct - {ob.prop!r}")
|
||||
|
||||
ob.testcollection()
|
||||
|
||||
# Now make sure my engines can evaluate stuff.
|
||||
result = engine.eParse.ParseScriptText(
|
||||
"1+1", None, None, None, 0, 0, axscript.SCRIPTTEXT_ISEXPRESSION
|
||||
)
|
||||
if result != 2:
|
||||
print("Engine could not evaluate '1+1' - said the result was", result)
|
||||
|
||||
|
||||
def dotestall():
|
||||
for i in range(10):
|
||||
TestEngine("Python", PyScript)
|
||||
print(sys.gettotalrefcount())
|
||||
|
||||
|
||||
# print("Testing Exceptions")
|
||||
# try:
|
||||
# TestEngine("Python", ErrScript, 0)
|
||||
# except pythoncom.com_error:
|
||||
# pass
|
||||
|
||||
|
||||
def testall():
|
||||
dotestall()
|
||||
pythoncom.CoUninitialize()
|
||||
print(
|
||||
"AXScript Host worked correctly - %d/%d COM objects left alive."
|
||||
% (pythoncom._GetInterfaceCount(), pythoncom._GetGatewayCount())
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
testall()
|
||||
@@ -0,0 +1,240 @@
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import pythoncom
|
||||
import win32com.server.policy
|
||||
import win32com.test.util
|
||||
from win32com.axscript import axscript
|
||||
from win32com.axscript.server import axsite
|
||||
from win32com.client.dynamic import Dispatch
|
||||
from win32com.server import connect, util
|
||||
|
||||
verbose = "-v" in sys.argv
|
||||
|
||||
|
||||
class MySite(axsite.AXSite):
|
||||
def __init__(self, *args):
|
||||
self.exception_seen = None
|
||||
axsite.AXSite.__init__(self, *args)
|
||||
|
||||
def OnScriptError(self, error):
|
||||
self.exception_seen = exc = error.GetExceptionInfo()
|
||||
context, line, char = error.GetSourcePosition()
|
||||
if not verbose:
|
||||
return
|
||||
print(" >Exception:", exc[1])
|
||||
try:
|
||||
st = error.GetSourceLineText()
|
||||
except pythoncom.com_error:
|
||||
st = None
|
||||
if st is None:
|
||||
st = ""
|
||||
text = st + "\n" + (" " * (char - 1)) + "^" + "\n" + exc[2]
|
||||
for line in text.splitlines():
|
||||
print(" >" + line)
|
||||
|
||||
|
||||
class MyCollection(util.Collection):
|
||||
def _NewEnum(self):
|
||||
return util.Collection._NewEnum(self)
|
||||
|
||||
|
||||
class Test:
|
||||
_public_methods_ = ["echo", "fail"]
|
||||
_public_attrs_ = ["collection"]
|
||||
|
||||
def __init__(self):
|
||||
self.verbose = verbose
|
||||
self.collection = util.wrap(MyCollection([1, "Two", 3]))
|
||||
self.last = ""
|
||||
self.fail_called = 0
|
||||
|
||||
# self._connect_server_ = TestConnectServer(self)
|
||||
|
||||
def echo(self, *args):
|
||||
self.last = "".join([str(s) for s in args])
|
||||
if self.verbose:
|
||||
for arg in args:
|
||||
print(arg, end=" ")
|
||||
print()
|
||||
|
||||
def fail(self, *args):
|
||||
print("**** fail() called ***")
|
||||
for arg in args:
|
||||
print(arg, end=" ")
|
||||
print()
|
||||
self.fail_called = 1
|
||||
|
||||
|
||||
# self._connect_server_.Broadcast(last)
|
||||
|
||||
|
||||
#### Connections currently won't work, as there is no way for the engine to
|
||||
#### know what events we support. We need typeinfo support.
|
||||
|
||||
IID_ITestEvents = pythoncom.MakeIID("{8EB72F90-0D44-11d1-9C4B-00AA00125A98}")
|
||||
|
||||
|
||||
class TestConnectServer(connect.ConnectableServer):
|
||||
_connect_interfaces_ = [IID_ITestEvents]
|
||||
|
||||
# The single public method that the client can call on us
|
||||
# (ie, as a normal COM server, this exposes just this single method.
|
||||
def __init__(self, object):
|
||||
self.object = object
|
||||
|
||||
def Broadcast(self, arg):
|
||||
# Simply broadcast a notification.
|
||||
self._BroadcastNotify(self.NotifyDoneIt, (arg,))
|
||||
|
||||
def NotifyDoneIt(self, interface, arg):
|
||||
interface.Invoke(1000, 0, pythoncom.DISPATCH_METHOD, 1, arg)
|
||||
|
||||
|
||||
VBScript = """\
|
||||
prop = "Property Value"
|
||||
|
||||
sub hello(arg1)
|
||||
test.echo arg1
|
||||
end sub
|
||||
|
||||
sub testcollection
|
||||
if test.collection.Item(0) <> 1 then
|
||||
test.fail("Index 0 was wrong")
|
||||
end if
|
||||
if test.collection.Item(1) <> "Two" then
|
||||
test.fail("Index 1 was wrong")
|
||||
end if
|
||||
if test.collection.Item(2) <> 3 then
|
||||
test.fail("Index 2 was wrong")
|
||||
end if
|
||||
num = 0
|
||||
for each item in test.collection
|
||||
num = num + 1
|
||||
next
|
||||
if num <> 3 then
|
||||
test.fail("Collection didn't have 3 items")
|
||||
end if
|
||||
end sub
|
||||
"""
|
||||
PyScript = """\
|
||||
# A unicode \xa9omment.
|
||||
prop = "Property Value"
|
||||
def hello(arg1):
|
||||
test.echo(arg1)
|
||||
|
||||
def testcollection():
|
||||
# test.collection[1] = "New one"
|
||||
got = []
|
||||
for item in test.collection:
|
||||
got.append(item)
|
||||
if got != [1, "Two", 3]:
|
||||
test.fail("Didn't get the collection")
|
||||
pass
|
||||
"""
|
||||
|
||||
ErrScript = """\
|
||||
bad code for everyone!
|
||||
"""
|
||||
|
||||
state_map = {
|
||||
axscript.SCRIPTSTATE_UNINITIALIZED: "SCRIPTSTATE_UNINITIALIZED",
|
||||
axscript.SCRIPTSTATE_INITIALIZED: "SCRIPTSTATE_INITIALIZED",
|
||||
axscript.SCRIPTSTATE_STARTED: "SCRIPTSTATE_STARTED",
|
||||
axscript.SCRIPTSTATE_CONNECTED: "SCRIPTSTATE_CONNECTED",
|
||||
axscript.SCRIPTSTATE_DISCONNECTED: "SCRIPTSTATE_DISCONNECTED",
|
||||
axscript.SCRIPTSTATE_CLOSED: "SCRIPTSTATE_CLOSED",
|
||||
}
|
||||
|
||||
|
||||
def _CheckEngineState(engine, name, state):
|
||||
got = engine.engine.eScript.GetScriptState()
|
||||
if got != state:
|
||||
got_name = state_map.get(got, str(got))
|
||||
state_name = state_map.get(state, str(state))
|
||||
raise RuntimeError(
|
||||
f"Warning - engine {name} has state {got_name}, but expected {state_name}"
|
||||
)
|
||||
|
||||
|
||||
class EngineTester(win32com.test.util.TestCase):
|
||||
def _TestEngine(self, engineName, code, expected_exc=None):
|
||||
echoer = Test()
|
||||
model = {
|
||||
"test": util.wrap(echoer),
|
||||
}
|
||||
site = MySite(model)
|
||||
engine = site._AddEngine(engineName)
|
||||
try:
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_INITIALIZED)
|
||||
engine.AddCode(code)
|
||||
engine.Start()
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_STARTED)
|
||||
self.assertTrue(not echoer.fail_called, "Fail should not have been called")
|
||||
# Now call into the scripts IDispatch
|
||||
ob = Dispatch(engine.GetScriptDispatch())
|
||||
try:
|
||||
ob.hello("Goober")
|
||||
self.assertTrue(
|
||||
expected_exc is None,
|
||||
f"Expected {expected_exc!r}, but no exception seen",
|
||||
)
|
||||
except pythoncom.com_error:
|
||||
if expected_exc is None:
|
||||
self.fail(
|
||||
f"Unexpected failure from script code: {site.exception_seen}"
|
||||
)
|
||||
if expected_exc not in site.exception_seen[2]:
|
||||
self.fail(
|
||||
f"Could not find {expected_exc!r} in {site.exception_seen[2]!r}"
|
||||
)
|
||||
return
|
||||
self.assertEqual(echoer.last, "Goober")
|
||||
|
||||
self.assertEqual(str(ob.prop), "Property Value")
|
||||
ob.testcollection()
|
||||
self.assertTrue(not echoer.fail_called, "Fail should not have been called")
|
||||
|
||||
# Now make sure my engines can evaluate stuff.
|
||||
result = engine.eParse.ParseScriptText(
|
||||
"1+1", None, None, None, 0, 0, axscript.SCRIPTTEXT_ISEXPRESSION
|
||||
)
|
||||
self.assertEqual(result, 2)
|
||||
# re-initialize to make sure it transitions back to initialized again.
|
||||
engine.SetScriptState(axscript.SCRIPTSTATE_INITIALIZED)
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_INITIALIZED)
|
||||
engine.Start()
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_STARTED)
|
||||
|
||||
# Transition back to initialized, then through connected too.
|
||||
engine.SetScriptState(axscript.SCRIPTSTATE_INITIALIZED)
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_INITIALIZED)
|
||||
engine.SetScriptState(axscript.SCRIPTSTATE_CONNECTED)
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_CONNECTED)
|
||||
engine.SetScriptState(axscript.SCRIPTSTATE_INITIALIZED)
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_INITIALIZED)
|
||||
|
||||
engine.SetScriptState(axscript.SCRIPTSTATE_CONNECTED)
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_CONNECTED)
|
||||
engine.SetScriptState(axscript.SCRIPTSTATE_DISCONNECTED)
|
||||
_CheckEngineState(site, engineName, axscript.SCRIPTSTATE_DISCONNECTED)
|
||||
finally:
|
||||
engine.Close()
|
||||
engine = None
|
||||
site = None
|
||||
|
||||
def testVB(self):
|
||||
self._TestEngine("VBScript", VBScript)
|
||||
|
||||
def testPython(self):
|
||||
self._TestEngine("Python", PyScript)
|
||||
|
||||
def testPythonUnicodeError(self):
|
||||
self._TestEngine("Python", PyScript)
|
||||
|
||||
def testVBExceptions(self):
|
||||
self.assertRaises(pythoncom.com_error, self._TestEngine, "VBScript", ErrScript)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,83 @@
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
import pythoncom
|
||||
import win32ui
|
||||
from win32com.axscript.server import axsite
|
||||
from win32com.server import util
|
||||
|
||||
version = "0.0.1"
|
||||
|
||||
|
||||
class MySite(axsite.AXSite):
|
||||
def OnScriptError(self, error):
|
||||
print("An error occurred in the Script Code")
|
||||
exc = error.GetExceptionInfo()
|
||||
try:
|
||||
text = error.GetSourceLineText()
|
||||
except:
|
||||
text = "<unknown>"
|
||||
context, line, char = error.GetSourcePosition()
|
||||
print(
|
||||
"Exception: %s (line %d)\n%s\n%s^\n%s"
|
||||
% (exc[1], line, text, " " * (char - 1), exc[2])
|
||||
)
|
||||
|
||||
|
||||
class ObjectModel:
|
||||
_public_methods_ = ["echo", "msgbox"]
|
||||
|
||||
def echo(self, *args):
|
||||
print("".join(map(str, args)))
|
||||
|
||||
def msgbox(self, *args):
|
||||
msg = "".join(map(str, args))
|
||||
win32ui.MessageBox(msg)
|
||||
|
||||
|
||||
def TestEngine():
|
||||
model = {"Test": util.wrap(ObjectModel())}
|
||||
scriptDir = "."
|
||||
site = MySite(model)
|
||||
pyEngine = site._AddEngine("Python")
|
||||
# pyEngine2 = site._AddEngine("Python")
|
||||
vbEngine = site._AddEngine("VBScript")
|
||||
# forthEngine = site._AddEngine("ForthScript")
|
||||
try:
|
||||
# code = open(os.path.join(scriptDir, "debugTest.4ths"),"rb").read()
|
||||
# forthEngine.AddCode(code)
|
||||
code = open(os.path.join(scriptDir, "debugTest.pys"), "rb").read()
|
||||
pyEngine.AddCode(code)
|
||||
code = open(os.path.join(scriptDir, "debugTest.vbs"), "rb").read()
|
||||
vbEngine.AddCode(code)
|
||||
# code = open(os.path.join(scriptDir, "debugTestFail.pys"),"rb").read()
|
||||
# pyEngine2.AddCode(code)
|
||||
|
||||
# from win32com.axdebug import axdebug
|
||||
# sessionProvider=pythoncom.CoCreateInstance(axdebug.CLSID_DefaultDebugSessionProvider,None,pythoncom.CLSCTX_ALL, axdebug.IID_IDebugSessionProvider)
|
||||
# sessionProvider.StartDebugSession(None)
|
||||
|
||||
input("Press enter to continue")
|
||||
# forthEngine.Start()
|
||||
pyEngine.Start() # Actually run the Python code
|
||||
vbEngine.Start() # Actually run the VB code
|
||||
except pythoncom.com_error as details:
|
||||
print(f"Script failed: {details[1]} (0x{details[0]:x})")
|
||||
# Now run the code expected to fail!
|
||||
# try:
|
||||
# pyEngine2.Start() # Actually run the Python code that fails!
|
||||
# print("Script code worked when it should have failed.")
|
||||
# except pythoncom.com_error:
|
||||
# pass
|
||||
|
||||
site._Close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
TestEngine()
|
||||
except:
|
||||
traceback.print_exc()
|
||||
sys.exc_type = sys.exc_value = sys.exc_traceback = None
|
||||
print(pythoncom._GetInterfaceCount(), "com objects still alive")
|
||||
@@ -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__)
|
||||
BIN
Utils/PythonNew32/Lib/site-packages/win32comext/bits/bits.pyd
Normal file
BIN
Utils/PythonNew32/Lib/site-packages/win32comext/bits/bits.pyd
Normal file
Binary file not shown.
@@ -0,0 +1,48 @@
|
||||
# Dump lots of info about BITS jobs.
|
||||
import pythoncom
|
||||
from win32com.bits import bits
|
||||
|
||||
states = {
|
||||
val: name[13:]
|
||||
for name, val in vars(bits).items()
|
||||
if name.startswith("BG_JOB_STATE_")
|
||||
}
|
||||
|
||||
job_types = {
|
||||
val: name[12:]
|
||||
for name, val in vars(bits).items()
|
||||
if name.startswith("BG_JOB_TYPE_")
|
||||
}
|
||||
|
||||
bcm = pythoncom.CoCreateInstance(
|
||||
bits.CLSID_BackgroundCopyManager,
|
||||
None,
|
||||
pythoncom.CLSCTX_LOCAL_SERVER,
|
||||
bits.IID_IBackgroundCopyManager,
|
||||
)
|
||||
|
||||
try:
|
||||
enum = bcm.EnumJobs(bits.BG_JOB_ENUM_ALL_USERS)
|
||||
except pythoncom.error:
|
||||
print("Failed to get jobs for all users - trying for current user")
|
||||
enum = bcm.EnumJobs(0)
|
||||
|
||||
for job in enum:
|
||||
print("Job:", job.GetDisplayName())
|
||||
print("Description:", job.GetDescription())
|
||||
print("Id:", job.GetId())
|
||||
print("State:", states.get(job.GetState()))
|
||||
print("Type:", job_types.get(job.GetType()))
|
||||
print("Owner:", job.GetOwner())
|
||||
print("Errors:", job.GetErrorCount())
|
||||
print("Created/Modified/Finished times:", [str(t) for t in job.GetTimes()])
|
||||
bytes_tot, bytes_xf, files_tot, files_xf = job.GetProgress()
|
||||
print("Bytes: %d complete of %d total" % (bytes_xf, bytes_tot))
|
||||
print("Files: %d complete of %d total" % (files_xf, files_tot))
|
||||
for f in job.EnumFiles():
|
||||
bytes, total, done = f.GetProgress()
|
||||
print(" Remote:", f.GetRemoteName())
|
||||
print(" Local:", f.GetLocalName())
|
||||
print(" Progress: %d of %d bytes - completed=%s)" % (bytes, total, done))
|
||||
print()
|
||||
print()
|
||||
@@ -0,0 +1,119 @@
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
import pythoncom
|
||||
import win32api
|
||||
import win32event
|
||||
from win32com.bits import bits
|
||||
from win32com.server.util import wrap
|
||||
|
||||
TIMEOUT = 200 # ms
|
||||
StopEvent = win32event.CreateEvent(None, 0, 0, None)
|
||||
|
||||
job_name = "bits-pywin32-test"
|
||||
states = {
|
||||
val: (name[13:])
|
||||
for name, val in vars(bits).items()
|
||||
if name.startswith("BG_JOB_STATE_")
|
||||
}
|
||||
|
||||
bcm = pythoncom.CoCreateInstance(
|
||||
bits.CLSID_BackgroundCopyManager,
|
||||
None,
|
||||
pythoncom.CLSCTX_LOCAL_SERVER,
|
||||
bits.IID_IBackgroundCopyManager,
|
||||
)
|
||||
|
||||
|
||||
class BackgroundJobCallback:
|
||||
_com_interfaces_ = [bits.IID_IBackgroundCopyCallback]
|
||||
_public_methods_ = ["JobTransferred", "JobError", "JobModification"]
|
||||
|
||||
def JobTransferred(self, job):
|
||||
print("Job Transferred", job)
|
||||
job.Complete()
|
||||
win32event.SetEvent(StopEvent) # exit msg pump
|
||||
|
||||
def JobError(self, job, error):
|
||||
print("Job Error", job, error)
|
||||
f = error.GetFile()
|
||||
print("While downloading", f.GetRemoteName())
|
||||
print("To", f.GetLocalName())
|
||||
print("The following error happened:")
|
||||
self._print_error(error)
|
||||
if f.GetRemoteName().endswith("missing-favicon.ico"):
|
||||
print("Changing to point to correct file")
|
||||
f2 = f.QueryInterface(bits.IID_IBackgroundCopyFile2)
|
||||
favicon = "https://www.python.org/favicon.ico"
|
||||
print("Changing RemoteName from", f2.GetRemoteName(), "to", favicon)
|
||||
f2.SetRemoteName(favicon)
|
||||
job.Resume()
|
||||
else:
|
||||
job.Cancel()
|
||||
|
||||
def _print_error(self, err):
|
||||
ctx, hresult = err.GetError()
|
||||
try:
|
||||
hresult_msg = win32api.FormatMessage(hresult)
|
||||
except win32api.error:
|
||||
hresult_msg = ""
|
||||
print(f"Context=0x{ctx:x}, hresult=0x{hresult:x} ({hresult_msg})")
|
||||
print(err.GetErrorDescription())
|
||||
|
||||
def JobModification(self, job, reserved):
|
||||
state = job.GetState()
|
||||
print("Job Modification", job.GetDisplayName(), states.get(state))
|
||||
# Need to catch TRANSIENT_ERROR here, as JobError doesn't get
|
||||
# called (apparently) when the error is transient.
|
||||
if state == bits.BG_JOB_STATE_TRANSIENT_ERROR:
|
||||
print("Error details:")
|
||||
err = job.GetError()
|
||||
self._print_error(err)
|
||||
|
||||
|
||||
job = bcm.CreateJob(job_name, bits.BG_JOB_TYPE_DOWNLOAD)
|
||||
|
||||
job.SetNotifyInterface(wrap(BackgroundJobCallback()))
|
||||
job.SetNotifyFlags(
|
||||
bits.BG_NOTIFY_JOB_TRANSFERRED
|
||||
| bits.BG_NOTIFY_JOB_ERROR
|
||||
| bits.BG_NOTIFY_JOB_MODIFICATION
|
||||
)
|
||||
|
||||
|
||||
# The idea here is to intentionally make one of the files fail to be
|
||||
# downloaded. Then the JobError notification will be triggered, where
|
||||
# we do fix the failing file by calling SetRemoteName to a valid URL
|
||||
# and call Resume() on the job, making the job finish successfully.
|
||||
#
|
||||
# Note to self: A domain that cannot be resolved will cause
|
||||
# TRANSIENT_ERROR instead of ERROR, and the JobError notification will
|
||||
# not be triggered! This can bite you during testing depending on how
|
||||
# your DNS is configured. For example, if you use OpenDNS.org's DNS
|
||||
# servers, an invalid hostname will *always* be resolved (they
|
||||
# redirect you to a search page), so be careful when testing.
|
||||
job.AddFile(
|
||||
"https://www.python.org/favicon.ico",
|
||||
os.path.join(tempfile.gettempdir(), "bits-favicon.ico"),
|
||||
)
|
||||
job.AddFile(
|
||||
"https://www.python.org/missing-favicon.ico",
|
||||
os.path.join(tempfile.gettempdir(), "bits-missing-favicon.ico"),
|
||||
)
|
||||
|
||||
for f in job.EnumFiles():
|
||||
print("Downloading", f.GetRemoteName())
|
||||
print("To", f.GetLocalName())
|
||||
|
||||
job.Resume()
|
||||
|
||||
while True:
|
||||
rc = win32event.MsgWaitForMultipleObjects(
|
||||
(StopEvent,), 0, TIMEOUT, win32event.QS_ALLEVENTS
|
||||
)
|
||||
|
||||
if rc == win32event.WAIT_OBJECT_0:
|
||||
break
|
||||
elif rc == win32event.WAIT_OBJECT_0 + 1:
|
||||
if pythoncom.PumpWaitingMessages():
|
||||
break # wm_quit
|
||||
@@ -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.
@@ -0,0 +1 @@
|
||||
# This is a Python package, imported by the win32com test suite.
|
||||
@@ -0,0 +1,60 @@
|
||||
import os
|
||||
import struct
|
||||
|
||||
import pywintypes
|
||||
import win32api
|
||||
import win32com.directsound.directsound as ds
|
||||
import win32event
|
||||
|
||||
|
||||
def wav_header_pack(wfx, datasize):
|
||||
return struct.pack(
|
||||
"<4sl4s4slhhllhh4sl",
|
||||
"RIFF",
|
||||
36 + datasize,
|
||||
"WAVE",
|
||||
"fmt ",
|
||||
16,
|
||||
wfx.wFormatTag,
|
||||
wfx.nChannels,
|
||||
wfx.nSamplesPerSec,
|
||||
wfx.nAvgBytesPerSec,
|
||||
wfx.nBlockAlign,
|
||||
wfx.wBitsPerSample,
|
||||
"data",
|
||||
datasize,
|
||||
)
|
||||
|
||||
|
||||
d = ds.DirectSoundCaptureCreate(None, None)
|
||||
|
||||
sdesc = ds.DSCBUFFERDESC()
|
||||
sdesc.dwBufferBytes = 352800 # 2 seconds
|
||||
sdesc.lpwfxFormat = pywintypes.WAVEFORMATEX()
|
||||
sdesc.lpwfxFormat.wFormatTag = pywintypes.WAVE_FORMAT_PCM
|
||||
sdesc.lpwfxFormat.nChannels = 2
|
||||
sdesc.lpwfxFormat.nSamplesPerSec = 44100
|
||||
sdesc.lpwfxFormat.nAvgBytesPerSec = 176400
|
||||
sdesc.lpwfxFormat.nBlockAlign = 4
|
||||
sdesc.lpwfxFormat.wBitsPerSample = 16
|
||||
|
||||
print(sdesc)
|
||||
print(d)
|
||||
buffer = d.CreateCaptureBuffer(sdesc)
|
||||
|
||||
event = win32event.CreateEvent(None, 0, 0, None)
|
||||
notify = buffer.QueryInterface(ds.IID_IDirectSoundNotify)
|
||||
|
||||
notify.SetNotificationPositions((ds.DSBPN_OFFSETSTOP, event))
|
||||
|
||||
buffer.Start(0)
|
||||
|
||||
win32event.WaitForSingleObject(event, -1)
|
||||
|
||||
data = buffer.Update(0, 352800)
|
||||
|
||||
fname = os.path.join(win32api.GetTempPath(), "test_directsound_record.wav")
|
||||
f = open(fname, "wb")
|
||||
f.write(wav_header_pack(sdesc.lpwfxFormat, 352800))
|
||||
f.write(data)
|
||||
f.close()
|
||||
@@ -0,0 +1,402 @@
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import pythoncom
|
||||
import pywintypes
|
||||
import win32api
|
||||
import win32com.directsound.directsound as ds
|
||||
import win32event
|
||||
from pywin32_testutil import TestSkipped, find_test_fixture
|
||||
|
||||
# next two lines are for for debugging:
|
||||
# import win32com
|
||||
# import directsound as ds
|
||||
|
||||
WAV_FORMAT_PCM = 1
|
||||
WAV_HEADER_SIZE = struct.calcsize("<4sl4s4slhhllhh4sl")
|
||||
|
||||
|
||||
def wav_header_unpack(data):
|
||||
(
|
||||
riff,
|
||||
riffsize,
|
||||
wave,
|
||||
fmt,
|
||||
fmtsize,
|
||||
format,
|
||||
nchannels,
|
||||
samplespersecond,
|
||||
datarate,
|
||||
blockalign,
|
||||
bitspersample,
|
||||
data,
|
||||
datalength,
|
||||
) = struct.unpack("<4sl4s4slhhllhh4sl", data)
|
||||
|
||||
assert riff == b"RIFF", "invalid wav header"
|
||||
|
||||
# fmt chuck is not first chunk, directly followed by data chuck
|
||||
# It is nowhere required that they are, it is just very common
|
||||
assert (
|
||||
fmtsize == 16 and fmt == b"fmt " and data == b"data"
|
||||
), "cannot understand wav header"
|
||||
|
||||
wfx = pywintypes.WAVEFORMATEX()
|
||||
wfx.wFormatTag = format
|
||||
wfx.nChannels = nchannels
|
||||
wfx.nSamplesPerSec = samplespersecond
|
||||
wfx.nAvgBytesPerSec = datarate
|
||||
wfx.nBlockAlign = blockalign
|
||||
wfx.wBitsPerSample = bitspersample
|
||||
|
||||
return wfx, datalength
|
||||
|
||||
|
||||
def wav_header_pack(wfx, datasize):
|
||||
return struct.pack(
|
||||
"<4sl4s4slhhllhh4sl",
|
||||
b"RIFF",
|
||||
36 + datasize,
|
||||
b"WAVE",
|
||||
b"fmt ",
|
||||
16,
|
||||
wfx.wFormatTag,
|
||||
wfx.nChannels,
|
||||
wfx.nSamplesPerSec,
|
||||
wfx.nAvgBytesPerSec,
|
||||
wfx.nBlockAlign,
|
||||
wfx.wBitsPerSample,
|
||||
b"data",
|
||||
datasize,
|
||||
)
|
||||
|
||||
|
||||
class WAVEFORMATTest(unittest.TestCase):
|
||||
def test_1_Type(self):
|
||||
"WAVEFORMATEX type"
|
||||
w = pywintypes.WAVEFORMATEX()
|
||||
self.assertTrue(isinstance(w, pywintypes.WAVEFORMATEXType))
|
||||
|
||||
def test_2_Attr(self):
|
||||
"WAVEFORMATEX attribute access"
|
||||
# A wav header for a soundfile from a CD should look like this...
|
||||
w = pywintypes.WAVEFORMATEX()
|
||||
w.wFormatTag = pywintypes.WAVE_FORMAT_PCM
|
||||
w.nChannels = 2
|
||||
w.nSamplesPerSec = 44100
|
||||
w.nAvgBytesPerSec = 176400
|
||||
w.nBlockAlign = 4
|
||||
w.wBitsPerSample = 16
|
||||
|
||||
self.assertTrue(w.wFormatTag == 1)
|
||||
self.assertTrue(w.nChannels == 2)
|
||||
self.assertTrue(w.nSamplesPerSec == 44100)
|
||||
self.assertTrue(w.nAvgBytesPerSec == 176400)
|
||||
self.assertTrue(w.nBlockAlign == 4)
|
||||
self.assertTrue(w.wBitsPerSample == 16)
|
||||
|
||||
|
||||
class DSCAPSTest(unittest.TestCase):
|
||||
def test_1_Type(self):
|
||||
"DSCAPS type"
|
||||
c = ds.DSCAPS()
|
||||
self.assertTrue(isinstance(c, ds.DSCAPSType))
|
||||
|
||||
def test_2_Attr(self):
|
||||
"DSCAPS attribute access"
|
||||
c = ds.DSCAPS()
|
||||
c.dwFlags = 1
|
||||
c.dwMinSecondarySampleRate = 2
|
||||
c.dwMaxSecondarySampleRate = 3
|
||||
c.dwPrimaryBuffers = 4
|
||||
c.dwMaxHwMixingAllBuffers = 5
|
||||
c.dwMaxHwMixingStaticBuffers = 6
|
||||
c.dwMaxHwMixingStreamingBuffers = 7
|
||||
c.dwFreeHwMixingAllBuffers = 8
|
||||
c.dwFreeHwMixingStaticBuffers = 9
|
||||
c.dwFreeHwMixingStreamingBuffers = 10
|
||||
c.dwMaxHw3DAllBuffers = 11
|
||||
c.dwMaxHw3DStaticBuffers = 12
|
||||
c.dwMaxHw3DStreamingBuffers = 13
|
||||
c.dwFreeHw3DAllBuffers = 14
|
||||
c.dwFreeHw3DStaticBuffers = 15
|
||||
c.dwFreeHw3DStreamingBuffers = 16
|
||||
c.dwTotalHwMemBytes = 17
|
||||
c.dwFreeHwMemBytes = 18
|
||||
c.dwMaxContigFreeHwMemBytes = 19
|
||||
c.dwUnlockTransferRateHwBuffers = 20
|
||||
c.dwPlayCpuOverheadSwBuffers = 21
|
||||
|
||||
self.assertTrue(c.dwFlags == 1)
|
||||
self.assertTrue(c.dwMinSecondarySampleRate == 2)
|
||||
self.assertTrue(c.dwMaxSecondarySampleRate == 3)
|
||||
self.assertTrue(c.dwPrimaryBuffers == 4)
|
||||
self.assertTrue(c.dwMaxHwMixingAllBuffers == 5)
|
||||
self.assertTrue(c.dwMaxHwMixingStaticBuffers == 6)
|
||||
self.assertTrue(c.dwMaxHwMixingStreamingBuffers == 7)
|
||||
self.assertTrue(c.dwFreeHwMixingAllBuffers == 8)
|
||||
self.assertTrue(c.dwFreeHwMixingStaticBuffers == 9)
|
||||
self.assertTrue(c.dwFreeHwMixingStreamingBuffers == 10)
|
||||
self.assertTrue(c.dwMaxHw3DAllBuffers == 11)
|
||||
self.assertTrue(c.dwMaxHw3DStaticBuffers == 12)
|
||||
self.assertTrue(c.dwMaxHw3DStreamingBuffers == 13)
|
||||
self.assertTrue(c.dwFreeHw3DAllBuffers == 14)
|
||||
self.assertTrue(c.dwFreeHw3DStaticBuffers == 15)
|
||||
self.assertTrue(c.dwFreeHw3DStreamingBuffers == 16)
|
||||
self.assertTrue(c.dwTotalHwMemBytes == 17)
|
||||
self.assertTrue(c.dwFreeHwMemBytes == 18)
|
||||
self.assertTrue(c.dwMaxContigFreeHwMemBytes == 19)
|
||||
self.assertTrue(c.dwUnlockTransferRateHwBuffers == 20)
|
||||
self.assertTrue(c.dwPlayCpuOverheadSwBuffers == 21)
|
||||
|
||||
|
||||
class DSBCAPSTest(unittest.TestCase):
|
||||
def test_1_Type(self):
|
||||
"DSBCAPS type"
|
||||
c = ds.DSBCAPS()
|
||||
self.assertTrue(isinstance(c, ds.DSBCAPSType))
|
||||
|
||||
def test_2_Attr(self):
|
||||
"DSBCAPS attribute access"
|
||||
c = ds.DSBCAPS()
|
||||
c.dwFlags = 1
|
||||
c.dwBufferBytes = 2
|
||||
c.dwUnlockTransferRate = 3
|
||||
c.dwPlayCpuOverhead = 4
|
||||
|
||||
self.assertTrue(c.dwFlags == 1)
|
||||
self.assertTrue(c.dwBufferBytes == 2)
|
||||
self.assertTrue(c.dwUnlockTransferRate == 3)
|
||||
self.assertTrue(c.dwPlayCpuOverhead == 4)
|
||||
|
||||
|
||||
class DSCCAPSTest(unittest.TestCase):
|
||||
def test_1_Type(self):
|
||||
"DSCCAPS type"
|
||||
c = ds.DSCCAPS()
|
||||
self.assertTrue(isinstance(c, ds.DSCCAPSType))
|
||||
|
||||
def test_2_Attr(self):
|
||||
"DSCCAPS attribute access"
|
||||
c = ds.DSCCAPS()
|
||||
c.dwFlags = 1
|
||||
c.dwFormats = 2
|
||||
c.dwChannels = 4
|
||||
|
||||
self.assertTrue(c.dwFlags == 1)
|
||||
self.assertTrue(c.dwFormats == 2)
|
||||
self.assertTrue(c.dwChannels == 4)
|
||||
|
||||
|
||||
class DSCBCAPSTest(unittest.TestCase):
|
||||
def test_1_Type(self):
|
||||
"DSCBCAPS type"
|
||||
c = ds.DSCBCAPS()
|
||||
self.assertTrue(isinstance(c, ds.DSCBCAPSType))
|
||||
|
||||
def test_2_Attr(self):
|
||||
"DSCBCAPS attribute access"
|
||||
c = ds.DSCBCAPS()
|
||||
c.dwFlags = 1
|
||||
c.dwBufferBytes = 2
|
||||
|
||||
self.assertTrue(c.dwFlags == 1)
|
||||
self.assertTrue(c.dwBufferBytes == 2)
|
||||
|
||||
|
||||
class DSBUFFERDESCTest(unittest.TestCase):
|
||||
def test_1_Type(self):
|
||||
"DSBUFFERDESC type"
|
||||
c = ds.DSBUFFERDESC()
|
||||
self.assertTrue(isinstance(c, ds.DSBUFFERDESCType))
|
||||
|
||||
def test_2_Attr(self):
|
||||
"DSBUFFERDESC attribute access"
|
||||
c = ds.DSBUFFERDESC()
|
||||
c.dwFlags = 1
|
||||
c.dwBufferBytes = 2
|
||||
c.lpwfxFormat = pywintypes.WAVEFORMATEX()
|
||||
c.lpwfxFormat.wFormatTag = pywintypes.WAVE_FORMAT_PCM
|
||||
c.lpwfxFormat.nChannels = 2
|
||||
c.lpwfxFormat.nSamplesPerSec = 44100
|
||||
c.lpwfxFormat.nAvgBytesPerSec = 176400
|
||||
c.lpwfxFormat.nBlockAlign = 4
|
||||
c.lpwfxFormat.wBitsPerSample = 16
|
||||
|
||||
self.assertTrue(c.dwFlags == 1)
|
||||
self.assertTrue(c.dwBufferBytes == 2)
|
||||
self.assertTrue(c.lpwfxFormat.wFormatTag == 1)
|
||||
self.assertTrue(c.lpwfxFormat.nChannels == 2)
|
||||
self.assertTrue(c.lpwfxFormat.nSamplesPerSec == 44100)
|
||||
self.assertTrue(c.lpwfxFormat.nAvgBytesPerSec == 176400)
|
||||
self.assertTrue(c.lpwfxFormat.nBlockAlign == 4)
|
||||
self.assertTrue(c.lpwfxFormat.wBitsPerSample == 16)
|
||||
|
||||
def invalid_format(self, c):
|
||||
c.lpwfxFormat = 17
|
||||
|
||||
def test_3_invalid_format(self):
|
||||
"DSBUFFERDESC invalid lpwfxFormat assignment"
|
||||
c = ds.DSBUFFERDESC()
|
||||
self.assertRaises(ValueError, self.invalid_format, c)
|
||||
|
||||
|
||||
class DSCBUFFERDESCTest(unittest.TestCase):
|
||||
def test_1_Type(self):
|
||||
"DSCBUFFERDESC type"
|
||||
c = ds.DSCBUFFERDESC()
|
||||
self.assertTrue(isinstance(c, ds.DSCBUFFERDESCType))
|
||||
|
||||
def test_2_Attr(self):
|
||||
"DSCBUFFERDESC attribute access"
|
||||
c = ds.DSCBUFFERDESC()
|
||||
c.dwFlags = 1
|
||||
c.dwBufferBytes = 2
|
||||
c.lpwfxFormat = pywintypes.WAVEFORMATEX()
|
||||
c.lpwfxFormat.wFormatTag = pywintypes.WAVE_FORMAT_PCM
|
||||
c.lpwfxFormat.nChannels = 2
|
||||
c.lpwfxFormat.nSamplesPerSec = 44100
|
||||
c.lpwfxFormat.nAvgBytesPerSec = 176400
|
||||
c.lpwfxFormat.nBlockAlign = 4
|
||||
c.lpwfxFormat.wBitsPerSample = 16
|
||||
|
||||
self.assertTrue(c.dwFlags == 1)
|
||||
self.assertTrue(c.dwBufferBytes == 2)
|
||||
self.assertTrue(c.lpwfxFormat.wFormatTag == 1)
|
||||
self.assertTrue(c.lpwfxFormat.nChannels == 2)
|
||||
self.assertTrue(c.lpwfxFormat.nSamplesPerSec == 44100)
|
||||
self.assertTrue(c.lpwfxFormat.nAvgBytesPerSec == 176400)
|
||||
self.assertTrue(c.lpwfxFormat.nBlockAlign == 4)
|
||||
self.assertTrue(c.lpwfxFormat.wBitsPerSample == 16)
|
||||
|
||||
def invalid_format(self, c):
|
||||
c.lpwfxFormat = 17
|
||||
|
||||
def test_3_invalid_format(self):
|
||||
"DSCBUFFERDESC invalid lpwfxFormat assignment"
|
||||
c = ds.DSCBUFFERDESC()
|
||||
self.assertRaises(ValueError, self.invalid_format, c)
|
||||
|
||||
|
||||
class DirectSoundTest(unittest.TestCase):
|
||||
# basic tests - mostly just exercise the functions
|
||||
def testEnumerate(self):
|
||||
"""DirectSoundEnumerate() sanity tests"""
|
||||
|
||||
devices = ds.DirectSoundEnumerate()
|
||||
# this might fail on machines without a sound card
|
||||
self.assertTrue(len(devices))
|
||||
# if we have an entry, it must be a tuple of size 3
|
||||
self.assertTrue(len(devices[0]) == 3)
|
||||
|
||||
def testCreate(self):
|
||||
"""DirectSoundCreate()"""
|
||||
try:
|
||||
d = ds.DirectSoundCreate(None, None)
|
||||
except pythoncom.com_error as exc:
|
||||
if exc.hresult != ds.DSERR_NODRIVER:
|
||||
raise
|
||||
raise TestSkipped(exc)
|
||||
|
||||
def testPlay(self):
|
||||
"""Mesdames et Messieurs, la cour de Devin Dazzle"""
|
||||
# relative to 'testall.py' in the win32com test suite.
|
||||
extra = os.path.join(
|
||||
os.path.dirname(sys.argv[0]), "../../win32comext/directsound/test"
|
||||
)
|
||||
|
||||
fname = find_test_fixture("01-Intro.wav", extra)
|
||||
|
||||
with open(fname, "rb") as f:
|
||||
hdr = f.read(WAV_HEADER_SIZE)
|
||||
wfx, size = wav_header_unpack(hdr)
|
||||
|
||||
try:
|
||||
d = ds.DirectSoundCreate(None, None)
|
||||
except pythoncom.com_error as exc:
|
||||
if exc.hresult != ds.DSERR_NODRIVER:
|
||||
raise
|
||||
raise TestSkipped(exc)
|
||||
d.SetCooperativeLevel(None, ds.DSSCL_PRIORITY)
|
||||
|
||||
sdesc = ds.DSBUFFERDESC()
|
||||
sdesc.dwFlags = ds.DSBCAPS_STICKYFOCUS | ds.DSBCAPS_CTRLPOSITIONNOTIFY
|
||||
sdesc.dwBufferBytes = size
|
||||
sdesc.lpwfxFormat = wfx
|
||||
|
||||
buffer = d.CreateSoundBuffer(sdesc, None)
|
||||
|
||||
event = win32event.CreateEvent(None, 0, 0, None)
|
||||
notify = buffer.QueryInterface(ds.IID_IDirectSoundNotify)
|
||||
|
||||
notify.SetNotificationPositions((ds.DSBPN_OFFSETSTOP, event))
|
||||
|
||||
buffer.Update(0, f.read(size))
|
||||
|
||||
buffer.Play(0)
|
||||
|
||||
win32event.WaitForSingleObject(event, -1)
|
||||
|
||||
|
||||
class DirectSoundCaptureTest(unittest.TestCase):
|
||||
# basic tests - mostly just exercise the functions
|
||||
def testEnumerate(self):
|
||||
"""DirectSoundCaptureEnumerate() sanity tests"""
|
||||
|
||||
devices = ds.DirectSoundCaptureEnumerate()
|
||||
# this might fail on machines without a sound card
|
||||
self.assertTrue(len(devices))
|
||||
# if we have an entry, it must be a tuple of size 3
|
||||
self.assertTrue(len(devices[0]) == 3)
|
||||
|
||||
def testCreate(self):
|
||||
"""DirectSoundCreate()"""
|
||||
try:
|
||||
d = ds.DirectSoundCaptureCreate(None, None)
|
||||
except pythoncom.com_error as exc:
|
||||
if exc.hresult != ds.DSERR_NODRIVER:
|
||||
raise
|
||||
raise TestSkipped(exc)
|
||||
|
||||
def testRecord(self):
|
||||
try:
|
||||
d = ds.DirectSoundCaptureCreate(None, None)
|
||||
except pythoncom.com_error as exc:
|
||||
if exc.hresult != ds.DSERR_NODRIVER:
|
||||
raise
|
||||
raise TestSkipped(exc)
|
||||
|
||||
sdesc = ds.DSCBUFFERDESC()
|
||||
sdesc.dwBufferBytes = 352800 # 2 seconds
|
||||
sdesc.lpwfxFormat = pywintypes.WAVEFORMATEX()
|
||||
sdesc.lpwfxFormat.wFormatTag = pywintypes.WAVE_FORMAT_PCM
|
||||
sdesc.lpwfxFormat.nChannels = 2
|
||||
sdesc.lpwfxFormat.nSamplesPerSec = 44100
|
||||
sdesc.lpwfxFormat.nAvgBytesPerSec = 176400
|
||||
sdesc.lpwfxFormat.nBlockAlign = 4
|
||||
sdesc.lpwfxFormat.wBitsPerSample = 16
|
||||
|
||||
buffer = d.CreateCaptureBuffer(sdesc)
|
||||
|
||||
event = win32event.CreateEvent(None, 0, 0, None)
|
||||
notify = buffer.QueryInterface(ds.IID_IDirectSoundNotify)
|
||||
|
||||
notify.SetNotificationPositions((ds.DSBPN_OFFSETSTOP, event))
|
||||
|
||||
buffer.Start(0)
|
||||
|
||||
win32event.WaitForSingleObject(event, -1)
|
||||
event.Close()
|
||||
|
||||
data = buffer.Update(0, 352800)
|
||||
fname = os.path.join(win32api.GetTempPath(), "test_directsound_record.wav")
|
||||
f = open(fname, "wb")
|
||||
f.write(wav_header_pack(sdesc.lpwfxFormat, 352800))
|
||||
f.write(data)
|
||||
f.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1 @@
|
||||
# empty file to designate as a package.
|
||||
@@ -0,0 +1,300 @@
|
||||
import pythoncom
|
||||
import pywintypes
|
||||
from win32com import storagecon
|
||||
from win32com.ifilter import ifilter
|
||||
from win32com.ifilter.ifiltercon import *
|
||||
|
||||
|
||||
class FileParser:
|
||||
# Property IDs for the Storage Property Set
|
||||
PIDS_BODY = 0x00000013
|
||||
|
||||
# property IDs for HTML Storage Property Set
|
||||
PIDH_DESCRIPTION = "DESCRIPTION"
|
||||
PIDH_HREF = "A.HREF"
|
||||
PIDH_IMGSRC = "IMG.SRC"
|
||||
|
||||
# conversion map to convert ifilter properties to more user friendly names
|
||||
propertyToName = {
|
||||
PSGUID_STORAGE: {PIDS_BODY: "body"},
|
||||
PSGUID_SUMMARYINFORMATION: {
|
||||
PIDSI_TITLE: "title",
|
||||
PIDSI_SUBJECT: "description",
|
||||
PIDSI_AUTHOR: "author",
|
||||
PIDSI_KEYWORDS: "keywords",
|
||||
PIDSI_COMMENTS: "comments",
|
||||
},
|
||||
PSGUID_HTMLINFORMATION: {PIDH_DESCRIPTION: "description"},
|
||||
PSGUID_HTML2_INFORMATION: {PIDH_HREF: "href", PIDH_IMGSRC: "img"},
|
||||
}
|
||||
|
||||
def __init__(self, verbose=False):
|
||||
self.f = None
|
||||
self.stg = None
|
||||
self.verbose = verbose
|
||||
|
||||
def Close(self):
|
||||
self.f = None
|
||||
self.stg = None
|
||||
|
||||
def Parse(self, fileName, maxErrors=10):
|
||||
properties = {}
|
||||
|
||||
try:
|
||||
self._bind_to_filter(fileName)
|
||||
try:
|
||||
flags = self.f.Init(
|
||||
IFILTER_INIT_APPLY_INDEX_ATTRIBUTES
|
||||
| IFILTER_INIT_APPLY_OTHER_ATTRIBUTES
|
||||
)
|
||||
if flags == IFILTER_FLAGS_OLE_PROPERTIES and self.stg is not None:
|
||||
self._trace("filter requires to get properities via ole")
|
||||
self._get_properties(properties)
|
||||
|
||||
errCnt = 0
|
||||
while True:
|
||||
try:
|
||||
# each chunk returns a tuple with the following:-
|
||||
# idChunk = The chunk identifier. each chunk has a unique identifier
|
||||
# breakType = The type of break that separates the previous chunk from the current chunk. Values are:-
|
||||
# CHUNK_NO_BREAK=0,CHUNK_EOW=1,CHUNK_EOS= 2,CHUNK_EOP= 3,CHUNK_EOC= 4
|
||||
# flags = Flags indicate whether this chunk contains a text-type or a value-type property
|
||||
# locale = The language and sublanguage associated with a chunk of text
|
||||
# attr = A tuple containing the property to be applied to the chunk. Tuple is (propertyset GUID, property ID)
|
||||
# Property ID can be a number or string
|
||||
# idChunkSource = The ID of the source of a chunk. The value of the idChunkSource member depends on the nature of the chunk
|
||||
# startSource = The offset from which the source text for a derived chunk starts in the source chunk
|
||||
# lenSource = The length in characters of the source text from which the current chunk was derived.
|
||||
# A zero value signifies character-by-character correspondence between the source text and the derived text.
|
||||
|
||||
(
|
||||
idChunk,
|
||||
breakType,
|
||||
flags,
|
||||
locale,
|
||||
attr,
|
||||
idChunkSource,
|
||||
startSource,
|
||||
lenSource,
|
||||
) = self.f.GetChunk()
|
||||
self._trace(
|
||||
"Chunk details:",
|
||||
idChunk,
|
||||
breakType,
|
||||
flags,
|
||||
locale,
|
||||
attr,
|
||||
idChunkSource,
|
||||
startSource,
|
||||
lenSource,
|
||||
)
|
||||
|
||||
# attempt to map each property to a more user friendly name. If we don't know what it is just return
|
||||
# the set guid and property id. (note: the id can be a number or a string.
|
||||
propSet = self.propertyToName.get(attr[0])
|
||||
if propSet:
|
||||
propName = propSet.get(attr[1], "{}:{}".format(*attr))
|
||||
else:
|
||||
propName = "{}:{}".format(*attr)
|
||||
|
||||
except pythoncom.com_error as e:
|
||||
if e[0] == FILTER_E_END_OF_CHUNKS:
|
||||
# we have read all the chunks
|
||||
break
|
||||
elif e[0] in [
|
||||
FILTER_E_EMBEDDING_UNAVAILABLE,
|
||||
FILTER_E_LINK_UNAVAILABLE,
|
||||
]:
|
||||
# the next chunk can't be read. Also keep track of the number of times we
|
||||
# fail as some filters (ie. the Msoft office ones can get stuck here)
|
||||
errCnt += 1
|
||||
if errCnt > maxErrors:
|
||||
raise
|
||||
else:
|
||||
continue
|
||||
elif e[0] == FILTER_E_ACCESS:
|
||||
self._trace("Access denied")
|
||||
raise
|
||||
elif e[0] == FILTER_E_PASSWORD:
|
||||
self._trace("Password required")
|
||||
raise
|
||||
else:
|
||||
# any other type of error really can't be recovered from
|
||||
raise
|
||||
|
||||
# reset consecutive errors (some filters may get stuck in a lopp if embedding or link failures occurs
|
||||
errCnt = 0
|
||||
|
||||
if flags == CHUNK_TEXT:
|
||||
# it's a text segment - get all available text for this chunk.
|
||||
body_chunks = properties.setdefault(propName, [])
|
||||
self._get_text(body_chunks)
|
||||
elif flags == CHUNK_VALUE:
|
||||
# it's a data segment - get the value
|
||||
properties[propName] = self.f.GetValue()
|
||||
else:
|
||||
self._trace("Unknown flag returned by GetChunk:", flags)
|
||||
finally:
|
||||
self.Close()
|
||||
|
||||
except pythoncom.com_error as e:
|
||||
self._trace("ERROR processing file", e)
|
||||
raise
|
||||
|
||||
return properties
|
||||
|
||||
def _bind_to_filter(self, fileName):
|
||||
"""
|
||||
See if the file is a structured storage file or a normal file
|
||||
and then return an ifilter interface by calling the appropriate bind/load function
|
||||
"""
|
||||
if pythoncom.StgIsStorageFile(fileName):
|
||||
self.stg = pythoncom.StgOpenStorage(
|
||||
fileName, None, storagecon.STGM_READ | storagecon.STGM_SHARE_DENY_WRITE
|
||||
)
|
||||
try:
|
||||
self.f = ifilter.BindIFilterFromStorage(self.stg)
|
||||
except pythoncom.com_error as e:
|
||||
if (
|
||||
e[0] == -2147467262
|
||||
): # 0x80004002: # no interface, try the load interface (this happens for some MSoft files)
|
||||
self.f = ifilter.LoadIFilter(fileName)
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
self.f = ifilter.LoadIFilter(fileName)
|
||||
self.stg = None
|
||||
|
||||
def _get_text(self, body_chunks):
|
||||
"""
|
||||
Gets all the text for a particular chunk. We need to keep calling get text till all the
|
||||
segments for this chunk are retrieved
|
||||
"""
|
||||
while True:
|
||||
try:
|
||||
body_chunks.append(self.f.GetText())
|
||||
except pythoncom.com_error as e:
|
||||
if e[0] in [
|
||||
FILTER_E_NO_MORE_TEXT,
|
||||
FILTER_E_NO_MORE_TEXT,
|
||||
FILTER_E_NO_TEXT,
|
||||
]:
|
||||
break
|
||||
else:
|
||||
raise # not one of the values we were expecting
|
||||
|
||||
def _get_properties(self, properties):
|
||||
"""
|
||||
Use OLE property sets to get base properties
|
||||
"""
|
||||
try:
|
||||
pss = self.stg.QueryInterface(pythoncom.IID_IPropertySetStorage)
|
||||
except pythoncom.com_error as e:
|
||||
self._trace("No Property information could be retrieved", e)
|
||||
return
|
||||
|
||||
ps = pss.Open(PSGUID_SUMMARYINFORMATION)
|
||||
|
||||
props = (
|
||||
PIDSI_TITLE,
|
||||
PIDSI_SUBJECT,
|
||||
PIDSI_AUTHOR,
|
||||
PIDSI_KEYWORDS,
|
||||
PIDSI_COMMENTS,
|
||||
)
|
||||
|
||||
title, subject, author, keywords, comments = ps.ReadMultiple(props)
|
||||
if title is not None:
|
||||
properties["title"] = title
|
||||
if subject is not None:
|
||||
properties["description"] = subject
|
||||
if author is not None:
|
||||
properties["author"] = author
|
||||
if keywords is not None:
|
||||
properties["keywords"] = keywords
|
||||
if comments is not None:
|
||||
properties["comments"] = comments
|
||||
|
||||
def _trace(self, *args):
|
||||
if self.verbose:
|
||||
ret = " ".join([str(arg) for arg in args])
|
||||
try:
|
||||
print(ret)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
def _usage():
|
||||
import os
|
||||
|
||||
print(f"Usage: {os.path.basename(sys.argv[0])} filename [verbose [dumpbody]]")
|
||||
print()
|
||||
print("Where:-")
|
||||
print("filename = name of the file to extract text & properties from")
|
||||
print("verbose = 1=debug output, 0=no debug output (default=0)")
|
||||
print("dumpbody = 1=print text content, 0=don't print content (default=1)")
|
||||
print()
|
||||
print("e.g. to dump a word file called spam.doc go:- filterDemo.py spam.doc")
|
||||
print()
|
||||
print("by default .htm, .txt, .doc, .dot, .xls, .xlt, .ppt are supported")
|
||||
print("you can filter .pdf's by downloading adobes ifilter component. ")
|
||||
print(
|
||||
"(currently found at https://download.adobe.com/pub/adobe/acrobat/win/all/ifilter50.exe)."
|
||||
)
|
||||
print("ifilters for other filetypes are also available.")
|
||||
print()
|
||||
print(
|
||||
"This extension is only supported on win2000 & winXP - because thats the only"
|
||||
)
|
||||
print("place the ifilter stuff is supported. For more info on the API check out ")
|
||||
print("MSDN under ifilters")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import operator
|
||||
import sys
|
||||
|
||||
fName = ""
|
||||
verbose = False
|
||||
bDumpBody = True
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
_usage()
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
fName = sys.argv[1]
|
||||
verbose = sys.argv[2] != "0"
|
||||
bDumpBody = sys.argv[3] != "0"
|
||||
except:
|
||||
pass
|
||||
|
||||
p = FileParser(verbose)
|
||||
propMap = p.Parse(fName)
|
||||
|
||||
if bDumpBody:
|
||||
print("Body")
|
||||
ch = " ".join(propMap.get("body", []))
|
||||
try:
|
||||
print(ch)
|
||||
except UnicodeError:
|
||||
print(ch.encode("iso8859-1", "ignore"))
|
||||
|
||||
print("Properties")
|
||||
for propName, propValue in propMap.items():
|
||||
print(propName, ":", end=" ")
|
||||
if propName == "body":
|
||||
print(
|
||||
"<%s length: %d>"
|
||||
% (
|
||||
propName,
|
||||
reduce(operator.add, [len(p) for p in propValue]),
|
||||
)
|
||||
)
|
||||
elif isinstance(propValue, list):
|
||||
print()
|
||||
for pv in propValue:
|
||||
print(pv)
|
||||
else:
|
||||
print(propValue)
|
||||
print()
|
||||
Binary file not shown.
@@ -0,0 +1,110 @@
|
||||
# manual stuff
|
||||
from pywintypes import IID
|
||||
|
||||
PSGUID_STORAGE = IID("{B725F130-47EF-101A-A5F1-02608C9EEBAC}")
|
||||
PSGUID_SUMMARYINFORMATION = IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}")
|
||||
PSGUID_HTMLINFORMATION = IID("{D1B5D3F0-C0B3-11CF-9A92-00A0C908DBF1}")
|
||||
PSGUID_HTML2_INFORMATION = IID("{C82BF597-B831-11D0-B733-00AA00A1EBD2}")
|
||||
|
||||
IFILTER_INIT_CANON_PARAGRAPHS = 1
|
||||
IFILTER_INIT_HARD_LINE_BREAKS = 2
|
||||
IFILTER_INIT_CANON_HYPHENS = 4
|
||||
IFILTER_INIT_CANON_SPACES = 8
|
||||
IFILTER_INIT_APPLY_INDEX_ATTRIBUTES = 16
|
||||
IFILTER_INIT_APPLY_CRAWL_ATTRIBUTES = 256
|
||||
IFILTER_INIT_APPLY_OTHER_ATTRIBUTES = 32
|
||||
IFILTER_INIT_INDEXING_ONLY = 64
|
||||
IFILTER_INIT_SEARCH_LINKS = 128
|
||||
IFILTER_INIT_FILTER_OWNED_VALUE_OK = 512
|
||||
|
||||
IFILTER_FLAGS_OLE_PROPERTIES = 1
|
||||
|
||||
CHUNK_TEXT = 0x1
|
||||
CHUNK_VALUE = 0x2
|
||||
CHUNK_NO_BREAK = 0
|
||||
CHUNK_EOW = 1
|
||||
CHUNK_EOS = 2
|
||||
CHUNK_EOP = 3
|
||||
CHUNK_EOC = 4
|
||||
|
||||
NOT_AN_ERROR = 0x00080000
|
||||
FILTER_E_END_OF_CHUNKS = -2147215616
|
||||
FILTER_E_NO_MORE_TEXT = -2147215615
|
||||
FILTER_E_NO_MORE_VALUES = -2147215614
|
||||
FILTER_E_ACCESS = -2147215613
|
||||
FILTER_W_MONIKER_CLIPPED = 0x00041704
|
||||
FILTER_E_NO_TEXT = -2147215611
|
||||
FILTER_E_NO_VALUES = -2147215610
|
||||
FILTER_E_EMBEDDING_UNAVAILABLE = -2147215609
|
||||
FILTER_E_LINK_UNAVAILABLE = -2147215608
|
||||
FILTER_S_LAST_TEXT = 0x00041709
|
||||
FILTER_S_LAST_VALUES = 0x0004170A
|
||||
FILTER_E_PASSWORD = -2147215605
|
||||
FILTER_E_UNKNOWNFORMAT = -2147215604
|
||||
|
||||
# Generated by h2py from PropIdl.h
|
||||
PROPSETFLAG_DEFAULT = 0
|
||||
PROPSETFLAG_NONSIMPLE = 1
|
||||
PROPSETFLAG_ANSI = 2
|
||||
PROPSETFLAG_UNBUFFERED = 4
|
||||
PROPSETFLAG_CASE_SENSITIVE = 8
|
||||
PROPSET_BEHAVIOR_CASE_SENSITIVE = 1
|
||||
PID_DICTIONARY = 0
|
||||
PID_CODEPAGE = 0x1
|
||||
PID_FIRST_USABLE = 0x2
|
||||
PID_FIRST_NAME_DEFAULT = 0xFFF
|
||||
PID_LOCALE = -2147483648
|
||||
PID_MODIFY_TIME = -2147483647
|
||||
PID_SECURITY = -2147483646
|
||||
PID_BEHAVIOR = -2147483645
|
||||
PID_ILLEGAL = -1
|
||||
PID_MIN_READONLY = -2147483648
|
||||
PID_MAX_READONLY = -1073741825
|
||||
PIDDI_THUMBNAIL = 0x00000002
|
||||
PIDSI_TITLE = 0x00000002
|
||||
PIDSI_SUBJECT = 0x00000003
|
||||
PIDSI_AUTHOR = 0x00000004
|
||||
PIDSI_KEYWORDS = 0x00000005
|
||||
PIDSI_COMMENTS = 0x00000006
|
||||
PIDSI_TEMPLATE = 0x00000007
|
||||
PIDSI_LASTAUTHOR = 0x00000008
|
||||
PIDSI_REVNUMBER = 0x00000009
|
||||
PIDSI_EDITTIME = 0x0000000A
|
||||
PIDSI_LASTPRINTED = 0x0000000B
|
||||
PIDSI_CREATE_DTM = 0x0000000C
|
||||
PIDSI_LASTSAVE_DTM = 0x0000000D
|
||||
PIDSI_PAGECOUNT = 0x0000000E
|
||||
PIDSI_WORDCOUNT = 0x0000000F
|
||||
PIDSI_CHARCOUNT = 0x00000010
|
||||
PIDSI_THUMBNAIL = 0x00000011
|
||||
PIDSI_APPNAME = 0x00000012
|
||||
PIDSI_DOC_SECURITY = 0x00000013
|
||||
PIDDSI_CATEGORY = 0x00000002
|
||||
PIDDSI_PRESFORMAT = 0x00000003
|
||||
PIDDSI_BYTECOUNT = 0x00000004
|
||||
PIDDSI_LINECOUNT = 0x00000005
|
||||
PIDDSI_PARCOUNT = 0x00000006
|
||||
PIDDSI_SLIDECOUNT = 0x00000007
|
||||
PIDDSI_NOTECOUNT = 0x00000008
|
||||
PIDDSI_HIDDENCOUNT = 0x00000009
|
||||
PIDDSI_MMCLIPCOUNT = 0x0000000A
|
||||
PIDDSI_SCALE = 0x0000000B
|
||||
PIDDSI_HEADINGPAIR = 0x0000000C
|
||||
PIDDSI_DOCPARTS = 0x0000000D
|
||||
PIDDSI_MANAGER = 0x0000000E
|
||||
PIDDSI_COMPANY = 0x0000000F
|
||||
PIDDSI_LINKSDIRTY = 0x00000010
|
||||
PIDMSI_EDITOR = 0x00000002
|
||||
PIDMSI_SUPPLIER = 0x00000003
|
||||
PIDMSI_SOURCE = 0x00000004
|
||||
PIDMSI_SEQUENCE_NO = 0x00000005
|
||||
PIDMSI_PROJECT = 0x00000006
|
||||
PIDMSI_STATUS = 0x00000007
|
||||
PIDMSI_OWNER = 0x00000008
|
||||
PIDMSI_RATING = 0x00000009
|
||||
PIDMSI_PRODUCTION = 0x0000000A
|
||||
PIDMSI_COPYRIGHT = 0x0000000B
|
||||
PRSPEC_INVALID = -1
|
||||
PRSPEC_LPWSTR = 0
|
||||
PRSPEC_PROPID = 1
|
||||
CCH_MAX_PROPSTG_NAME = 31
|
||||
@@ -0,0 +1,4 @@
|
||||
# See if we have a special directory for the binaries (for developers)
|
||||
import win32com
|
||||
|
||||
win32com.__PackageSupportBuildPath__(__path__)
|
||||
@@ -0,0 +1,261 @@
|
||||
INET_E_USE_DEFAULT_PROTOCOLHANDLER = -2146697199 # _HRESULT_TYPEDEF_(0x800C0011L)
|
||||
INET_E_USE_DEFAULT_SETTING = -2146697198 # _HRESULT_TYPEDEF_(0x800C0012L)
|
||||
INET_E_DEFAULT_ACTION = INET_E_USE_DEFAULT_PROTOCOLHANDLER
|
||||
INET_E_QUERYOPTION_UNKNOWN = -2146697197 # _HRESULT_TYPEDEF_(0x800C0013L)
|
||||
INET_E_REDIRECTING = -2146697196 # _HRESULT_TYPEDEF_(0x800C0014L)
|
||||
|
||||
INET_E_INVALID_URL = -2146697214 # _HRESULT_TYPEDEF_(0x800C0002L)
|
||||
INET_E_NO_SESSION = -2146697213 # _HRESULT_TYPEDEF_(0x800C0003L)
|
||||
INET_E_CANNOT_CONNECT = -2146697212 # _HRESULT_TYPEDEF_(0x800C0004L)
|
||||
INET_E_RESOURCE_NOT_FOUND = -2146697211 # _HRESULT_TYPEDEF_(0x800C0005L)
|
||||
INET_E_OBJECT_NOT_FOUND = -2146697210 # _HRESULT_TYPEDEF_(0x800C0006L)
|
||||
INET_E_DATA_NOT_AVAILABLE = -2146697209 # _HRESULT_TYPEDEF_(0x800C0007L)
|
||||
INET_E_DOWNLOAD_FAILURE = -2146697208 # _HRESULT_TYPEDEF_(0x800C0008L)
|
||||
INET_E_AUTHENTICATION_REQUIRED = -2146697207 # _HRESULT_TYPEDEF_(0x800C0009L)
|
||||
INET_E_NO_VALID_MEDIA = -2146697206 # _HRESULT_TYPEDEF_(0x800C000AL)
|
||||
INET_E_CONNECTION_TIMEOUT = -2146697205 # _HRESULT_TYPEDEF_(0x800C000BL)
|
||||
INET_E_INVALID_REQUEST = -2146697204 # _HRESULT_TYPEDEF_(0x800C000CL)
|
||||
INET_E_UNKNOWN_PROTOCOL = -2146697203 # _HRESULT_TYPEDEF_(0x800C000DL)
|
||||
INET_E_SECURITY_PROBLEM = -2146697202 # _HRESULT_TYPEDEF_(0x800C000EL)
|
||||
INET_E_CANNOT_LOAD_DATA = -2146697201 # _HRESULT_TYPEDEF_(0x800C000FL)
|
||||
INET_E_CANNOT_INSTANTIATE_OBJECT = -2146697200 # _HRESULT_TYPEDEF_(0x800C0010L)
|
||||
INET_E_INVALID_CERTIFICATE = -2146697191 # _HRESULT_TYPEDEF_(0x800C0019L)
|
||||
INET_E_REDIRECT_FAILED = -2146697196 # _HRESULT_TYPEDEF_(0x800C0014L)
|
||||
INET_E_REDIRECT_TO_DIR = -2146697195 # _HRESULT_TYPEDEF_(0x800C0015L)
|
||||
INET_E_CANNOT_LOCK_REQUEST = -2146697194 # _HRESULT_TYPEDEF_(0x800C0016L)
|
||||
INET_E_USE_EXTEND_BINDING = -2146697193 # _HRESULT_TYPEDEF_(0x800C0017L)
|
||||
INET_E_TERMINATED_BIND = -2146697192 # _HRESULT_TYPEDEF_(0x800C0018L)
|
||||
INET_E_CODE_DOWNLOAD_DECLINED = -2146696960 # _HRESULT_TYPEDEF_(0x800C0100L)
|
||||
INET_E_RESULT_DISPATCHED = -2146696704 # _HRESULT_TYPEDEF_(0x800C0200L)
|
||||
INET_E_CANNOT_REPLACE_SFP_FILE = -2146696448 # _HRESULT_TYPEDEF_(0x800C0300L)
|
||||
INET_E_CODE_INSTALL_SUPPRESSED = -2146696192 # _HRESULT_TYPEDEF_(0x800C0400L)
|
||||
INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY = (
|
||||
-2146695936
|
||||
) # _HRESULT_TYPEDEF_(0x800C0500L)
|
||||
|
||||
# Generated by h2py from UrlMon.h
|
||||
MKSYS_URLMONIKER = 6
|
||||
URL_MK_LEGACY = 0
|
||||
URL_MK_UNIFORM = 1
|
||||
URL_MK_NO_CANONICALIZE = 2
|
||||
FIEF_FLAG_FORCE_JITUI = 0x1
|
||||
FIEF_FLAG_PEEK = 0x2
|
||||
FIEF_FLAG_SKIP_INSTALLED_VERSION_CHECK = 0x4
|
||||
FMFD_DEFAULT = 0x00000000
|
||||
FMFD_URLASFILENAME = 0x00000001
|
||||
FMFD_ENABLEMIMESNIFFING = 0x00000002
|
||||
FMFD_IGNOREMIMETEXTPLAIN = 0x00000004
|
||||
URLMON_OPTION_USERAGENT = 0x10000001
|
||||
URLMON_OPTION_USERAGENT_REFRESH = 0x10000002
|
||||
URLMON_OPTION_URL_ENCODING = 0x10000004
|
||||
URLMON_OPTION_USE_BINDSTRINGCREDS = 0x10000008
|
||||
URLMON_OPTION_USE_BROWSERAPPSDOCUMENTS = 0x10000010
|
||||
CF_NULL = 0
|
||||
Uri_CREATE_ALLOW_RELATIVE = 0x00000001
|
||||
Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME = 0x00000002
|
||||
Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME = 0x00000004
|
||||
Uri_CREATE_NOFRAG = 0x00000008
|
||||
Uri_CREATE_NO_CANONICALIZE = 0x00000010
|
||||
Uri_CREATE_CANONICALIZE = 0x00000100
|
||||
Uri_CREATE_FILE_USE_DOS_PATH = 0x00000020
|
||||
Uri_CREATE_DECODE_EXTRA_INFO = 0x00000040
|
||||
Uri_CREATE_NO_DECODE_EXTRA_INFO = 0x00000080
|
||||
Uri_CREATE_CRACK_UNKNOWN_SCHEMES = 0x00000200
|
||||
Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES = 0x00000400
|
||||
Uri_CREATE_PRE_PROCESS_HTML_URI = 0x00000800
|
||||
Uri_CREATE_NO_PRE_PROCESS_HTML_URI = 0x00001000
|
||||
Uri_CREATE_IE_SETTINGS = 0x00002000
|
||||
Uri_CREATE_NO_IE_SETTINGS = 0x00004000
|
||||
Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS = 0x00008000
|
||||
Uri_DISPLAY_NO_FRAGMENT = 0x00000001
|
||||
Uri_PUNYCODE_IDN_HOST = 0x00000002
|
||||
Uri_DISPLAY_IDN_HOST = 0x00000004
|
||||
Uri_ENCODING_USER_INFO_AND_PATH_IS_PERCENT_ENCODED_UTF8 = 0x00000001
|
||||
Uri_ENCODING_USER_INFO_AND_PATH_IS_CP = 0x00000002
|
||||
Uri_ENCODING_HOST_IS_IDN = 0x00000004
|
||||
Uri_ENCODING_HOST_IS_PERCENT_ENCODED_UTF8 = 0x00000008
|
||||
Uri_ENCODING_HOST_IS_PERCENT_ENCODED_CP = 0x00000010
|
||||
Uri_ENCODING_QUERY_AND_FRAGMENT_IS_PERCENT_ENCODED_UTF8 = 0x00000020
|
||||
Uri_ENCODING_QUERY_AND_FRAGMENT_IS_CP = 0x00000040
|
||||
Uri_ENCODING_RFC = (
|
||||
Uri_ENCODING_USER_INFO_AND_PATH_IS_PERCENT_ENCODED_UTF8
|
||||
| Uri_ENCODING_HOST_IS_PERCENT_ENCODED_UTF8
|
||||
| Uri_ENCODING_QUERY_AND_FRAGMENT_IS_PERCENT_ENCODED_UTF8
|
||||
)
|
||||
UriBuilder_USE_ORIGINAL_FLAGS = 0x00000001
|
||||
WININETINFO_OPTION_LOCK_HANDLE = 65534
|
||||
URLOSTRM_USECACHEDCOPY_ONLY = 0x1
|
||||
URLOSTRM_USECACHEDCOPY = 0x2
|
||||
URLOSTRM_GETNEWESTVERSION = 0x3
|
||||
SET_FEATURE_ON_THREAD = 0x00000001
|
||||
SET_FEATURE_ON_PROCESS = 0x00000002
|
||||
SET_FEATURE_IN_REGISTRY = 0x00000004
|
||||
SET_FEATURE_ON_THREAD_LOCALMACHINE = 0x00000008
|
||||
SET_FEATURE_ON_THREAD_INTRANET = 0x00000010
|
||||
SET_FEATURE_ON_THREAD_TRUSTED = 0x00000020
|
||||
SET_FEATURE_ON_THREAD_INTERNET = 0x00000040
|
||||
SET_FEATURE_ON_THREAD_RESTRICTED = 0x00000080
|
||||
GET_FEATURE_FROM_THREAD = 0x00000001
|
||||
GET_FEATURE_FROM_PROCESS = 0x00000002
|
||||
GET_FEATURE_FROM_REGISTRY = 0x00000004
|
||||
GET_FEATURE_FROM_THREAD_LOCALMACHINE = 0x00000008
|
||||
GET_FEATURE_FROM_THREAD_INTRANET = 0x00000010
|
||||
GET_FEATURE_FROM_THREAD_TRUSTED = 0x00000020
|
||||
GET_FEATURE_FROM_THREAD_INTERNET = 0x00000040
|
||||
GET_FEATURE_FROM_THREAD_RESTRICTED = 0x00000080
|
||||
PROTOCOLFLAG_NO_PICS_CHECK = 0x00000001
|
||||
MUTZ_NOSAVEDFILECHECK = 0x00000001
|
||||
MUTZ_ISFILE = 0x00000002
|
||||
MUTZ_ACCEPT_WILDCARD_SCHEME = 0x00000080
|
||||
MUTZ_ENFORCERESTRICTED = 0x00000100
|
||||
MUTZ_RESERVED = 0x00000200
|
||||
MUTZ_REQUIRESAVEDFILECHECK = 0x00000400
|
||||
MUTZ_DONT_UNESCAPE = 0x00000800
|
||||
MUTZ_DONT_USE_CACHE = 0x00001000
|
||||
MUTZ_FORCE_INTRANET_FLAGS = 0x00002000
|
||||
MUTZ_IGNORE_ZONE_MAPPINGS = 0x00004000
|
||||
MAX_SIZE_SECURITY_ID = 512
|
||||
URLACTION_MIN = 0x00001000
|
||||
URLACTION_DOWNLOAD_MIN = 0x00001000
|
||||
URLACTION_DOWNLOAD_SIGNED_ACTIVEX = 0x00001001
|
||||
URLACTION_DOWNLOAD_UNSIGNED_ACTIVEX = 0x00001004
|
||||
URLACTION_DOWNLOAD_CURR_MAX = 0x00001004
|
||||
URLACTION_DOWNLOAD_MAX = 0x000011FF
|
||||
URLACTION_ACTIVEX_MIN = 0x00001200
|
||||
URLACTION_ACTIVEX_RUN = 0x00001200
|
||||
URLPOLICY_ACTIVEX_CHECK_LIST = 0x00010000
|
||||
URLACTION_ACTIVEX_OVERRIDE_OBJECT_SAFETY = 0x00001201
|
||||
URLACTION_ACTIVEX_OVERRIDE_DATA_SAFETY = 0x00001202
|
||||
URLACTION_ACTIVEX_OVERRIDE_SCRIPT_SAFETY = 0x00001203
|
||||
URLACTION_SCRIPT_OVERRIDE_SAFETY = 0x00001401
|
||||
URLACTION_ACTIVEX_CONFIRM_NOOBJECTSAFETY = 0x00001204
|
||||
URLACTION_ACTIVEX_TREATASUNTRUSTED = 0x00001205
|
||||
URLACTION_ACTIVEX_NO_WEBOC_SCRIPT = 0x00001206
|
||||
URLACTION_ACTIVEX_OVERRIDE_REPURPOSEDETECTION = 0x00001207
|
||||
URLACTION_ACTIVEX_OVERRIDE_OPTIN = 0x00001208
|
||||
URLACTION_ACTIVEX_SCRIPTLET_RUN = 0x00001209
|
||||
URLACTION_ACTIVEX_DYNSRC_VIDEO_AND_ANIMATION = 0x0000120A
|
||||
URLACTION_ACTIVEX_CURR_MAX = 0x0000120A
|
||||
URLACTION_ACTIVEX_MAX = 0x000013FF
|
||||
URLACTION_SCRIPT_MIN = 0x00001400
|
||||
URLACTION_SCRIPT_RUN = 0x00001400
|
||||
URLACTION_SCRIPT_JAVA_USE = 0x00001402
|
||||
URLACTION_SCRIPT_SAFE_ACTIVEX = 0x00001405
|
||||
URLACTION_CROSS_DOMAIN_DATA = 0x00001406
|
||||
URLACTION_SCRIPT_PASTE = 0x00001407
|
||||
URLACTION_ALLOW_XDOMAIN_SUBFRAME_RESIZE = 0x00001408
|
||||
URLACTION_SCRIPT_CURR_MAX = 0x00001408
|
||||
URLACTION_SCRIPT_MAX = 0x000015FF
|
||||
URLACTION_HTML_MIN = 0x00001600
|
||||
URLACTION_HTML_SUBMIT_FORMS = 0x00001601
|
||||
URLACTION_HTML_SUBMIT_FORMS_FROM = 0x00001602
|
||||
URLACTION_HTML_SUBMIT_FORMS_TO = 0x00001603
|
||||
URLACTION_HTML_FONT_DOWNLOAD = 0x00001604
|
||||
URLACTION_HTML_JAVA_RUN = 0x00001605
|
||||
URLACTION_HTML_USERDATA_SAVE = 0x00001606
|
||||
URLACTION_HTML_SUBFRAME_NAVIGATE = 0x00001607
|
||||
URLACTION_HTML_META_REFRESH = 0x00001608
|
||||
URLACTION_HTML_MIXED_CONTENT = 0x00001609
|
||||
URLACTION_HTML_INCLUDE_FILE_PATH = 0x0000160A
|
||||
URLACTION_HTML_MAX = 0x000017FF
|
||||
URLACTION_SHELL_MIN = 0x00001800
|
||||
URLACTION_SHELL_INSTALL_DTITEMS = 0x00001800
|
||||
URLACTION_SHELL_MOVE_OR_COPY = 0x00001802
|
||||
URLACTION_SHELL_FILE_DOWNLOAD = 0x00001803
|
||||
URLACTION_SHELL_VERB = 0x00001804
|
||||
URLACTION_SHELL_WEBVIEW_VERB = 0x00001805
|
||||
URLACTION_SHELL_SHELLEXECUTE = 0x00001806
|
||||
URLACTION_SHELL_EXECUTE_HIGHRISK = 0x00001806
|
||||
URLACTION_SHELL_EXECUTE_MODRISK = 0x00001807
|
||||
URLACTION_SHELL_EXECUTE_LOWRISK = 0x00001808
|
||||
URLACTION_SHELL_POPUPMGR = 0x00001809
|
||||
URLACTION_SHELL_RTF_OBJECTS_LOAD = 0x0000180A
|
||||
URLACTION_SHELL_ENHANCED_DRAGDROP_SECURITY = 0x0000180B
|
||||
URLACTION_SHELL_EXTENSIONSECURITY = 0x0000180C
|
||||
URLACTION_SHELL_SECURE_DRAGSOURCE = 0x0000180D
|
||||
URLACTION_SHELL_CURR_MAX = 0x0000180D
|
||||
URLACTION_SHELL_MAX = 0x000019FF
|
||||
URLACTION_NETWORK_MIN = 0x00001A00
|
||||
URLACTION_CREDENTIALS_USE = 0x00001A00
|
||||
URLPOLICY_CREDENTIALS_SILENT_LOGON_OK = 0x00000000
|
||||
URLPOLICY_CREDENTIALS_MUST_PROMPT_USER = 0x00010000
|
||||
URLPOLICY_CREDENTIALS_CONDITIONAL_PROMPT = 0x00020000
|
||||
URLPOLICY_CREDENTIALS_ANONYMOUS_ONLY = 0x00030000
|
||||
URLACTION_AUTHENTICATE_CLIENT = 0x00001A01
|
||||
URLPOLICY_AUTHENTICATE_CLEARTEXT_OK = 0x00000000
|
||||
URLPOLICY_AUTHENTICATE_CHALLENGE_RESPONSE = 0x00010000
|
||||
URLPOLICY_AUTHENTICATE_MUTUAL_ONLY = 0x00030000
|
||||
URLACTION_COOKIES = 0x00001A02
|
||||
URLACTION_COOKIES_SESSION = 0x00001A03
|
||||
URLACTION_CLIENT_CERT_PROMPT = 0x00001A04
|
||||
URLACTION_COOKIES_THIRD_PARTY = 0x00001A05
|
||||
URLACTION_COOKIES_SESSION_THIRD_PARTY = 0x00001A06
|
||||
URLACTION_COOKIES_ENABLED = 0x00001A10
|
||||
URLACTION_NETWORK_CURR_MAX = 0x00001A10
|
||||
URLACTION_NETWORK_MAX = 0x00001BFF
|
||||
URLACTION_JAVA_MIN = 0x00001C00
|
||||
URLACTION_JAVA_PERMISSIONS = 0x00001C00
|
||||
URLPOLICY_JAVA_PROHIBIT = 0x00000000
|
||||
URLPOLICY_JAVA_HIGH = 0x00010000
|
||||
URLPOLICY_JAVA_MEDIUM = 0x00020000
|
||||
URLPOLICY_JAVA_LOW = 0x00030000
|
||||
URLPOLICY_JAVA_CUSTOM = 0x00800000
|
||||
URLACTION_JAVA_CURR_MAX = 0x00001C00
|
||||
URLACTION_JAVA_MAX = 0x00001CFF
|
||||
URLACTION_INFODELIVERY_MIN = 0x00001D00
|
||||
URLACTION_INFODELIVERY_NO_ADDING_CHANNELS = 0x00001D00
|
||||
URLACTION_INFODELIVERY_NO_EDITING_CHANNELS = 0x00001D01
|
||||
URLACTION_INFODELIVERY_NO_REMOVING_CHANNELS = 0x00001D02
|
||||
URLACTION_INFODELIVERY_NO_ADDING_SUBSCRIPTIONS = 0x00001D03
|
||||
URLACTION_INFODELIVERY_NO_EDITING_SUBSCRIPTIONS = 0x00001D04
|
||||
URLACTION_INFODELIVERY_NO_REMOVING_SUBSCRIPTIONS = 0x00001D05
|
||||
URLACTION_INFODELIVERY_NO_CHANNEL_LOGGING = 0x00001D06
|
||||
URLACTION_INFODELIVERY_CURR_MAX = 0x00001D06
|
||||
URLACTION_INFODELIVERY_MAX = 0x00001DFF
|
||||
URLACTION_CHANNEL_SOFTDIST_MIN = 0x00001E00
|
||||
URLACTION_CHANNEL_SOFTDIST_PERMISSIONS = 0x00001E05
|
||||
URLPOLICY_CHANNEL_SOFTDIST_PROHIBIT = 0x00010000
|
||||
URLPOLICY_CHANNEL_SOFTDIST_PRECACHE = 0x00020000
|
||||
URLPOLICY_CHANNEL_SOFTDIST_AUTOINSTALL = 0x00030000
|
||||
URLACTION_CHANNEL_SOFTDIST_MAX = 0x00001EFF
|
||||
URLACTION_BEHAVIOR_MIN = 0x00002000
|
||||
URLACTION_BEHAVIOR_RUN = 0x00002000
|
||||
URLPOLICY_BEHAVIOR_CHECK_LIST = 0x00010000
|
||||
URLACTION_FEATURE_MIN = 0x00002100
|
||||
URLACTION_FEATURE_MIME_SNIFFING = 0x00002100
|
||||
URLACTION_FEATURE_ZONE_ELEVATION = 0x00002101
|
||||
URLACTION_FEATURE_WINDOW_RESTRICTIONS = 0x00002102
|
||||
URLACTION_FEATURE_SCRIPT_STATUS_BAR = 0x00002103
|
||||
URLACTION_FEATURE_FORCE_ADDR_AND_STATUS = 0x00002104
|
||||
URLACTION_FEATURE_BLOCK_INPUT_PROMPTS = 0x00002105
|
||||
URLACTION_AUTOMATIC_DOWNLOAD_UI_MIN = 0x00002200
|
||||
URLACTION_AUTOMATIC_DOWNLOAD_UI = 0x00002200
|
||||
URLACTION_AUTOMATIC_ACTIVEX_UI = 0x00002201
|
||||
URLACTION_ALLOW_RESTRICTEDPROTOCOLS = 0x00002300
|
||||
URLACTION_ALLOW_APEVALUATION = 0x00002301
|
||||
URLACTION_WINDOWS_BROWSER_APPLICATIONS = 0x00002400
|
||||
URLACTION_XPS_DOCUMENTS = 0x00002401
|
||||
URLACTION_LOOSE_XAML = 0x00002402
|
||||
URLACTION_LOWRIGHTS = 0x00002500
|
||||
URLACTION_WINFX_SETUP = 0x00002600
|
||||
URLPOLICY_ALLOW = 0x00
|
||||
URLPOLICY_QUERY = 0x01
|
||||
URLPOLICY_DISALLOW = 0x03
|
||||
URLPOLICY_NOTIFY_ON_ALLOW = 0x10
|
||||
URLPOLICY_NOTIFY_ON_DISALLOW = 0x20
|
||||
URLPOLICY_LOG_ON_ALLOW = 0x40
|
||||
URLPOLICY_LOG_ON_DISALLOW = 0x80
|
||||
URLPOLICY_MASK_PERMISSIONS = 0x0F
|
||||
URLPOLICY_DONTCHECKDLGBOX = 0x100
|
||||
URLZONE_ESC_FLAG = 0x100
|
||||
SECURITY_IE_STATE_GREEN = 0x00000000
|
||||
SECURITY_IE_STATE_RED = 0x00000001
|
||||
SOFTDIST_FLAG_USAGE_EMAIL = 0x00000001
|
||||
SOFTDIST_FLAG_USAGE_PRECACHE = 0x00000002
|
||||
SOFTDIST_FLAG_USAGE_AUTOINSTALL = 0x00000004
|
||||
SOFTDIST_FLAG_DELETE_SUBSCRIPTION = 0x00000008
|
||||
SOFTDIST_ADSTATE_NONE = 0x00000000
|
||||
SOFTDIST_ADSTATE_AVAILABLE = 0x00000001
|
||||
SOFTDIST_ADSTATE_DOWNLOADED = 0x00000002
|
||||
SOFTDIST_ADSTATE_INSTALLED = 0x00000003
|
||||
CONFIRMSAFETYACTION_LOADOBJECT = 0x00000001
|
||||
Binary file not shown.
@@ -0,0 +1,21 @@
|
||||
if isinstance(__path__, str):
|
||||
# For freeze to work!
|
||||
import sys
|
||||
|
||||
try:
|
||||
import mapi
|
||||
|
||||
sys.modules["win32com.mapi.mapi"] = mapi
|
||||
except ImportError:
|
||||
pass
|
||||
try:
|
||||
import exchange
|
||||
|
||||
sys.modules["win32com.mapi.exchange"] = exchange
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
import win32com
|
||||
|
||||
# See if we have a special directory for the binaries (for developers)
|
||||
win32com.__PackageSupportBuildPath__(__path__)
|
||||
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""module to send mail with Extended MAPI using the pywin32 mapi wrappers..."""
|
||||
|
||||
# this was based on Jason Hattingh's C++ code at http://www.codeproject.com/internet/mapadmin.asp (dead link)
|
||||
# written by David Fraser <davidf at sjsoft.com> and Stephen Emslie <stephene at sjsoft.com>
|
||||
# you can test this by changing the variables at the bottom and running from the command line
|
||||
|
||||
from win32com.mapi import mapi, mapitags
|
||||
|
||||
|
||||
def SendEMAPIMail(
|
||||
Subject="", Message="", SendTo=None, SendCC=None, SendBCC=None, MAPIProfile=None
|
||||
):
|
||||
"""Sends an email to the recipient using the extended MAPI interface
|
||||
Subject and Message are strings
|
||||
Send{To,CC,BCC} are comma-separated address lists
|
||||
MAPIProfile is the name of the MAPI profile"""
|
||||
|
||||
# initialize and log on
|
||||
mapi.MAPIInitialize(None)
|
||||
session = mapi.MAPILogonEx(
|
||||
0, MAPIProfile, None, mapi.MAPI_EXTENDED | mapi.MAPI_USE_DEFAULT
|
||||
)
|
||||
messagestorestable = session.GetMsgStoresTable(0)
|
||||
messagestorestable.SetColumns(
|
||||
(mapitags.PR_ENTRYID, mapitags.PR_DISPLAY_NAME_A, mapitags.PR_DEFAULT_STORE), 0
|
||||
)
|
||||
|
||||
while True:
|
||||
rows = messagestorestable.QueryRows(1, 0)
|
||||
# if this is the last row then stop
|
||||
if len(rows) != 1:
|
||||
break
|
||||
row = rows[0]
|
||||
# if this is the default store then stop
|
||||
if (mapitags.PR_DEFAULT_STORE, True) in row:
|
||||
break
|
||||
|
||||
# unpack the row and open the message store
|
||||
(eid_tag, eid), (name_tag, name), (def_store_tag, def_store) = row
|
||||
msgstore = session.OpenMsgStore(
|
||||
0, eid, None, mapi.MDB_NO_DIALOG | mapi.MAPI_BEST_ACCESS
|
||||
)
|
||||
|
||||
# get the outbox
|
||||
hr, props = msgstore.GetProps((mapitags.PR_IPM_OUTBOX_ENTRYID), 0)
|
||||
(tag, eid) = props[0]
|
||||
# check for errors
|
||||
if mapitags.PROP_TYPE(tag) == mapitags.PT_ERROR:
|
||||
raise TypeError("got PT_ERROR instead of PT_BINARY: %s" % eid)
|
||||
outboxfolder = msgstore.OpenEntry(eid, None, mapi.MAPI_BEST_ACCESS)
|
||||
|
||||
# create the message and the addrlist
|
||||
message = outboxfolder.CreateMessage(None, 0)
|
||||
# note: you can use the resolveaddress functions for this. but you may get headaches
|
||||
pal = []
|
||||
|
||||
def makeentry(recipient, recipienttype):
|
||||
return (
|
||||
(mapitags.PR_RECIPIENT_TYPE, recipienttype),
|
||||
(mapitags.PR_SEND_RICH_INFO, False),
|
||||
(mapitags.PR_DISPLAY_TYPE, 0),
|
||||
(mapitags.PR_OBJECT_TYPE, 6),
|
||||
(mapitags.PR_EMAIL_ADDRESS_A, recipient),
|
||||
(mapitags.PR_ADDRTYPE_A, "SMTP"),
|
||||
(mapitags.PR_DISPLAY_NAME_A, recipient),
|
||||
)
|
||||
|
||||
if SendTo:
|
||||
pal.extend(
|
||||
[makeentry(recipient, mapi.MAPI_TO) for recipient in SendTo.split(",")]
|
||||
)
|
||||
if SendCC:
|
||||
pal.extend(
|
||||
[makeentry(recipient, mapi.MAPI_CC) for recipient in SendCC.split(",")]
|
||||
)
|
||||
if SendBCC:
|
||||
pal.extend(
|
||||
[makeentry(recipient, mapi.MAPI_BCC) for recipient in SendBCC.split(",")]
|
||||
)
|
||||
|
||||
# add the resolved recipients to the message
|
||||
message.ModifyRecipients(mapi.MODRECIP_ADD, pal)
|
||||
message.SetProps([(mapitags.PR_BODY_A, Message), (mapitags.PR_SUBJECT_A, Subject)])
|
||||
|
||||
# save changes and submit
|
||||
outboxfolder.SaveChanges(0)
|
||||
message.SubmitMessage(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
MAPIProfile = ""
|
||||
# Change this to a valid email address to test
|
||||
SendTo = "an.invalid at address"
|
||||
SendMessage = "testing one two three"
|
||||
SendSubject = "Testing Extended MAPI!!"
|
||||
SendEMAPIMail(SendSubject, SendMessage, SendTo, MAPIProfile=MAPIProfile)
|
||||
@@ -0,0 +1,875 @@
|
||||
# nopycln: file # Re-exporting many constants
|
||||
# Converted "manually" from EMSABTAG.H
|
||||
from .mapitags import (
|
||||
PROP_TAG,
|
||||
PT_APPTIME,
|
||||
PT_BINARY,
|
||||
PT_BOOLEAN,
|
||||
PT_CLSID,
|
||||
PT_CURRENCY,
|
||||
PT_DOUBLE,
|
||||
PT_ERROR,
|
||||
PT_FLOAT,
|
||||
PT_I2,
|
||||
PT_I4,
|
||||
PT_I8,
|
||||
PT_LONG,
|
||||
PT_LONGLONG,
|
||||
PT_MV_APPTIME,
|
||||
PT_MV_BINARY,
|
||||
PT_MV_CLSID,
|
||||
PT_MV_CURRENCY,
|
||||
PT_MV_DOUBLE,
|
||||
PT_MV_FLOAT,
|
||||
PT_MV_I2,
|
||||
PT_MV_I4,
|
||||
PT_MV_I8,
|
||||
PT_MV_LONG,
|
||||
PT_MV_LONGLONG,
|
||||
PT_MV_R4,
|
||||
PT_MV_R8,
|
||||
PT_MV_SHORT,
|
||||
PT_MV_STRING8,
|
||||
PT_MV_SYSTIME,
|
||||
PT_MV_TSTRING,
|
||||
PT_MV_UNICODE,
|
||||
PT_NULL,
|
||||
PT_OBJECT,
|
||||
PT_R4,
|
||||
PT_SHORT,
|
||||
PT_STRING8,
|
||||
PT_SYSTIME,
|
||||
PT_TSTRING,
|
||||
PT_UNICODE,
|
||||
PT_UNSPECIFIED,
|
||||
)
|
||||
|
||||
AB_SHOW_PHANTOMS = 2
|
||||
AB_SHOW_OTHERS = 4
|
||||
|
||||
# Flags for ulFlag on ResolveNames
|
||||
EMS_AB_ADDRESS_LOOKUP = 1
|
||||
|
||||
|
||||
# Constructed, but externally visible.
|
||||
PR_EMS_AB_SERVER = PROP_TAG(PT_TSTRING, 65534)
|
||||
PR_EMS_AB_SERVER_A = PROP_TAG(PT_STRING8, 65534)
|
||||
PR_EMS_AB_SERVER_W = PROP_TAG(PT_UNICODE, 65534)
|
||||
PR_EMS_AB_CONTAINERID = PROP_TAG(PT_LONG, 65533)
|
||||
PR_EMS_AB_DOS_ENTRYID = PR_EMS_AB_CONTAINERID
|
||||
PR_EMS_AB_PARENT_ENTRYID = PROP_TAG(PT_BINARY, 65532)
|
||||
PR_EMS_AB_IS_MASTER = PROP_TAG(PT_BOOLEAN, 65531)
|
||||
PR_EMS_AB_OBJECT_OID = PROP_TAG(PT_BINARY, 65530)
|
||||
PR_EMS_AB_HIERARCHY_PATH = PROP_TAG(PT_TSTRING, 65529)
|
||||
PR_EMS_AB_HIERARCHY_PATH_A = PROP_TAG(PT_STRING8, 65529)
|
||||
PR_EMS_AB_HIERARCHY_PATH_W = PROP_TAG(PT_UNICODE, 65529)
|
||||
PR_EMS_AB_CHILD_RDNS = PROP_TAG(PT_MV_STRING8, 65528)
|
||||
|
||||
MIN_EMS_AB_CONSTRUCTED_PROP_ID = 65528
|
||||
|
||||
PR_EMS_AB_OTHER_RECIPS = PROP_TAG(PT_OBJECT, 61440)
|
||||
|
||||
# Prop tags defined in the schema.
|
||||
PR_EMS_AB_DISPLAY_NAME_PRINTABLE = PROP_TAG(PT_TSTRING, 14847)
|
||||
PR_EMS_AB_DISPLAY_NAME_PRINTABLE_A = PROP_TAG(PT_STRING8, 14847)
|
||||
PR_EMS_AB_DISPLAY_NAME_PRINTABLE_W = PROP_TAG(PT_UNICODE, 14847)
|
||||
|
||||
PR_EMS_AB_ACCESS_CATEGORY = PROP_TAG(PT_LONG, 32836)
|
||||
PR_EMS_AB_ACTIVATION_SCHEDULE = PROP_TAG(PT_BINARY, 32837)
|
||||
PR_EMS_AB_ACTIVATION_STYLE = PROP_TAG(PT_LONG, 32838)
|
||||
PR_EMS_AB_ADDRESS_ENTRY_DISPLAY_TABLE = PROP_TAG(PT_BINARY, 32791)
|
||||
PR_EMS_AB_ADDRESS_ENTRY_DISPLAY_TABLE_MSDOS = PROP_TAG(PT_BINARY, 32839)
|
||||
PR_EMS_AB_ADDRESS_SYNTAX = PROP_TAG(PT_BINARY, 32792)
|
||||
PR_EMS_AB_ADDRESS_TYPE = PROP_TAG(PT_TSTRING, 32840)
|
||||
PR_EMS_AB_ADDRESS_TYPE_A = PROP_TAG(PT_STRING8, 32840)
|
||||
PR_EMS_AB_ADDRESS_TYPE_W = PROP_TAG(PT_UNICODE, 32840)
|
||||
PR_EMS_AB_ADMD = PROP_TAG(PT_TSTRING, 32841)
|
||||
PR_EMS_AB_ADMD_A = PROP_TAG(PT_STRING8, 32841)
|
||||
PR_EMS_AB_ADMD_W = PROP_TAG(PT_UNICODE, 32841)
|
||||
PR_EMS_AB_ADMIN_DESCRIPTION = PROP_TAG(PT_TSTRING, 32842)
|
||||
PR_EMS_AB_ADMIN_DESCRIPTION_A = PROP_TAG(PT_STRING8, 32842)
|
||||
PR_EMS_AB_ADMIN_DESCRIPTION_W = PROP_TAG(PT_UNICODE, 32842)
|
||||
PR_EMS_AB_ADMIN_DISPLAY_NAME = PROP_TAG(PT_TSTRING, 32843)
|
||||
PR_EMS_AB_ADMIN_DISPLAY_NAME_A = PROP_TAG(PT_STRING8, 32843)
|
||||
PR_EMS_AB_ADMIN_DISPLAY_NAME_W = PROP_TAG(PT_UNICODE, 32843)
|
||||
PR_EMS_AB_ADMIN_EXTENSION_DLL = PROP_TAG(PT_TSTRING, 32844)
|
||||
PR_EMS_AB_ADMIN_EXTENSION_DLL_A = PROP_TAG(PT_STRING8, 32844)
|
||||
PR_EMS_AB_ADMIN_EXTENSION_DLL_W = PROP_TAG(PT_UNICODE, 32844)
|
||||
PR_EMS_AB_ALIASED_OBJECT_NAME = PROP_TAG(PT_TSTRING, 32845)
|
||||
PR_EMS_AB_ALIASED_OBJECT_NAME_A = PROP_TAG(PT_STRING8, 32845)
|
||||
PR_EMS_AB_ALIASED_OBJECT_NAME_W = PROP_TAG(PT_UNICODE, 32845)
|
||||
PR_EMS_AB_ALIASED_OBJECT_NAME_O = PROP_TAG(PT_OBJECT, 32845)
|
||||
PR_EMS_AB_ALIASED_OBJECT_NAME_T = PROP_TAG(PT_TSTRING, 32845)
|
||||
PR_EMS_AB_ALT_RECIPIENT = PROP_TAG(PT_TSTRING, 32846)
|
||||
PR_EMS_AB_ALT_RECIPIENT_A = PROP_TAG(PT_STRING8, 32846)
|
||||
PR_EMS_AB_ALT_RECIPIENT_W = PROP_TAG(PT_UNICODE, 32846)
|
||||
PR_EMS_AB_ALT_RECIPIENT_O = PROP_TAG(PT_OBJECT, 32846)
|
||||
PR_EMS_AB_ALT_RECIPIENT_T = PROP_TAG(PT_TSTRING, 32846)
|
||||
PR_EMS_AB_ALT_RECIPIENT_BL = PROP_TAG(PT_MV_TSTRING, 32847)
|
||||
PR_EMS_AB_ALT_RECIPIENT_BL_A = PROP_TAG(PT_MV_STRING8, 32847)
|
||||
PR_EMS_AB_ALT_RECIPIENT_BL_W = PROP_TAG(PT_MV_UNICODE, 32847)
|
||||
PR_EMS_AB_ALT_RECIPIENT_BL_O = PROP_TAG(PT_OBJECT, 32847)
|
||||
PR_EMS_AB_ALT_RECIPIENT_BL_T = PROP_TAG(PT_MV_TSTRING, 32847)
|
||||
PR_EMS_AB_ANCESTOR_ID = PROP_TAG(PT_BINARY, 32848)
|
||||
PR_EMS_AB_ASSOC_NT_ACCOUNT = PROP_TAG(PT_BINARY, 32807)
|
||||
PR_EMS_AB_ASSOC_REMOTE_DXA = PROP_TAG(PT_MV_TSTRING, 32849)
|
||||
PR_EMS_AB_ASSOC_REMOTE_DXA_A = PROP_TAG(PT_MV_STRING8, 32849)
|
||||
PR_EMS_AB_ASSOC_REMOTE_DXA_W = PROP_TAG(PT_MV_UNICODE, 32849)
|
||||
PR_EMS_AB_ASSOC_REMOTE_DXA_O = PROP_TAG(PT_OBJECT, 32849)
|
||||
PR_EMS_AB_ASSOC_REMOTE_DXA_T = PROP_TAG(PT_MV_TSTRING, 32849)
|
||||
PR_EMS_AB_ASSOCIATION_LIFETIME = PROP_TAG(PT_LONG, 32850)
|
||||
PR_EMS_AB_AUTH_ORIG_BL = PROP_TAG(PT_MV_TSTRING, 32851)
|
||||
PR_EMS_AB_AUTH_ORIG_BL_A = PROP_TAG(PT_MV_STRING8, 32851)
|
||||
PR_EMS_AB_AUTH_ORIG_BL_W = PROP_TAG(PT_MV_UNICODE, 32851)
|
||||
PR_EMS_AB_AUTH_ORIG_BL_O = PROP_TAG(PT_OBJECT, 32851)
|
||||
PR_EMS_AB_AUTH_ORIG_BL_T = PROP_TAG(PT_MV_TSTRING, 32851)
|
||||
PR_EMS_AB_AUTHORITY_REVOCATION_LIST = PROP_TAG(PT_MV_BINARY, 32806)
|
||||
PR_EMS_AB_AUTHORIZED_DOMAIN = PROP_TAG(PT_TSTRING, 32852)
|
||||
PR_EMS_AB_AUTHORIZED_DOMAIN_A = PROP_TAG(PT_STRING8, 32852)
|
||||
PR_EMS_AB_AUTHORIZED_DOMAIN_W = PROP_TAG(PT_UNICODE, 32852)
|
||||
PR_EMS_AB_AUTHORIZED_PASSWORD = PROP_TAG(PT_BINARY, 32853)
|
||||
PR_EMS_AB_AUTHORIZED_USER = PROP_TAG(PT_TSTRING, 32854)
|
||||
PR_EMS_AB_AUTHORIZED_USER_A = PROP_TAG(PT_STRING8, 32854)
|
||||
PR_EMS_AB_AUTHORIZED_USER_W = PROP_TAG(PT_UNICODE, 32854)
|
||||
PR_EMS_AB_AUTOREPLY = PROP_TAG(PT_BOOLEAN, 32779)
|
||||
PR_EMS_AB_AUTOREPLY_MESSAGE = PROP_TAG(PT_TSTRING, 32778)
|
||||
PR_EMS_AB_AUTOREPLY_MESSAGE_A = PROP_TAG(PT_STRING8, 32778)
|
||||
PR_EMS_AB_AUTOREPLY_MESSAGE_W = PROP_TAG(PT_UNICODE, 32778)
|
||||
PR_EMS_AB_AUTOREPLY_SUBJECT = PROP_TAG(PT_TSTRING, 32830)
|
||||
PR_EMS_AB_AUTOREPLY_SUBJECT_A = PROP_TAG(PT_STRING8, 32830)
|
||||
PR_EMS_AB_AUTOREPLY_SUBJECT_W = PROP_TAG(PT_UNICODE, 32830)
|
||||
PR_EMS_AB_BRIDGEHEAD_SERVERS = PROP_TAG(PT_MV_TSTRING, 33140)
|
||||
PR_EMS_AB_BRIDGEHEAD_SERVERS_A = PROP_TAG(PT_MV_STRING8, 33140)
|
||||
PR_EMS_AB_BRIDGEHEAD_SERVERS_W = PROP_TAG(PT_MV_UNICODE, 33140)
|
||||
PR_EMS_AB_BRIDGEHEAD_SERVERS_O = PROP_TAG(PT_OBJECT, 33140)
|
||||
PR_EMS_AB_BRIDGEHEAD_SERVERS_T = PROP_TAG(PT_MV_TSTRING, 33140)
|
||||
PR_EMS_AB_BUSINESS_CATEGORY = PROP_TAG(PT_MV_TSTRING, 32855)
|
||||
PR_EMS_AB_BUSINESS_CATEGORY_A = PROP_TAG(PT_MV_STRING8, 32855)
|
||||
PR_EMS_AB_BUSINESS_CATEGORY_W = PROP_TAG(PT_MV_UNICODE, 32855)
|
||||
PR_EMS_AB_BUSINESS_ROLES = PROP_TAG(PT_BINARY, 32803)
|
||||
PR_EMS_AB_CA_CERTIFICATE = PROP_TAG(PT_MV_BINARY, 32771)
|
||||
PR_EMS_AB_CAN_CREATE_PF = PROP_TAG(PT_MV_TSTRING, 32856)
|
||||
PR_EMS_AB_CAN_CREATE_PF_A = PROP_TAG(PT_MV_STRING8, 32856)
|
||||
PR_EMS_AB_CAN_CREATE_PF_W = PROP_TAG(PT_MV_UNICODE, 32856)
|
||||
PR_EMS_AB_CAN_CREATE_PF_O = PROP_TAG(PT_OBJECT, 32856)
|
||||
PR_EMS_AB_CAN_CREATE_PF_T = PROP_TAG(PT_MV_TSTRING, 32856)
|
||||
PR_EMS_AB_CAN_CREATE_PF_BL = PROP_TAG(PT_MV_TSTRING, 32857)
|
||||
PR_EMS_AB_CAN_CREATE_PF_BL_A = PROP_TAG(PT_MV_STRING8, 32857)
|
||||
PR_EMS_AB_CAN_CREATE_PF_BL_W = PROP_TAG(PT_MV_UNICODE, 32857)
|
||||
PR_EMS_AB_CAN_CREATE_PF_BL_O = PROP_TAG(PT_OBJECT, 32857)
|
||||
PR_EMS_AB_CAN_CREATE_PF_BL_T = PROP_TAG(PT_MV_TSTRING, 32857)
|
||||
PR_EMS_AB_CAN_CREATE_PF_DL = PROP_TAG(PT_MV_TSTRING, 32858)
|
||||
PR_EMS_AB_CAN_CREATE_PF_DL_A = PROP_TAG(PT_MV_STRING8, 32858)
|
||||
PR_EMS_AB_CAN_CREATE_PF_DL_W = PROP_TAG(PT_MV_UNICODE, 32858)
|
||||
PR_EMS_AB_CAN_CREATE_PF_DL_O = PROP_TAG(PT_OBJECT, 32858)
|
||||
PR_EMS_AB_CAN_CREATE_PF_DL_T = PROP_TAG(PT_MV_TSTRING, 32858)
|
||||
PR_EMS_AB_CAN_CREATE_PF_DL_BL = PROP_TAG(PT_MV_TSTRING, 32859)
|
||||
PR_EMS_AB_CAN_CREATE_PF_DL_BL_A = PROP_TAG(PT_MV_STRING8, 32859)
|
||||
PR_EMS_AB_CAN_CREATE_PF_DL_BL_W = PROP_TAG(PT_MV_UNICODE, 32859)
|
||||
PR_EMS_AB_CAN_CREATE_PF_DL_BL_O = PROP_TAG(PT_OBJECT, 32859)
|
||||
PR_EMS_AB_CAN_CREATE_PF_DL_BL_T = PROP_TAG(PT_MV_TSTRING, 32859)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF = PROP_TAG(PT_MV_TSTRING, 32860)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_A = PROP_TAG(PT_MV_STRING8, 32860)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_W = PROP_TAG(PT_MV_UNICODE, 32860)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_O = PROP_TAG(PT_OBJECT, 32860)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_T = PROP_TAG(PT_MV_TSTRING, 32860)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_BL = PROP_TAG(PT_MV_TSTRING, 32861)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_BL_A = PROP_TAG(PT_MV_STRING8, 32861)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_BL_W = PROP_TAG(PT_MV_UNICODE, 32861)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_BL_O = PROP_TAG(PT_OBJECT, 32861)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_BL_T = PROP_TAG(PT_MV_TSTRING, 32861)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_DL = PROP_TAG(PT_MV_TSTRING, 32862)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_DL_A = PROP_TAG(PT_MV_STRING8, 32862)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_DL_W = PROP_TAG(PT_MV_UNICODE, 32862)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_DL_O = PROP_TAG(PT_OBJECT, 32862)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_DL_T = PROP_TAG(PT_MV_TSTRING, 32862)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_DL_BL = PROP_TAG(PT_MV_TSTRING, 32863)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_DL_BL_A = PROP_TAG(PT_MV_STRING8, 32863)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_DL_BL_W = PROP_TAG(PT_MV_UNICODE, 32863)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_DL_BL_O = PROP_TAG(PT_OBJECT, 32863)
|
||||
PR_EMS_AB_CAN_NOT_CREATE_PF_DL_BL_T = PROP_TAG(PT_MV_TSTRING, 32863)
|
||||
PR_EMS_AB_CAN_PRESERVE_DNS = PROP_TAG(PT_BOOLEAN, 32864)
|
||||
PR_EMS_AB_CERTIFICATE_REVOCATION_LIST = PROP_TAG(PT_BINARY, 32790)
|
||||
PR_EMS_AB_CLOCK_ALERT_OFFSET = PROP_TAG(PT_LONG, 32865)
|
||||
PR_EMS_AB_CLOCK_ALERT_REPAIR = PROP_TAG(PT_BOOLEAN, 32866)
|
||||
PR_EMS_AB_CLOCK_WARNING_OFFSET = PROP_TAG(PT_LONG, 32867)
|
||||
PR_EMS_AB_CLOCK_WARNING_REPAIR = PROP_TAG(PT_BOOLEAN, 32868)
|
||||
PR_EMS_AB_COMPUTER_NAME = PROP_TAG(PT_TSTRING, 32869)
|
||||
PR_EMS_AB_COMPUTER_NAME_A = PROP_TAG(PT_STRING8, 32869)
|
||||
PR_EMS_AB_COMPUTER_NAME_W = PROP_TAG(PT_UNICODE, 32869)
|
||||
PR_EMS_AB_CONNECTED_DOMAINS = PROP_TAG(PT_MV_TSTRING, 32870)
|
||||
PR_EMS_AB_CONNECTED_DOMAINS_A = PROP_TAG(PT_MV_STRING8, 32870)
|
||||
PR_EMS_AB_CONNECTED_DOMAINS_W = PROP_TAG(PT_MV_UNICODE, 32870)
|
||||
PR_EMS_AB_CONTAINER_INFO = PROP_TAG(PT_LONG, 32871)
|
||||
PR_EMS_AB_COST = PROP_TAG(PT_LONG, 32872)
|
||||
PR_EMS_AB_COUNTRY_NAME = PROP_TAG(PT_TSTRING, 32873)
|
||||
PR_EMS_AB_COUNTRY_NAME_A = PROP_TAG(PT_STRING8, 32873)
|
||||
PR_EMS_AB_COUNTRY_NAME_W = PROP_TAG(PT_UNICODE, 32873)
|
||||
PR_EMS_AB_CROSS_CERTIFICATE_PAIR = PROP_TAG(PT_MV_BINARY, 32805)
|
||||
PR_EMS_AB_DELIV_CONT_LENGTH = PROP_TAG(PT_LONG, 32874)
|
||||
PR_EMS_AB_DELIV_EITS = PROP_TAG(PT_MV_BINARY, 32875)
|
||||
PR_EMS_AB_DELIV_EXT_CONT_TYPES = PROP_TAG(PT_MV_BINARY, 32876)
|
||||
PR_EMS_AB_DELIVER_AND_REDIRECT = PROP_TAG(PT_BOOLEAN, 32877)
|
||||
PR_EMS_AB_DELIVERY_MECHANISM = PROP_TAG(PT_LONG, 32878)
|
||||
PR_EMS_AB_DESCRIPTION = PROP_TAG(PT_MV_TSTRING, 32879)
|
||||
PR_EMS_AB_DESCRIPTION_A = PROP_TAG(PT_MV_STRING8, 32879)
|
||||
PR_EMS_AB_DESCRIPTION_W = PROP_TAG(PT_MV_UNICODE, 32879)
|
||||
PR_EMS_AB_DESTINATION_INDICATOR = PROP_TAG(PT_MV_TSTRING, 32880)
|
||||
PR_EMS_AB_DESTINATION_INDICATOR_A = PROP_TAG(PT_MV_STRING8, 32880)
|
||||
PR_EMS_AB_DESTINATION_INDICATOR_W = PROP_TAG(PT_MV_UNICODE, 32880)
|
||||
PR_EMS_AB_DIAGNOSTIC_REG_KEY = PROP_TAG(PT_TSTRING, 32881)
|
||||
PR_EMS_AB_DIAGNOSTIC_REG_KEY_A = PROP_TAG(PT_STRING8, 32881)
|
||||
PR_EMS_AB_DIAGNOSTIC_REG_KEY_W = PROP_TAG(PT_UNICODE, 32881)
|
||||
PR_EMS_AB_DISPLAY_NAME_OVERRIDE = PROP_TAG(PT_BOOLEAN, 32769)
|
||||
PR_EMS_AB_DL_MEM_REJECT_PERMS_BL = PROP_TAG(PT_MV_TSTRING, 32882)
|
||||
PR_EMS_AB_DL_MEM_REJECT_PERMS_BL_A = PROP_TAG(PT_MV_STRING8, 32882)
|
||||
PR_EMS_AB_DL_MEM_REJECT_PERMS_BL_W = PROP_TAG(PT_MV_UNICODE, 32882)
|
||||
PR_EMS_AB_DL_MEM_REJECT_PERMS_BL_O = PROP_TAG(PT_OBJECT, 32882)
|
||||
PR_EMS_AB_DL_MEM_REJECT_PERMS_BL_T = PROP_TAG(PT_MV_TSTRING, 32882)
|
||||
PR_EMS_AB_DL_MEM_SUBMIT_PERMS_BL = PROP_TAG(PT_MV_TSTRING, 32883)
|
||||
PR_EMS_AB_DL_MEM_SUBMIT_PERMS_BL_A = PROP_TAG(PT_MV_STRING8, 32883)
|
||||
PR_EMS_AB_DL_MEM_SUBMIT_PERMS_BL_W = PROP_TAG(PT_MV_UNICODE, 32883)
|
||||
PR_EMS_AB_DL_MEM_SUBMIT_PERMS_BL_O = PROP_TAG(PT_OBJECT, 32883)
|
||||
PR_EMS_AB_DL_MEM_SUBMIT_PERMS_BL_T = PROP_TAG(PT_MV_TSTRING, 32883)
|
||||
PR_EMS_AB_DL_MEMBER_RULE = PROP_TAG(PT_MV_BINARY, 32884)
|
||||
PR_EMS_AB_DOMAIN_DEF_ALT_RECIP = PROP_TAG(PT_TSTRING, 32885)
|
||||
PR_EMS_AB_DOMAIN_DEF_ALT_RECIP_A = PROP_TAG(PT_STRING8, 32885)
|
||||
PR_EMS_AB_DOMAIN_DEF_ALT_RECIP_W = PROP_TAG(PT_UNICODE, 32885)
|
||||
PR_EMS_AB_DOMAIN_DEF_ALT_RECIP_O = PROP_TAG(PT_OBJECT, 32885)
|
||||
PR_EMS_AB_DOMAIN_DEF_ALT_RECIP_T = PROP_TAG(PT_TSTRING, 32885)
|
||||
PR_EMS_AB_DOMAIN_NAME = PROP_TAG(PT_TSTRING, 32886)
|
||||
PR_EMS_AB_DOMAIN_NAME_A = PROP_TAG(PT_STRING8, 32886)
|
||||
PR_EMS_AB_DOMAIN_NAME_W = PROP_TAG(PT_UNICODE, 32886)
|
||||
PR_EMS_AB_DSA_SIGNATURE = PROP_TAG(PT_BINARY, 32887)
|
||||
PR_EMS_AB_DXA_ADMIN_COPY = PROP_TAG(PT_BOOLEAN, 32888)
|
||||
PR_EMS_AB_DXA_ADMIN_FORWARD = PROP_TAG(PT_BOOLEAN, 32889)
|
||||
PR_EMS_AB_DXA_ADMIN_UPDATE = PROP_TAG(PT_LONG, 32890)
|
||||
PR_EMS_AB_DXA_APPEND_REQCN = PROP_TAG(PT_BOOLEAN, 32891)
|
||||
PR_EMS_AB_DXA_CONF_CONTAINER_LIST = PROP_TAG(PT_MV_TSTRING, 32892)
|
||||
PR_EMS_AB_DXA_CONF_CONTAINER_LIST_A = PROP_TAG(PT_MV_STRING8, 32892)
|
||||
PR_EMS_AB_DXA_CONF_CONTAINER_LIST_W = PROP_TAG(PT_MV_UNICODE, 32892)
|
||||
PR_EMS_AB_DXA_CONF_CONTAINER_LIST_O = PROP_TAG(PT_OBJECT, 32892)
|
||||
PR_EMS_AB_DXA_CONF_CONTAINER_LIST_T = PROP_TAG(PT_MV_TSTRING, 32892)
|
||||
PR_EMS_AB_DXA_CONF_REQ_TIME = PROP_TAG(PT_SYSTIME, 32893)
|
||||
PR_EMS_AB_DXA_CONF_SEQ = PROP_TAG(PT_TSTRING, 32894)
|
||||
PR_EMS_AB_DXA_CONF_SEQ_A = PROP_TAG(PT_STRING8, 32894)
|
||||
PR_EMS_AB_DXA_CONF_SEQ_W = PROP_TAG(PT_UNICODE, 32894)
|
||||
PR_EMS_AB_DXA_CONF_SEQ_USN = PROP_TAG(PT_LONG, 32895)
|
||||
PR_EMS_AB_DXA_EXCHANGE_OPTIONS = PROP_TAG(PT_LONG, 32896)
|
||||
PR_EMS_AB_DXA_EXPORT_NOW = PROP_TAG(PT_BOOLEAN, 32897)
|
||||
PR_EMS_AB_DXA_FLAGS = PROP_TAG(PT_LONG, 32898)
|
||||
PR_EMS_AB_DXA_IMP_SEQ = PROP_TAG(PT_TSTRING, 32899)
|
||||
PR_EMS_AB_DXA_IMP_SEQ_A = PROP_TAG(PT_STRING8, 32899)
|
||||
PR_EMS_AB_DXA_IMP_SEQ_W = PROP_TAG(PT_UNICODE, 32899)
|
||||
PR_EMS_AB_DXA_IMP_SEQ_TIME = PROP_TAG(PT_SYSTIME, 32900)
|
||||
PR_EMS_AB_DXA_IMP_SEQ_USN = PROP_TAG(PT_LONG, 32901)
|
||||
PR_EMS_AB_DXA_IMPORT_NOW = PROP_TAG(PT_BOOLEAN, 32902)
|
||||
PR_EMS_AB_DXA_IN_TEMPLATE_MAP = PROP_TAG(PT_MV_TSTRING, 32903)
|
||||
PR_EMS_AB_DXA_IN_TEMPLATE_MAP_A = PROP_TAG(PT_MV_STRING8, 32903)
|
||||
PR_EMS_AB_DXA_IN_TEMPLATE_MAP_W = PROP_TAG(PT_MV_UNICODE, 32903)
|
||||
PR_EMS_AB_DXA_LOCAL_ADMIN = PROP_TAG(PT_TSTRING, 32904)
|
||||
PR_EMS_AB_DXA_LOCAL_ADMIN_A = PROP_TAG(PT_STRING8, 32904)
|
||||
PR_EMS_AB_DXA_LOCAL_ADMIN_W = PROP_TAG(PT_UNICODE, 32904)
|
||||
PR_EMS_AB_DXA_LOCAL_ADMIN_O = PROP_TAG(PT_OBJECT, 32904)
|
||||
PR_EMS_AB_DXA_LOCAL_ADMIN_T = PROP_TAG(PT_TSTRING, 32904)
|
||||
PR_EMS_AB_DXA_LOGGING_LEVEL = PROP_TAG(PT_LONG, 32905)
|
||||
PR_EMS_AB_DXA_NATIVE_ADDRESS_TYPE = PROP_TAG(PT_TSTRING, 32906)
|
||||
PR_EMS_AB_DXA_NATIVE_ADDRESS_TYPE_A = PROP_TAG(PT_STRING8, 32906)
|
||||
PR_EMS_AB_DXA_NATIVE_ADDRESS_TYPE_W = PROP_TAG(PT_UNICODE, 32906)
|
||||
PR_EMS_AB_DXA_OUT_TEMPLATE_MAP = PROP_TAG(PT_MV_TSTRING, 32907)
|
||||
PR_EMS_AB_DXA_OUT_TEMPLATE_MAP_A = PROP_TAG(PT_MV_STRING8, 32907)
|
||||
PR_EMS_AB_DXA_OUT_TEMPLATE_MAP_W = PROP_TAG(PT_MV_UNICODE, 32907)
|
||||
PR_EMS_AB_DXA_PASSWORD = PROP_TAG(PT_TSTRING, 32908)
|
||||
PR_EMS_AB_DXA_PASSWORD_A = PROP_TAG(PT_STRING8, 32908)
|
||||
PR_EMS_AB_DXA_PASSWORD_W = PROP_TAG(PT_UNICODE, 32908)
|
||||
PR_EMS_AB_DXA_PREV_EXCHANGE_OPTIONS = PROP_TAG(PT_LONG, 32909)
|
||||
PR_EMS_AB_DXA_PREV_EXPORT_NATIVE_ONLY = PROP_TAG(PT_BOOLEAN, 32910)
|
||||
PR_EMS_AB_DXA_PREV_IN_EXCHANGE_SENSITIVITY = PROP_TAG(PT_LONG, 32911)
|
||||
PR_EMS_AB_DXA_PREV_REMOTE_ENTRIES = PROP_TAG(PT_TSTRING, 32912)
|
||||
PR_EMS_AB_DXA_PREV_REMOTE_ENTRIES_A = PROP_TAG(PT_STRING8, 32912)
|
||||
PR_EMS_AB_DXA_PREV_REMOTE_ENTRIES_W = PROP_TAG(PT_UNICODE, 32912)
|
||||
PR_EMS_AB_DXA_PREV_REMOTE_ENTRIES_O = PROP_TAG(PT_OBJECT, 32912)
|
||||
PR_EMS_AB_DXA_PREV_REMOTE_ENTRIES_T = PROP_TAG(PT_TSTRING, 32912)
|
||||
PR_EMS_AB_DXA_PREV_REPLICATION_SENSITIVITY = PROP_TAG(PT_LONG, 32913)
|
||||
PR_EMS_AB_DXA_PREV_TEMPLATE_OPTIONS = PROP_TAG(PT_LONG, 32914)
|
||||
PR_EMS_AB_DXA_PREV_TYPES = PROP_TAG(PT_LONG, 32915)
|
||||
PR_EMS_AB_DXA_RECIPIENT_CP = PROP_TAG(PT_TSTRING, 32916)
|
||||
PR_EMS_AB_DXA_RECIPIENT_CP_A = PROP_TAG(PT_STRING8, 32916)
|
||||
PR_EMS_AB_DXA_RECIPIENT_CP_W = PROP_TAG(PT_UNICODE, 32916)
|
||||
PR_EMS_AB_DXA_REMOTE_CLIENT = PROP_TAG(PT_TSTRING, 32917)
|
||||
PR_EMS_AB_DXA_REMOTE_CLIENT_A = PROP_TAG(PT_STRING8, 32917)
|
||||
PR_EMS_AB_DXA_REMOTE_CLIENT_W = PROP_TAG(PT_UNICODE, 32917)
|
||||
PR_EMS_AB_DXA_REMOTE_CLIENT_O = PROP_TAG(PT_OBJECT, 32917)
|
||||
PR_EMS_AB_DXA_REMOTE_CLIENT_T = PROP_TAG(PT_TSTRING, 32917)
|
||||
PR_EMS_AB_DXA_REQ_SEQ = PROP_TAG(PT_TSTRING, 32918)
|
||||
PR_EMS_AB_DXA_REQ_SEQ_A = PROP_TAG(PT_STRING8, 32918)
|
||||
PR_EMS_AB_DXA_REQ_SEQ_W = PROP_TAG(PT_UNICODE, 32918)
|
||||
PR_EMS_AB_DXA_REQ_SEQ_TIME = PROP_TAG(PT_SYSTIME, 32919)
|
||||
PR_EMS_AB_DXA_REQ_SEQ_USN = PROP_TAG(PT_LONG, 32920)
|
||||
PR_EMS_AB_DXA_REQNAME = PROP_TAG(PT_TSTRING, 32921)
|
||||
PR_EMS_AB_DXA_REQNAME_A = PROP_TAG(PT_STRING8, 32921)
|
||||
PR_EMS_AB_DXA_REQNAME_W = PROP_TAG(PT_UNICODE, 32921)
|
||||
PR_EMS_AB_DXA_SVR_SEQ = PROP_TAG(PT_TSTRING, 32922)
|
||||
PR_EMS_AB_DXA_SVR_SEQ_A = PROP_TAG(PT_STRING8, 32922)
|
||||
PR_EMS_AB_DXA_SVR_SEQ_W = PROP_TAG(PT_UNICODE, 32922)
|
||||
PR_EMS_AB_DXA_SVR_SEQ_TIME = PROP_TAG(PT_SYSTIME, 32923)
|
||||
PR_EMS_AB_DXA_SVR_SEQ_USN = PROP_TAG(PT_LONG, 32924)
|
||||
PR_EMS_AB_DXA_TASK = PROP_TAG(PT_LONG, 32925)
|
||||
PR_EMS_AB_DXA_TEMPLATE_OPTIONS = PROP_TAG(PT_LONG, 32926)
|
||||
PR_EMS_AB_DXA_TEMPLATE_TIMESTAMP = PROP_TAG(PT_SYSTIME, 32927)
|
||||
PR_EMS_AB_DXA_TYPES = PROP_TAG(PT_LONG, 32928)
|
||||
PR_EMS_AB_DXA_UNCONF_CONTAINER_LIST = PROP_TAG(PT_MV_TSTRING, 32929)
|
||||
PR_EMS_AB_DXA_UNCONF_CONTAINER_LIST_A = PROP_TAG(PT_MV_STRING8, 32929)
|
||||
PR_EMS_AB_DXA_UNCONF_CONTAINER_LIST_W = PROP_TAG(PT_MV_UNICODE, 32929)
|
||||
PR_EMS_AB_DXA_UNCONF_CONTAINER_LIST_O = PROP_TAG(PT_OBJECT, 32929)
|
||||
PR_EMS_AB_DXA_UNCONF_CONTAINER_LIST_T = PROP_TAG(PT_MV_TSTRING, 32929)
|
||||
PR_EMS_AB_ENABLED_PROTOCOLS = PROP_TAG(PT_LONG, 33151)
|
||||
PR_EMS_AB_ENCAPSULATION_METHOD = PROP_TAG(PT_LONG, 32930)
|
||||
PR_EMS_AB_ENCRYPT = PROP_TAG(PT_BOOLEAN, 32931)
|
||||
PR_EMS_AB_ENCRYPT_ALG_LIST_NA = PROP_TAG(PT_MV_TSTRING, 32832)
|
||||
PR_EMS_AB_ENCRYPT_ALG_LIST_NA_A = PROP_TAG(PT_MV_STRING8, 32832)
|
||||
PR_EMS_AB_ENCRYPT_ALG_LIST_NA_W = PROP_TAG(PT_MV_UNICODE, 32832)
|
||||
PR_EMS_AB_ENCRYPT_ALG_LIST_OTHER = PROP_TAG(PT_MV_TSTRING, 32833)
|
||||
PR_EMS_AB_ENCRYPT_ALG_LIST_OTHER_A = PROP_TAG(PT_MV_STRING8, 32833)
|
||||
PR_EMS_AB_ENCRYPT_ALG_LIST_OTHER_W = PROP_TAG(PT_MV_UNICODE, 32833)
|
||||
PR_EMS_AB_ENCRYPT_ALG_SELECTED_NA = PROP_TAG(PT_TSTRING, 32835)
|
||||
PR_EMS_AB_ENCRYPT_ALG_SELECTED_NA_A = PROP_TAG(PT_STRING8, 32835)
|
||||
PR_EMS_AB_ENCRYPT_ALG_SELECTED_NA_W = PROP_TAG(PT_UNICODE, 32835)
|
||||
PR_EMS_AB_ENCRYPT_ALG_SELECTED_OTHER = PROP_TAG(PT_TSTRING, 32829)
|
||||
PR_EMS_AB_ENCRYPT_ALG_SELECTED_OTHER_A = PROP_TAG(PT_STRING8, 32829)
|
||||
PR_EMS_AB_ENCRYPT_ALG_SELECTED_OTHER_W = PROP_TAG(PT_UNICODE, 32829)
|
||||
PR_EMS_AB_EXPAND_DLS_LOCALLY = PROP_TAG(PT_BOOLEAN, 32932)
|
||||
PR_EMS_AB_EXPIRATION_TIME = PROP_TAG(PT_SYSTIME, 32808)
|
||||
PR_EMS_AB_EXPORT_CONTAINERS = PROP_TAG(PT_MV_TSTRING, 32933)
|
||||
PR_EMS_AB_EXPORT_CONTAINERS_A = PROP_TAG(PT_MV_STRING8, 32933)
|
||||
PR_EMS_AB_EXPORT_CONTAINERS_W = PROP_TAG(PT_MV_UNICODE, 32933)
|
||||
PR_EMS_AB_EXPORT_CONTAINERS_O = PROP_TAG(PT_OBJECT, 32933)
|
||||
PR_EMS_AB_EXPORT_CONTAINERS_T = PROP_TAG(PT_MV_TSTRING, 32933)
|
||||
PR_EMS_AB_EXPORT_CUSTOM_RECIPIENTS = PROP_TAG(PT_BOOLEAN, 32934)
|
||||
PR_EMS_AB_EXTENDED_CHARS_ALLOWED = PROP_TAG(PT_BOOLEAN, 32935)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_1 = PROP_TAG(PT_TSTRING, 32813)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_1_A = PROP_TAG(PT_STRING8, 32813)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_1_W = PROP_TAG(PT_UNICODE, 32813)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_10 = PROP_TAG(PT_TSTRING, 32822)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_10_A = PROP_TAG(PT_STRING8, 32822)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_10_W = PROP_TAG(PT_UNICODE, 32822)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_2 = PROP_TAG(PT_TSTRING, 32814)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_2_A = PROP_TAG(PT_STRING8, 32814)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_2_W = PROP_TAG(PT_UNICODE, 32814)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_3 = PROP_TAG(PT_TSTRING, 32815)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_3_A = PROP_TAG(PT_STRING8, 32815)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_3_W = PROP_TAG(PT_UNICODE, 32815)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_4 = PROP_TAG(PT_TSTRING, 32816)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_4_A = PROP_TAG(PT_STRING8, 32816)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_4_W = PROP_TAG(PT_UNICODE, 32816)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_5 = PROP_TAG(PT_TSTRING, 32817)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_5_A = PROP_TAG(PT_STRING8, 32817)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_5_W = PROP_TAG(PT_UNICODE, 32817)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_6 = PROP_TAG(PT_TSTRING, 32818)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_6_A = PROP_TAG(PT_STRING8, 32818)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_6_W = PROP_TAG(PT_UNICODE, 32818)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_7 = PROP_TAG(PT_TSTRING, 32819)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_7_A = PROP_TAG(PT_STRING8, 32819)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_7_W = PROP_TAG(PT_UNICODE, 32819)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_8 = PROP_TAG(PT_TSTRING, 32820)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_8_A = PROP_TAG(PT_STRING8, 32820)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_8_W = PROP_TAG(PT_UNICODE, 32820)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_9 = PROP_TAG(PT_TSTRING, 32821)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_9_A = PROP_TAG(PT_STRING8, 32821)
|
||||
PR_EMS_AB_EXTENSION_ATTRIBUTE_9_W = PROP_TAG(PT_UNICODE, 32821)
|
||||
PR_EMS_AB_EXTENSION_DATA = PROP_TAG(PT_MV_BINARY, 32936)
|
||||
PR_EMS_AB_EXTENSION_NAME = PROP_TAG(PT_MV_TSTRING, 32937)
|
||||
PR_EMS_AB_EXTENSION_NAME_A = PROP_TAG(PT_MV_STRING8, 32937)
|
||||
PR_EMS_AB_EXTENSION_NAME_W = PROP_TAG(PT_MV_UNICODE, 32937)
|
||||
PR_EMS_AB_EXTENSION_NAME_INHERITED = PROP_TAG(PT_MV_TSTRING, 32938)
|
||||
PR_EMS_AB_EXTENSION_NAME_INHERITED_A = PROP_TAG(PT_MV_STRING8, 32938)
|
||||
PR_EMS_AB_EXTENSION_NAME_INHERITED_W = PROP_TAG(PT_MV_UNICODE, 32938)
|
||||
PR_EMS_AB_FACSIMILE_TELEPHONE_NUMBER = PROP_TAG(PT_MV_BINARY, 32939)
|
||||
PR_EMS_AB_FILE_VERSION = PROP_TAG(PT_BINARY, 32940)
|
||||
PR_EMS_AB_FILTER_LOCAL_ADDRESSES = PROP_TAG(PT_BOOLEAN, 32941)
|
||||
PR_EMS_AB_FOLDER_PATHNAME = PROP_TAG(PT_TSTRING, 32772)
|
||||
PR_EMS_AB_FOLDER_PATHNAME_A = PROP_TAG(PT_STRING8, 32772)
|
||||
PR_EMS_AB_FOLDER_PATHNAME_W = PROP_TAG(PT_UNICODE, 32772)
|
||||
PR_EMS_AB_FOLDERS_CONTAINER = PROP_TAG(PT_TSTRING, 32942)
|
||||
PR_EMS_AB_FOLDERS_CONTAINER_A = PROP_TAG(PT_STRING8, 32942)
|
||||
PR_EMS_AB_FOLDERS_CONTAINER_W = PROP_TAG(PT_UNICODE, 32942)
|
||||
PR_EMS_AB_FOLDERS_CONTAINER_O = PROP_TAG(PT_OBJECT, 32942)
|
||||
PR_EMS_AB_FOLDERS_CONTAINER_T = PROP_TAG(PT_TSTRING, 32942)
|
||||
PR_EMS_AB_GARBAGE_COLL_PERIOD = PROP_TAG(PT_LONG, 32943)
|
||||
PR_EMS_AB_GATEWAY_LOCAL_CRED = PROP_TAG(PT_TSTRING, 32944)
|
||||
PR_EMS_AB_GATEWAY_LOCAL_CRED_A = PROP_TAG(PT_STRING8, 32944)
|
||||
PR_EMS_AB_GATEWAY_LOCAL_CRED_W = PROP_TAG(PT_UNICODE, 32944)
|
||||
PR_EMS_AB_GATEWAY_LOCAL_DESIG = PROP_TAG(PT_TSTRING, 32945)
|
||||
PR_EMS_AB_GATEWAY_LOCAL_DESIG_A = PROP_TAG(PT_STRING8, 32945)
|
||||
PR_EMS_AB_GATEWAY_LOCAL_DESIG_W = PROP_TAG(PT_UNICODE, 32945)
|
||||
PR_EMS_AB_GATEWAY_PROXY = PROP_TAG(PT_MV_TSTRING, 32946)
|
||||
PR_EMS_AB_GATEWAY_PROXY_A = PROP_TAG(PT_MV_STRING8, 32946)
|
||||
PR_EMS_AB_GATEWAY_PROXY_W = PROP_TAG(PT_MV_UNICODE, 32946)
|
||||
PR_EMS_AB_GATEWAY_ROUTING_TREE = PROP_TAG(PT_BINARY, 32947)
|
||||
PR_EMS_AB_GWART_LAST_MODIFIED = PROP_TAG(PT_SYSTIME, 32948)
|
||||
PR_EMS_AB_HAS_FULL_REPLICA_NCS = PROP_TAG(PT_MV_TSTRING, 32949)
|
||||
PR_EMS_AB_HAS_FULL_REPLICA_NCS_A = PROP_TAG(PT_MV_STRING8, 32949)
|
||||
PR_EMS_AB_HAS_FULL_REPLICA_NCS_W = PROP_TAG(PT_MV_UNICODE, 32949)
|
||||
PR_EMS_AB_HAS_FULL_REPLICA_NCS_O = PROP_TAG(PT_OBJECT, 32949)
|
||||
PR_EMS_AB_HAS_FULL_REPLICA_NCS_T = PROP_TAG(PT_MV_TSTRING, 32949)
|
||||
PR_EMS_AB_HAS_MASTER_NCS = PROP_TAG(PT_MV_TSTRING, 32950)
|
||||
PR_EMS_AB_HAS_MASTER_NCS_A = PROP_TAG(PT_MV_STRING8, 32950)
|
||||
PR_EMS_AB_HAS_MASTER_NCS_W = PROP_TAG(PT_MV_UNICODE, 32950)
|
||||
PR_EMS_AB_HAS_MASTER_NCS_O = PROP_TAG(PT_OBJECT, 32950)
|
||||
PR_EMS_AB_HAS_MASTER_NCS_T = PROP_TAG(PT_MV_TSTRING, 32950)
|
||||
PR_EMS_AB_HELP_DATA16 = PROP_TAG(PT_BINARY, 32826)
|
||||
PR_EMS_AB_HELP_DATA32 = PROP_TAG(PT_BINARY, 32784)
|
||||
PR_EMS_AB_HELP_FILE_NAME = PROP_TAG(PT_TSTRING, 32827)
|
||||
PR_EMS_AB_HELP_FILE_NAME_A = PROP_TAG(PT_STRING8, 32827)
|
||||
PR_EMS_AB_HELP_FILE_NAME_W = PROP_TAG(PT_UNICODE, 32827)
|
||||
PR_EMS_AB_HEURISTICS = PROP_TAG(PT_LONG, 32951)
|
||||
PR_EMS_AB_HIDE_DL_MEMBERSHIP = PROP_TAG(PT_BOOLEAN, 32952)
|
||||
PR_EMS_AB_HIDE_FROM_ADDRESS_BOOK = PROP_TAG(PT_BOOLEAN, 32953)
|
||||
PR_EMS_AB_HOME_MDB = PROP_TAG(PT_TSTRING, 32774)
|
||||
PR_EMS_AB_HOME_MDB_A = PROP_TAG(PT_STRING8, 32774)
|
||||
PR_EMS_AB_HOME_MDB_W = PROP_TAG(PT_UNICODE, 32774)
|
||||
PR_EMS_AB_HOME_MDB_O = PROP_TAG(PT_OBJECT, 32774)
|
||||
PR_EMS_AB_HOME_MDB_T = PROP_TAG(PT_TSTRING, 32774)
|
||||
PR_EMS_AB_HOME_MDB_BL = PROP_TAG(PT_MV_TSTRING, 32788)
|
||||
PR_EMS_AB_HOME_MDB_BL_A = PROP_TAG(PT_MV_STRING8, 32788)
|
||||
PR_EMS_AB_HOME_MDB_BL_W = PROP_TAG(PT_MV_UNICODE, 32788)
|
||||
PR_EMS_AB_HOME_MDB_BL_O = PROP_TAG(PT_OBJECT, 32788)
|
||||
PR_EMS_AB_HOME_MDB_BL_T = PROP_TAG(PT_MV_TSTRING, 32788)
|
||||
PR_EMS_AB_HOME_MTA = PROP_TAG(PT_TSTRING, 32775)
|
||||
PR_EMS_AB_HOME_MTA_A = PROP_TAG(PT_STRING8, 32775)
|
||||
PR_EMS_AB_HOME_MTA_W = PROP_TAG(PT_UNICODE, 32775)
|
||||
PR_EMS_AB_HOME_MTA_O = PROP_TAG(PT_OBJECT, 32775)
|
||||
PR_EMS_AB_HOME_MTA_T = PROP_TAG(PT_TSTRING, 32775)
|
||||
PR_EMS_AB_HOME_PUBLIC_SERVER = PROP_TAG(PT_TSTRING, 32831)
|
||||
PR_EMS_AB_HOME_PUBLIC_SERVER_A = PROP_TAG(PT_STRING8, 32831)
|
||||
PR_EMS_AB_HOME_PUBLIC_SERVER_W = PROP_TAG(PT_UNICODE, 32831)
|
||||
PR_EMS_AB_HOME_PUBLIC_SERVER_O = PROP_TAG(PT_OBJECT, 32831)
|
||||
PR_EMS_AB_HOME_PUBLIC_SERVER_T = PROP_TAG(PT_TSTRING, 32831)
|
||||
PR_EMS_AB_IMPORT_CONTAINER = PROP_TAG(PT_TSTRING, 32954)
|
||||
PR_EMS_AB_IMPORT_CONTAINER_A = PROP_TAG(PT_STRING8, 32954)
|
||||
PR_EMS_AB_IMPORT_CONTAINER_W = PROP_TAG(PT_UNICODE, 32954)
|
||||
PR_EMS_AB_IMPORT_CONTAINER_O = PROP_TAG(PT_OBJECT, 32954)
|
||||
PR_EMS_AB_IMPORT_CONTAINER_T = PROP_TAG(PT_TSTRING, 32954)
|
||||
PR_EMS_AB_IMPORT_SENSITIVITY = PROP_TAG(PT_LONG, 32955)
|
||||
PR_EMS_AB_IMPORTED_FROM = PROP_TAG(PT_TSTRING, 32834)
|
||||
PR_EMS_AB_IMPORTED_FROM_A = PROP_TAG(PT_STRING8, 32834)
|
||||
PR_EMS_AB_IMPORTED_FROM_W = PROP_TAG(PT_UNICODE, 32834)
|
||||
PR_EMS_AB_INBOUND_SITES = PROP_TAG(PT_MV_TSTRING, 32956)
|
||||
PR_EMS_AB_INBOUND_SITES_A = PROP_TAG(PT_MV_STRING8, 32956)
|
||||
PR_EMS_AB_INBOUND_SITES_W = PROP_TAG(PT_MV_UNICODE, 32956)
|
||||
PR_EMS_AB_INBOUND_SITES_O = PROP_TAG(PT_OBJECT, 32956)
|
||||
PR_EMS_AB_INBOUND_SITES_T = PROP_TAG(PT_MV_TSTRING, 32956)
|
||||
PR_EMS_AB_INSTANCE_TYPE = PROP_TAG(PT_LONG, 32957)
|
||||
PR_EMS_AB_INTERNATIONAL_ISDN_NUMBER = PROP_TAG(PT_MV_TSTRING, 32958)
|
||||
PR_EMS_AB_INTERNATIONAL_ISDN_NUMBER_A = PROP_TAG(PT_MV_STRING8, 32958)
|
||||
PR_EMS_AB_INTERNATIONAL_ISDN_NUMBER_W = PROP_TAG(PT_MV_UNICODE, 32958)
|
||||
PR_EMS_AB_INVOCATION_ID = PROP_TAG(PT_BINARY, 32959)
|
||||
PR_EMS_AB_IS_DELETED = PROP_TAG(PT_BOOLEAN, 32960)
|
||||
PR_EMS_AB_IS_MEMBER_OF_DL = PROP_TAG(PT_OBJECT, 32776)
|
||||
PR_EMS_AB_IS_MEMBER_OF_DL_A = PROP_TAG(PT_MV_STRING8, 32776)
|
||||
PR_EMS_AB_IS_MEMBER_OF_DL_W = PROP_TAG(PT_MV_UNICODE, 32776)
|
||||
PR_EMS_AB_IS_MEMBER_OF_DL_O = PROP_TAG(PT_OBJECT, 32776)
|
||||
PR_EMS_AB_IS_MEMBER_OF_DL_T = PROP_TAG(PT_MV_TSTRING, 32776)
|
||||
PR_EMS_AB_IS_SINGLE_VALUED = PROP_TAG(PT_BOOLEAN, 32961)
|
||||
PR_EMS_AB_KCC_STATUS = PROP_TAG(PT_MV_BINARY, 32962)
|
||||
PR_EMS_AB_KM_SERVER = PROP_TAG(PT_TSTRING, 32781)
|
||||
PR_EMS_AB_KM_SERVER_A = PROP_TAG(PT_STRING8, 32781)
|
||||
PR_EMS_AB_KM_SERVER_W = PROP_TAG(PT_UNICODE, 32781)
|
||||
PR_EMS_AB_KM_SERVER_O = PROP_TAG(PT_OBJECT, 32781)
|
||||
PR_EMS_AB_KM_SERVER_T = PROP_TAG(PT_TSTRING, 32781)
|
||||
PR_EMS_AB_KNOWLEDGE_INFORMATION = PROP_TAG(PT_MV_TSTRING, 32963)
|
||||
PR_EMS_AB_KNOWLEDGE_INFORMATION_A = PROP_TAG(PT_MV_STRING8, 32963)
|
||||
PR_EMS_AB_KNOWLEDGE_INFORMATION_W = PROP_TAG(PT_MV_UNICODE, 32963)
|
||||
PR_EMS_AB_LANGUAGE = PROP_TAG(PT_LONG, 33144)
|
||||
PR_EMS_AB_LDAP_DISPLAY_NAME = PROP_TAG(PT_MV_TSTRING, 33137)
|
||||
PR_EMS_AB_LDAP_DISPLAY_NAME_A = PROP_TAG(PT_MV_STRING8, 33137)
|
||||
PR_EMS_AB_LDAP_DISPLAY_NAME_W = PROP_TAG(PT_MV_UNICODE, 33137)
|
||||
PR_EMS_AB_LINE_WRAP = PROP_TAG(PT_LONG, 32964)
|
||||
PR_EMS_AB_LINK_ID = PROP_TAG(PT_LONG, 32965)
|
||||
PR_EMS_AB_LOCAL_BRIDGE_HEAD = PROP_TAG(PT_TSTRING, 32966)
|
||||
PR_EMS_AB_LOCAL_BRIDGE_HEAD_A = PROP_TAG(PT_STRING8, 32966)
|
||||
PR_EMS_AB_LOCAL_BRIDGE_HEAD_W = PROP_TAG(PT_UNICODE, 32966)
|
||||
PR_EMS_AB_LOCAL_BRIDGE_HEAD_ADDRESS = PROP_TAG(PT_TSTRING, 32967)
|
||||
PR_EMS_AB_LOCAL_BRIDGE_HEAD_ADDRESS_A = PROP_TAG(PT_STRING8, 32967)
|
||||
PR_EMS_AB_LOCAL_BRIDGE_HEAD_ADDRESS_W = PROP_TAG(PT_UNICODE, 32967)
|
||||
PR_EMS_AB_LOCAL_INITIAL_TURN = PROP_TAG(PT_BOOLEAN, 32968)
|
||||
PR_EMS_AB_LOCAL_SCOPE = PROP_TAG(PT_MV_TSTRING, 32969)
|
||||
PR_EMS_AB_LOCAL_SCOPE_A = PROP_TAG(PT_MV_STRING8, 32969)
|
||||
PR_EMS_AB_LOCAL_SCOPE_W = PROP_TAG(PT_MV_UNICODE, 32969)
|
||||
PR_EMS_AB_LOCAL_SCOPE_O = PROP_TAG(PT_OBJECT, 32969)
|
||||
PR_EMS_AB_LOCAL_SCOPE_T = PROP_TAG(PT_MV_TSTRING, 32969)
|
||||
PR_EMS_AB_LOG_FILENAME = PROP_TAG(PT_TSTRING, 32970)
|
||||
PR_EMS_AB_LOG_FILENAME_A = PROP_TAG(PT_STRING8, 32970)
|
||||
PR_EMS_AB_LOG_FILENAME_W = PROP_TAG(PT_UNICODE, 32970)
|
||||
PR_EMS_AB_LOG_ROLLOVER_INTERVAL = PROP_TAG(PT_LONG, 32971)
|
||||
PR_EMS_AB_MAINTAIN_AUTOREPLY_HISTORY = PROP_TAG(PT_BOOLEAN, 32972)
|
||||
PR_EMS_AB_MANAGER = PROP_TAG(PT_OBJECT, 32773)
|
||||
PR_EMS_AB_MANAGER_A = PROP_TAG(PT_STRING8, 32773)
|
||||
PR_EMS_AB_MANAGER_W = PROP_TAG(PT_UNICODE, 32773)
|
||||
PR_EMS_AB_MANAGER_O = PROP_TAG(PT_OBJECT, 32773)
|
||||
PR_EMS_AB_MANAGER_T = PROP_TAG(PT_TSTRING, 32773)
|
||||
PR_EMS_AB_MAPI_DISPLAY_TYPE = PROP_TAG(PT_LONG, 32973)
|
||||
PR_EMS_AB_MAPI_ID = PROP_TAG(PT_LONG, 32974)
|
||||
PR_EMS_AB_MAXIMUM_OBJECT_ID = PROP_TAG(PT_BINARY, 33129)
|
||||
PR_EMS_AB_MDB_BACKOFF_INTERVAL = PROP_TAG(PT_LONG, 32975)
|
||||
PR_EMS_AB_MDB_MSG_TIME_OUT_PERIOD = PROP_TAG(PT_LONG, 32976)
|
||||
PR_EMS_AB_MDB_OVER_QUOTA_LIMIT = PROP_TAG(PT_LONG, 32977)
|
||||
PR_EMS_AB_MDB_STORAGE_QUOTA = PROP_TAG(PT_LONG, 32978)
|
||||
PR_EMS_AB_MDB_UNREAD_LIMIT = PROP_TAG(PT_LONG, 32979)
|
||||
PR_EMS_AB_MDB_USE_DEFAULTS = PROP_TAG(PT_BOOLEAN, 32980)
|
||||
PR_EMS_AB_MEMBER = PROP_TAG(PT_OBJECT, 32777)
|
||||
PR_EMS_AB_MEMBER_A = PROP_TAG(PT_MV_STRING8, 32777)
|
||||
PR_EMS_AB_MEMBER_W = PROP_TAG(PT_MV_UNICODE, 32777)
|
||||
PR_EMS_AB_MEMBER_O = PROP_TAG(PT_OBJECT, 32777)
|
||||
PR_EMS_AB_MEMBER_T = PROP_TAG(PT_MV_TSTRING, 32777)
|
||||
PR_EMS_AB_MESSAGE_TRACKING_ENABLED = PROP_TAG(PT_BOOLEAN, 32981)
|
||||
PR_EMS_AB_MONITOR_CLOCK = PROP_TAG(PT_BOOLEAN, 32982)
|
||||
PR_EMS_AB_MONITOR_SERVERS = PROP_TAG(PT_BOOLEAN, 32983)
|
||||
PR_EMS_AB_MONITOR_SERVICES = PROP_TAG(PT_BOOLEAN, 32984)
|
||||
PR_EMS_AB_MONITORED_CONFIGURATIONS = PROP_TAG(PT_MV_TSTRING, 32985)
|
||||
PR_EMS_AB_MONITORED_CONFIGURATIONS_A = PROP_TAG(PT_MV_STRING8, 32985)
|
||||
PR_EMS_AB_MONITORED_CONFIGURATIONS_W = PROP_TAG(PT_MV_UNICODE, 32985)
|
||||
PR_EMS_AB_MONITORED_CONFIGURATIONS_O = PROP_TAG(PT_OBJECT, 32985)
|
||||
PR_EMS_AB_MONITORED_CONFIGURATIONS_T = PROP_TAG(PT_MV_TSTRING, 32985)
|
||||
PR_EMS_AB_MONITORED_SERVERS = PROP_TAG(PT_MV_TSTRING, 32986)
|
||||
PR_EMS_AB_MONITORED_SERVERS_A = PROP_TAG(PT_MV_STRING8, 32986)
|
||||
PR_EMS_AB_MONITORED_SERVERS_W = PROP_TAG(PT_MV_UNICODE, 32986)
|
||||
PR_EMS_AB_MONITORED_SERVERS_O = PROP_TAG(PT_OBJECT, 32986)
|
||||
PR_EMS_AB_MONITORED_SERVERS_T = PROP_TAG(PT_MV_TSTRING, 32986)
|
||||
PR_EMS_AB_MONITORED_SERVICES = PROP_TAG(PT_MV_TSTRING, 32987)
|
||||
PR_EMS_AB_MONITORED_SERVICES_A = PROP_TAG(PT_MV_STRING8, 32987)
|
||||
PR_EMS_AB_MONITORED_SERVICES_W = PROP_TAG(PT_MV_UNICODE, 32987)
|
||||
PR_EMS_AB_MONITORING_ALERT_DELAY = PROP_TAG(PT_LONG, 32988)
|
||||
PR_EMS_AB_MONITORING_ALERT_UNITS = PROP_TAG(PT_LONG, 32989)
|
||||
PR_EMS_AB_MONITORING_AVAILABILITY_STYLE = PROP_TAG(PT_LONG, 32990)
|
||||
PR_EMS_AB_MONITORING_AVAILABILITY_WINDOW = PROP_TAG(PT_BINARY, 32991)
|
||||
PR_EMS_AB_MONITORING_CACHED_VIA_MAIL = PROP_TAG(PT_MV_TSTRING, 32992)
|
||||
PR_EMS_AB_MONITORING_CACHED_VIA_MAIL_A = PROP_TAG(PT_MV_STRING8, 32992)
|
||||
PR_EMS_AB_MONITORING_CACHED_VIA_MAIL_W = PROP_TAG(PT_MV_UNICODE, 32992)
|
||||
PR_EMS_AB_MONITORING_CACHED_VIA_MAIL_O = PROP_TAG(PT_OBJECT, 32992)
|
||||
PR_EMS_AB_MONITORING_CACHED_VIA_MAIL_T = PROP_TAG(PT_MV_TSTRING, 32992)
|
||||
PR_EMS_AB_MONITORING_CACHED_VIA_RPC = PROP_TAG(PT_MV_TSTRING, 32993)
|
||||
PR_EMS_AB_MONITORING_CACHED_VIA_RPC_A = PROP_TAG(PT_MV_STRING8, 32993)
|
||||
PR_EMS_AB_MONITORING_CACHED_VIA_RPC_W = PROP_TAG(PT_MV_UNICODE, 32993)
|
||||
PR_EMS_AB_MONITORING_CACHED_VIA_RPC_O = PROP_TAG(PT_OBJECT, 32993)
|
||||
PR_EMS_AB_MONITORING_CACHED_VIA_RPC_T = PROP_TAG(PT_MV_TSTRING, 32993)
|
||||
PR_EMS_AB_MONITORING_ESCALATION_PROCEDURE = PROP_TAG(PT_MV_BINARY, 32994)
|
||||
PR_EMS_AB_MONITORING_HOTSITE_POLL_INTERVAL = PROP_TAG(PT_LONG, 32995)
|
||||
PR_EMS_AB_MONITORING_HOTSITE_POLL_UNITS = PROP_TAG(PT_LONG, 32996)
|
||||
PR_EMS_AB_MONITORING_MAIL_UPDATE_INTERVAL = PROP_TAG(PT_LONG, 32997)
|
||||
PR_EMS_AB_MONITORING_MAIL_UPDATE_UNITS = PROP_TAG(PT_LONG, 32998)
|
||||
PR_EMS_AB_MONITORING_NORMAL_POLL_INTERVAL = PROP_TAG(PT_LONG, 32999)
|
||||
PR_EMS_AB_MONITORING_NORMAL_POLL_UNITS = PROP_TAG(PT_LONG, 33000)
|
||||
PR_EMS_AB_MONITORING_RECIPIENTS = PROP_TAG(PT_MV_TSTRING, 33001)
|
||||
PR_EMS_AB_MONITORING_RECIPIENTS_A = PROP_TAG(PT_MV_STRING8, 33001)
|
||||
PR_EMS_AB_MONITORING_RECIPIENTS_W = PROP_TAG(PT_MV_UNICODE, 33001)
|
||||
PR_EMS_AB_MONITORING_RECIPIENTS_O = PROP_TAG(PT_OBJECT, 33001)
|
||||
PR_EMS_AB_MONITORING_RECIPIENTS_T = PROP_TAG(PT_MV_TSTRING, 33001)
|
||||
PR_EMS_AB_MONITORING_RECIPIENTS_NDR = PROP_TAG(PT_MV_TSTRING, 33002)
|
||||
PR_EMS_AB_MONITORING_RECIPIENTS_NDR_A = PROP_TAG(PT_MV_STRING8, 33002)
|
||||
PR_EMS_AB_MONITORING_RECIPIENTS_NDR_W = PROP_TAG(PT_MV_UNICODE, 33002)
|
||||
PR_EMS_AB_MONITORING_RECIPIENTS_NDR_O = PROP_TAG(PT_OBJECT, 33002)
|
||||
PR_EMS_AB_MONITORING_RECIPIENTS_NDR_T = PROP_TAG(PT_MV_TSTRING, 33002)
|
||||
PR_EMS_AB_MONITORING_RPC_UPDATE_INTERVAL = PROP_TAG(PT_LONG, 33003)
|
||||
PR_EMS_AB_MONITORING_RPC_UPDATE_UNITS = PROP_TAG(PT_LONG, 33004)
|
||||
PR_EMS_AB_MONITORING_WARNING_DELAY = PROP_TAG(PT_LONG, 33005)
|
||||
PR_EMS_AB_MONITORING_WARNING_UNITS = PROP_TAG(PT_LONG, 33006)
|
||||
PR_EMS_AB_MTA_LOCAL_CRED = PROP_TAG(PT_TSTRING, 33007)
|
||||
PR_EMS_AB_MTA_LOCAL_CRED_A = PROP_TAG(PT_STRING8, 33007)
|
||||
PR_EMS_AB_MTA_LOCAL_CRED_W = PROP_TAG(PT_UNICODE, 33007)
|
||||
PR_EMS_AB_MTA_LOCAL_DESIG = PROP_TAG(PT_TSTRING, 33008)
|
||||
PR_EMS_AB_MTA_LOCAL_DESIG_A = PROP_TAG(PT_STRING8, 33008)
|
||||
PR_EMS_AB_MTA_LOCAL_DESIG_W = PROP_TAG(PT_UNICODE, 33008)
|
||||
PR_EMS_AB_N_ADDRESS = PROP_TAG(PT_BINARY, 33009)
|
||||
PR_EMS_AB_N_ADDRESS_TYPE = PROP_TAG(PT_LONG, 33010)
|
||||
PR_EMS_AB_NETWORK_ADDRESS = PROP_TAG(PT_MV_TSTRING, 33136)
|
||||
PR_EMS_AB_NETWORK_ADDRESS_A = PROP_TAG(PT_MV_STRING8, 33136)
|
||||
PR_EMS_AB_NETWORK_ADDRESS_W = PROP_TAG(PT_MV_UNICODE, 33136)
|
||||
PR_EMS_AB_NNTP_CHARACTER_SET = PROP_TAG(PT_TSTRING, 33149)
|
||||
PR_EMS_AB_NNTP_CHARACTER_SET_A = PROP_TAG(PT_STRING8, 33149)
|
||||
PR_EMS_AB_NNTP_CHARACTER_SET_W = PROP_TAG(PT_UNICODE, 33149)
|
||||
PR_EMS_AB_NNTP_CONTENT_FORMAT = PROP_TAG(PT_TSTRING, 33142)
|
||||
PR_EMS_AB_NNTP_CONTENT_FORMAT_A = PROP_TAG(PT_STRING8, 33142)
|
||||
PR_EMS_AB_NNTP_CONTENT_FORMAT_W = PROP_TAG(PT_UNICODE, 33142)
|
||||
PR_EMS_AB_NT_MACHINE_NAME = PROP_TAG(PT_TSTRING, 33011)
|
||||
PR_EMS_AB_NT_MACHINE_NAME_A = PROP_TAG(PT_STRING8, 33011)
|
||||
PR_EMS_AB_NT_MACHINE_NAME_W = PROP_TAG(PT_UNICODE, 33011)
|
||||
PR_EMS_AB_NT_SECURITY_DESCRIPTOR = PROP_TAG(PT_BINARY, 32787)
|
||||
PR_EMS_AB_NUM_OF_OPEN_RETRIES = PROP_TAG(PT_LONG, 33012)
|
||||
PR_EMS_AB_NUM_OF_TRANSFER_RETRIES = PROP_TAG(PT_LONG, 33013)
|
||||
PR_EMS_AB_OBJ_DIST_NAME = PROP_TAG(PT_TSTRING, 32828)
|
||||
PR_EMS_AB_OBJ_DIST_NAME_A = PROP_TAG(PT_STRING8, 32828)
|
||||
PR_EMS_AB_OBJ_DIST_NAME_W = PROP_TAG(PT_UNICODE, 32828)
|
||||
PR_EMS_AB_OBJ_DIST_NAME_O = PROP_TAG(PT_OBJECT, 32828)
|
||||
PR_EMS_AB_OBJ_DIST_NAME_T = PROP_TAG(PT_TSTRING, 32828)
|
||||
PR_EMS_AB_OBJECT_CLASS_CATEGORY = PROP_TAG(PT_LONG, 33014)
|
||||
PR_EMS_AB_OBJECT_VERSION = PROP_TAG(PT_LONG, 33015)
|
||||
PR_EMS_AB_OFF_LINE_AB_CONTAINERS = PROP_TAG(PT_MV_TSTRING, 33016)
|
||||
PR_EMS_AB_OFF_LINE_AB_CONTAINERS_A = PROP_TAG(PT_MV_STRING8, 33016)
|
||||
PR_EMS_AB_OFF_LINE_AB_CONTAINERS_W = PROP_TAG(PT_MV_UNICODE, 33016)
|
||||
PR_EMS_AB_OFF_LINE_AB_CONTAINERS_O = PROP_TAG(PT_OBJECT, 33016)
|
||||
PR_EMS_AB_OFF_LINE_AB_CONTAINERS_T = PROP_TAG(PT_MV_TSTRING, 33016)
|
||||
PR_EMS_AB_OFF_LINE_AB_SCHEDULE = PROP_TAG(PT_BINARY, 33017)
|
||||
PR_EMS_AB_OFF_LINE_AB_SERVER = PROP_TAG(PT_TSTRING, 33018)
|
||||
PR_EMS_AB_OFF_LINE_AB_SERVER_A = PROP_TAG(PT_STRING8, 33018)
|
||||
PR_EMS_AB_OFF_LINE_AB_SERVER_W = PROP_TAG(PT_UNICODE, 33018)
|
||||
PR_EMS_AB_OFF_LINE_AB_SERVER_O = PROP_TAG(PT_OBJECT, 33018)
|
||||
PR_EMS_AB_OFF_LINE_AB_SERVER_T = PROP_TAG(PT_TSTRING, 33018)
|
||||
PR_EMS_AB_OFF_LINE_AB_STYLE = PROP_TAG(PT_LONG, 33019)
|
||||
PR_EMS_AB_OID_TYPE = PROP_TAG(PT_LONG, 33020)
|
||||
PR_EMS_AB_OM_OBJECT_CLASS = PROP_TAG(PT_BINARY, 33021)
|
||||
PR_EMS_AB_OM_SYNTAX = PROP_TAG(PT_LONG, 33022)
|
||||
PR_EMS_AB_OOF_REPLY_TO_ORIGINATOR = PROP_TAG(PT_BOOLEAN, 33023)
|
||||
PR_EMS_AB_OPEN_RETRY_INTERVAL = PROP_TAG(PT_LONG, 33024)
|
||||
PR_EMS_AB_ORGANIZATION_NAME = PROP_TAG(PT_MV_TSTRING, 33025)
|
||||
PR_EMS_AB_ORGANIZATION_NAME_A = PROP_TAG(PT_MV_STRING8, 33025)
|
||||
PR_EMS_AB_ORGANIZATION_NAME_W = PROP_TAG(PT_MV_UNICODE, 33025)
|
||||
PR_EMS_AB_ORGANIZATIONAL_UNIT_NAME = PROP_TAG(PT_MV_TSTRING, 33026)
|
||||
PR_EMS_AB_ORGANIZATIONAL_UNIT_NAME_A = PROP_TAG(PT_MV_STRING8, 33026)
|
||||
PR_EMS_AB_ORGANIZATIONAL_UNIT_NAME_W = PROP_TAG(PT_MV_UNICODE, 33026)
|
||||
PR_EMS_AB_ORIGINAL_DISPLAY_TABLE = PROP_TAG(PT_BINARY, 33027)
|
||||
PR_EMS_AB_ORIGINAL_DISPLAY_TABLE_MSDOS = PROP_TAG(PT_BINARY, 33028)
|
||||
PR_EMS_AB_OUTBOUND_SITES = PROP_TAG(PT_MV_TSTRING, 33029)
|
||||
PR_EMS_AB_OUTBOUND_SITES_A = PROP_TAG(PT_MV_STRING8, 33029)
|
||||
PR_EMS_AB_OUTBOUND_SITES_W = PROP_TAG(PT_MV_UNICODE, 33029)
|
||||
PR_EMS_AB_OUTBOUND_SITES_O = PROP_TAG(PT_OBJECT, 33029)
|
||||
PR_EMS_AB_OUTBOUND_SITES_T = PROP_TAG(PT_MV_TSTRING, 33029)
|
||||
PR_EMS_AB_OWNER = PROP_TAG(PT_TSTRING, 32780)
|
||||
PR_EMS_AB_OWNER_A = PROP_TAG(PT_STRING8, 32780)
|
||||
PR_EMS_AB_OWNER_W = PROP_TAG(PT_UNICODE, 32780)
|
||||
PR_EMS_AB_OWNER_O = PROP_TAG(PT_OBJECT, 32780)
|
||||
PR_EMS_AB_OWNER_T = PROP_TAG(PT_TSTRING, 32780)
|
||||
PR_EMS_AB_OWNER_BL = PROP_TAG(PT_TSTRING, 32804)
|
||||
PR_EMS_AB_OWNER_BL_A = PROP_TAG(PT_STRING8, 32804)
|
||||
PR_EMS_AB_OWNER_BL_W = PROP_TAG(PT_UNICODE, 32804)
|
||||
PR_EMS_AB_OWNER_BL_O = PROP_TAG(PT_OBJECT, 32804)
|
||||
PR_EMS_AB_OWNER_BL_T = PROP_TAG(PT_TSTRING, 32804)
|
||||
PR_EMS_AB_P_SELECTOR = PROP_TAG(PT_BINARY, 33030)
|
||||
PR_EMS_AB_P_SELECTOR_INBOUND = PROP_TAG(PT_BINARY, 33031)
|
||||
PR_EMS_AB_PER_MSG_DIALOG_DISPLAY_TABLE = PROP_TAG(PT_BINARY, 33032)
|
||||
PR_EMS_AB_PER_RECIP_DIALOG_DISPLAY_TABLE = PROP_TAG(PT_BINARY, 33033)
|
||||
PR_EMS_AB_PERIOD_REP_SYNC_TIMES = PROP_TAG(PT_BINARY, 33034)
|
||||
PR_EMS_AB_PERIOD_REPL_STAGGER = PROP_TAG(PT_LONG, 33035)
|
||||
PR_EMS_AB_PF_CONTACTS = PROP_TAG(PT_MV_TSTRING, 32824)
|
||||
PR_EMS_AB_PF_CONTACTS_A = PROP_TAG(PT_MV_STRING8, 32824)
|
||||
PR_EMS_AB_PF_CONTACTS_W = PROP_TAG(PT_MV_UNICODE, 32824)
|
||||
PR_EMS_AB_PF_CONTACTS_O = PROP_TAG(PT_OBJECT, 32824)
|
||||
PR_EMS_AB_PF_CONTACTS_T = PROP_TAG(PT_MV_TSTRING, 32824)
|
||||
PR_EMS_AB_POP_CHARACTER_SET = PROP_TAG(PT_TSTRING, 33145)
|
||||
PR_EMS_AB_POP_CHARACTER_SET_A = PROP_TAG(PT_STRING8, 33145)
|
||||
PR_EMS_AB_POP_CHARACTER_SET_W = PROP_TAG(PT_UNICODE, 33145)
|
||||
PR_EMS_AB_POP_CONTENT_FORMAT = PROP_TAG(PT_TSTRING, 33143)
|
||||
PR_EMS_AB_POP_CONTENT_FORMAT_A = PROP_TAG(PT_STRING8, 33143)
|
||||
PR_EMS_AB_POP_CONTENT_FORMAT_W = PROP_TAG(PT_UNICODE, 33143)
|
||||
PR_EMS_AB_POSTAL_ADDRESS = PROP_TAG(PT_MV_BINARY, 33036)
|
||||
PR_EMS_AB_PREFERRED_DELIVERY_METHOD = PROP_TAG(PT_MV_LONG, 33037)
|
||||
PR_EMS_AB_PRMD = PROP_TAG(PT_TSTRING, 33038)
|
||||
PR_EMS_AB_PRMD_A = PROP_TAG(PT_STRING8, 33038)
|
||||
PR_EMS_AB_PRMD_W = PROP_TAG(PT_UNICODE, 33038)
|
||||
PR_EMS_AB_PROXY_ADDRESSES = PROP_TAG(PT_MV_TSTRING, 32783)
|
||||
PR_EMS_AB_PROXY_ADDRESSES_A = PROP_TAG(PT_MV_STRING8, 32783)
|
||||
PR_EMS_AB_PROXY_ADDRESSES_W = PROP_TAG(PT_MV_UNICODE, 32783)
|
||||
PR_EMS_AB_PROXY_GENERATOR_DLL = PROP_TAG(PT_TSTRING, 33039)
|
||||
PR_EMS_AB_PROXY_GENERATOR_DLL_A = PROP_TAG(PT_STRING8, 33039)
|
||||
PR_EMS_AB_PROXY_GENERATOR_DLL_W = PROP_TAG(PT_UNICODE, 33039)
|
||||
PR_EMS_AB_PUBLIC_DELEGATES = PROP_TAG(PT_OBJECT, 32789)
|
||||
PR_EMS_AB_PUBLIC_DELEGATES_A = PROP_TAG(PT_MV_STRING8, 32789)
|
||||
PR_EMS_AB_PUBLIC_DELEGATES_W = PROP_TAG(PT_MV_UNICODE, 32789)
|
||||
PR_EMS_AB_PUBLIC_DELEGATES_O = PROP_TAG(PT_OBJECT, 32789)
|
||||
PR_EMS_AB_PUBLIC_DELEGATES_T = PROP_TAG(PT_MV_TSTRING, 32789)
|
||||
PR_EMS_AB_PUBLIC_DELEGATES_BL = PROP_TAG(PT_MV_TSTRING, 33040)
|
||||
PR_EMS_AB_PUBLIC_DELEGATES_BL_A = PROP_TAG(PT_MV_STRING8, 33040)
|
||||
PR_EMS_AB_PUBLIC_DELEGATES_BL_W = PROP_TAG(PT_MV_UNICODE, 33040)
|
||||
PR_EMS_AB_PUBLIC_DELEGATES_BL_O = PROP_TAG(PT_OBJECT, 33040)
|
||||
PR_EMS_AB_PUBLIC_DELEGATES_BL_T = PROP_TAG(PT_MV_TSTRING, 33040)
|
||||
PR_EMS_AB_QUOTA_NOTIFICATION_SCHEDULE = PROP_TAG(PT_BINARY, 33041)
|
||||
PR_EMS_AB_QUOTA_NOTIFICATION_STYLE = PROP_TAG(PT_LONG, 33042)
|
||||
PR_EMS_AB_RANGE_LOWER = PROP_TAG(PT_LONG, 33043)
|
||||
PR_EMS_AB_RANGE_UPPER = PROP_TAG(PT_LONG, 33044)
|
||||
PR_EMS_AB_RAS_CALLBACK_NUMBER = PROP_TAG(PT_TSTRING, 33045)
|
||||
PR_EMS_AB_RAS_CALLBACK_NUMBER_A = PROP_TAG(PT_STRING8, 33045)
|
||||
PR_EMS_AB_RAS_CALLBACK_NUMBER_W = PROP_TAG(PT_UNICODE, 33045)
|
||||
PR_EMS_AB_RAS_PHONE_NUMBER = PROP_TAG(PT_TSTRING, 33046)
|
||||
PR_EMS_AB_RAS_PHONE_NUMBER_A = PROP_TAG(PT_STRING8, 33046)
|
||||
PR_EMS_AB_RAS_PHONE_NUMBER_W = PROP_TAG(PT_UNICODE, 33046)
|
||||
PR_EMS_AB_RAS_PHONEBOOK_ENTRY_NAME = PROP_TAG(PT_TSTRING, 33047)
|
||||
PR_EMS_AB_RAS_PHONEBOOK_ENTRY_NAME_A = PROP_TAG(PT_STRING8, 33047)
|
||||
PR_EMS_AB_RAS_PHONEBOOK_ENTRY_NAME_W = PROP_TAG(PT_UNICODE, 33047)
|
||||
PR_EMS_AB_RAS_REMOTE_SRVR_NAME = PROP_TAG(PT_TSTRING, 33048)
|
||||
PR_EMS_AB_RAS_REMOTE_SRVR_NAME_A = PROP_TAG(PT_STRING8, 33048)
|
||||
PR_EMS_AB_RAS_REMOTE_SRVR_NAME_W = PROP_TAG(PT_UNICODE, 33048)
|
||||
PR_EMS_AB_REGISTERED_ADDRESS = PROP_TAG(PT_MV_BINARY, 33049)
|
||||
PR_EMS_AB_REMOTE_BRIDGE_HEAD = PROP_TAG(PT_TSTRING, 33050)
|
||||
PR_EMS_AB_REMOTE_BRIDGE_HEAD_A = PROP_TAG(PT_STRING8, 33050)
|
||||
PR_EMS_AB_REMOTE_BRIDGE_HEAD_W = PROP_TAG(PT_UNICODE, 33050)
|
||||
PR_EMS_AB_REMOTE_BRIDGE_HEAD_ADDRESS = PROP_TAG(PT_TSTRING, 33051)
|
||||
PR_EMS_AB_REMOTE_BRIDGE_HEAD_ADDRESS_A = PROP_TAG(PT_STRING8, 33051)
|
||||
PR_EMS_AB_REMOTE_BRIDGE_HEAD_ADDRESS_W = PROP_TAG(PT_UNICODE, 33051)
|
||||
PR_EMS_AB_REMOTE_OUT_BH_SERVER = PROP_TAG(PT_TSTRING, 33052)
|
||||
PR_EMS_AB_REMOTE_OUT_BH_SERVER_A = PROP_TAG(PT_STRING8, 33052)
|
||||
PR_EMS_AB_REMOTE_OUT_BH_SERVER_W = PROP_TAG(PT_UNICODE, 33052)
|
||||
PR_EMS_AB_REMOTE_OUT_BH_SERVER_O = PROP_TAG(PT_OBJECT, 33052)
|
||||
PR_EMS_AB_REMOTE_OUT_BH_SERVER_T = PROP_TAG(PT_TSTRING, 33052)
|
||||
PR_EMS_AB_REMOTE_SITE = PROP_TAG(PT_TSTRING, 33053)
|
||||
PR_EMS_AB_REMOTE_SITE_A = PROP_TAG(PT_STRING8, 33053)
|
||||
PR_EMS_AB_REMOTE_SITE_W = PROP_TAG(PT_UNICODE, 33053)
|
||||
PR_EMS_AB_REMOTE_SITE_O = PROP_TAG(PT_OBJECT, 33053)
|
||||
PR_EMS_AB_REMOTE_SITE_T = PROP_TAG(PT_TSTRING, 33053)
|
||||
PR_EMS_AB_REPLICATION_MAIL_MSG_SIZE = PROP_TAG(PT_LONG, 33128)
|
||||
PR_EMS_AB_REPLICATION_SENSITIVITY = PROP_TAG(PT_LONG, 33054)
|
||||
PR_EMS_AB_REPLICATION_STAGGER = PROP_TAG(PT_LONG, 33055)
|
||||
PR_EMS_AB_REPORT_TO_ORIGINATOR = PROP_TAG(PT_BOOLEAN, 33056)
|
||||
PR_EMS_AB_REPORT_TO_OWNER = PROP_TAG(PT_BOOLEAN, 33057)
|
||||
PR_EMS_AB_REPORTS = PROP_TAG(PT_OBJECT, 32782)
|
||||
PR_EMS_AB_REPORTS_A = PROP_TAG(PT_MV_STRING8, 32782)
|
||||
PR_EMS_AB_REPORTS_W = PROP_TAG(PT_MV_UNICODE, 32782)
|
||||
PR_EMS_AB_REPORTS_O = PROP_TAG(PT_OBJECT, 32782)
|
||||
PR_EMS_AB_REPORTS_T = PROP_TAG(PT_MV_TSTRING, 32782)
|
||||
PR_EMS_AB_REQ_SEQ = PROP_TAG(PT_LONG, 33058)
|
||||
PR_EMS_AB_RESPONSIBLE_LOCAL_DXA = PROP_TAG(PT_TSTRING, 33059)
|
||||
PR_EMS_AB_RESPONSIBLE_LOCAL_DXA_A = PROP_TAG(PT_STRING8, 33059)
|
||||
PR_EMS_AB_RESPONSIBLE_LOCAL_DXA_W = PROP_TAG(PT_UNICODE, 33059)
|
||||
PR_EMS_AB_RESPONSIBLE_LOCAL_DXA_O = PROP_TAG(PT_OBJECT, 33059)
|
||||
PR_EMS_AB_RESPONSIBLE_LOCAL_DXA_T = PROP_TAG(PT_TSTRING, 33059)
|
||||
PR_EMS_AB_RID_SERVER = PROP_TAG(PT_TSTRING, 33060)
|
||||
PR_EMS_AB_RID_SERVER_A = PROP_TAG(PT_STRING8, 33060)
|
||||
PR_EMS_AB_RID_SERVER_W = PROP_TAG(PT_UNICODE, 33060)
|
||||
PR_EMS_AB_RID_SERVER_O = PROP_TAG(PT_OBJECT, 33060)
|
||||
PR_EMS_AB_RID_SERVER_T = PROP_TAG(PT_TSTRING, 33060)
|
||||
PR_EMS_AB_ROLE_OCCUPANT = PROP_TAG(PT_MV_TSTRING, 33061)
|
||||
PR_EMS_AB_ROLE_OCCUPANT_A = PROP_TAG(PT_MV_STRING8, 33061)
|
||||
PR_EMS_AB_ROLE_OCCUPANT_W = PROP_TAG(PT_MV_UNICODE, 33061)
|
||||
PR_EMS_AB_ROLE_OCCUPANT_O = PROP_TAG(PT_OBJECT, 33061)
|
||||
PR_EMS_AB_ROLE_OCCUPANT_T = PROP_TAG(PT_MV_TSTRING, 33061)
|
||||
PR_EMS_AB_ROUTING_LIST = PROP_TAG(PT_MV_TSTRING, 33062)
|
||||
PR_EMS_AB_ROUTING_LIST_A = PROP_TAG(PT_MV_STRING8, 33062)
|
||||
PR_EMS_AB_ROUTING_LIST_W = PROP_TAG(PT_MV_UNICODE, 33062)
|
||||
PR_EMS_AB_RTS_CHECKPOINT_SIZE = PROP_TAG(PT_LONG, 33063)
|
||||
PR_EMS_AB_RTS_RECOVERY_TIMEOUT = PROP_TAG(PT_LONG, 33064)
|
||||
PR_EMS_AB_RTS_WINDOW_SIZE = PROP_TAG(PT_LONG, 33065)
|
||||
PR_EMS_AB_RUNS_ON = PROP_TAG(PT_MV_TSTRING, 33066)
|
||||
PR_EMS_AB_RUNS_ON_A = PROP_TAG(PT_MV_STRING8, 33066)
|
||||
PR_EMS_AB_RUNS_ON_W = PROP_TAG(PT_MV_UNICODE, 33066)
|
||||
PR_EMS_AB_RUNS_ON_O = PROP_TAG(PT_OBJECT, 33066)
|
||||
PR_EMS_AB_RUNS_ON_T = PROP_TAG(PT_MV_TSTRING, 33066)
|
||||
PR_EMS_AB_S_SELECTOR = PROP_TAG(PT_BINARY, 33067)
|
||||
PR_EMS_AB_S_SELECTOR_INBOUND = PROP_TAG(PT_BINARY, 33068)
|
||||
PR_EMS_AB_SCHEMA_FLAGS = PROP_TAG(PT_LONG, 33139)
|
||||
PR_EMS_AB_SCHEMA_VERSION = PROP_TAG(PT_MV_LONG, 33148)
|
||||
PR_EMS_AB_SEARCH_FLAGS = PROP_TAG(PT_LONG, 33069)
|
||||
PR_EMS_AB_SEARCH_GUIDE = PROP_TAG(PT_MV_BINARY, 33070)
|
||||
PR_EMS_AB_SECURITY_PROTOCOL = PROP_TAG(PT_MV_BINARY, 32823)
|
||||
PR_EMS_AB_SEE_ALSO = PROP_TAG(PT_MV_TSTRING, 33071)
|
||||
PR_EMS_AB_SEE_ALSO_A = PROP_TAG(PT_MV_STRING8, 33071)
|
||||
PR_EMS_AB_SEE_ALSO_W = PROP_TAG(PT_MV_UNICODE, 33071)
|
||||
PR_EMS_AB_SEE_ALSO_O = PROP_TAG(PT_OBJECT, 33071)
|
||||
PR_EMS_AB_SEE_ALSO_T = PROP_TAG(PT_MV_TSTRING, 33071)
|
||||
PR_EMS_AB_SERIAL_NUMBER = PROP_TAG(PT_MV_TSTRING, 33072)
|
||||
PR_EMS_AB_SERIAL_NUMBER_A = PROP_TAG(PT_MV_STRING8, 33072)
|
||||
PR_EMS_AB_SERIAL_NUMBER_W = PROP_TAG(PT_MV_UNICODE, 33072)
|
||||
PR_EMS_AB_SERVICE_ACTION_FIRST = PROP_TAG(PT_LONG, 33073)
|
||||
PR_EMS_AB_SERVICE_ACTION_OTHER = PROP_TAG(PT_LONG, 33074)
|
||||
PR_EMS_AB_SERVICE_ACTION_SECOND = PROP_TAG(PT_LONG, 33075)
|
||||
PR_EMS_AB_SERVICE_RESTART_DELAY = PROP_TAG(PT_LONG, 33076)
|
||||
PR_EMS_AB_SERVICE_RESTART_MESSAGE = PROP_TAG(PT_TSTRING, 33077)
|
||||
PR_EMS_AB_SERVICE_RESTART_MESSAGE_A = PROP_TAG(PT_STRING8, 33077)
|
||||
PR_EMS_AB_SERVICE_RESTART_MESSAGE_W = PROP_TAG(PT_UNICODE, 33077)
|
||||
PR_EMS_AB_SESSION_DISCONNECT_TIMER = PROP_TAG(PT_LONG, 33078)
|
||||
PR_EMS_AB_SITE_AFFINITY = PROP_TAG(PT_MV_TSTRING, 33079)
|
||||
PR_EMS_AB_SITE_AFFINITY_A = PROP_TAG(PT_MV_STRING8, 33079)
|
||||
PR_EMS_AB_SITE_AFFINITY_W = PROP_TAG(PT_MV_UNICODE, 33079)
|
||||
PR_EMS_AB_SITE_FOLDER_GUID = PROP_TAG(PT_BINARY, 33126)
|
||||
PR_EMS_AB_SITE_FOLDER_SERVER = PROP_TAG(PT_TSTRING, 33127)
|
||||
PR_EMS_AB_SITE_FOLDER_SERVER_A = PROP_TAG(PT_STRING8, 33127)
|
||||
PR_EMS_AB_SITE_FOLDER_SERVER_W = PROP_TAG(PT_UNICODE, 33127)
|
||||
PR_EMS_AB_SITE_FOLDER_SERVER_O = PROP_TAG(PT_OBJECT, 33127)
|
||||
PR_EMS_AB_SITE_FOLDER_SERVER_T = PROP_TAG(PT_TSTRING, 33127)
|
||||
PR_EMS_AB_SITE_PROXY_SPACE = PROP_TAG(PT_MV_TSTRING, 33080)
|
||||
PR_EMS_AB_SITE_PROXY_SPACE_A = PROP_TAG(PT_MV_STRING8, 33080)
|
||||
PR_EMS_AB_SITE_PROXY_SPACE_W = PROP_TAG(PT_MV_UNICODE, 33080)
|
||||
PR_EMS_AB_SPACE_LAST_COMPUTED = PROP_TAG(PT_SYSTIME, 33081)
|
||||
PR_EMS_AB_STREET_ADDRESS = PROP_TAG(PT_TSTRING, 33082)
|
||||
PR_EMS_AB_STREET_ADDRESS_A = PROP_TAG(PT_STRING8, 33082)
|
||||
PR_EMS_AB_STREET_ADDRESS_W = PROP_TAG(PT_UNICODE, 33082)
|
||||
PR_EMS_AB_SUB_REFS = PROP_TAG(PT_MV_TSTRING, 33083)
|
||||
PR_EMS_AB_SUB_REFS_A = PROP_TAG(PT_MV_STRING8, 33083)
|
||||
PR_EMS_AB_SUB_REFS_W = PROP_TAG(PT_MV_UNICODE, 33083)
|
||||
PR_EMS_AB_SUB_REFS_O = PROP_TAG(PT_OBJECT, 33083)
|
||||
PR_EMS_AB_SUB_REFS_T = PROP_TAG(PT_MV_TSTRING, 33083)
|
||||
PR_EMS_AB_SUB_SITE = PROP_TAG(PT_TSTRING, 33147)
|
||||
PR_EMS_AB_SUB_SITE_A = PROP_TAG(PT_STRING8, 33147)
|
||||
PR_EMS_AB_SUB_SITE_W = PROP_TAG(PT_UNICODE, 33147)
|
||||
PR_EMS_AB_SUBMISSION_CONT_LENGTH = PROP_TAG(PT_LONG, 33084)
|
||||
PR_EMS_AB_SUPPORTED_APPLICATION_CONTEXT = PROP_TAG(PT_MV_BINARY, 33085)
|
||||
PR_EMS_AB_SUPPORTING_STACK = PROP_TAG(PT_MV_TSTRING, 33086)
|
||||
PR_EMS_AB_SUPPORTING_STACK_A = PROP_TAG(PT_MV_STRING8, 33086)
|
||||
PR_EMS_AB_SUPPORTING_STACK_W = PROP_TAG(PT_MV_UNICODE, 33086)
|
||||
PR_EMS_AB_SUPPORTING_STACK_O = PROP_TAG(PT_OBJECT, 33086)
|
||||
PR_EMS_AB_SUPPORTING_STACK_T = PROP_TAG(PT_MV_TSTRING, 33086)
|
||||
PR_EMS_AB_SUPPORTING_STACK_BL = PROP_TAG(PT_MV_TSTRING, 33087)
|
||||
PR_EMS_AB_SUPPORTING_STACK_BL_A = PROP_TAG(PT_MV_STRING8, 33087)
|
||||
PR_EMS_AB_SUPPORTING_STACK_BL_W = PROP_TAG(PT_MV_UNICODE, 33087)
|
||||
PR_EMS_AB_SUPPORTING_STACK_BL_O = PROP_TAG(PT_OBJECT, 33087)
|
||||
PR_EMS_AB_SUPPORTING_STACK_BL_T = PROP_TAG(PT_MV_TSTRING, 33087)
|
||||
PR_EMS_AB_T_SELECTOR = PROP_TAG(PT_BINARY, 33088)
|
||||
PR_EMS_AB_T_SELECTOR_INBOUND = PROP_TAG(PT_BINARY, 33089)
|
||||
PR_EMS_AB_TARGET_ADDRESS = PROP_TAG(PT_TSTRING, 32785)
|
||||
PR_EMS_AB_TARGET_ADDRESS_A = PROP_TAG(PT_STRING8, 32785)
|
||||
PR_EMS_AB_TARGET_ADDRESS_W = PROP_TAG(PT_UNICODE, 32785)
|
||||
PR_EMS_AB_TARGET_MTAS = PROP_TAG(PT_MV_TSTRING, 33090)
|
||||
PR_EMS_AB_TARGET_MTAS_A = PROP_TAG(PT_MV_STRING8, 33090)
|
||||
PR_EMS_AB_TARGET_MTAS_W = PROP_TAG(PT_MV_UNICODE, 33090)
|
||||
PR_EMS_AB_TELEPHONE_NUMBER = PROP_TAG(PT_MV_TSTRING, 32786)
|
||||
PR_EMS_AB_TELEPHONE_NUMBER_A = PROP_TAG(PT_MV_STRING8, 32786)
|
||||
PR_EMS_AB_TELEPHONE_NUMBER_W = PROP_TAG(PT_MV_UNICODE, 32786)
|
||||
PR_EMS_AB_TELETEX_TERMINAL_IDENTIFIER = PROP_TAG(PT_MV_BINARY, 33091)
|
||||
PR_EMS_AB_TEMP_ASSOC_THRESHOLD = PROP_TAG(PT_LONG, 33092)
|
||||
PR_EMS_AB_TOMBSTONE_LIFETIME = PROP_TAG(PT_LONG, 33093)
|
||||
PR_EMS_AB_TRACKING_LOG_PATH_NAME = PROP_TAG(PT_TSTRING, 33094)
|
||||
PR_EMS_AB_TRACKING_LOG_PATH_NAME_A = PROP_TAG(PT_STRING8, 33094)
|
||||
PR_EMS_AB_TRACKING_LOG_PATH_NAME_W = PROP_TAG(PT_UNICODE, 33094)
|
||||
PR_EMS_AB_TRANS_RETRY_MINS = PROP_TAG(PT_LONG, 33095)
|
||||
PR_EMS_AB_TRANS_TIMEOUT_MINS = PROP_TAG(PT_LONG, 33096)
|
||||
PR_EMS_AB_TRANSFER_RETRY_INTERVAL = PROP_TAG(PT_LONG, 33097)
|
||||
PR_EMS_AB_TRANSFER_TIMEOUT_NON_URGENT = PROP_TAG(PT_LONG, 33098)
|
||||
PR_EMS_AB_TRANSFER_TIMEOUT_NORMAL = PROP_TAG(PT_LONG, 33099)
|
||||
PR_EMS_AB_TRANSFER_TIMEOUT_URGENT = PROP_TAG(PT_LONG, 33100)
|
||||
PR_EMS_AB_TRANSLATION_TABLE_USED = PROP_TAG(PT_LONG, 33101)
|
||||
PR_EMS_AB_TRANSPORT_EXPEDITED_DATA = PROP_TAG(PT_BOOLEAN, 33102)
|
||||
PR_EMS_AB_TRUST_LEVEL = PROP_TAG(PT_LONG, 33103)
|
||||
PR_EMS_AB_TURN_REQUEST_THRESHOLD = PROP_TAG(PT_LONG, 33104)
|
||||
PR_EMS_AB_TWO_WAY_ALTERNATE_FACILITY = PROP_TAG(PT_BOOLEAN, 33105)
|
||||
PR_EMS_AB_UNAUTH_ORIG_BL = PROP_TAG(PT_MV_TSTRING, 33106)
|
||||
PR_EMS_AB_UNAUTH_ORIG_BL_A = PROP_TAG(PT_MV_STRING8, 33106)
|
||||
PR_EMS_AB_UNAUTH_ORIG_BL_W = PROP_TAG(PT_MV_UNICODE, 33106)
|
||||
PR_EMS_AB_UNAUTH_ORIG_BL_O = PROP_TAG(PT_OBJECT, 33106)
|
||||
PR_EMS_AB_UNAUTH_ORIG_BL_T = PROP_TAG(PT_MV_TSTRING, 33106)
|
||||
PR_EMS_AB_USE_SERVER_VALUES = PROP_TAG(PT_BOOLEAN, 33150)
|
||||
PR_EMS_AB_USER_PASSWORD = PROP_TAG(PT_MV_BINARY, 33107)
|
||||
PR_EMS_AB_USN_CHANGED = PROP_TAG(PT_LONG, 32809)
|
||||
PR_EMS_AB_USN_CREATED = PROP_TAG(PT_LONG, 33108)
|
||||
PR_EMS_AB_USN_DSA_LAST_OBJ_REMOVED = PROP_TAG(PT_LONG, 33109)
|
||||
PR_EMS_AB_USN_INTERSITE = PROP_TAG(PT_LONG, 33146)
|
||||
PR_EMS_AB_USN_LAST_OBJ_REM = PROP_TAG(PT_LONG, 33110)
|
||||
PR_EMS_AB_USN_SOURCE = PROP_TAG(PT_LONG, 33111)
|
||||
PR_EMS_AB_WWW_HOME_PAGE = PROP_TAG(PT_TSTRING, 33141)
|
||||
PR_EMS_AB_WWW_HOME_PAGE_A = PROP_TAG(PT_STRING8, 33141)
|
||||
PR_EMS_AB_WWW_HOME_PAGE_W = PROP_TAG(PT_UNICODE, 33141)
|
||||
PR_EMS_AB_X121_ADDRESS = PROP_TAG(PT_MV_TSTRING, 33112)
|
||||
PR_EMS_AB_X121_ADDRESS_A = PROP_TAG(PT_MV_STRING8, 33112)
|
||||
PR_EMS_AB_X121_ADDRESS_W = PROP_TAG(PT_MV_UNICODE, 33112)
|
||||
PR_EMS_AB_X25_CALL_USER_DATA_INCOMING = PROP_TAG(PT_BINARY, 33113)
|
||||
PR_EMS_AB_X25_CALL_USER_DATA_OUTGOING = PROP_TAG(PT_BINARY, 33114)
|
||||
PR_EMS_AB_X25_FACILITIES_DATA_INCOMING = PROP_TAG(PT_BINARY, 33115)
|
||||
PR_EMS_AB_X25_FACILITIES_DATA_OUTGOING = PROP_TAG(PT_BINARY, 33116)
|
||||
PR_EMS_AB_X25_LEASED_LINE_PORT = PROP_TAG(PT_BINARY, 33117)
|
||||
PR_EMS_AB_X25_LEASED_OR_SWITCHED = PROP_TAG(PT_BOOLEAN, 33118)
|
||||
PR_EMS_AB_X25_REMOTE_MTA_PHONE = PROP_TAG(PT_TSTRING, 33119)
|
||||
PR_EMS_AB_X25_REMOTE_MTA_PHONE_A = PROP_TAG(PT_STRING8, 33119)
|
||||
PR_EMS_AB_X25_REMOTE_MTA_PHONE_W = PROP_TAG(PT_UNICODE, 33119)
|
||||
PR_EMS_AB_X400_ATTACHMENT_TYPE = PROP_TAG(PT_BINARY, 33120)
|
||||
PR_EMS_AB_X400_SELECTOR_SYNTAX = PROP_TAG(PT_LONG, 33121)
|
||||
PR_EMS_AB_X500_ACCESS_CONTROL_LIST = PROP_TAG(PT_BINARY, 33122)
|
||||
PR_EMS_AB_XMIT_TIMEOUT_NON_URGENT = PROP_TAG(PT_LONG, 33123)
|
||||
PR_EMS_AB_XMIT_TIMEOUT_NORMAL = PROP_TAG(PT_LONG, 33124)
|
||||
PR_EMS_AB_XMIT_TIMEOUT_URGENT = PROP_TAG(PT_LONG, 33125)
|
||||
Binary file not shown.
BIN
Utils/PythonNew32/Lib/site-packages/win32comext/mapi/mapi.pyd
Normal file
BIN
Utils/PythonNew32/Lib/site-packages/win32comext/mapi/mapi.pyd
Normal file
Binary file not shown.
1023
Utils/PythonNew32/Lib/site-packages/win32comext/mapi/mapitags.py
Normal file
1023
Utils/PythonNew32/Lib/site-packages/win32comext/mapi/mapitags.py
Normal file
File diff suppressed because it is too large
Load Diff
211
Utils/PythonNew32/Lib/site-packages/win32comext/mapi/mapiutil.py
Normal file
211
Utils/PythonNew32/Lib/site-packages/win32comext/mapi/mapiutil.py
Normal file
@@ -0,0 +1,211 @@
|
||||
# General utilities for MAPI and MAPI objects.
|
||||
from __future__ import annotations
|
||||
|
||||
import pythoncom
|
||||
from pywintypes import TimeType
|
||||
|
||||
from . import mapi, mapitags
|
||||
|
||||
prTable: dict[int, str] = {}
|
||||
|
||||
|
||||
def GetPropTagName(pt):
|
||||
if not prTable:
|
||||
for name, value in mapitags.__dict__.items():
|
||||
if name[:3] == "PR_":
|
||||
# Store both the full ID (including type) and just the ID.
|
||||
# This is so PR_FOO_A and PR_FOO_W are still differentiated,
|
||||
# but should we get a PT_FOO with PT_ERROR set, we fallback
|
||||
# to the ID.
|
||||
|
||||
# String types should have 3 definitions in mapitags.py
|
||||
# PR_BODY = PROP_TAG( PT_TSTRING, 4096)
|
||||
# PR_BODY_W = PROP_TAG( PT_UNICODE, 4096)
|
||||
# PR_BODY_A = PROP_TAG( PT_STRING8, 4096)
|
||||
# The following change ensures a lookup using only the the
|
||||
# property id returns the conditional default.
|
||||
|
||||
# PT_TSTRING is a conditional assignment for either PT_UNICODE or
|
||||
# PT_STRING8 and should not be returned during a lookup.
|
||||
|
||||
if (
|
||||
mapitags.PROP_TYPE(value) == mapitags.PT_UNICODE
|
||||
or mapitags.PROP_TYPE(value) == mapitags.PT_STRING8
|
||||
):
|
||||
if name[-2:] == "_A" or name[-2:] == "_W":
|
||||
prTable[value] = name
|
||||
else:
|
||||
prTable[mapitags.PROP_ID(value)] = name
|
||||
|
||||
else:
|
||||
prTable[value] = name
|
||||
prTable[mapitags.PROP_ID(value)] = name
|
||||
|
||||
try:
|
||||
try:
|
||||
return prTable[pt]
|
||||
except KeyError:
|
||||
# Can't find it exactly - see if the raw ID exists.
|
||||
return prTable[mapitags.PROP_ID(pt)]
|
||||
except KeyError:
|
||||
# god-damn bullshit hex() warnings: I don't see a way to get the
|
||||
# old behaviour without a warning!!
|
||||
ret = hex(int(pt))
|
||||
# -0x8000000L -> 0x80000000
|
||||
if ret[0] == "-":
|
||||
ret = ret[1:]
|
||||
if ret[-1] == "L":
|
||||
ret = ret[:-1]
|
||||
return ret
|
||||
|
||||
|
||||
mapiErrorTable: dict[int, str] = {}
|
||||
|
||||
|
||||
def GetScodeString(hr):
|
||||
if not mapiErrorTable:
|
||||
for name, value in mapi.__dict__.items():
|
||||
if name[:7] in ["MAPI_E_", "MAPI_W_"]:
|
||||
mapiErrorTable[value] = name
|
||||
return mapiErrorTable.get(hr, pythoncom.GetScodeString(hr))
|
||||
|
||||
|
||||
ptTable: dict[int, str] = {}
|
||||
|
||||
|
||||
def GetMapiTypeName(propType, rawType=True):
|
||||
"""Given a mapi type flag, return a string description of the type"""
|
||||
if not ptTable:
|
||||
for name, value in mapitags.__dict__.items():
|
||||
if name[:3] == "PT_":
|
||||
# PT_TSTRING is a conditional assignment
|
||||
# for either PT_UNICODE or PT_STRING8 and
|
||||
# should not be returned during a lookup.
|
||||
if name in ["PT_TSTRING", "PT_MV_TSTRING"]:
|
||||
continue
|
||||
ptTable[value] = name
|
||||
|
||||
if rawType:
|
||||
propType &= ~mapitags.MV_FLAG
|
||||
return ptTable.get(propType, str(hex(propType)))
|
||||
|
||||
|
||||
def GetProperties(obj, propList):
|
||||
"""Given a MAPI object and a list of properties, return a list of property values.
|
||||
|
||||
Allows a single property to be passed, and the result is a single object.
|
||||
|
||||
Each request property can be an integer or a string. Of a string, it is
|
||||
automatically converted to an integer via the GetIdsFromNames function.
|
||||
|
||||
If the property fetch fails, the result is None.
|
||||
"""
|
||||
bRetList = 1
|
||||
if not isinstance(propList, (tuple, list)):
|
||||
bRetList = 0
|
||||
propList = (propList,)
|
||||
realPropList = []
|
||||
rc = []
|
||||
for prop in propList:
|
||||
if not isinstance(prop, int):
|
||||
props = ((mapi.PS_PUBLIC_STRINGS, prop),)
|
||||
propIds = obj.GetIDsFromNames(props, 0)
|
||||
prop = mapitags.PROP_TAG(
|
||||
mapitags.PT_UNSPECIFIED, mapitags.PROP_ID(propIds[0])
|
||||
)
|
||||
realPropList.append(prop)
|
||||
|
||||
hr, data = obj.GetProps(realPropList, 0)
|
||||
if hr != 0:
|
||||
data = None
|
||||
return None
|
||||
if bRetList:
|
||||
return [v[1] for v in data]
|
||||
else:
|
||||
return data[0][1]
|
||||
|
||||
|
||||
def GetAllProperties(obj, make_tag_names=True):
|
||||
tags = obj.GetPropList(0)
|
||||
hr, data = obj.GetProps(tags)
|
||||
ret = []
|
||||
for tag, val in data:
|
||||
if make_tag_names:
|
||||
hr, tags, array = obj.GetNamesFromIDs((tag,))
|
||||
if isinstance(array[0][1], str):
|
||||
name = array[0][1]
|
||||
else:
|
||||
name = GetPropTagName(tag)
|
||||
else:
|
||||
name = tag
|
||||
ret.append((name, val))
|
||||
return ret
|
||||
|
||||
|
||||
_MapiTypeMap = {
|
||||
float: mapitags.PT_DOUBLE,
|
||||
int: mapitags.PT_I4,
|
||||
bytes: mapitags.PT_STRING8,
|
||||
str: mapitags.PT_UNICODE,
|
||||
type(None): mapitags.PT_UNSPECIFIED,
|
||||
bool: mapitags.PT_BOOLEAN,
|
||||
}
|
||||
|
||||
|
||||
def SetPropertyValue(obj, prop, val):
|
||||
if not isinstance(prop, int):
|
||||
props = ((mapi.PS_PUBLIC_STRINGS, prop),)
|
||||
propIds = obj.GetIDsFromNames(props, mapi.MAPI_CREATE)
|
||||
if val == True or val == False:
|
||||
type_tag = mapitags.PT_BOOLEAN
|
||||
else:
|
||||
type_tag = _MapiTypeMap.get(type(val))
|
||||
if type_tag is None:
|
||||
raise ValueError(
|
||||
f"Don't know what to do with '{val!r}' ('{type(val)}')"
|
||||
)
|
||||
prop = mapitags.PROP_TAG(type_tag, mapitags.PROP_ID(propIds[0]))
|
||||
if val is None:
|
||||
# Delete the property
|
||||
obj.DeleteProps((prop,))
|
||||
else:
|
||||
obj.SetProps(((prop, val),))
|
||||
|
||||
|
||||
def SetProperties(msg, propDict):
|
||||
"""Given a Python dictionary, set the objects properties.
|
||||
|
||||
If the dictionary key is a string, then a property ID is queried
|
||||
otherwise the ID is assumed native.
|
||||
|
||||
Coded for maximum efficiency wrt server calls - ie, maximum of
|
||||
2 calls made to the object, regardless of the dictionary contents
|
||||
(only 1 if dictionary full of int keys)
|
||||
"""
|
||||
|
||||
newProps = []
|
||||
# First pass over the properties we should get IDs for.
|
||||
for key, val in propDict.items():
|
||||
if isinstance(key, str):
|
||||
newProps.append((mapi.PS_PUBLIC_STRINGS, key))
|
||||
# Query for the new IDs
|
||||
if newProps:
|
||||
newIds = msg.GetIDsFromNames(newProps, mapi.MAPI_CREATE)
|
||||
newIdNo = 0
|
||||
newProps = []
|
||||
for key, val in propDict.items():
|
||||
if isinstance(key, str):
|
||||
if isinstance(val, str):
|
||||
tagType = mapitags.PT_UNICODE
|
||||
elif isinstance(val, int):
|
||||
tagType = mapitags.PT_I4
|
||||
elif isinstance(val, TimeType):
|
||||
tagType = mapitags.PT_SYSTIME
|
||||
else:
|
||||
raise ValueError(
|
||||
f"The type of object {val!r}({type(val)}) can not be written"
|
||||
)
|
||||
key = mapitags.PROP_TAG(tagType, mapitags.PROP_ID(newIds[newIdNo]))
|
||||
newIdNo += 1
|
||||
newProps.append((key, val))
|
||||
msg.SetProps(newProps)
|
||||
@@ -0,0 +1 @@
|
||||
# this is a python package
|
||||
Binary file not shown.
838
Utils/PythonNew32/Lib/site-packages/win32comext/propsys/pscon.py
Normal file
838
Utils/PythonNew32/Lib/site-packages/win32comext/propsys/pscon.py
Normal file
@@ -0,0 +1,838 @@
|
||||
# hand generated from propsys.h
|
||||
|
||||
## PROPENUMTYPE, used with IPropertyEnumType
|
||||
PET_DISCRETEVALUE = 0
|
||||
PET_RANGEDVALUE = 1
|
||||
PET_DEFAULTVALUE = 2
|
||||
PET_ENDRANGE = 3
|
||||
|
||||
PDTF_DEFAULT = 0
|
||||
PDTF_MULTIPLEVALUES = 0x1
|
||||
PDTF_ISINNATE = 0x2
|
||||
PDTF_ISGROUP = 0x4
|
||||
PDTF_CANGROUPBY = 0x8
|
||||
PDTF_CANSTACKBY = 0x10
|
||||
PDTF_ISTREEPROPERTY = 0x20
|
||||
PDTF_INCLUDEINFULLTEXTQUERY = 0x40
|
||||
PDTF_ISVIEWABLE = 0x80
|
||||
PDTF_ISQUERYABLE = 0x100
|
||||
PDTF_ISSYSTEMPROPERTY = 0x80000000
|
||||
PDTF_MASK_ALL = 0x800001FF
|
||||
|
||||
PDVF_DEFAULT = 0
|
||||
PDVF_CENTERALIGN = 0x1
|
||||
PDVF_RIGHTALIGN = 0x2
|
||||
PDVF_BEGINNEWGROUP = 0x4
|
||||
PDVF_FILLAREA = 0x8
|
||||
PDVF_SORTDESCENDING = 0x10
|
||||
PDVF_SHOWONLYIFPRESENT = 0x20
|
||||
PDVF_SHOWBYDEFAULT = 0x40
|
||||
PDVF_SHOWINPRIMARYLIST = 0x80
|
||||
PDVF_SHOWINSECONDARYLIST = 0x100
|
||||
PDVF_HIDELABEL = 0x200
|
||||
PDVF_HIDDEN = 0x800
|
||||
PDVF_CANWRAP = 0x1000
|
||||
PDVF_MASK_ALL = 0x1BFF
|
||||
|
||||
PDDT_STRING = 0
|
||||
PDDT_NUMBER = 1
|
||||
PDDT_BOOLEAN = 2
|
||||
PDDT_DATETIME = 3
|
||||
PDDT_ENUMERATED = 4
|
||||
|
||||
PDGR_DISCRETE = 0
|
||||
PDGR_ALPHANUMERIC = 1
|
||||
PDGR_SIZE = 2
|
||||
PDGR_DYNAMIC = 3
|
||||
PDGR_DATE = 4
|
||||
PDGR_PERCENT = 5
|
||||
PDGR_ENUMERATED = 6
|
||||
|
||||
## PROPDESC_FORMAT_FLAGS
|
||||
PDFF_DEFAULT = 0
|
||||
PDFF_PREFIXNAME = 0x1
|
||||
PDFF_FILENAME = 0x2
|
||||
PDFF_ALWAYSKB = 0x4
|
||||
PDFF_RESERVED_RIGHTTOLEFT = 0x8
|
||||
PDFF_SHORTTIME = 0x10
|
||||
PDFF_LONGTIME = 0x20
|
||||
PDFF_HIDETIME = 0x40
|
||||
PDFF_SHORTDATE = 0x80
|
||||
PDFF_LONGDATE = 0x100
|
||||
PDFF_HIDEDATE = 0x200
|
||||
PDFF_RELATIVEDATE = 0x400
|
||||
PDFF_USEEDITINVITATION = 0x800
|
||||
PDFF_READONLY = 0x1000
|
||||
PDFF_NOAUTOREADINGORDER = 0x2000
|
||||
|
||||
PDSD_GENERAL = 0
|
||||
PDSD_A_Z = 1
|
||||
PDSD_LOWEST_HIGHEST = 2
|
||||
PDSD_SMALLEST_BIGGEST = 3
|
||||
PDSD_OLDEST_NEWEST = 4
|
||||
|
||||
PDRDT_GENERAL = 0
|
||||
PDRDT_DATE = 1
|
||||
PDRDT_SIZE = 2
|
||||
PDRDT_COUNT = 3
|
||||
PDRDT_REVISION = 4
|
||||
PDRDT_LENGTH = 5
|
||||
PDRDT_DURATION = 6
|
||||
PDRDT_SPEED = 7
|
||||
PDRDT_RATE = 8
|
||||
PDRDT_RATING = 9
|
||||
PDRDT_PRIORITY = 10
|
||||
|
||||
PDAT_DEFAULT = 0
|
||||
PDAT_FIRST = 1
|
||||
PDAT_SUM = 2
|
||||
PDAT_AVERAGE = 3
|
||||
PDAT_DATERANGE = 4
|
||||
PDAT_UNION = 5
|
||||
PDAT_MAX = 6
|
||||
PDAT_MIN = 7
|
||||
|
||||
PDCOT_NONE = 0
|
||||
PDCOT_STRING = 1
|
||||
PDCOT_SIZE = 2
|
||||
PDCOT_DATETIME = 3
|
||||
PDCOT_BOOLEAN = 4
|
||||
PDCOT_NUMBER = 5
|
||||
|
||||
PDSIF_DEFAULT = 0
|
||||
PDSIF_ININVERTEDINDEX = 0x1
|
||||
PDSIF_ISCOLUMN = 0x2
|
||||
PDSIF_ISCOLUMNSPARSE = 0x4
|
||||
PDCIT_NONE = 0
|
||||
PDCIT_ONDISK = 1
|
||||
PDCIT_INMEMORY = 2
|
||||
|
||||
## PROPDESC_ENUMFILTER, used with IPropertySystem::EnumeratePropertyDescriptions
|
||||
PDEF_ALL = 0
|
||||
PDEF_SYSTEM = 1
|
||||
PDEF_NONSYSTEM = 2
|
||||
PDEF_VIEWABLE = 3
|
||||
PDEF_QUERYABLE = 4
|
||||
PDEF_INFULLTEXTQUERY = 5
|
||||
PDEF_COLUMN = 6
|
||||
|
||||
## PSC_STATE, used with IPropertyStoreCache
|
||||
PSC_NORMAL = 0
|
||||
PSC_NOTINSOURCE = 1
|
||||
PSC_DIRTY = 2
|
||||
|
||||
## CONDITION_OPERATION
|
||||
COP_IMPLICIT = 0
|
||||
COP_EQUAL = 1
|
||||
COP_NOTEQUAL = 2
|
||||
COP_LESSTHAN = 3
|
||||
COP_GREATERTHAN = 4
|
||||
COP_LESSTHANOREQUAL = 5
|
||||
COP_GREATERTHANOREQUAL = 6
|
||||
COP_VALUE_STARTSWITH = 7
|
||||
COP_VALUE_ENDSWITH = 8
|
||||
COP_VALUE_CONTAINS = 9
|
||||
COP_VALUE_NOTCONTAINS = 10
|
||||
COP_DOSWILDCARDS = 11
|
||||
COP_WORD_EQUAL = 12
|
||||
COP_WORD_STARTSWITH = 13
|
||||
COP_APPLICATION_SPECIFIC = 14
|
||||
|
||||
## PERSIST_SPROPSTORE_FLAGS, used with IPersistSerializedPropStorage
|
||||
FPSPS_READONLY = 1
|
||||
|
||||
PKEY_PIDSTR_MAX = 10 # will take care of any long integer value
|
||||
# define GUIDSTRING_MAX (1 + 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1) // "{12345678-1234-1234-1234-123456789012}"
|
||||
GUIDSTRING_MAX = 1 + 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1 # hrm ???
|
||||
# define PKEYSTR_MAX (GUIDSTRING_MAX + 1 + PKEY_PIDSTR_MAX)
|
||||
PKEYSTR_MAX = GUIDSTRING_MAX + 1 + PKEY_PIDSTR_MAX
|
||||
|
||||
## Property keys from propkey.h
|
||||
from pywintypes import IID
|
||||
|
||||
PKEY_Audio_ChannelCount = (IID("{64440490-4C8B-11D1-8B70-080036B11A03}"), 7)
|
||||
PKEY_Audio_Compression = (IID("{64440490-4C8B-11D1-8B70-080036B11A03}"), 10)
|
||||
PKEY_Audio_EncodingBitrate = (IID("{64440490-4C8B-11D1-8B70-080036B11A03}"), 4)
|
||||
PKEY_Audio_Format = (IID("{64440490-4C8B-11D1-8B70-080036B11A03}"), 2)
|
||||
PKEY_Audio_IsVariableBitRate = (IID("{E6822FEE-8C17-4D62-823C-8E9CFCBD1D5C}"), 100)
|
||||
PKEY_Audio_PeakValue = (IID("{2579E5D0-1116-4084-BD9A-9B4F7CB4DF5E}"), 100)
|
||||
PKEY_Audio_SampleRate = (IID("{64440490-4C8B-11D1-8B70-080036B11A03}"), 5)
|
||||
PKEY_Audio_SampleSize = (IID("{64440490-4C8B-11D1-8B70-080036B11A03}"), 6)
|
||||
PKEY_Audio_StreamName = (IID("{64440490-4C8B-11D1-8B70-080036B11A03}"), 9)
|
||||
PKEY_Audio_StreamNumber = (IID("{64440490-4C8B-11D1-8B70-080036B11A03}"), 8)
|
||||
PKEY_Calendar_Duration = (IID("{293CA35A-09AA-4DD2-B180-1FE245728A52}"), 100)
|
||||
PKEY_Calendar_IsOnline = (IID("{BFEE9149-E3E2-49A7-A862-C05988145CEC}"), 100)
|
||||
PKEY_Calendar_IsRecurring = (IID("{315B9C8D-80A9-4EF9-AE16-8E746DA51D70}"), 100)
|
||||
PKEY_Calendar_Location = (IID("{F6272D18-CECC-40B1-B26A-3911717AA7BD}"), 100)
|
||||
PKEY_Calendar_OptionalAttendeeAddresses = (
|
||||
IID("{D55BAE5A-3892-417A-A649-C6AC5AAAEAB3}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Calendar_OptionalAttendeeNames = (
|
||||
IID("{09429607-582D-437F-84C3-DE93A2B24C3C}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Calendar_OrganizerAddress = (IID("{744C8242-4DF5-456C-AB9E-014EFB9021E3}"), 100)
|
||||
PKEY_Calendar_OrganizerName = (IID("{AAA660F9-9865-458E-B484-01BC7FE3973E}"), 100)
|
||||
PKEY_Calendar_ReminderTime = (IID("{72FC5BA4-24F9-4011-9F3F-ADD27AFAD818}"), 100)
|
||||
PKEY_Calendar_RequiredAttendeeAddresses = (
|
||||
IID("{0BA7D6C3-568D-4159-AB91-781A91FB71E5}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Calendar_RequiredAttendeeNames = (
|
||||
IID("{B33AF30B-F552-4584-936C-CB93E5CDA29F}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Calendar_Resources = (IID("{00F58A38-C54B-4C40-8696-97235980EAE1}"), 100)
|
||||
PKEY_Calendar_ShowTimeAs = (IID("{5BF396D4-5EB2-466F-BDE9-2FB3F2361D6E}"), 100)
|
||||
PKEY_Calendar_ShowTimeAsText = (IID("{53DA57CF-62C0-45C4-81DE-7610BCEFD7F5}"), 100)
|
||||
PKEY_Communication_AccountName = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 9)
|
||||
PKEY_Communication_Suffix = (IID("{807B653A-9E91-43EF-8F97-11CE04EE20C5}"), 100)
|
||||
PKEY_Communication_TaskStatus = (IID("{BE1A72C6-9A1D-46B7-AFE7-AFAF8CEF4999}"), 100)
|
||||
PKEY_Communication_TaskStatusText = (IID("{A6744477-C237-475B-A075-54F34498292A}"), 100)
|
||||
PKEY_Computer_DecoratedFreeSpace = (IID("{9B174B35-40FF-11D2-A27E-00C04FC30871}"), 7)
|
||||
PKEY_Contact_Anniversary = (IID("{9AD5BADB-CEA7-4470-A03D-B84E51B9949E}"), 100)
|
||||
PKEY_Contact_AssistantName = (IID("{CD102C9C-5540-4A88-A6F6-64E4981C8CD1}"), 100)
|
||||
PKEY_Contact_AssistantTelephone = (IID("{9A93244D-A7AD-4FF8-9B99-45EE4CC09AF6}"), 100)
|
||||
PKEY_Contact_Birthday = (IID("{176DC63C-2688-4E89-8143-A347800F25E9}"), 47)
|
||||
PKEY_Contact_BusinessAddress = (IID("{730FB6DD-CF7C-426B-A03F-BD166CC9EE24}"), 100)
|
||||
PKEY_Contact_BusinessAddressCity = (IID("{402B5934-EC5A-48C3-93E6-85E86A2D934E}"), 100)
|
||||
PKEY_Contact_BusinessAddressCountry = (
|
||||
IID("{B0B87314-FCF6-4FEB-8DFF-A50DA6AF561C}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Contact_BusinessAddressPostalCode = (
|
||||
IID("{E1D4A09E-D758-4CD1-B6EC-34A8B5A73F80}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Contact_BusinessAddressPostOfficeBox = (
|
||||
IID("{BC4E71CE-17F9-48D5-BEE9-021DF0EA5409}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Contact_BusinessAddressState = (IID("{446F787F-10C4-41CB-A6C4-4D0343551597}"), 100)
|
||||
PKEY_Contact_BusinessAddressStreet = (
|
||||
IID("{DDD1460F-C0BF-4553-8CE4-10433C908FB0}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Contact_BusinessFaxNumber = (IID("{91EFF6F3-2E27-42CA-933E-7C999FBE310B}"), 100)
|
||||
PKEY_Contact_BusinessHomePage = (IID("{56310920-2491-4919-99CE-EADB06FAFDB2}"), 100)
|
||||
PKEY_Contact_BusinessTelephone = (IID("{6A15E5A0-0A1E-4CD7-BB8C-D2F1B0C929BC}"), 100)
|
||||
PKEY_Contact_CallbackTelephone = (IID("{BF53D1C3-49E0-4F7F-8567-5A821D8AC542}"), 100)
|
||||
PKEY_Contact_CarTelephone = (IID("{8FDC6DEA-B929-412B-BA90-397A257465FE}"), 100)
|
||||
PKEY_Contact_Children = (IID("{D4729704-8EF1-43EF-9024-2BD381187FD5}"), 100)
|
||||
PKEY_Contact_CompanyMainTelephone = (IID("{8589E481-6040-473D-B171-7FA89C2708ED}"), 100)
|
||||
PKEY_Contact_Department = (IID("{FC9F7306-FF8F-4D49-9FB6-3FFE5C0951EC}"), 100)
|
||||
PKEY_Contact_EmailAddress = (IID("{F8FA7FA3-D12B-4785-8A4E-691A94F7A3E7}"), 100)
|
||||
PKEY_Contact_EmailAddress2 = (IID("{38965063-EDC8-4268-8491-B7723172CF29}"), 100)
|
||||
PKEY_Contact_EmailAddress3 = (IID("{644D37B4-E1B3-4BAD-B099-7E7C04966ACA}"), 100)
|
||||
PKEY_Contact_EmailAddresses = (IID("{84D8F337-981D-44B3-9615-C7596DBA17E3}"), 100)
|
||||
PKEY_Contact_EmailName = (IID("{CC6F4F24-6083-4BD4-8754-674D0DE87AB8}"), 100)
|
||||
PKEY_Contact_FileAsName = (IID("{F1A24AA7-9CA7-40F6-89EC-97DEF9FFE8DB}"), 100)
|
||||
PKEY_Contact_FirstName = (IID("{14977844-6B49-4AAD-A714-A4513BF60460}"), 100)
|
||||
PKEY_Contact_FullName = (IID("{635E9051-50A5-4BA2-B9DB-4ED056C77296}"), 100)
|
||||
PKEY_Contact_Gender = (IID("{3C8CEE58-D4F0-4CF9-B756-4E5D24447BCD}"), 100)
|
||||
PKEY_Contact_Hobbies = (IID("{5DC2253F-5E11-4ADF-9CFE-910DD01E3E70}"), 100)
|
||||
PKEY_Contact_HomeAddress = (IID("{98F98354-617A-46B8-8560-5B1B64BF1F89}"), 100)
|
||||
PKEY_Contact_HomeAddressCity = (IID("{176DC63C-2688-4E89-8143-A347800F25E9}"), 65)
|
||||
PKEY_Contact_HomeAddressCountry = (IID("{08A65AA1-F4C9-43DD-9DDF-A33D8E7EAD85}"), 100)
|
||||
PKEY_Contact_HomeAddressPostalCode = (
|
||||
IID("{8AFCC170-8A46-4B53-9EEE-90BAE7151E62}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Contact_HomeAddressPostOfficeBox = (
|
||||
IID("{7B9F6399-0A3F-4B12-89BD-4ADC51C918AF}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Contact_HomeAddressState = (IID("{C89A23D0-7D6D-4EB8-87D4-776A82D493E5}"), 100)
|
||||
PKEY_Contact_HomeAddressStreet = (IID("{0ADEF160-DB3F-4308-9A21-06237B16FA2A}"), 100)
|
||||
PKEY_Contact_HomeFaxNumber = (IID("{660E04D6-81AB-4977-A09F-82313113AB26}"), 100)
|
||||
PKEY_Contact_HomeTelephone = (IID("{176DC63C-2688-4E89-8143-A347800F25E9}"), 20)
|
||||
PKEY_Contact_IMAddress = (IID("{D68DBD8A-3374-4B81-9972-3EC30682DB3D}"), 100)
|
||||
PKEY_Contact_Initials = (IID("{F3D8F40D-50CB-44A2-9718-40CB9119495D}"), 100)
|
||||
PKEY_Contact_JA_CompanyNamePhonetic = (IID("{897B3694-FE9E-43E6-8066-260F590C0100}"), 2)
|
||||
PKEY_Contact_JA_FirstNamePhonetic = (IID("{897B3694-FE9E-43E6-8066-260F590C0100}"), 3)
|
||||
PKEY_Contact_JA_LastNamePhonetic = (IID("{897B3694-FE9E-43E6-8066-260F590C0100}"), 4)
|
||||
PKEY_Contact_JobTitle = (IID("{176DC63C-2688-4E89-8143-A347800F25E9}"), 6)
|
||||
PKEY_Contact_Label = (IID("{97B0AD89-DF49-49CC-834E-660974FD755B}"), 100)
|
||||
PKEY_Contact_LastName = (IID("{8F367200-C270-457C-B1D4-E07C5BCD90C7}"), 100)
|
||||
PKEY_Contact_MailingAddress = (IID("{C0AC206A-827E-4650-95AE-77E2BB74FCC9}"), 100)
|
||||
PKEY_Contact_MiddleName = (IID("{176DC63C-2688-4E89-8143-A347800F25E9}"), 71)
|
||||
PKEY_Contact_MobileTelephone = (IID("{176DC63C-2688-4E89-8143-A347800F25E9}"), 35)
|
||||
PKEY_Contact_NickName = (IID("{176DC63C-2688-4E89-8143-A347800F25E9}"), 74)
|
||||
PKEY_Contact_OfficeLocation = (IID("{176DC63C-2688-4E89-8143-A347800F25E9}"), 7)
|
||||
PKEY_Contact_OtherAddress = (IID("{508161FA-313B-43D5-83A1-C1ACCF68622C}"), 100)
|
||||
PKEY_Contact_OtherAddressCity = (IID("{6E682923-7F7B-4F0C-A337-CFCA296687BF}"), 100)
|
||||
PKEY_Contact_OtherAddressCountry = (IID("{8F167568-0AAE-4322-8ED9-6055B7B0E398}"), 100)
|
||||
PKEY_Contact_OtherAddressPostalCode = (
|
||||
IID("{95C656C1-2ABF-4148-9ED3-9EC602E3B7CD}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Contact_OtherAddressPostOfficeBox = (
|
||||
IID("{8B26EA41-058F-43F6-AECC-4035681CE977}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Contact_OtherAddressState = (IID("{71B377D6-E570-425F-A170-809FAE73E54E}"), 100)
|
||||
PKEY_Contact_OtherAddressStreet = (IID("{FF962609-B7D6-4999-862D-95180D529AEA}"), 100)
|
||||
PKEY_Contact_PagerTelephone = (IID("{D6304E01-F8F5-4F45-8B15-D024A6296789}"), 100)
|
||||
PKEY_Contact_PersonalTitle = (IID("{176DC63C-2688-4E89-8143-A347800F25E9}"), 69)
|
||||
PKEY_Contact_PrimaryAddressCity = (IID("{C8EA94F0-A9E3-4969-A94B-9C62A95324E0}"), 100)
|
||||
PKEY_Contact_PrimaryAddressCountry = (
|
||||
IID("{E53D799D-0F3F-466E-B2FF-74634A3CB7A4}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Contact_PrimaryAddressPostalCode = (
|
||||
IID("{18BBD425-ECFD-46EF-B612-7B4A6034EDA0}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Contact_PrimaryAddressPostOfficeBox = (
|
||||
IID("{DE5EF3C7-46E1-484E-9999-62C5308394C1}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Contact_PrimaryAddressState = (IID("{F1176DFE-7138-4640-8B4C-AE375DC70A6D}"), 100)
|
||||
PKEY_Contact_PrimaryAddressStreet = (IID("{63C25B20-96BE-488F-8788-C09C407AD812}"), 100)
|
||||
PKEY_Contact_PrimaryEmailAddress = (IID("{176DC63C-2688-4E89-8143-A347800F25E9}"), 48)
|
||||
PKEY_Contact_PrimaryTelephone = (IID("{176DC63C-2688-4E89-8143-A347800F25E9}"), 25)
|
||||
PKEY_Contact_Profession = (IID("{7268AF55-1CE4-4F6E-A41F-B6E4EF10E4A9}"), 100)
|
||||
PKEY_Contact_SpouseName = (IID("{9D2408B6-3167-422B-82B0-F583B7A7CFE3}"), 100)
|
||||
PKEY_Contact_Suffix = (IID("{176DC63C-2688-4E89-8143-A347800F25E9}"), 73)
|
||||
PKEY_Contact_TelexNumber = (IID("{C554493C-C1F7-40C1-A76C-EF8C0614003E}"), 100)
|
||||
PKEY_Contact_TTYTDDTelephone = (IID("{AAF16BAC-2B55-45E6-9F6D-415EB94910DF}"), 100)
|
||||
PKEY_Contact_WebPage = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 18)
|
||||
PKEY_AcquisitionID = (IID("{65A98875-3C80-40AB-ABBC-EFDAF77DBEE2}"), 100)
|
||||
PKEY_ApplicationName = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 18)
|
||||
PKEY_Author = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 4)
|
||||
PKEY_Capacity = (IID("{9B174B35-40FF-11D2-A27E-00C04FC30871}"), 3)
|
||||
PKEY_Category = (IID("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}"), 2)
|
||||
PKEY_Comment = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 6)
|
||||
PKEY_Company = (IID("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}"), 15)
|
||||
PKEY_ComputerName = (IID("{28636AA6-953D-11D2-B5D6-00C04FD918D0}"), 5)
|
||||
PKEY_ContainedItems = (IID("{28636AA6-953D-11D2-B5D6-00C04FD918D0}"), 29)
|
||||
PKEY_ContentStatus = (IID("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}"), 27)
|
||||
PKEY_ContentType = (IID("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}"), 26)
|
||||
PKEY_Copyright = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 11)
|
||||
PKEY_DateAccessed = (IID("{B725F130-47EF-101A-A5F1-02608C9EEBAC}"), 16)
|
||||
PKEY_DateAcquired = (IID("{2CBAA8F5-D81F-47CA-B17A-F8D822300131}"), 100)
|
||||
PKEY_DateArchived = (IID("{43F8D7B7-A444-4F87-9383-52271C9B915C}"), 100)
|
||||
PKEY_DateCompleted = (IID("{72FAB781-ACDA-43E5-B155-B2434F85E678}"), 100)
|
||||
PKEY_DateCreated = (IID("{B725F130-47EF-101A-A5F1-02608C9EEBAC}"), 15)
|
||||
PKEY_DateImported = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 18258)
|
||||
PKEY_DateModified = (IID("{B725F130-47EF-101A-A5F1-02608C9EEBAC}"), 14)
|
||||
PKEY_DueDate = (IID("{3F8472B5-E0AF-4DB2-8071-C53FE76AE7CE}"), 100)
|
||||
PKEY_EndDate = (IID("{C75FAA05-96FD-49E7-9CB4-9F601082D553}"), 100)
|
||||
PKEY_FileAllocationSize = (IID("{B725F130-47EF-101A-A5F1-02608C9EEBAC}"), 18)
|
||||
PKEY_FileAttributes = (IID("{B725F130-47EF-101A-A5F1-02608C9EEBAC}"), 13)
|
||||
PKEY_FileCount = (IID("{28636AA6-953D-11D2-B5D6-00C04FD918D0}"), 12)
|
||||
PKEY_FileDescription = (IID("{0CEF7D53-FA64-11D1-A203-0000F81FEDEE}"), 3)
|
||||
PKEY_FileExtension = (IID("{E4F10A3C-49E6-405D-8288-A23BD4EEAA6C}"), 100)
|
||||
PKEY_FileFRN = (IID("{B725F130-47EF-101A-A5F1-02608C9EEBAC}"), 21)
|
||||
PKEY_FileName = (IID("{41CF5AE0-F75A-4806-BD87-59C7D9248EB9}"), 100)
|
||||
PKEY_FileOwner = (IID("{9B174B34-40FF-11D2-A27E-00C04FC30871}"), 4)
|
||||
PKEY_FileVersion = (IID("{0CEF7D53-FA64-11D1-A203-0000F81FEDEE}"), 4)
|
||||
PKEY_FindData = (IID("{28636AA6-953D-11D2-B5D6-00C04FD918D0}"), 0)
|
||||
PKEY_FlagColor = (IID("{67DF94DE-0CA7-4D6F-B792-053A3E4F03CF}"), 100)
|
||||
PKEY_FlagColorText = (IID("{45EAE747-8E2A-40AE-8CBF-CA52ABA6152A}"), 100)
|
||||
PKEY_FlagStatus = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 12)
|
||||
PKEY_FlagStatusText = (IID("{DC54FD2E-189D-4871-AA01-08C2F57A4ABC}"), 100)
|
||||
PKEY_FreeSpace = (IID("{9B174B35-40FF-11D2-A27E-00C04FC30871}"), 2)
|
||||
PKEY_Identity = (IID("{A26F4AFC-7346-4299-BE47-EB1AE613139F}"), 100)
|
||||
PKEY_Importance = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 11)
|
||||
PKEY_ImportanceText = (IID("{A3B29791-7713-4E1D-BB40-17DB85F01831}"), 100)
|
||||
PKEY_IsAttachment = (IID("{F23F425C-71A1-4FA8-922F-678EA4A60408}"), 100)
|
||||
PKEY_IsDeleted = (IID("{5CDA5FC8-33EE-4FF3-9094-AE7BD8868C4D}"), 100)
|
||||
PKEY_IsFlagged = (IID("{5DA84765-E3FF-4278-86B0-A27967FBDD03}"), 100)
|
||||
PKEY_IsFlaggedComplete = (IID("{A6F360D2-55F9-48DE-B909-620E090A647C}"), 100)
|
||||
PKEY_IsIncomplete = (IID("{346C8BD1-2E6A-4C45-89A4-61B78E8E700F}"), 100)
|
||||
PKEY_IsRead = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 10)
|
||||
PKEY_IsSendToTarget = (IID("{28636AA6-953D-11D2-B5D6-00C04FD918D0}"), 33)
|
||||
PKEY_IsShared = (IID("{EF884C5B-2BFE-41BB-AAE5-76EEDF4F9902}"), 100)
|
||||
PKEY_ItemAuthors = (IID("{D0A04F0A-462A-48A4-BB2F-3706E88DBD7D}"), 100)
|
||||
PKEY_ItemDate = (IID("{F7DB74B4-4287-4103-AFBA-F1B13DCD75CF}"), 100)
|
||||
PKEY_ItemFolderNameDisplay = (IID("{B725F130-47EF-101A-A5F1-02608C9EEBAC}"), 2)
|
||||
PKEY_ItemFolderPathDisplay = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 6)
|
||||
PKEY_ItemFolderPathDisplayNarrow = (IID("{DABD30ED-0043-4789-A7F8-D013A4736622}"), 100)
|
||||
PKEY_ItemName = (IID("{6B8DA074-3B5C-43BC-886F-0A2CDCE00B6F}"), 100)
|
||||
PKEY_ItemNameDisplay = (IID("{B725F130-47EF-101A-A5F1-02608C9EEBAC}"), 10)
|
||||
PKEY_ItemNamePrefix = (IID("{D7313FF1-A77A-401C-8C99-3DBDD68ADD36}"), 100)
|
||||
PKEY_ItemParticipants = (IID("{D4D0AA16-9948-41A4-AA85-D97FF9646993}"), 100)
|
||||
PKEY_ItemPathDisplay = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 7)
|
||||
PKEY_ItemPathDisplayNarrow = (IID("{28636AA6-953D-11D2-B5D6-00C04FD918D0}"), 8)
|
||||
PKEY_ItemType = (IID("{28636AA6-953D-11D2-B5D6-00C04FD918D0}"), 11)
|
||||
PKEY_ItemTypeText = (IID("{B725F130-47EF-101A-A5F1-02608C9EEBAC}"), 4)
|
||||
PKEY_ItemUrl = (IID("{49691C90-7E17-101A-A91C-08002B2ECDA9}"), 9)
|
||||
PKEY_Keywords = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 5)
|
||||
PKEY_Kind = (IID("{1E3EE840-BC2B-476C-8237-2ACD1A839B22}"), 3)
|
||||
PKEY_KindText = (IID("{F04BEF95-C585-4197-A2B7-DF46FDC9EE6D}"), 100)
|
||||
PKEY_Language = (IID("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}"), 28)
|
||||
PKEY_MileageInformation = (IID("{FDF84370-031A-4ADD-9E91-0D775F1C6605}"), 100)
|
||||
PKEY_MIMEType = (IID("{0B63E350-9CCC-11D0-BCDB-00805FCCCE04}"), 5)
|
||||
PKEY_Null = (IID("{00000000-0000-0000-0000-000000000000}"), 0)
|
||||
PKEY_OfflineAvailability = (IID("{A94688B6-7D9F-4570-A648-E3DFC0AB2B3F}"), 100)
|
||||
PKEY_OfflineStatus = (IID("{6D24888F-4718-4BDA-AFED-EA0FB4386CD8}"), 100)
|
||||
PKEY_OriginalFileName = (IID("{0CEF7D53-FA64-11D1-A203-0000F81FEDEE}"), 6)
|
||||
PKEY_ParentalRating = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 21)
|
||||
PKEY_ParentalRatingReason = (IID("{10984E0A-F9F2-4321-B7EF-BAF195AF4319}"), 100)
|
||||
PKEY_ParentalRatingsOrganization = (IID("{A7FE0840-1344-46F0-8D37-52ED712A4BF9}"), 100)
|
||||
PKEY_ParsingBindContext = (IID("{DFB9A04D-362F-4CA3-B30B-0254B17B5B84}"), 100)
|
||||
PKEY_ParsingName = (IID("{28636AA6-953D-11D2-B5D6-00C04FD918D0}"), 24)
|
||||
PKEY_ParsingPath = (IID("{28636AA6-953D-11D2-B5D6-00C04FD918D0}"), 30)
|
||||
PKEY_PerceivedType = (IID("{28636AA6-953D-11D2-B5D6-00C04FD918D0}"), 9)
|
||||
PKEY_PercentFull = (IID("{9B174B35-40FF-11D2-A27E-00C04FC30871}"), 5)
|
||||
PKEY_Priority = (IID("{9C1FCF74-2D97-41BA-B4AE-CB2E3661A6E4}"), 5)
|
||||
PKEY_PriorityText = (IID("{D98BE98B-B86B-4095-BF52-9D23B2E0A752}"), 100)
|
||||
PKEY_Project = (IID("{39A7F922-477C-48DE-8BC8-B28441E342E3}"), 100)
|
||||
PKEY_ProviderItemID = (IID("{F21D9941-81F0-471A-ADEE-4E74B49217ED}"), 100)
|
||||
PKEY_Rating = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 9)
|
||||
PKEY_RatingText = (IID("{90197CA7-FD8F-4E8C-9DA3-B57E1E609295}"), 100)
|
||||
PKEY_Sensitivity = (IID("{F8D3F6AC-4874-42CB-BE59-AB454B30716A}"), 100)
|
||||
PKEY_SensitivityText = (IID("{D0C7F054-3F72-4725-8527-129A577CB269}"), 100)
|
||||
PKEY_SFGAOFlags = (IID("{28636AA6-953D-11D2-B5D6-00C04FD918D0}"), 25)
|
||||
PKEY_SharedWith = (IID("{EF884C5B-2BFE-41BB-AAE5-76EEDF4F9902}"), 200)
|
||||
PKEY_ShareUserRating = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 12)
|
||||
PKEY_Shell_OmitFromView = (IID("{DE35258C-C695-4CBC-B982-38B0AD24CED0}"), 2)
|
||||
PKEY_SimpleRating = (IID("{A09F084E-AD41-489F-8076-AA5BE3082BCA}"), 100)
|
||||
PKEY_Size = (IID("{B725F130-47EF-101A-A5F1-02608C9EEBAC}"), 12)
|
||||
PKEY_SoftwareUsed = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 305)
|
||||
PKEY_SourceItem = (IID("{668CDFA5-7A1B-4323-AE4B-E527393A1D81}"), 100)
|
||||
PKEY_StartDate = (IID("{48FD6EC8-8A12-4CDF-A03E-4EC5A511EDDE}"), 100)
|
||||
PKEY_Status = (IID("{000214A1-0000-0000-C000-000000000046}"), 9)
|
||||
PKEY_Subject = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 3)
|
||||
PKEY_Thumbnail = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 17)
|
||||
PKEY_ThumbnailCacheId = (IID("{446D16B1-8DAD-4870-A748-402EA43D788C}"), 100)
|
||||
PKEY_ThumbnailStream = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 27)
|
||||
PKEY_Title = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 2)
|
||||
PKEY_TotalFileSize = (IID("{28636AA6-953D-11D2-B5D6-00C04FD918D0}"), 14)
|
||||
PKEY_Trademarks = (IID("{0CEF7D53-FA64-11D1-A203-0000F81FEDEE}"), 9)
|
||||
PKEY_Document_ByteCount = (IID("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}"), 4)
|
||||
PKEY_Document_CharacterCount = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 16)
|
||||
PKEY_Document_ClientID = (IID("{276D7BB0-5B34-4FB0-AA4B-158ED12A1809}"), 100)
|
||||
PKEY_Document_Contributor = (IID("{F334115E-DA1B-4509-9B3D-119504DC7ABB}"), 100)
|
||||
PKEY_Document_DateCreated = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 12)
|
||||
PKEY_Document_DatePrinted = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 11)
|
||||
PKEY_Document_DateSaved = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 13)
|
||||
PKEY_Document_Division = (IID("{1E005EE6-BF27-428B-B01C-79676ACD2870}"), 100)
|
||||
PKEY_Document_DocumentID = (IID("{E08805C8-E395-40DF-80D2-54F0D6C43154}"), 100)
|
||||
PKEY_Document_HiddenSlideCount = (IID("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}"), 9)
|
||||
PKEY_Document_LastAuthor = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 8)
|
||||
PKEY_Document_LineCount = (IID("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}"), 5)
|
||||
PKEY_Document_Manager = (IID("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}"), 14)
|
||||
PKEY_Document_MultimediaClipCount = (IID("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}"), 10)
|
||||
PKEY_Document_NoteCount = (IID("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}"), 8)
|
||||
PKEY_Document_PageCount = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 14)
|
||||
PKEY_Document_ParagraphCount = (IID("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}"), 6)
|
||||
PKEY_Document_PresentationFormat = (IID("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}"), 3)
|
||||
PKEY_Document_RevisionNumber = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 9)
|
||||
PKEY_Document_Security = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 19)
|
||||
PKEY_Document_SlideCount = (IID("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}"), 7)
|
||||
PKEY_Document_Template = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 7)
|
||||
PKEY_Document_TotalEditingTime = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 10)
|
||||
PKEY_Document_Version = (IID("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}"), 29)
|
||||
PKEY_Document_WordCount = (IID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"), 15)
|
||||
PKEY_DRM_DatePlayExpires = (IID("{AEAC19E4-89AE-4508-B9B7-BB867ABEE2ED}"), 6)
|
||||
PKEY_DRM_DatePlayStarts = (IID("{AEAC19E4-89AE-4508-B9B7-BB867ABEE2ED}"), 5)
|
||||
PKEY_DRM_Description = (IID("{AEAC19E4-89AE-4508-B9B7-BB867ABEE2ED}"), 3)
|
||||
PKEY_DRM_IsProtected = (IID("{AEAC19E4-89AE-4508-B9B7-BB867ABEE2ED}"), 2)
|
||||
PKEY_DRM_PlayCount = (IID("{AEAC19E4-89AE-4508-B9B7-BB867ABEE2ED}"), 4)
|
||||
PKEY_GPS_Altitude = (IID("{827EDB4F-5B73-44A7-891D-FDFFABEA35CA}"), 100)
|
||||
PKEY_GPS_AltitudeDenominator = (IID("{78342DCB-E358-4145-AE9A-6BFE4E0F9F51}"), 100)
|
||||
PKEY_GPS_AltitudeNumerator = (IID("{2DAD1EB7-816D-40D3-9EC3-C9773BE2AADE}"), 100)
|
||||
PKEY_GPS_AltitudeRef = (IID("{46AC629D-75EA-4515-867F-6DC4321C5844}"), 100)
|
||||
PKEY_GPS_AreaInformation = (IID("{972E333E-AC7E-49F1-8ADF-A70D07A9BCAB}"), 100)
|
||||
PKEY_GPS_Date = (IID("{3602C812-0F3B-45F0-85AD-603468D69423}"), 100)
|
||||
PKEY_GPS_DestBearing = (IID("{C66D4B3C-E888-47CC-B99F-9DCA3EE34DEA}"), 100)
|
||||
PKEY_GPS_DestBearingDenominator = (IID("{7ABCF4F8-7C3F-4988-AC91-8D2C2E97ECA5}"), 100)
|
||||
PKEY_GPS_DestBearingNumerator = (IID("{BA3B1DA9-86EE-4B5D-A2A4-A271A429F0CF}"), 100)
|
||||
PKEY_GPS_DestBearingRef = (IID("{9AB84393-2A0F-4B75-BB22-7279786977CB}"), 100)
|
||||
PKEY_GPS_DestDistance = (IID("{A93EAE04-6804-4F24-AC81-09B266452118}"), 100)
|
||||
PKEY_GPS_DestDistanceDenominator = (IID("{9BC2C99B-AC71-4127-9D1C-2596D0D7DCB7}"), 100)
|
||||
PKEY_GPS_DestDistanceNumerator = (IID("{2BDA47DA-08C6-4FE1-80BC-A72FC517C5D0}"), 100)
|
||||
PKEY_GPS_DestDistanceRef = (IID("{ED4DF2D3-8695-450B-856F-F5C1C53ACB66}"), 100)
|
||||
PKEY_GPS_DestLatitude = (IID("{9D1D7CC5-5C39-451C-86B3-928E2D18CC47}"), 100)
|
||||
PKEY_GPS_DestLatitudeDenominator = (IID("{3A372292-7FCA-49A7-99D5-E47BB2D4E7AB}"), 100)
|
||||
PKEY_GPS_DestLatitudeNumerator = (IID("{ECF4B6F6-D5A6-433C-BB92-4076650FC890}"), 100)
|
||||
PKEY_GPS_DestLatitudeRef = (IID("{CEA820B9-CE61-4885-A128-005D9087C192}"), 100)
|
||||
PKEY_GPS_DestLongitude = (IID("{47A96261-CB4C-4807-8AD3-40B9D9DBC6BC}"), 100)
|
||||
PKEY_GPS_DestLongitudeDenominator = (IID("{425D69E5-48AD-4900-8D80-6EB6B8D0AC86}"), 100)
|
||||
PKEY_GPS_DestLongitudeNumerator = (IID("{A3250282-FB6D-48D5-9A89-DBCACE75CCCF}"), 100)
|
||||
PKEY_GPS_DestLongitudeRef = (IID("{182C1EA6-7C1C-4083-AB4B-AC6C9F4ED128}"), 100)
|
||||
PKEY_GPS_Differential = (IID("{AAF4EE25-BD3B-4DD7-BFC4-47F77BB00F6D}"), 100)
|
||||
PKEY_GPS_DOP = (IID("{0CF8FB02-1837-42F1-A697-A7017AA289B9}"), 100)
|
||||
PKEY_GPS_DOPDenominator = (IID("{A0BE94C5-50BA-487B-BD35-0654BE8881ED}"), 100)
|
||||
PKEY_GPS_DOPNumerator = (IID("{47166B16-364F-4AA0-9F31-E2AB3DF449C3}"), 100)
|
||||
PKEY_GPS_ImgDirection = (IID("{16473C91-D017-4ED9-BA4D-B6BAA55DBCF8}"), 100)
|
||||
PKEY_GPS_ImgDirectionDenominator = (IID("{10B24595-41A2-4E20-93C2-5761C1395F32}"), 100)
|
||||
PKEY_GPS_ImgDirectionNumerator = (IID("{DC5877C7-225F-45F7-BAC7-E81334B6130A}"), 100)
|
||||
PKEY_GPS_ImgDirectionRef = (IID("{A4AAA5B7-1AD0-445F-811A-0F8F6E67F6B5}"), 100)
|
||||
PKEY_GPS_Latitude = (IID("{8727CFFF-4868-4EC6-AD5B-81B98521D1AB}"), 100)
|
||||
PKEY_GPS_LatitudeDenominator = (IID("{16E634EE-2BFF-497B-BD8A-4341AD39EEB9}"), 100)
|
||||
PKEY_GPS_LatitudeNumerator = (IID("{7DDAAAD1-CCC8-41AE-B750-B2CB8031AEA2}"), 100)
|
||||
PKEY_GPS_LatitudeRef = (IID("{029C0252-5B86-46C7-ACA0-2769FFC8E3D4}"), 100)
|
||||
PKEY_GPS_Longitude = (IID("{C4C4DBB2-B593-466B-BBDA-D03D27D5E43A}"), 100)
|
||||
PKEY_GPS_LongitudeDenominator = (IID("{BE6E176C-4534-4D2C-ACE5-31DEDAC1606B}"), 100)
|
||||
PKEY_GPS_LongitudeNumerator = (IID("{02B0F689-A914-4E45-821D-1DDA452ED2C4}"), 100)
|
||||
PKEY_GPS_LongitudeRef = (IID("{33DCF22B-28D5-464C-8035-1EE9EFD25278}"), 100)
|
||||
PKEY_GPS_MapDatum = (IID("{2CA2DAE6-EDDC-407D-BEF1-773942ABFA95}"), 100)
|
||||
PKEY_GPS_MeasureMode = (IID("{A015ED5D-AAEA-4D58-8A86-3C586920EA0B}"), 100)
|
||||
PKEY_GPS_ProcessingMethod = (IID("{59D49E61-840F-4AA9-A939-E2099B7F6399}"), 100)
|
||||
PKEY_GPS_Satellites = (IID("{467EE575-1F25-4557-AD4E-B8B58B0D9C15}"), 100)
|
||||
PKEY_GPS_Speed = (IID("{DA5D0862-6E76-4E1B-BABD-70021BD25494}"), 100)
|
||||
PKEY_GPS_SpeedDenominator = (IID("{7D122D5A-AE5E-4335-8841-D71E7CE72F53}"), 100)
|
||||
PKEY_GPS_SpeedNumerator = (IID("{ACC9CE3D-C213-4942-8B48-6D0820F21C6D}"), 100)
|
||||
PKEY_GPS_SpeedRef = (IID("{ECF7F4C9-544F-4D6D-9D98-8AD79ADAF453}"), 100)
|
||||
PKEY_GPS_Status = (IID("{125491F4-818F-46B2-91B5-D537753617B2}"), 100)
|
||||
PKEY_GPS_Track = (IID("{76C09943-7C33-49E3-9E7E-CDBA872CFADA}"), 100)
|
||||
PKEY_GPS_TrackDenominator = (IID("{C8D1920C-01F6-40C0-AC86-2F3A4AD00770}"), 100)
|
||||
PKEY_GPS_TrackNumerator = (IID("{702926F4-44A6-43E1-AE71-45627116893B}"), 100)
|
||||
PKEY_GPS_TrackRef = (IID("{35DBE6FE-44C3-4400-AAAE-D2C799C407E8}"), 100)
|
||||
PKEY_GPS_VersionID = (IID("{22704DA4-C6B2-4A99-8E56-F16DF8C92599}"), 100)
|
||||
PKEY_Image_BitDepth = (IID("{6444048F-4C8B-11D1-8B70-080036B11A03}"), 7)
|
||||
PKEY_Image_ColorSpace = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 40961)
|
||||
PKEY_Image_CompressedBitsPerPixel = (IID("{364B6FA9-37AB-482A-BE2B-AE02F60D4318}"), 100)
|
||||
PKEY_Image_CompressedBitsPerPixelDenominator = (
|
||||
IID("{1F8844E1-24AD-4508-9DFD-5326A415CE02}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Image_CompressedBitsPerPixelNumerator = (
|
||||
IID("{D21A7148-D32C-4624-8900-277210F79C0F}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Image_Compression = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 259)
|
||||
PKEY_Image_CompressionText = (IID("{3F08E66F-2F44-4BB9-A682-AC35D2562322}"), 100)
|
||||
PKEY_Image_Dimensions = (IID("{6444048F-4C8B-11D1-8B70-080036B11A03}"), 13)
|
||||
PKEY_Image_HorizontalResolution = (IID("{6444048F-4C8B-11D1-8B70-080036B11A03}"), 5)
|
||||
PKEY_Image_HorizontalSize = (IID("{6444048F-4C8B-11D1-8B70-080036B11A03}"), 3)
|
||||
PKEY_Image_ImageID = (IID("{10DABE05-32AA-4C29-BF1A-63E2D220587F}"), 100)
|
||||
PKEY_Image_ResolutionUnit = (IID("{19B51FA6-1F92-4A5C-AB48-7DF0ABD67444}"), 100)
|
||||
PKEY_Image_VerticalResolution = (IID("{6444048F-4C8B-11D1-8B70-080036B11A03}"), 6)
|
||||
PKEY_Image_VerticalSize = (IID("{6444048F-4C8B-11D1-8B70-080036B11A03}"), 4)
|
||||
PKEY_Journal_Contacts = (IID("{DEA7C82C-1D89-4A66-9427-A4E3DEBABCB1}"), 100)
|
||||
PKEY_Journal_EntryType = (IID("{95BEB1FC-326D-4644-B396-CD3ED90E6DDF}"), 100)
|
||||
PKEY_Link_Comment = (IID("{B9B4B3FC-2B51-4A42-B5D8-324146AFCF25}"), 5)
|
||||
PKEY_Link_DateVisited = (IID("{5CBF2787-48CF-4208-B90E-EE5E5D420294}"), 23)
|
||||
PKEY_Link_Description = (IID("{5CBF2787-48CF-4208-B90E-EE5E5D420294}"), 21)
|
||||
PKEY_Link_Status = (IID("{B9B4B3FC-2B51-4A42-B5D8-324146AFCF25}"), 3)
|
||||
PKEY_Link_TargetExtension = (IID("{7A7D76F4-B630-4BD7-95FF-37CC51A975C9}"), 2)
|
||||
PKEY_Link_TargetParsingPath = (IID("{B9B4B3FC-2B51-4A42-B5D8-324146AFCF25}"), 2)
|
||||
PKEY_Link_TargetSFGAOFlags = (IID("{B9B4B3FC-2B51-4A42-B5D8-324146AFCF25}"), 8)
|
||||
PKEY_Media_AuthorUrl = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 32)
|
||||
PKEY_Media_AverageLevel = (IID("{09EDD5B6-B301-43C5-9990-D00302EFFD46}"), 100)
|
||||
PKEY_Media_ClassPrimaryID = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 13)
|
||||
PKEY_Media_ClassSecondaryID = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 14)
|
||||
PKEY_Media_CollectionGroupID = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 24)
|
||||
PKEY_Media_CollectionID = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 25)
|
||||
PKEY_Media_ContentDistributor = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 18)
|
||||
PKEY_Media_ContentID = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 26)
|
||||
PKEY_Media_CreatorApplication = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 27)
|
||||
PKEY_Media_CreatorApplicationVersion = (
|
||||
IID("{64440492-4C8B-11D1-8B70-080036B11A03}"),
|
||||
28,
|
||||
)
|
||||
PKEY_Media_DateEncoded = (IID("{2E4B640D-5019-46D8-8881-55414CC5CAA0}"), 100)
|
||||
PKEY_Media_DateReleased = (IID("{DE41CC29-6971-4290-B472-F59F2E2F31E2}"), 100)
|
||||
PKEY_Media_Duration = (IID("{64440490-4C8B-11D1-8B70-080036B11A03}"), 3)
|
||||
PKEY_Media_DVDID = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 15)
|
||||
PKEY_Media_EncodedBy = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 36)
|
||||
PKEY_Media_EncodingSettings = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 37)
|
||||
PKEY_Media_FrameCount = (IID("{6444048F-4C8B-11D1-8B70-080036B11A03}"), 12)
|
||||
PKEY_Media_MCDI = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 16)
|
||||
PKEY_Media_MetadataContentProvider = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 17)
|
||||
PKEY_Media_Producer = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 22)
|
||||
PKEY_Media_PromotionUrl = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 33)
|
||||
PKEY_Media_ProtectionType = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 38)
|
||||
PKEY_Media_ProviderRating = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 39)
|
||||
PKEY_Media_ProviderStyle = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 40)
|
||||
PKEY_Media_Publisher = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 30)
|
||||
PKEY_Media_SubscriptionContentId = (IID("{9AEBAE7A-9644-487D-A92C-657585ED751A}"), 100)
|
||||
PKEY_Media_SubTitle = (IID("{56A3372E-CE9C-11D2-9F0E-006097C686F6}"), 38)
|
||||
PKEY_Media_UniqueFileIdentifier = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 35)
|
||||
PKEY_Media_UserNoAutoInfo = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 41)
|
||||
PKEY_Media_UserWebUrl = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 34)
|
||||
PKEY_Media_Writer = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 23)
|
||||
PKEY_Media_Year = (IID("{56A3372E-CE9C-11D2-9F0E-006097C686F6}"), 5)
|
||||
PKEY_Message_AttachmentContents = (IID("{3143BF7C-80A8-4854-8880-E2E40189BDD0}"), 100)
|
||||
PKEY_Message_AttachmentNames = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 21)
|
||||
PKEY_Message_BccAddress = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 2)
|
||||
PKEY_Message_BccName = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 3)
|
||||
PKEY_Message_CcAddress = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 4)
|
||||
PKEY_Message_CcName = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 5)
|
||||
PKEY_Message_ConversationID = (IID("{DC8F80BD-AF1E-4289-85B6-3DFC1B493992}"), 100)
|
||||
PKEY_Message_ConversationIndex = (IID("{DC8F80BD-AF1E-4289-85B6-3DFC1B493992}"), 101)
|
||||
PKEY_Message_DateReceived = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 20)
|
||||
PKEY_Message_DateSent = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 19)
|
||||
PKEY_Message_FromAddress = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 13)
|
||||
PKEY_Message_FromName = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 14)
|
||||
PKEY_Message_HasAttachments = (IID("{9C1FCF74-2D97-41BA-B4AE-CB2E3661A6E4}"), 8)
|
||||
PKEY_Message_IsFwdOrReply = (IID("{9A9BC088-4F6D-469E-9919-E705412040F9}"), 100)
|
||||
PKEY_Message_MessageClass = (IID("{CD9ED458-08CE-418F-A70E-F912C7BB9C5C}"), 103)
|
||||
PKEY_Message_SenderAddress = (IID("{0BE1C8E7-1981-4676-AE14-FDD78F05A6E7}"), 100)
|
||||
PKEY_Message_SenderName = (IID("{0DA41CFA-D224-4A18-AE2F-596158DB4B3A}"), 100)
|
||||
PKEY_Message_Store = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 15)
|
||||
PKEY_Message_ToAddress = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 16)
|
||||
PKEY_Message_ToDoTitle = (IID("{BCCC8A3C-8CEF-42E5-9B1C-C69079398BC7}"), 100)
|
||||
PKEY_Message_ToName = (IID("{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD}"), 17)
|
||||
PKEY_Music_AlbumArtist = (IID("{56A3372E-CE9C-11D2-9F0E-006097C686F6}"), 13)
|
||||
PKEY_Music_AlbumTitle = (IID("{56A3372E-CE9C-11D2-9F0E-006097C686F6}"), 4)
|
||||
PKEY_Music_Artist = (IID("{56A3372E-CE9C-11D2-9F0E-006097C686F6}"), 2)
|
||||
PKEY_Music_BeatsPerMinute = (IID("{56A3372E-CE9C-11D2-9F0E-006097C686F6}"), 35)
|
||||
PKEY_Music_Composer = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 19)
|
||||
PKEY_Music_Conductor = (IID("{56A3372E-CE9C-11D2-9F0E-006097C686F6}"), 36)
|
||||
PKEY_Music_ContentGroupDescription = (IID("{56A3372E-CE9C-11D2-9F0E-006097C686F6}"), 33)
|
||||
PKEY_Music_Genre = (IID("{56A3372E-CE9C-11D2-9F0E-006097C686F6}"), 11)
|
||||
PKEY_Music_InitialKey = (IID("{56A3372E-CE9C-11D2-9F0E-006097C686F6}"), 34)
|
||||
PKEY_Music_Lyrics = (IID("{56A3372E-CE9C-11D2-9F0E-006097C686F6}"), 12)
|
||||
PKEY_Music_Mood = (IID("{56A3372E-CE9C-11D2-9F0E-006097C686F6}"), 39)
|
||||
PKEY_Music_PartOfSet = (IID("{56A3372E-CE9C-11D2-9F0E-006097C686F6}"), 37)
|
||||
PKEY_Music_Period = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 31)
|
||||
PKEY_Music_SynchronizedLyrics = (IID("{6B223B6A-162E-4AA9-B39F-05D678FC6D77}"), 100)
|
||||
PKEY_Music_TrackNumber = (IID("{56A3372E-CE9C-11D2-9F0E-006097C686F6}"), 7)
|
||||
PKEY_Note_Color = (IID("{4776CAFA-BCE4-4CB1-A23E-265E76D8EB11}"), 100)
|
||||
PKEY_Note_ColorText = (IID("{46B4E8DE-CDB2-440D-885C-1658EB65B914}"), 100)
|
||||
PKEY_Photo_Aperture = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 37378)
|
||||
PKEY_Photo_ApertureDenominator = (IID("{E1A9A38B-6685-46BD-875E-570DC7AD7320}"), 100)
|
||||
PKEY_Photo_ApertureNumerator = (IID("{0337ECEC-39FB-4581-A0BD-4C4CC51E9914}"), 100)
|
||||
PKEY_Photo_Brightness = (IID("{1A701BF6-478C-4361-83AB-3701BB053C58}"), 100)
|
||||
PKEY_Photo_BrightnessDenominator = (IID("{6EBE6946-2321-440A-90F0-C043EFD32476}"), 100)
|
||||
PKEY_Photo_BrightnessNumerator = (IID("{9E7D118F-B314-45A0-8CFB-D654B917C9E9}"), 100)
|
||||
PKEY_Photo_CameraManufacturer = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 271)
|
||||
PKEY_Photo_CameraModel = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 272)
|
||||
PKEY_Photo_CameraSerialNumber = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 273)
|
||||
PKEY_Photo_Contrast = (IID("{2A785BA9-8D23-4DED-82E6-60A350C86A10}"), 100)
|
||||
PKEY_Photo_ContrastText = (IID("{59DDE9F2-5253-40EA-9A8B-479E96C6249A}"), 100)
|
||||
PKEY_Photo_DateTaken = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 36867)
|
||||
PKEY_Photo_DigitalZoom = (IID("{F85BF840-A925-4BC2-B0C4-8E36B598679E}"), 100)
|
||||
PKEY_Photo_DigitalZoomDenominator = (IID("{745BAF0E-E5C1-4CFB-8A1B-D031A0A52393}"), 100)
|
||||
PKEY_Photo_DigitalZoomNumerator = (IID("{16CBB924-6500-473B-A5BE-F1599BCBE413}"), 100)
|
||||
PKEY_Photo_Event = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 18248)
|
||||
PKEY_Photo_EXIFVersion = (IID("{D35F743A-EB2E-47F2-A286-844132CB1427}"), 100)
|
||||
PKEY_Photo_ExposureBias = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 37380)
|
||||
PKEY_Photo_ExposureBiasDenominator = (
|
||||
IID("{AB205E50-04B7-461C-A18C-2F233836E627}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Photo_ExposureBiasNumerator = (IID("{738BF284-1D87-420B-92CF-5834BF6EF9ED}"), 100)
|
||||
PKEY_Photo_ExposureIndex = (IID("{967B5AF8-995A-46ED-9E11-35B3C5B9782D}"), 100)
|
||||
PKEY_Photo_ExposureIndexDenominator = (
|
||||
IID("{93112F89-C28B-492F-8A9D-4BE2062CEE8A}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Photo_ExposureIndexNumerator = (IID("{CDEDCF30-8919-44DF-8F4C-4EB2FFDB8D89}"), 100)
|
||||
PKEY_Photo_ExposureProgram = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 34850)
|
||||
PKEY_Photo_ExposureProgramText = (IID("{FEC690B7-5F30-4646-AE47-4CAAFBA884A3}"), 100)
|
||||
PKEY_Photo_ExposureTime = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 33434)
|
||||
PKEY_Photo_ExposureTimeDenominator = (
|
||||
IID("{55E98597-AD16-42E0-B624-21599A199838}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Photo_ExposureTimeNumerator = (IID("{257E44E2-9031-4323-AC38-85C552871B2E}"), 100)
|
||||
PKEY_Photo_Flash = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 37385)
|
||||
PKEY_Photo_FlashEnergy = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 41483)
|
||||
PKEY_Photo_FlashEnergyDenominator = (IID("{D7B61C70-6323-49CD-A5FC-C84277162C97}"), 100)
|
||||
PKEY_Photo_FlashEnergyNumerator = (IID("{FCAD3D3D-0858-400F-AAA3-2F66CCE2A6BC}"), 100)
|
||||
PKEY_Photo_FlashManufacturer = (IID("{AABAF6C9-E0C5-4719-8585-57B103E584FE}"), 100)
|
||||
PKEY_Photo_FlashModel = (IID("{FE83BB35-4D1A-42E2-916B-06F3E1AF719E}"), 100)
|
||||
PKEY_Photo_FlashText = (IID("{6B8B68F6-200B-47EA-8D25-D8050F57339F}"), 100)
|
||||
PKEY_Photo_FNumber = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 33437)
|
||||
PKEY_Photo_FNumberDenominator = (IID("{E92A2496-223B-4463-A4E3-30EABBA79D80}"), 100)
|
||||
PKEY_Photo_FNumberNumerator = (IID("{1B97738A-FDFC-462F-9D93-1957E08BE90C}"), 100)
|
||||
PKEY_Photo_FocalLength = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 37386)
|
||||
PKEY_Photo_FocalLengthDenominator = (IID("{305BC615-DCA1-44A5-9FD4-10C0BA79412E}"), 100)
|
||||
PKEY_Photo_FocalLengthInFilm = (IID("{A0E74609-B84D-4F49-B860-462BD9971F98}"), 100)
|
||||
PKEY_Photo_FocalLengthNumerator = (IID("{776B6B3B-1E3D-4B0C-9A0E-8FBAF2A8492A}"), 100)
|
||||
PKEY_Photo_FocalPlaneXResolution = (IID("{CFC08D97-C6F7-4484-89DD-EBEF4356FE76}"), 100)
|
||||
PKEY_Photo_FocalPlaneXResolutionDenominator = (
|
||||
IID("{0933F3F5-4786-4F46-A8E8-D64DD37FA521}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Photo_FocalPlaneXResolutionNumerator = (
|
||||
IID("{DCCB10AF-B4E2-4B88-95F9-031B4D5AB490}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Photo_FocalPlaneYResolution = (IID("{4FFFE4D0-914F-4AC4-8D6F-C9C61DE169B1}"), 100)
|
||||
PKEY_Photo_FocalPlaneYResolutionDenominator = (
|
||||
IID("{1D6179A6-A876-4031-B013-3347B2B64DC8}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Photo_FocalPlaneYResolutionNumerator = (
|
||||
IID("{A2E541C5-4440-4BA8-867E-75CFC06828CD}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Photo_GainControl = (IID("{FA304789-00C7-4D80-904A-1E4DCC7265AA}"), 100)
|
||||
PKEY_Photo_GainControlDenominator = (IID("{42864DFD-9DA4-4F77-BDED-4AAD7B256735}"), 100)
|
||||
PKEY_Photo_GainControlNumerator = (IID("{8E8ECF7C-B7B8-4EB8-A63F-0EE715C96F9E}"), 100)
|
||||
PKEY_Photo_GainControlText = (IID("{C06238B2-0BF9-4279-A723-25856715CB9D}"), 100)
|
||||
PKEY_Photo_ISOSpeed = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 34855)
|
||||
PKEY_Photo_LensManufacturer = (IID("{E6DDCAF7-29C5-4F0A-9A68-D19412EC7090}"), 100)
|
||||
PKEY_Photo_LensModel = (IID("{E1277516-2B5F-4869-89B1-2E585BD38B7A}"), 100)
|
||||
PKEY_Photo_LightSource = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 37384)
|
||||
PKEY_Photo_MakerNote = (IID("{FA303353-B659-4052-85E9-BCAC79549B84}"), 100)
|
||||
PKEY_Photo_MakerNoteOffset = (IID("{813F4124-34E6-4D17-AB3E-6B1F3C2247A1}"), 100)
|
||||
PKEY_Photo_MaxAperture = (IID("{08F6D7C2-E3F2-44FC-AF1E-5AA5C81A2D3E}"), 100)
|
||||
PKEY_Photo_MaxApertureDenominator = (IID("{C77724D4-601F-46C5-9B89-C53F93BCEB77}"), 100)
|
||||
PKEY_Photo_MaxApertureNumerator = (IID("{C107E191-A459-44C5-9AE6-B952AD4B906D}"), 100)
|
||||
PKEY_Photo_MeteringMode = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 37383)
|
||||
PKEY_Photo_MeteringModeText = (IID("{F628FD8C-7BA8-465A-A65B-C5AA79263A9E}"), 100)
|
||||
PKEY_Photo_Orientation = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 274)
|
||||
PKEY_Photo_OrientationText = (IID("{A9EA193C-C511-498A-A06B-58E2776DCC28}"), 100)
|
||||
PKEY_Photo_PhotometricInterpretation = (
|
||||
IID("{341796F1-1DF9-4B1C-A564-91BDEFA43877}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Photo_PhotometricInterpretationText = (
|
||||
IID("{821437D6-9EAB-4765-A589-3B1CBBD22A61}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Photo_ProgramMode = (IID("{6D217F6D-3F6A-4825-B470-5F03CA2FBE9B}"), 100)
|
||||
PKEY_Photo_ProgramModeText = (IID("{7FE3AA27-2648-42F3-89B0-454E5CB150C3}"), 100)
|
||||
PKEY_Photo_RelatedSoundFile = (IID("{318A6B45-087F-4DC2-B8CC-05359551FC9E}"), 100)
|
||||
PKEY_Photo_Saturation = (IID("{49237325-A95A-4F67-B211-816B2D45D2E0}"), 100)
|
||||
PKEY_Photo_SaturationText = (IID("{61478C08-B600-4A84-BBE4-E99C45F0A072}"), 100)
|
||||
PKEY_Photo_Sharpness = (IID("{FC6976DB-8349-4970-AE97-B3C5316A08F0}"), 100)
|
||||
PKEY_Photo_SharpnessText = (IID("{51EC3F47-DD50-421D-8769-334F50424B1E}"), 100)
|
||||
PKEY_Photo_ShutterSpeed = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 37377)
|
||||
PKEY_Photo_ShutterSpeedDenominator = (
|
||||
IID("{E13D8975-81C7-4948-AE3F-37CAE11E8FF7}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Photo_ShutterSpeedNumerator = (IID("{16EA4042-D6F4-4BCA-8349-7C78D30FB333}"), 100)
|
||||
PKEY_Photo_SubjectDistance = (IID("{14B81DA1-0135-4D31-96D9-6CBFC9671A99}"), 37382)
|
||||
PKEY_Photo_SubjectDistanceDenominator = (
|
||||
IID("{0C840A88-B043-466D-9766-D4B26DA3FA77}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Photo_SubjectDistanceNumerator = (
|
||||
IID("{8AF4961C-F526-43E5-AA81-DB768219178D}"),
|
||||
100,
|
||||
)
|
||||
PKEY_Photo_TranscodedForSync = (IID("{9A8EBB75-6458-4E82-BACB-35C0095B03BB}"), 100)
|
||||
PKEY_Photo_WhiteBalance = (IID("{EE3D3D8A-5381-4CFA-B13B-AAF66B5F4EC9}"), 100)
|
||||
PKEY_Photo_WhiteBalanceText = (IID("{6336B95E-C7A7-426D-86FD-7AE3D39C84B4}"), 100)
|
||||
PKEY_PropGroup_Advanced = (IID("{900A403B-097B-4B95-8AE2-071FDAEEB118}"), 100)
|
||||
PKEY_PropGroup_Audio = (IID("{2804D469-788F-48AA-8570-71B9C187E138}"), 100)
|
||||
PKEY_PropGroup_Calendar = (IID("{9973D2B5-BFD8-438A-BA94-5349B293181A}"), 100)
|
||||
PKEY_PropGroup_Camera = (IID("{DE00DE32-547E-4981-AD4B-542F2E9007D8}"), 100)
|
||||
PKEY_PropGroup_Contact = (IID("{DF975FD3-250A-4004-858F-34E29A3E37AA}"), 100)
|
||||
PKEY_PropGroup_Content = (IID("{D0DAB0BA-368A-4050-A882-6C010FD19A4F}"), 100)
|
||||
PKEY_PropGroup_Description = (IID("{8969B275-9475-4E00-A887-FF93B8B41E44}"), 100)
|
||||
PKEY_PropGroup_FileSystem = (IID("{E3A7D2C1-80FC-4B40-8F34-30EA111BDC2E}"), 100)
|
||||
PKEY_PropGroup_General = (IID("{CC301630-B192-4C22-B372-9F4C6D338E07}"), 100)
|
||||
PKEY_PropGroup_GPS = (IID("{F3713ADA-90E3-4E11-AAE5-FDC17685B9BE}"), 100)
|
||||
PKEY_PropGroup_Image = (IID("{E3690A87-0FA8-4A2A-9A9F-FCE8827055AC}"), 100)
|
||||
PKEY_PropGroup_Media = (IID("{61872CF7-6B5E-4B4B-AC2D-59DA84459248}"), 100)
|
||||
PKEY_PropGroup_MediaAdvanced = (IID("{8859A284-DE7E-4642-99BA-D431D044B1EC}"), 100)
|
||||
PKEY_PropGroup_Message = (IID("{7FD7259D-16B4-4135-9F97-7C96ECD2FA9E}"), 100)
|
||||
PKEY_PropGroup_Music = (IID("{68DD6094-7216-40F1-A029-43FE7127043F}"), 100)
|
||||
PKEY_PropGroup_Origin = (IID("{2598D2FB-5569-4367-95DF-5CD3A177E1A5}"), 100)
|
||||
PKEY_PropGroup_PhotoAdvanced = (IID("{0CB2BF5A-9EE7-4A86-8222-F01E07FDADAF}"), 100)
|
||||
PKEY_PropGroup_RecordedTV = (IID("{E7B33238-6584-4170-A5C0-AC25EFD9DA56}"), 100)
|
||||
PKEY_PropGroup_Video = (IID("{BEBE0920-7671-4C54-A3EB-49FDDFC191EE}"), 100)
|
||||
PKEY_PropList_ConflictPrompt = (IID("{C9944A21-A406-48FE-8225-AEC7E24C211B}"), 11)
|
||||
PKEY_PropList_ExtendedTileInfo = (IID("{C9944A21-A406-48FE-8225-AEC7E24C211B}"), 9)
|
||||
PKEY_PropList_FileOperationPrompt = (IID("{C9944A21-A406-48FE-8225-AEC7E24C211B}"), 10)
|
||||
PKEY_PropList_FullDetails = (IID("{C9944A21-A406-48FE-8225-AEC7E24C211B}"), 2)
|
||||
PKEY_PropList_InfoTip = (IID("{C9944A21-A406-48FE-8225-AEC7E24C211B}"), 4)
|
||||
PKEY_PropList_NonPersonal = (IID("{49D1091F-082E-493F-B23F-D2308AA9668C}"), 100)
|
||||
PKEY_PropList_PreviewDetails = (IID("{C9944A21-A406-48FE-8225-AEC7E24C211B}"), 8)
|
||||
PKEY_PropList_PreviewTitle = (IID("{C9944A21-A406-48FE-8225-AEC7E24C211B}"), 6)
|
||||
PKEY_PropList_QuickTip = (IID("{C9944A21-A406-48FE-8225-AEC7E24C211B}"), 5)
|
||||
PKEY_PropList_TileInfo = (IID("{C9944A21-A406-48FE-8225-AEC7E24C211B}"), 3)
|
||||
PKEY_PropList_XPDetailsPanel = (IID("{F2275480-F782-4291-BD94-F13693513AEC}"), 0)
|
||||
PKEY_RecordedTV_ChannelNumber = (IID("{6D748DE2-8D38-4CC3-AC60-F009B057C557}"), 7)
|
||||
PKEY_RecordedTV_Credits = (IID("{6D748DE2-8D38-4CC3-AC60-F009B057C557}"), 4)
|
||||
PKEY_RecordedTV_DateContentExpires = (IID("{6D748DE2-8D38-4CC3-AC60-F009B057C557}"), 15)
|
||||
PKEY_RecordedTV_EpisodeName = (IID("{6D748DE2-8D38-4CC3-AC60-F009B057C557}"), 2)
|
||||
PKEY_RecordedTV_IsATSCContent = (IID("{6D748DE2-8D38-4CC3-AC60-F009B057C557}"), 16)
|
||||
PKEY_RecordedTV_IsClosedCaptioningAvailable = (
|
||||
IID("{6D748DE2-8D38-4CC3-AC60-F009B057C557}"),
|
||||
12,
|
||||
)
|
||||
PKEY_RecordedTV_IsDTVContent = (IID("{6D748DE2-8D38-4CC3-AC60-F009B057C557}"), 17)
|
||||
PKEY_RecordedTV_IsHDContent = (IID("{6D748DE2-8D38-4CC3-AC60-F009B057C557}"), 18)
|
||||
PKEY_RecordedTV_IsRepeatBroadcast = (IID("{6D748DE2-8D38-4CC3-AC60-F009B057C557}"), 13)
|
||||
PKEY_RecordedTV_IsSAP = (IID("{6D748DE2-8D38-4CC3-AC60-F009B057C557}"), 14)
|
||||
PKEY_RecordedTV_NetworkAffiliation = (
|
||||
IID("{2C53C813-FB63-4E22-A1AB-0B331CA1E273}"),
|
||||
100,
|
||||
)
|
||||
PKEY_RecordedTV_OriginalBroadcastDate = (
|
||||
IID("{4684FE97-8765-4842-9C13-F006447B178C}"),
|
||||
100,
|
||||
)
|
||||
PKEY_RecordedTV_ProgramDescription = (IID("{6D748DE2-8D38-4CC3-AC60-F009B057C557}"), 3)
|
||||
PKEY_RecordedTV_RecordingTime = (IID("{A5477F61-7A82-4ECA-9DDE-98B69B2479B3}"), 100)
|
||||
PKEY_RecordedTV_StationCallSign = (IID("{6D748DE2-8D38-4CC3-AC60-F009B057C557}"), 5)
|
||||
PKEY_RecordedTV_StationName = (IID("{1B5439E7-EBA1-4AF8-BDD7-7AF1D4549493}"), 100)
|
||||
PKEY_Search_AutoSummary = (IID("{560C36C0-503A-11CF-BAA1-00004C752A9A}"), 2)
|
||||
PKEY_Search_ContainerHash = (IID("{BCEEE283-35DF-4D53-826A-F36A3EEFC6BE}"), 100)
|
||||
PKEY_Search_Contents = (IID("{B725F130-47EF-101A-A5F1-02608C9EEBAC}"), 19)
|
||||
PKEY_Search_EntryID = (IID("{49691C90-7E17-101A-A91C-08002B2ECDA9}"), 5)
|
||||
PKEY_Search_GatherTime = (IID("{0B63E350-9CCC-11D0-BCDB-00805FCCCE04}"), 8)
|
||||
PKEY_Search_IsClosedDirectory = (IID("{0B63E343-9CCC-11D0-BCDB-00805FCCCE04}"), 23)
|
||||
PKEY_Search_IsFullyContained = (IID("{0B63E343-9CCC-11D0-BCDB-00805FCCCE04}"), 24)
|
||||
PKEY_Search_QueryFocusedSummary = (IID("{560C36C0-503A-11CF-BAA1-00004C752A9A}"), 3)
|
||||
PKEY_Search_Rank = (IID("{49691C90-7E17-101A-A91C-08002B2ECDA9}"), 3)
|
||||
PKEY_Search_Store = (IID("{A06992B3-8CAF-4ED7-A547-B259E32AC9FC}"), 100)
|
||||
PKEY_Search_UrlToIndex = (IID("{0B63E343-9CCC-11D0-BCDB-00805FCCCE04}"), 2)
|
||||
PKEY_Search_UrlToIndexWithModificationTime = (
|
||||
IID("{0B63E343-9CCC-11D0-BCDB-00805FCCCE04}"),
|
||||
12,
|
||||
)
|
||||
PKEY_DescriptionID = (IID("{28636AA6-953D-11D2-B5D6-00C04FD918D0}"), 2)
|
||||
PKEY_Link_TargetSFGAOFlagsStrings = (IID("{D6942081-D53B-443D-AD47-5E059D9CD27A}"), 3)
|
||||
PKEY_Link_TargetUrl = (IID("{5CBF2787-48CF-4208-B90E-EE5E5D420294}"), 2)
|
||||
PKEY_Shell_SFGAOFlagsStrings = (IID("{D6942081-D53B-443D-AD47-5E059D9CD27A}"), 2)
|
||||
PKEY_Software_DateLastUsed = (IID("{841E4F90-FF59-4D16-8947-E81BBFFAB36D}"), 16)
|
||||
PKEY_Software_ProductName = (IID("{0CEF7D53-FA64-11D1-A203-0000F81FEDEE}"), 7)
|
||||
PKEY_Sync_Comments = (IID("{7BD5533E-AF15-44DB-B8C8-BD6624E1D032}"), 13)
|
||||
PKEY_Sync_ConflictDescription = (IID("{CE50C159-2FB8-41FD-BE68-D3E042E274BC}"), 4)
|
||||
PKEY_Sync_ConflictFirstLocation = (IID("{CE50C159-2FB8-41FD-BE68-D3E042E274BC}"), 6)
|
||||
PKEY_Sync_ConflictSecondLocation = (IID("{CE50C159-2FB8-41FD-BE68-D3E042E274BC}"), 7)
|
||||
PKEY_Sync_HandlerCollectionID = (IID("{7BD5533E-AF15-44DB-B8C8-BD6624E1D032}"), 2)
|
||||
PKEY_Sync_HandlerID = (IID("{7BD5533E-AF15-44DB-B8C8-BD6624E1D032}"), 3)
|
||||
PKEY_Sync_HandlerName = (IID("{CE50C159-2FB8-41FD-BE68-D3E042E274BC}"), 2)
|
||||
PKEY_Sync_HandlerType = (IID("{7BD5533E-AF15-44DB-B8C8-BD6624E1D032}"), 8)
|
||||
PKEY_Sync_HandlerTypeLabel = (IID("{7BD5533E-AF15-44DB-B8C8-BD6624E1D032}"), 9)
|
||||
PKEY_Sync_ItemID = (IID("{7BD5533E-AF15-44DB-B8C8-BD6624E1D032}"), 6)
|
||||
PKEY_Sync_ItemName = (IID("{CE50C159-2FB8-41FD-BE68-D3E042E274BC}"), 3)
|
||||
PKEY_Task_BillingInformation = (IID("{D37D52C6-261C-4303-82B3-08B926AC6F12}"), 100)
|
||||
PKEY_Task_CompletionStatus = (IID("{084D8A0A-E6D5-40DE-BF1F-C8820E7C877C}"), 100)
|
||||
PKEY_Task_Owner = (IID("{08C7CC5F-60F2-4494-AD75-55E3E0B5ADD0}"), 100)
|
||||
PKEY_Video_Compression = (IID("{64440491-4C8B-11D1-8B70-080036B11A03}"), 10)
|
||||
PKEY_Video_Director = (IID("{64440492-4C8B-11D1-8B70-080036B11A03}"), 20)
|
||||
PKEY_Video_EncodingBitrate = (IID("{64440491-4C8B-11D1-8B70-080036B11A03}"), 8)
|
||||
PKEY_Video_FourCC = (IID("{64440491-4C8B-11D1-8B70-080036B11A03}"), 44)
|
||||
PKEY_Video_FrameHeight = (IID("{64440491-4C8B-11D1-8B70-080036B11A03}"), 4)
|
||||
PKEY_Video_FrameRate = (IID("{64440491-4C8B-11D1-8B70-080036B11A03}"), 6)
|
||||
PKEY_Video_FrameWidth = (IID("{64440491-4C8B-11D1-8B70-080036B11A03}"), 3)
|
||||
PKEY_Video_HorizontalAspectRatio = (IID("{64440491-4C8B-11D1-8B70-080036B11A03}"), 42)
|
||||
PKEY_Video_SampleSize = (IID("{64440491-4C8B-11D1-8B70-080036B11A03}"), 9)
|
||||
PKEY_Video_StreamName = (IID("{64440491-4C8B-11D1-8B70-080036B11A03}"), 2)
|
||||
PKEY_Video_StreamNumber = (IID("{64440491-4C8B-11D1-8B70-080036B11A03}"), 11)
|
||||
PKEY_Video_TotalBitrate = (IID("{64440491-4C8B-11D1-8B70-080036B11A03}"), 43)
|
||||
PKEY_Video_VerticalAspectRatio = (IID("{64440491-4C8B-11D1-8B70-080036B11A03}"), 45)
|
||||
PKEY_Volume_FileSystem = (IID("{9B174B35-40FF-11D2-A27E-00C04FC30871}"), 4)
|
||||
PKEY_Volume_IsMappedDrive = (IID("{149C0B69-2C2D-48FC-808F-D318D78C4636}"), 2)
|
||||
PKEY_Volume_IsRoot = (IID("{9B174B35-40FF-11D2-A27E-00C04FC30871}"), 10)
|
||||
|
||||
PKEY_AppUserModel_RelaunchCommand = (IID("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}"), 2)
|
||||
PKEY_AppUserModel_RelaunchIconResource = (
|
||||
IID("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}"),
|
||||
3,
|
||||
)
|
||||
PKEY_AppUserModel_RelaunchDisplayNameResource = (
|
||||
IID("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}"),
|
||||
4,
|
||||
)
|
||||
PKEY_AppUserModel_ID = (IID("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}"), 5)
|
||||
PKEY_AppUserModel_IsDestListSeparator = (
|
||||
IID("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}"),
|
||||
6,
|
||||
)
|
||||
PKEY_AppUserModel_ExcludeFromShowInNewInstall = (
|
||||
IID("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}"),
|
||||
8,
|
||||
)
|
||||
PKEY_AppUserModel_PreventPinning = (IID("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}"), 9)
|
||||
|
||||
# PKA_FLAGS, used with IPropertyChange
|
||||
PKA_SET = 0
|
||||
PKA_APPEND = 1
|
||||
PKA_DELETE = 2
|
||||
@@ -0,0 +1,5 @@
|
||||
from win32com.propsys import propsys, pscon # nopycln: import
|
||||
|
||||
print("propsys was imported (sorry - that is the extent of the tests,")
|
||||
print("but see the shell folder_view demo, which uses this module)")
|
||||
# that's all folks!
|
||||
@@ -0,0 +1,4 @@
|
||||
# See if we have a special directory for the binaries (for developers)
|
||||
import win32com
|
||||
|
||||
win32com.__PackageSupportBuildPath__(__path__)
|
||||
@@ -0,0 +1,83 @@
|
||||
import time
|
||||
|
||||
import pythoncom
|
||||
from win32com.shell import shell, shellcon
|
||||
|
||||
website = "https://github.com/mhammond/pywin32/"
|
||||
iad = pythoncom.CoCreateInstance(
|
||||
shell.CLSID_ActiveDesktop,
|
||||
None,
|
||||
pythoncom.CLSCTX_INPROC_SERVER,
|
||||
shell.IID_IActiveDesktop,
|
||||
)
|
||||
opts = iad.GetDesktopItemOptions()
|
||||
if not (opts["ActiveDesktop"] and opts["EnableComponents"]):
|
||||
print("Warning: Enabling Active Desktop")
|
||||
opts["ActiveDesktop"] = True
|
||||
opts["EnableComponents"] = True
|
||||
iad.SetDesktopItemOptions(opts)
|
||||
iad.ApplyChanges(0xFFFF)
|
||||
iad = None
|
||||
## apparently takes a short while for it to become active
|
||||
time.sleep(2)
|
||||
iad = pythoncom.CoCreateInstance(
|
||||
shell.CLSID_ActiveDesktop,
|
||||
None,
|
||||
pythoncom.CLSCTX_INPROC_SERVER,
|
||||
shell.IID_IActiveDesktop,
|
||||
)
|
||||
|
||||
cnt = iad.GetDesktopItemCount()
|
||||
print("Count:", cnt)
|
||||
for i in range(cnt):
|
||||
print(iad.GetDesktopItem(i))
|
||||
|
||||
component = {
|
||||
"ID": cnt + 1,
|
||||
"ComponentType": shellcon.COMP_TYPE_WEBSITE,
|
||||
"CurItemState": shellcon.IS_NORMAL,
|
||||
"SubscribedURL": website,
|
||||
"Source": website,
|
||||
"FriendlyName": "Pywin32 on SF",
|
||||
"Checked": True, ## this controls whether item is currently displayed
|
||||
"NoScroll": False,
|
||||
"Dirty": False,
|
||||
"Pos": {
|
||||
"Top": 69,
|
||||
"Left": 69,
|
||||
"Height": 400,
|
||||
"Width": 400,
|
||||
"zIndex": 1002,
|
||||
"CanResize": True,
|
||||
"CanResizeX": True,
|
||||
"CanResizeY": True,
|
||||
"PreferredLeftPercent": 0,
|
||||
"PreferredTopPercent": 0,
|
||||
},
|
||||
"Original": {
|
||||
"Top": 33,
|
||||
"Left": 304,
|
||||
"Height": 362,
|
||||
"Width": 372,
|
||||
"ItemState": shellcon.IS_NORMAL,
|
||||
},
|
||||
"Restored": {
|
||||
"Top": 33,
|
||||
"Left": 304,
|
||||
"Height": 362,
|
||||
"Width": 372,
|
||||
"ItemState": shellcon.IS_NORMAL,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
try:
|
||||
existing_item = iad.GetDesktopItemBySource(website)
|
||||
except pythoncom.com_error:
|
||||
pass
|
||||
else:
|
||||
iad.RemoveDesktopItem(existing_item)
|
||||
iad.ApplyChanges(0xFFFF)
|
||||
|
||||
iad.AddDesktopItem(component)
|
||||
iad.ApplyChanges(0xFFFF) ## need to check which AD_APPLY constants are actually needed
|
||||
@@ -0,0 +1,179 @@
|
||||
# Sample implementation of IFileOperationProgressSink that just prints
|
||||
# some basic info
|
||||
|
||||
import pythoncom
|
||||
from win32com.server.policy import DesignatedWrapPolicy
|
||||
from win32com.shell import shell, shellcon
|
||||
|
||||
tsf_flags = [(k, v) for k, v in shellcon.__dict__.items() if k.startswith("TSF_")]
|
||||
|
||||
|
||||
def decode_flags(flags):
|
||||
if flags == 0:
|
||||
return "TSF_NORMAL"
|
||||
flag_txt = ""
|
||||
for k, v in tsf_flags:
|
||||
if flags & v:
|
||||
if flag_txt:
|
||||
flag_txt += "|" + k
|
||||
else:
|
||||
flag_txt = k
|
||||
return flag_txt
|
||||
|
||||
|
||||
class FileOperationProgressSink(DesignatedWrapPolicy):
|
||||
_com_interfaces_ = [shell.IID_IFileOperationProgressSink]
|
||||
_public_methods_ = [
|
||||
"StartOperations",
|
||||
"FinishOperations",
|
||||
"PreRenameItem",
|
||||
"PostRenameItem",
|
||||
"PreMoveItem",
|
||||
"PostMoveItem",
|
||||
"PreCopyItem",
|
||||
"PostCopyItem",
|
||||
"PreDeleteItem",
|
||||
"PostDeleteItem",
|
||||
"PreNewItem",
|
||||
"PostNewItem",
|
||||
"UpdateProgress",
|
||||
"ResetTimer",
|
||||
"PauseTimer",
|
||||
"ResumeTimer",
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
self._wrap_(self)
|
||||
|
||||
def StartOperations(self):
|
||||
print("StartOperations")
|
||||
|
||||
def FinishOperations(self, Result):
|
||||
print("FinishOperations: HRESULT ", Result)
|
||||
|
||||
def PreRenameItem(self, Flags, Item, NewName):
|
||||
print(
|
||||
"PreRenameItem: Renaming "
|
||||
+ Item.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
+ " to "
|
||||
+ NewName
|
||||
)
|
||||
|
||||
def PostRenameItem(self, Flags, Item, NewName, hrRename, NewlyCreated):
|
||||
if NewlyCreated is not None:
|
||||
newfile = NewlyCreated.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
else:
|
||||
newfile = "not renamed, HRESULT " + str(hrRename)
|
||||
print(
|
||||
"PostRenameItem: renamed "
|
||||
+ Item.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
+ " to "
|
||||
+ newfile
|
||||
)
|
||||
|
||||
def PreMoveItem(self, Flags, Item, DestinationFolder, NewName):
|
||||
print(
|
||||
"PreMoveItem: Moving "
|
||||
+ Item.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
+ " to "
|
||||
+ DestinationFolder.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
+ "\\"
|
||||
+ str(NewName)
|
||||
)
|
||||
|
||||
def PostMoveItem(
|
||||
self, Flags, Item, DestinationFolder, NewName, hrMove, NewlyCreated
|
||||
):
|
||||
if NewlyCreated is not None:
|
||||
newfile = NewlyCreated.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
else:
|
||||
newfile = "not copied, HRESULT " + str(hrMove)
|
||||
print(
|
||||
"PostMoveItem: Moved "
|
||||
+ Item.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
+ " to "
|
||||
+ newfile
|
||||
)
|
||||
|
||||
def PreCopyItem(self, Flags, Item, DestinationFolder, NewName):
|
||||
if not NewName:
|
||||
NewName = ""
|
||||
print(
|
||||
"PreCopyItem: Copying "
|
||||
+ Item.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
+ " to "
|
||||
+ DestinationFolder.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
+ "\\"
|
||||
+ NewName
|
||||
)
|
||||
print("Flags: ", decode_flags(Flags))
|
||||
|
||||
def PostCopyItem(
|
||||
self, Flags, Item, DestinationFolder, NewName, hrCopy, NewlyCreated
|
||||
):
|
||||
if NewlyCreated is not None:
|
||||
newfile = NewlyCreated.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
else:
|
||||
newfile = "not copied, HRESULT " + str(hrCopy)
|
||||
print(
|
||||
"PostCopyItem: Copied "
|
||||
+ Item.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
+ " to "
|
||||
+ newfile
|
||||
)
|
||||
print("Flags: ", decode_flags(Flags))
|
||||
|
||||
def PreDeleteItem(self, Flags, Item):
|
||||
print(
|
||||
"PreDeleteItem: Deleting " + Item.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
)
|
||||
|
||||
def PostDeleteItem(self, Flags, Item, hrDelete, NewlyCreated):
|
||||
print(
|
||||
"PostDeleteItem: Deleted " + Item.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
)
|
||||
if NewlyCreated:
|
||||
print(
|
||||
" Moved to recycle bin - "
|
||||
+ NewlyCreated.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
)
|
||||
|
||||
def PreNewItem(self, Flags, DestinationFolder, NewName):
|
||||
print(
|
||||
"PreNewItem: Creating "
|
||||
+ DestinationFolder.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
+ "\\"
|
||||
+ NewName
|
||||
)
|
||||
|
||||
def PostNewItem(
|
||||
self,
|
||||
Flags,
|
||||
DestinationFolder,
|
||||
NewName,
|
||||
TemplateName,
|
||||
FileAttributes,
|
||||
hrNew,
|
||||
NewItem,
|
||||
):
|
||||
print(
|
||||
"PostNewItem: Created " + NewItem.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
)
|
||||
|
||||
def UpdateProgress(self, WorkTotal, WorkSoFar):
|
||||
print("UpdateProgress: ", WorkSoFar, WorkTotal)
|
||||
|
||||
def ResetTimer(self):
|
||||
print("ResetTimer")
|
||||
|
||||
def PauseTimer(self):
|
||||
print("PauseTimer")
|
||||
|
||||
def ResumeTimer(self):
|
||||
print("ResumeTimer")
|
||||
|
||||
|
||||
def CreateSink():
|
||||
return pythoncom.WrapObject(
|
||||
FileOperationProgressSink(), shell.IID_IFileOperationProgressSink
|
||||
)
|
||||
@@ -0,0 +1,67 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pythoncom
|
||||
import win32api
|
||||
from win32com.shell import shell, shellcon
|
||||
|
||||
temp_dir = win32api.GetTempPath()
|
||||
linkname = win32api.GetTempFileName(temp_dir, "cmd")[0]
|
||||
os.remove(linkname)
|
||||
linkname += ".lnk"
|
||||
print("Link name:", linkname)
|
||||
ish = pythoncom.CoCreateInstance(
|
||||
shell.CLSID_ShellLink, None, pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IShellLink
|
||||
)
|
||||
ish.SetPath(os.environ["cOMSPEC"])
|
||||
ish.SetWorkingDirectory(os.path.split(sys.executable)[0])
|
||||
ish.SetDescription("shortcut made by python")
|
||||
|
||||
console_props = {
|
||||
"Signature": shellcon.NT_CONSOLE_PROPS_SIG,
|
||||
"InsertMode": True,
|
||||
"FullScreen": False, ## True looks like "DOS Mode" from win98!
|
||||
"FontFamily": 54,
|
||||
"CursorSize": 75, ## pct of character size
|
||||
"ScreenBufferSize": (152, 256),
|
||||
"AutoPosition": False,
|
||||
"FontSize": (4, 5),
|
||||
"FaceName": "",
|
||||
"HistoryBufferSize": 32,
|
||||
"InputBufferSize": 0,
|
||||
"QuickEdit": True,
|
||||
"Font": 0, ## 0 should always be present, use win32console.GetNumberOfConsoleFonts() to find how many available
|
||||
"FillAttribute": 7,
|
||||
"PopupFillAttribute": 245,
|
||||
"WindowSize": (128, 32),
|
||||
"WindowOrigin": (0, 0),
|
||||
"FontWeight": 400,
|
||||
"HistoryNoDup": False,
|
||||
"NumberOfHistoryBuffers": 32,
|
||||
## ColorTable copied from a 'normal' console shortcut, with some obvious changes
|
||||
## These do not appear to be documented. From experimentation, [0] is background, [7] is foreground text
|
||||
"ColorTable": (
|
||||
255,
|
||||
8388608,
|
||||
32768,
|
||||
8421376,
|
||||
128,
|
||||
8388736,
|
||||
32896,
|
||||
12582912,
|
||||
8421504,
|
||||
16711680,
|
||||
65280,
|
||||
16776960,
|
||||
255,
|
||||
16711935,
|
||||
65535,
|
||||
16777215,
|
||||
),
|
||||
}
|
||||
|
||||
ishdl = ish.QueryInterface(shell.IID_IShellLinkDataList)
|
||||
ishdl.AddDataBlock(console_props)
|
||||
ipf = ish.QueryInterface(pythoncom.IID_IPersistFile)
|
||||
ipf.Save(linkname, 1)
|
||||
os.startfile(linkname)
|
||||
@@ -0,0 +1,93 @@
|
||||
# ITransferAdviseSink implementation template
|
||||
|
||||
import pythoncom
|
||||
from win32com.server.policy import DesignatedWrapPolicy
|
||||
from win32com.shell import shell, shellcon
|
||||
|
||||
tsf_flags = []
|
||||
TRANSFER_ADVISE_STATES = {}
|
||||
|
||||
for k, v in shellcon.__dict__.items():
|
||||
if k.startswith("TS_"):
|
||||
TRANSFER_ADVISE_STATES[v] = k
|
||||
elif k.startswith("TSF_"):
|
||||
tsf_flags.append((k, v))
|
||||
|
||||
|
||||
def decode_flags(flags):
|
||||
if flags == 0:
|
||||
return "TSF_NORMAL"
|
||||
flag_txt = ""
|
||||
for k, v in tsf_flags:
|
||||
if flags & v:
|
||||
if flag_txt:
|
||||
flag_txt += "|" + k
|
||||
else:
|
||||
flag_txt = k
|
||||
return flag_txt
|
||||
|
||||
|
||||
class TransferAdviseSink(DesignatedWrapPolicy):
|
||||
_com_interfaces_ = [shell.IID_ITransferAdviseSink]
|
||||
_public_methods_ = [
|
||||
"UpdateProgress",
|
||||
"UpdateTransferState",
|
||||
"ConfirmOverwrite",
|
||||
"ConfirmEncryptionLoss",
|
||||
"FileFailure",
|
||||
"SubStreamFailure",
|
||||
"PropertyFailure",
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
self._wrap_(self)
|
||||
|
||||
def UpdateProgress(
|
||||
self,
|
||||
SizeCurrent,
|
||||
SizeTotal,
|
||||
FilesCurrent,
|
||||
FilesTotal,
|
||||
FoldersCurrent,
|
||||
FoldersTotal,
|
||||
):
|
||||
print("UpdateProgress - processed so far:")
|
||||
print(f"\t {SizeCurrent} out of {SizeTotal} bytes")
|
||||
print(f"\t {FilesCurrent} out of {FilesTotal} files")
|
||||
print(f"\t {FoldersCurrent} out of {FoldersTotal} folders")
|
||||
|
||||
def UpdateTransferState(self, State):
|
||||
print(
|
||||
"Current state: ",
|
||||
TRANSFER_ADVISE_STATES.get(State, "??? Unknown state %s ???" % State),
|
||||
)
|
||||
|
||||
def ConfirmOverwrite(self, Source, DestParent, Name):
|
||||
print(
|
||||
"ConfirmOverwrite: ",
|
||||
Source.GetDisplayName(shellcon.SHGDN_FORPARSING),
|
||||
DestParent.GetDisplayName(shellcon.SHGDN_FORPARSING),
|
||||
Name,
|
||||
)
|
||||
|
||||
def ConfirmEncryptionLoss(self, Source):
|
||||
print(
|
||||
"ConfirmEncryptionLoss:", Source.GetDisplayName(shellcon.SHGDN_FORPARSING)
|
||||
)
|
||||
|
||||
def FileFailure(self, Item, ItemName, Error):
|
||||
print("FileFailure:", Item.GetDisplayName(shellcon.SHGDN_FORPARSING), ItemName)
|
||||
|
||||
def SubStreamFailure(self, Item, StreamName, Error):
|
||||
print("SubStreamFailure:\n")
|
||||
|
||||
def PropertyFailure(self, Item, key, Error):
|
||||
print("PropertyFailure:\n")
|
||||
|
||||
|
||||
def CreateSink():
|
||||
return pythoncom.WrapObject(
|
||||
TransferAdviseSink(),
|
||||
shell.IID_ITransferAdviseSink,
|
||||
shell.IID_ITransferAdviseSink,
|
||||
)
|
||||
@@ -0,0 +1,56 @@
|
||||
import os
|
||||
|
||||
import pythoncom
|
||||
import win32api
|
||||
from win32com.shell import shell, shellcon
|
||||
|
||||
|
||||
class InternetShortcut:
|
||||
def __init__(self):
|
||||
self._base = pythoncom.CoCreateInstance(
|
||||
shell.CLSID_InternetShortcut,
|
||||
None,
|
||||
pythoncom.CLSCTX_INPROC_SERVER,
|
||||
shell.IID_IUniformResourceLocator,
|
||||
)
|
||||
|
||||
def load(self, filename):
|
||||
# Get an IPersist interface
|
||||
# which allows save/restore of object to/from files
|
||||
self._base.QueryInterface(pythoncom.IID_IPersistFile).Load(filename)
|
||||
|
||||
def save(self, filename):
|
||||
self._base.QueryInterface(pythoncom.IID_IPersistFile).Save(filename, 1)
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name != "_base":
|
||||
return getattr(self._base, name)
|
||||
|
||||
|
||||
temp_dir = win32api.GetTempPath()
|
||||
linkname = win32api.GetTempFileName(temp_dir, "ish")[0]
|
||||
print("Link:", linkname)
|
||||
os.remove(linkname)
|
||||
linkname += ".url"
|
||||
|
||||
ish = InternetShortcut()
|
||||
ish.SetURL("https://github.com/mhammond/pywin32")
|
||||
ish.save(linkname)
|
||||
|
||||
## IUniformResourceLocator also give access to IPropertySetStorage
|
||||
pss = ish.QueryInterface(pythoncom.IID_IPropertySetStorage)
|
||||
ps = pss.Open(shell.FMTID_InternetSite)
|
||||
property_ids = [
|
||||
(k, v) for k, v in shellcon.__dict__.items() if k.startswith("PID_INTSITE_")
|
||||
]
|
||||
for pname, pval in property_ids:
|
||||
print(pname, ps.ReadMultiple((pval,))[0])
|
||||
|
||||
ps = pss.Open(shell.FMTID_Intshcut)
|
||||
property_ids = [(k, v) for k, v in shellcon.__dict__.items() if k.startswith("PID_IS_")]
|
||||
for pname, pval in property_ids:
|
||||
print(pname, ps.ReadMultiple((pval,))[0])
|
||||
|
||||
new_sh = InternetShortcut()
|
||||
new_sh.load(linkname)
|
||||
new_sh.InvokeCommand("Open")
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user