mirror of
https://github.com/aykhans/AzSuicideDataVisualization.git
synced 2025-07-02 14:27:31 +00:00
first commit
This commit is contained in:
121
.venv/Lib/site-packages/win32comext/adsi/__init__.py
Normal file
121
.venv/Lib/site-packages/win32comext/adsi/__init__.py
Normal file
@ -0,0 +1,121 @@
|
||||
import win32com
|
||||
import win32com.client
|
||||
|
||||
if type(__path__) == type(""):
|
||||
# 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 *
|
||||
|
||||
LCID = 0
|
||||
|
||||
IDispatchType = pythoncom.TypeIIDs[pythoncom.IID_IDispatch]
|
||||
IADsContainerType = pythoncom.TypeIIDs[adsi.IID_IADsContainer]
|
||||
|
||||
|
||||
def _get_good_ret(
|
||||
ob,
|
||||
# Named arguments used internally
|
||||
resultCLSID=None,
|
||||
):
|
||||
assert resultCLSID is None, "Now have type info for ADSI objects - fix me!"
|
||||
# See if the object supports IDispatch
|
||||
if hasattr(ob, "Invoke"):
|
||||
import win32com.client.dynamic
|
||||
|
||||
name = "Dispatch wrapper around %r" % ob
|
||||
return win32com.client.dynamic.Dispatch(ob, name, ADSIDispatch)
|
||||
return ob
|
||||
|
||||
|
||||
class ADSIEnumerator:
|
||||
def __init__(self, ob):
|
||||
# Query the object for the container interface.
|
||||
self._cont_ = ob.QueryInterface(IID_IADsContainer)
|
||||
self._oleobj_ = ADsBuildEnumerator(self._cont_) # a PyIADsEnumVARIANT
|
||||
self.index = -1
|
||||
|
||||
def __getitem__(self, index):
|
||||
return self.__GetIndex(index)
|
||||
|
||||
def __call__(self, index):
|
||||
return self.__GetIndex(index)
|
||||
|
||||
def __GetIndex(self, index):
|
||||
if type(index) != type(0):
|
||||
raise TypeError("Only integer indexes are supported for enumerators")
|
||||
if index != self.index + 1:
|
||||
# Index requested out of sequence.
|
||||
raise ValueError("You must index this object sequentially")
|
||||
self.index = index
|
||||
result = ADsEnumerateNext(self._oleobj_, 1)
|
||||
if len(result):
|
||||
return _get_good_ret(result[0])
|
||||
# Failed - reset for next time around.
|
||||
self.index = -1
|
||||
self._oleobj_ = ADsBuildEnumerator(self._cont_) # a PyIADsEnumVARIANT
|
||||
raise IndexError("list index out of range")
|
||||
|
||||
|
||||
class ADSIDispatch(win32com.client.CDispatch):
|
||||
def _wrap_dispatch_(
|
||||
self, ob, userName=None, returnCLSID=None, UnicodeToString=None
|
||||
):
|
||||
assert UnicodeToString is None, "this is deprectated and will be removed"
|
||||
if not userName:
|
||||
userName = "ADSI-object"
|
||||
olerepr = win32com.client.dynamic.MakeOleRepr(ob, None, None)
|
||||
return ADSIDispatch(ob, olerepr, userName)
|
||||
|
||||
def _NewEnum(self):
|
||||
try:
|
||||
return ADSIEnumerator(self)
|
||||
except pythoncom.com_error:
|
||||
# doesnt support it - let our base try!
|
||||
return win32com.client.CDispatch._NewEnum(self)
|
||||
|
||||
def __getattr__(self, attr):
|
||||
try:
|
||||
return getattr(self._oleobj_, attr)
|
||||
except AttributeError:
|
||||
return win32com.client.CDispatch.__getattr__(self, attr)
|
||||
|
||||
def QueryInterface(self, iid):
|
||||
ret = self._oleobj_.QueryInterface(iid)
|
||||
return _get_good_ret(ret)
|
||||
|
||||
|
||||
# We override the global methods to do the right thing.
|
||||
_ADsGetObject = ADsGetObject # The one in the .pyd
|
||||
|
||||
|
||||
def ADsGetObject(path, iid=pythoncom.IID_IDispatch):
|
||||
ret = _ADsGetObject(path, iid)
|
||||
return _get_good_ret(ret)
|
||||
|
||||
|
||||
_ADsOpenObject = ADsOpenObject
|
||||
|
||||
|
||||
def ADsOpenObject(path, username, password, reserved=0, iid=pythoncom.IID_IDispatch):
|
||||
ret = _ADsOpenObject(path, username, password, reserved, iid)
|
||||
return _get_good_ret(ret)
|
BIN
.venv/Lib/site-packages/win32comext/adsi/adsi.pyd
Normal file
BIN
.venv/Lib/site-packages/win32comext/adsi/adsi.pyd
Normal file
Binary file not shown.
340
.venv/Lib/site-packages/win32comext/adsi/adsicon.py
Normal file
340
.venv/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 win32clipboard
|
||||
import pythoncom
|
||||
from win32com.adsi import adsi
|
||||
from win32com.adsi.adsicon import *
|
||||
|
||||
cf_objectpicker = win32clipboard.RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST)
|
||||
|
||||
|
||||
def main():
|
||||
hwnd = 0
|
||||
|
||||
# Create an instance of the object picker.
|
||||
picker = pythoncom.CoCreateInstance(
|
||||
adsi.CLSID_DsObjectPicker,
|
||||
None,
|
||||
pythoncom.CLSCTX_INPROC_SERVER,
|
||||
adsi.IID_IDsObjectPicker,
|
||||
)
|
||||
|
||||
# Create our scope init info.
|
||||
siis = adsi.DSOP_SCOPE_INIT_INFOs(1)
|
||||
sii = siis[0]
|
||||
|
||||
# Combine multiple scope types in a single array entry.
|
||||
|
||||
sii.type = (
|
||||
DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN
|
||||
)
|
||||
|
||||
# Set uplevel and downlevel filters to include only computer objects.
|
||||
# Uplevel filters apply to both mixed and native modes.
|
||||
# Notice that the uplevel and downlevel flags are different.
|
||||
|
||||
sii.filterFlags.uplevel.bothModes = DSOP_FILTER_COMPUTERS
|
||||
sii.filterFlags.downlevel = DSOP_DOWNLEVEL_FILTER_COMPUTERS
|
||||
|
||||
# Initialize the interface.
|
||||
picker.Initialize(
|
||||
None, # Target is the local computer.
|
||||
siis, # scope infos
|
||||
DSOP_FLAG_MULTISELECT, # options
|
||||
("objectGUID", "displayName"),
|
||||
) # attributes to fetch
|
||||
|
||||
do = picker.InvokeDialog(hwnd)
|
||||
# Extract the data from the IDataObject.
|
||||
format_etc = (
|
||||
cf_objectpicker,
|
||||
None,
|
||||
pythoncom.DVASPECT_CONTENT,
|
||||
-1,
|
||||
pythoncom.TYMED_HGLOBAL,
|
||||
)
|
||||
medium = do.GetData(format_etc)
|
||||
data = adsi.StringAsDS_SELECTION_LIST(medium.data)
|
||||
for item in data:
|
||||
name, klass, adspath, upn, attrs, flags = item
|
||||
print("Item", name)
|
||||
print(" Class:", klass)
|
||||
print(" AdsPath:", adspath)
|
||||
print(" UPN:", upn)
|
||||
print(" Attrs:", attrs)
|
||||
print(" Flags:", flags)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
561
.venv/Lib/site-packages/win32comext/adsi/demos/scp.py
Normal file
561
.venv/Lib/site-packages/win32comext/adsi/demos/scp.py
Normal file
@ -0,0 +1,561 @@
|
||||
"""A re-implementation of the MS DirectoryService samples related to services.
|
||||
|
||||
* Adds and removes an ActiveDirectory "Service Connection Point",
|
||||
including managing the security on the object.
|
||||
* Creates and registers Service Principal Names.
|
||||
* Changes the username for a domain user.
|
||||
|
||||
Some of these functions are likely to become move to a module - but there
|
||||
is also a little command-line-interface to try these functions out.
|
||||
|
||||
For example:
|
||||
|
||||
scp.py --account-name=domain\\user --service-class=PythonScpTest \\
|
||||
--keyword=foo --keyword=bar --binding-string=bind_info \\
|
||||
ScpCreate SpnCreate SpnRegister
|
||||
|
||||
would:
|
||||
* Attempt to delete a Service Connection Point for the service class
|
||||
'PythonScpTest'
|
||||
* Attempt to create a Service Connection Point for that class, with 2
|
||||
keywords and a binding string of 'bind_info'
|
||||
* Create a Service Principal Name for the service and register it
|
||||
|
||||
to undo those changes, you could execute:
|
||||
|
||||
scp.py --account-name=domain\\user --service-class=PythonScpTest \\
|
||||
SpnCreate SpnUnregister ScpDelete
|
||||
|
||||
which will:
|
||||
* Create a SPN
|
||||
* Unregister that SPN from the Active Directory.
|
||||
* Delete the Service Connection Point
|
||||
|
||||
Executing with --test will create and remove one of everything.
|
||||
"""
|
||||
|
||||
from win32com.adsi.adsicon import *
|
||||
from win32com.adsi import adsi
|
||||
import win32api, win32con, winerror
|
||||
from win32com.client import Dispatch
|
||||
import ntsecuritycon as dscon
|
||||
import win32security
|
||||
import optparse, textwrap
|
||||
import traceback
|
||||
|
||||
verbose = 1
|
||||
g_createdSCP = None
|
||||
g_createdSPNs = []
|
||||
g_createdSPNLast = None
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging # use logging module global methods for now.
|
||||
|
||||
# still a bit confused about log(n, ...) vs logger.info/debug()
|
||||
|
||||
# Returns distinguished name of SCP.
|
||||
def ScpCreate(
|
||||
service_binding_info,
|
||||
service_class_name, # Service class string to store in SCP.
|
||||
account_name=None, # Logon account that needs access to SCP.
|
||||
container_name=None,
|
||||
keywords=None,
|
||||
object_class="serviceConnectionPoint",
|
||||
dns_name_type="A",
|
||||
dn=None,
|
||||
dns_name=None,
|
||||
):
|
||||
container_name = container_name or service_class_name
|
||||
if not dns_name:
|
||||
# Get the DNS name of the local computer
|
||||
dns_name = win32api.GetComputerNameEx(win32con.ComputerNameDnsFullyQualified)
|
||||
# Get the distinguished name of the computer object for the local computer
|
||||
if dn is None:
|
||||
dn = win32api.GetComputerObjectName(win32con.NameFullyQualifiedDN)
|
||||
|
||||
# Compose the ADSpath and bind to the computer object for the local computer
|
||||
comp = adsi.ADsGetObject("LDAP://" + dn, adsi.IID_IDirectoryObject)
|
||||
|
||||
# Publish the SCP as a child of the computer object
|
||||
keywords = keywords or []
|
||||
# Fill in the attribute values to be stored in the SCP.
|
||||
attrs = [
|
||||
("cn", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, (container_name,)),
|
||||
("objectClass", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, (object_class,)),
|
||||
("keywords", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, keywords),
|
||||
("serviceDnsName", ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, (dns_name,)),
|
||||
(
|
||||
"serviceDnsNameType",
|
||||
ADS_ATTR_UPDATE,
|
||||
ADSTYPE_CASE_IGNORE_STRING,
|
||||
(dns_name_type,),
|
||||
),
|
||||
(
|
||||
"serviceClassName",
|
||||
ADS_ATTR_UPDATE,
|
||||
ADSTYPE_CASE_IGNORE_STRING,
|
||||
(service_class_name,),
|
||||
),
|
||||
(
|
||||
"serviceBindingInformation",
|
||||
ADS_ATTR_UPDATE,
|
||||
ADSTYPE_CASE_IGNORE_STRING,
|
||||
(service_binding_info,),
|
||||
),
|
||||
]
|
||||
new = comp.CreateDSObject("cn=" + container_name, attrs)
|
||||
logger.info("New connection point is at %s", container_name)
|
||||
# Wrap in a usable IDispatch object.
|
||||
new = Dispatch(new)
|
||||
# And allow access to the SCP for the specified account name
|
||||
AllowAccessToScpProperties(account_name, new)
|
||||
return new
|
||||
|
||||
|
||||
def ScpDelete(container_name, dn=None):
|
||||
if dn is None:
|
||||
dn = win32api.GetComputerObjectName(win32con.NameFullyQualifiedDN)
|
||||
logger.debug("Removing connection point '%s' from %s", container_name, dn)
|
||||
|
||||
# Compose the ADSpath and bind to the computer object for the local computer
|
||||
comp = adsi.ADsGetObject("LDAP://" + dn, adsi.IID_IDirectoryObject)
|
||||
comp.DeleteDSObject("cn=" + container_name)
|
||||
logger.info("Deleted service connection point '%s'", container_name)
|
||||
|
||||
|
||||
# This function is described in detail in the MSDN article titled
|
||||
# "Enabling Service Account to Access SCP Properties"
|
||||
# From that article:
|
||||
# The following sample code sets a pair of ACEs on a service connection point
|
||||
# (SCP) object. The ACEs grant read/write access to the user or computer account
|
||||
# under which the service instance will be running. Your service installation
|
||||
# program calls this code to ensure that the service will be allowed to update
|
||||
# its properties at run time. If you don't set ACEs like these, your service
|
||||
# will get access-denied errors if it tries to modify the SCP's properties.
|
||||
#
|
||||
# The code uses the IADsSecurityDescriptor, IADsAccessControlList, and
|
||||
# IADsAccessControlEntry interfaces to do the following:
|
||||
# * Get the SCP object's security descriptor.
|
||||
# * Set ACEs in the DACL of the security descriptor.
|
||||
# * Set the security descriptor back on the SCP object.
|
||||
|
||||
|
||||
def AllowAccessToScpProperties(
|
||||
accountSAM, # Service account to allow access.
|
||||
scpObject, # The IADs SCP object.
|
||||
schemaIDGUIDs=( # Attributes to allow write-access to.
|
||||
"{28630eb8-41d5-11d1-a9c1-0000f80367c1}", # serviceDNSName
|
||||
"{b7b1311c-b82e-11d0-afee-0000f80367c1}", # serviceBindingInformation
|
||||
),
|
||||
):
|
||||
|
||||
# If no service account is specified, service runs under LocalSystem.
|
||||
# So allow access to the computer account of the service's host.
|
||||
if accountSAM:
|
||||
trustee = accountSAM
|
||||
else:
|
||||
# Get the SAM account name of the computer object for the server.
|
||||
trustee = win32api.GetComputerObjectName(win32con.NameSamCompatible)
|
||||
|
||||
# Get the nTSecurityDescriptor attribute
|
||||
attribute = "nTSecurityDescriptor"
|
||||
sd = getattr(scpObject, attribute)
|
||||
acl = sd.DiscretionaryAcl
|
||||
|
||||
for sguid in schemaIDGUIDs:
|
||||
ace = Dispatch(adsi.CLSID_AccessControlEntry)
|
||||
|
||||
# Set the properties of the ACE.
|
||||
# Allow read and write access to the property.
|
||||
ace.AccessMask = ADS_RIGHT_DS_READ_PROP | ADS_RIGHT_DS_WRITE_PROP
|
||||
|
||||
# Set the trustee, which is either the service account or the
|
||||
# host computer account.
|
||||
ace.Trustee = trustee
|
||||
|
||||
# Set the ACE type.
|
||||
ace.AceType = ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
|
||||
|
||||
# Set AceFlags to zero because ACE is not inheritable.
|
||||
ace.AceFlags = 0
|
||||
|
||||
# Set Flags to indicate an ACE that protects a specified object.
|
||||
ace.Flags = ADS_FLAG_OBJECT_TYPE_PRESENT
|
||||
|
||||
# Set ObjectType to the schemaIDGUID of the attribute.
|
||||
ace.ObjectType = sguid
|
||||
|
||||
# Add the ACEs to the DACL.
|
||||
acl.AddAce(ace)
|
||||
|
||||
# Write the modified DACL back to the security descriptor.
|
||||
sd.DiscretionaryAcl = acl
|
||||
# Write the ntSecurityDescriptor property to the property cache.
|
||||
setattr(scpObject, attribute, sd)
|
||||
# SetInfo updates the SCP object in the directory.
|
||||
scpObject.SetInfo()
|
||||
logger.info("Set security on object for account '%s'" % (trustee,))
|
||||
|
||||
|
||||
# Service Principal Names functions from the same sample.
|
||||
# The example calls the DsWriteAccountSpn function, which stores the SPNs in
|
||||
# Microsoft Active Directory under the servicePrincipalName attribute of the
|
||||
# account object specified by the serviceAcctDN parameter. The account object
|
||||
# corresponds to the logon account specified in the CreateService call for this
|
||||
# service instance. If the logon account is a domain user account,
|
||||
# serviceAcctDN must be the distinguished name of the account object in
|
||||
# Active Directory for that user account. If the service's logon account is the
|
||||
# LocalSystem account, serviceAcctDN must be the distinguished name of the
|
||||
# computer account object for the host computer on which the service is
|
||||
# installed. win32api.TranslateNames and win32security.DsCrackNames can
|
||||
# be used to convert a domain\account format name to a distinguished name.
|
||||
def SpnRegister(
|
||||
serviceAcctDN, # DN of the service's logon account
|
||||
spns, # List of SPNs to register
|
||||
operation, # Add, replace, or delete SPNs
|
||||
):
|
||||
assert type(spns) not in [str, str] and hasattr(spns, "__iter__"), (
|
||||
"spns must be a sequence of strings (got %r)" % spns
|
||||
)
|
||||
# Bind to a domain controller.
|
||||
# Get the domain for the current user.
|
||||
samName = win32api.GetUserNameEx(win32api.NameSamCompatible)
|
||||
samName = samName.split("\\", 1)[0]
|
||||
|
||||
if not serviceAcctDN:
|
||||
# Get the SAM account name of the computer object for the server.
|
||||
serviceAcctDN = win32api.GetComputerObjectName(win32con.NameFullyQualifiedDN)
|
||||
logger.debug("SpnRegister using DN '%s'", serviceAcctDN)
|
||||
|
||||
# Get the name of a domain controller in that domain.
|
||||
info = win32security.DsGetDcName(
|
||||
domainName=samName,
|
||||
flags=dscon.DS_IS_FLAT_NAME
|
||||
| dscon.DS_RETURN_DNS_NAME
|
||||
| dscon.DS_DIRECTORY_SERVICE_REQUIRED,
|
||||
)
|
||||
# Bind to the domain controller.
|
||||
handle = win32security.DsBind(info["DomainControllerName"])
|
||||
|
||||
# Write the SPNs to the service account or computer account.
|
||||
logger.debug("DsWriteAccountSpn with spns %s")
|
||||
win32security.DsWriteAccountSpn(
|
||||
handle, # handle to the directory
|
||||
operation, # Add or remove SPN from account's existing SPNs
|
||||
serviceAcctDN, # DN of service account or computer account
|
||||
spns,
|
||||
) # names
|
||||
|
||||
# Unbind the DS in any case (but Python would do it anyway)
|
||||
handle.Close()
|
||||
|
||||
|
||||
def UserChangePassword(username_dn, new_password):
|
||||
# set the password on the account.
|
||||
# Use the distinguished name to bind to the account object.
|
||||
accountPath = "LDAP://" + username_dn
|
||||
user = adsi.ADsGetObject(accountPath, adsi.IID_IADsUser)
|
||||
|
||||
# Set the password on the account.
|
||||
user.SetPassword(new_password)
|
||||
|
||||
|
||||
# functions related to the command-line interface
|
||||
def log(level, msg, *args):
|
||||
if verbose >= level:
|
||||
print(msg % args)
|
||||
|
||||
|
||||
class _NoDefault:
|
||||
pass
|
||||
|
||||
|
||||
def _get_option(po, opt_name, default=_NoDefault):
|
||||
parser, options = po
|
||||
ret = getattr(options, opt_name, default)
|
||||
if not ret and default is _NoDefault:
|
||||
parser.error("The '%s' option must be specified for this operation" % opt_name)
|
||||
if not ret:
|
||||
ret = default
|
||||
return ret
|
||||
|
||||
|
||||
def _option_error(po, why):
|
||||
parser = po[0]
|
||||
parser.error(why)
|
||||
|
||||
|
||||
def do_ScpCreate(po):
|
||||
"""Create a Service Connection Point"""
|
||||
global g_createdSCP
|
||||
scp = ScpCreate(
|
||||
_get_option(po, "binding_string"),
|
||||
_get_option(po, "service_class"),
|
||||
_get_option(po, "account_name_sam", None),
|
||||
keywords=_get_option(po, "keywords", None),
|
||||
)
|
||||
g_createdSCP = scp
|
||||
return scp.distinguishedName
|
||||
|
||||
|
||||
def do_ScpDelete(po):
|
||||
"""Delete a Service Connection Point"""
|
||||
sc = _get_option(po, "service_class")
|
||||
try:
|
||||
ScpDelete(sc)
|
||||
except adsi.error as details:
|
||||
if details[0] != winerror.ERROR_DS_OBJ_NOT_FOUND:
|
||||
raise
|
||||
log(2, "ScpDelete ignoring ERROR_DS_OBJ_NOT_FOUND for service-class '%s'", sc)
|
||||
return sc
|
||||
|
||||
|
||||
def do_SpnCreate(po):
|
||||
"""Create a Service Principal Name"""
|
||||
# The 'service name' is the dn of our scp.
|
||||
if g_createdSCP is None:
|
||||
# Could accept an arg to avoid this?
|
||||
_option_error(po, "ScpCreate must have been specified before SpnCreate")
|
||||
# Create a Service Principal Name"
|
||||
spns = win32security.DsGetSpn(
|
||||
dscon.DS_SPN_SERVICE,
|
||||
_get_option(po, "service_class"),
|
||||
g_createdSCP.distinguishedName,
|
||||
_get_option(po, "port", 0),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
spn = spns[0]
|
||||
log(2, "Created SPN: %s", spn)
|
||||
global g_createdSPNLast
|
||||
g_createdSPNLast = spn
|
||||
g_createdSPNs.append(spn)
|
||||
return spn
|
||||
|
||||
|
||||
def do_SpnRegister(po):
|
||||
"""Register a previously created Service Principal Name"""
|
||||
if not g_createdSPNLast:
|
||||
_option_error(po, "SpnCreate must appear before SpnRegister")
|
||||
|
||||
SpnRegister(
|
||||
_get_option(po, "account_name_dn", None),
|
||||
(g_createdSPNLast,),
|
||||
dscon.DS_SPN_ADD_SPN_OP,
|
||||
)
|
||||
return g_createdSPNLast
|
||||
|
||||
|
||||
def do_SpnUnregister(po):
|
||||
"""Unregister a previously created Service Principal Name"""
|
||||
if not g_createdSPNLast:
|
||||
_option_error(po, "SpnCreate must appear before SpnUnregister")
|
||||
SpnRegister(
|
||||
_get_option(po, "account_name_dn", None),
|
||||
(g_createdSPNLast,),
|
||||
dscon.DS_SPN_DELETE_SPN_OP,
|
||||
)
|
||||
return g_createdSPNLast
|
||||
|
||||
|
||||
def do_UserChangePassword(po):
|
||||
"""Change the password for a specified user"""
|
||||
UserChangePassword(_get_option(po, "account_name_dn"), _get_option(po, "password"))
|
||||
return "Password changed OK"
|
||||
|
||||
|
||||
handlers = (
|
||||
("ScpCreate", do_ScpCreate),
|
||||
("ScpDelete", do_ScpDelete),
|
||||
("SpnCreate", do_SpnCreate),
|
||||
("SpnRegister", do_SpnRegister),
|
||||
("SpnUnregister", do_SpnUnregister),
|
||||
("UserChangePassword", do_UserChangePassword),
|
||||
)
|
||||
|
||||
|
||||
class HelpFormatter(optparse.IndentedHelpFormatter):
|
||||
def format_description(self, description):
|
||||
return description
|
||||
|
||||
|
||||
def main():
|
||||
global verbose
|
||||
_handlers_dict = {}
|
||||
|
||||
arg_descs = []
|
||||
for arg, func in handlers:
|
||||
this_desc = "\n".join(textwrap.wrap(func.__doc__, subsequent_indent=" " * 8))
|
||||
arg_descs.append(" %s: %s" % (arg, this_desc))
|
||||
_handlers_dict[arg.lower()] = func
|
||||
|
||||
description = __doc__ + "\ncommands:\n" + "\n".join(arg_descs) + "\n"
|
||||
|
||||
parser = optparse.OptionParser(
|
||||
usage="%prog [options] command ...",
|
||||
description=description,
|
||||
formatter=HelpFormatter(),
|
||||
)
|
||||
|
||||
parser.add_option(
|
||||
"-v",
|
||||
action="count",
|
||||
dest="verbose",
|
||||
default=1,
|
||||
help="increase the verbosity of status messages",
|
||||
)
|
||||
|
||||
parser.add_option(
|
||||
"-q", "--quiet", action="store_true", help="Don't print any status messages"
|
||||
)
|
||||
|
||||
parser.add_option(
|
||||
"-t",
|
||||
"--test",
|
||||
action="store_true",
|
||||
help="Execute a mini-test suite, providing defaults for most options and args",
|
||||
),
|
||||
|
||||
parser.add_option(
|
||||
"",
|
||||
"--show-tracebacks",
|
||||
action="store_true",
|
||||
help="Show the tracebacks for any exceptions",
|
||||
)
|
||||
|
||||
parser.add_option("", "--service-class", help="The service class name to use")
|
||||
|
||||
parser.add_option(
|
||||
"", "--port", default=0, help="The port number to associate with the SPN"
|
||||
)
|
||||
|
||||
parser.add_option(
|
||||
"", "--binding-string", help="The binding string to use for SCP creation"
|
||||
)
|
||||
|
||||
parser.add_option(
|
||||
"", "--account-name", help="The account name to use (default is LocalSystem)"
|
||||
)
|
||||
|
||||
parser.add_option("", "--password", help="The password to set.")
|
||||
|
||||
parser.add_option(
|
||||
"",
|
||||
"--keyword",
|
||||
action="append",
|
||||
dest="keywords",
|
||||
help="""A keyword to add to the SCP. May be specified
|
||||
multiple times""",
|
||||
)
|
||||
|
||||
parser.add_option(
|
||||
"",
|
||||
"--log-level",
|
||||
help="""The log-level to use - may be a number or a logging
|
||||
module constant""",
|
||||
default=str(logging.WARNING),
|
||||
)
|
||||
|
||||
options, args = parser.parse_args()
|
||||
po = (parser, options)
|
||||
# fixup misc
|
||||
try:
|
||||
options.port = int(options.port)
|
||||
except (TypeError, ValueError):
|
||||
parser.error("--port must be numeric")
|
||||
# fixup log-level
|
||||
try:
|
||||
log_level = int(options.log_level)
|
||||
except (TypeError, ValueError):
|
||||
try:
|
||||
log_level = int(getattr(logging, options.log_level.upper()))
|
||||
except (ValueError, TypeError, AttributeError):
|
||||
parser.error("Invalid --log-level value")
|
||||
try:
|
||||
sl = logger.setLevel
|
||||
# logger is a real logger
|
||||
except AttributeError:
|
||||
# logger is logging module
|
||||
sl = logging.getLogger().setLevel
|
||||
sl(log_level)
|
||||
# Check -q/-v
|
||||
if options.quiet and options.verbose:
|
||||
parser.error("Can't specify --quiet and --verbose")
|
||||
if options.quiet:
|
||||
options.verbose -= 1
|
||||
verbose = options.verbose
|
||||
# --test
|
||||
if options.test:
|
||||
if args:
|
||||
parser.error("Can't specify args with --test")
|
||||
|
||||
args = "ScpDelete ScpCreate SpnCreate SpnRegister SpnUnregister ScpDelete"
|
||||
log(1, "--test - pretending args are:\n %s", args)
|
||||
args = args.split()
|
||||
if not options.service_class:
|
||||
options.service_class = "PythonScpTest"
|
||||
log(2, "--test: --service-class=%s", options.service_class)
|
||||
if not options.keywords:
|
||||
options.keywords = "Python Powered".split()
|
||||
log(2, "--test: --keyword=%s", options.keywords)
|
||||
if not options.binding_string:
|
||||
options.binding_string = "test binding string"
|
||||
log(2, "--test: --binding-string=%s", options.binding_string)
|
||||
|
||||
# check args
|
||||
if not args:
|
||||
parser.error("No command specified (use --help for valid commands)")
|
||||
for arg in args:
|
||||
if arg.lower() not in _handlers_dict:
|
||||
parser.error("Invalid command '%s' (use --help for valid commands)" % arg)
|
||||
|
||||
# Patch up account-name.
|
||||
if options.account_name:
|
||||
log(2, "Translating account name '%s'", options.account_name)
|
||||
options.account_name_sam = win32security.TranslateName(
|
||||
options.account_name, win32api.NameUnknown, win32api.NameSamCompatible
|
||||
)
|
||||
log(2, "NameSamCompatible is '%s'", options.account_name_sam)
|
||||
options.account_name_dn = win32security.TranslateName(
|
||||
options.account_name, win32api.NameUnknown, win32api.NameFullyQualifiedDN
|
||||
)
|
||||
log(2, "NameFullyQualifiedDNis '%s'", options.account_name_dn)
|
||||
|
||||
# do it.
|
||||
for arg in args:
|
||||
handler = _handlers_dict[arg.lower()] # already been validated
|
||||
if handler is None:
|
||||
parser.error("Invalid command '%s'" % arg)
|
||||
err_msg = None
|
||||
try:
|
||||
try:
|
||||
log(2, "Executing '%s'...", arg)
|
||||
result = handler(po)
|
||||
log(1, "%s: %s", arg, result)
|
||||
except:
|
||||
if options.show_tracebacks:
|
||||
print("--show-tracebacks specified - dumping exception")
|
||||
traceback.print_exc()
|
||||
raise
|
||||
except adsi.error as xxx_todo_changeme:
|
||||
(hr, desc, exc, argerr) = xxx_todo_changeme.args
|
||||
if exc:
|
||||
extra_desc = exc[2]
|
||||
else:
|
||||
extra_desc = ""
|
||||
err_msg = desc
|
||||
if extra_desc:
|
||||
err_msg += "\n\t" + extra_desc
|
||||
except win32api.error as xxx_todo_changeme1:
|
||||
(hr, func, msg) = xxx_todo_changeme1.args
|
||||
err_msg = msg
|
||||
if err_msg:
|
||||
log(1, "Command '%s' failed: %s", arg, err_msg)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
print("*** Interrupted")
|
151
.venv/Lib/site-packages/win32comext/adsi/demos/search.py
Normal file
151
.venv/Lib/site-packages/win32comext/adsi/demos/search.py
Normal file
@ -0,0 +1,151 @@
|
||||
from win32com.adsi import adsi
|
||||
from win32com.adsi.adsicon import *
|
||||
from win32com.adsi import adsicon
|
||||
import pythoncom, pywintypes, win32security
|
||||
|
||||
options = None # set to optparse options object
|
||||
|
||||
ADsTypeNameMap = {}
|
||||
|
||||
|
||||
def getADsTypeName(type_val):
|
||||
# convert integer type to the 'typename' as known in the headerfiles.
|
||||
if not ADsTypeNameMap:
|
||||
for n, v in adsicon.__dict__.items():
|
||||
if n.startswith("ADSTYPE_"):
|
||||
ADsTypeNameMap[v] = n
|
||||
return ADsTypeNameMap.get(type_val, hex(type_val))
|
||||
|
||||
|
||||
def _guid_from_buffer(b):
|
||||
return pywintypes.IID(b, True)
|
||||
|
||||
|
||||
def _sid_from_buffer(b):
|
||||
return str(pywintypes.SID(b))
|
||||
|
||||
|
||||
_null_converter = lambda x: x
|
||||
|
||||
converters = {
|
||||
"objectGUID": _guid_from_buffer,
|
||||
"objectSid": _sid_from_buffer,
|
||||
"instanceType": getADsTypeName,
|
||||
}
|
||||
|
||||
|
||||
def log(level, msg, *args):
|
||||
if options.verbose >= level:
|
||||
print("log:", msg % args)
|
||||
|
||||
|
||||
def getGC():
|
||||
cont = adsi.ADsOpenObject(
|
||||
"GC:", options.user, options.password, 0, adsi.IID_IADsContainer
|
||||
)
|
||||
enum = adsi.ADsBuildEnumerator(cont)
|
||||
# Only 1 child of the global catalog.
|
||||
for e in enum:
|
||||
gc = e.QueryInterface(adsi.IID_IDirectorySearch)
|
||||
return gc
|
||||
return None
|
||||
|
||||
|
||||
def print_attribute(col_data):
|
||||
prop_name, prop_type, values = col_data
|
||||
if values is not None:
|
||||
log(2, "property '%s' has type '%s'", prop_name, getADsTypeName(prop_type))
|
||||
value = [converters.get(prop_name, _null_converter)(v[0]) for v in values]
|
||||
if len(value) == 1:
|
||||
value = value[0]
|
||||
print(" %s=%r" % (prop_name, value))
|
||||
else:
|
||||
print(" %s is None" % (prop_name,))
|
||||
|
||||
|
||||
def search():
|
||||
gc = getGC()
|
||||
if gc is None:
|
||||
log(0, "Can't find the global catalog")
|
||||
return
|
||||
|
||||
prefs = [(ADS_SEARCHPREF_SEARCH_SCOPE, (ADS_SCOPE_SUBTREE,))]
|
||||
hr, statuses = gc.SetSearchPreference(prefs)
|
||||
log(3, "SetSearchPreference returned %d/%r", hr, statuses)
|
||||
|
||||
if options.attributes:
|
||||
attributes = options.attributes.split(",")
|
||||
else:
|
||||
attributes = None
|
||||
|
||||
h = gc.ExecuteSearch(options.filter, attributes)
|
||||
hr = gc.GetNextRow(h)
|
||||
while hr != S_ADS_NOMORE_ROWS:
|
||||
print("-- new row --")
|
||||
if attributes is None:
|
||||
# Loop over all columns returned
|
||||
while 1:
|
||||
col_name = gc.GetNextColumnName(h)
|
||||
if col_name is None:
|
||||
break
|
||||
data = gc.GetColumn(h, col_name)
|
||||
print_attribute(data)
|
||||
else:
|
||||
# loop over attributes specified.
|
||||
for a in attributes:
|
||||
try:
|
||||
data = gc.GetColumn(h, a)
|
||||
print_attribute(data)
|
||||
except adsi.error as details:
|
||||
if details[0] != E_ADS_COLUMN_NOT_SET:
|
||||
raise
|
||||
print_attribute((a, None, None))
|
||||
hr = gc.GetNextRow(h)
|
||||
gc.CloseSearchHandle(h)
|
||||
|
||||
|
||||
def main():
|
||||
global options
|
||||
from optparse import OptionParser
|
||||
|
||||
parser = OptionParser()
|
||||
parser.add_option(
|
||||
"-f", "--file", dest="filename", help="write report to FILE", metavar="FILE"
|
||||
)
|
||||
parser.add_option(
|
||||
"-v",
|
||||
"--verbose",
|
||||
action="count",
|
||||
default=1,
|
||||
help="increase verbosity of output",
|
||||
)
|
||||
parser.add_option(
|
||||
"-q", "--quiet", action="store_true", help="suppress output messages"
|
||||
)
|
||||
|
||||
parser.add_option("-U", "--user", help="specify the username used to connect")
|
||||
parser.add_option("-P", "--password", help="specify the password used to connect")
|
||||
parser.add_option(
|
||||
"",
|
||||
"--filter",
|
||||
default="(&(objectCategory=person)(objectClass=User))",
|
||||
help="specify the search filter",
|
||||
)
|
||||
parser.add_option(
|
||||
"", "--attributes", help="comma sep'd list of attribute names to print"
|
||||
)
|
||||
|
||||
options, args = parser.parse_args()
|
||||
if options.quiet:
|
||||
if options.verbose != 1:
|
||||
parser.error("Can not use '--verbose' and '--quiet'")
|
||||
options.verbose = 0
|
||||
|
||||
if args:
|
||||
parser.error("You need not specify args")
|
||||
|
||||
search()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
271
.venv/Lib/site-packages/win32comext/adsi/demos/test.py
Normal file
271
.venv/Lib/site-packages/win32comext/adsi/demos/test.py
Normal file
@ -0,0 +1,271 @@
|
||||
import sys, string
|
||||
import pythoncom
|
||||
|
||||
import win32api
|
||||
from win32com.adsi import *
|
||||
|
||||
verbose_level = 0
|
||||
|
||||
server = "" # Must have trailing /
|
||||
local_name = win32api.GetComputerName()
|
||||
|
||||
|
||||
def DumpRoot():
|
||||
"Dumps the root DSE"
|
||||
path = "LDAP://%srootDSE" % server
|
||||
rootdse = ADsGetObject(path)
|
||||
|
||||
for item in rootdse.Get("SupportedLDAPVersion"):
|
||||
print("%s supports ldap version %s" % (path, item))
|
||||
|
||||
attributes = ["CurrentTime", "defaultNamingContext"]
|
||||
for attr in attributes:
|
||||
val = rootdse.Get(attr)
|
||||
print(" %s=%s" % (attr, val))
|
||||
|
||||
|
||||
###############################################
|
||||
#
|
||||
# Code taken from article titled:
|
||||
# Reading attributeSchema and classSchema Objects
|
||||
def _DumpClass(child):
|
||||
attrs = "Abstract lDAPDisplayName schemaIDGUID schemaNamingContext attributeSyntax oMSyntax"
|
||||
_DumpTheseAttributes(child, string.split(attrs))
|
||||
|
||||
|
||||
def _DumpAttribute(child):
|
||||
attrs = "lDAPDisplayName schemaIDGUID adminDescription adminDisplayName rDNAttID defaultHidingValue defaultObjectCategory systemOnly defaultSecurityDescriptor"
|
||||
_DumpTheseAttributes(child, string.split(attrs))
|
||||
|
||||
|
||||
def _DumpTheseAttributes(child, attrs):
|
||||
for attr in attrs:
|
||||
try:
|
||||
val = child.Get(attr)
|
||||
except pythoncom.com_error as details:
|
||||
continue
|
||||
# ###
|
||||
(hr, msg, exc, arg) = details
|
||||
if exc and exc[2]:
|
||||
msg = exc[2]
|
||||
val = "<Error: %s>" % (msg,)
|
||||
if verbose_level >= 2:
|
||||
print(" %s: %s=%s" % (child.Class, attr, val))
|
||||
|
||||
|
||||
def DumpSchema():
|
||||
"Dumps the default DSE schema"
|
||||
# Bind to rootDSE to get the schemaNamingContext property.
|
||||
path = "LDAP://%srootDSE" % server
|
||||
rootdse = ADsGetObject(path)
|
||||
name = rootdse.Get("schemaNamingContext")
|
||||
|
||||
# Bind to the actual schema container.
|
||||
path = "LDAP://" + server + name
|
||||
print("Binding to", path)
|
||||
ob = ADsGetObject(path)
|
||||
nclasses = nattr = nsub = nunk = 0
|
||||
|
||||
# Enumerate the attribute and class objects in the schema container.
|
||||
for child in ob:
|
||||
# Find out if this is a class, attribute, or subSchema object.
|
||||
class_name = child.Class
|
||||
if class_name == "classSchema":
|
||||
_DumpClass(child)
|
||||
nclasses = nclasses + 1
|
||||
elif class_name == "attributeSchema":
|
||||
_DumpAttribute(child)
|
||||
nattr = nattr + 1
|
||||
elif class_name == "subSchema":
|
||||
nsub = nsub + 1
|
||||
else:
|
||||
print("Unknown class:", class_name)
|
||||
nunk = nunk + 1
|
||||
if verbose_level:
|
||||
print("Processed", nclasses, "classes")
|
||||
print("Processed", nattr, "attributes")
|
||||
print("Processed", nsub, "sub-schema's")
|
||||
print("Processed", nunk, "unknown types")
|
||||
|
||||
|
||||
def _DumpObject(ob, level=0):
|
||||
prefix = " " * level
|
||||
print("%s%s object: %s" % (prefix, ob.Class, ob.Name))
|
||||
# Do the directory object thing
|
||||
try:
|
||||
dir_ob = ADsGetObject(ob.ADsPath, IID_IDirectoryObject)
|
||||
except pythoncom.com_error:
|
||||
dir_ob = None
|
||||
if dir_ob is not None:
|
||||
info = dir_ob.GetObjectInformation()
|
||||
print("%s RDN='%s', ObjectDN='%s'" % (prefix, info.RDN, info.ObjectDN))
|
||||
# Create a list of names to fetch
|
||||
names = ["distinguishedName"]
|
||||
attrs = dir_ob.GetObjectAttributes(names)
|
||||
for attr in attrs:
|
||||
for val, typ in attr.Values:
|
||||
print("%s Attribute '%s' = %s" % (prefix, attr.AttrName, val))
|
||||
|
||||
for child in ob:
|
||||
_DumpObject(child, level + 1)
|
||||
|
||||
|
||||
def DumpAllObjects():
|
||||
"Recursively dump the entire directory!"
|
||||
path = "LDAP://%srootDSE" % server
|
||||
rootdse = ADsGetObject(path)
|
||||
name = rootdse.Get("defaultNamingContext")
|
||||
|
||||
# Bind to the actual schema container.
|
||||
path = "LDAP://" + server + name
|
||||
print("Binding to", path)
|
||||
ob = ADsGetObject(path)
|
||||
|
||||
# Enumerate the attribute and class objects in the schema container.
|
||||
_DumpObject(ob)
|
||||
|
||||
|
||||
##########################################################
|
||||
#
|
||||
# Code taken from article:
|
||||
# Example Code for Enumerating Schema Classes, Attributes, and Syntaxes
|
||||
|
||||
# Fill a map with VT_ datatypes, to give us better names:
|
||||
vt_map = {}
|
||||
for name, val in pythoncom.__dict__.items():
|
||||
if name[:3] == "VT_":
|
||||
vt_map[val] = name
|
||||
|
||||
|
||||
def DumpSchema2():
|
||||
"Dumps the schema using an alternative technique"
|
||||
path = "LDAP://%sschema" % (server,)
|
||||
schema = ADsGetObject(path, IID_IADsContainer)
|
||||
nclass = nprop = nsyntax = 0
|
||||
for item in schema:
|
||||
item_class = string.lower(item.Class)
|
||||
if item_class == "class":
|
||||
items = []
|
||||
if item.Abstract:
|
||||
items.append("Abstract")
|
||||
if item.Auxiliary:
|
||||
items.append("Auxiliary")
|
||||
# if item.Structural: items.append("Structural")
|
||||
desc = string.join(items, ", ")
|
||||
import win32com.util
|
||||
|
||||
iid_name = win32com.util.IIDToInterfaceName(item.PrimaryInterface)
|
||||
if verbose_level >= 2:
|
||||
print(
|
||||
"Class: Name=%s, Flags=%s, Primary Interface=%s"
|
||||
% (item.Name, desc, iid_name)
|
||||
)
|
||||
nclass = nclass + 1
|
||||
elif item_class == "property":
|
||||
if item.MultiValued:
|
||||
val_type = "Multi-Valued"
|
||||
else:
|
||||
val_type = "Single-Valued"
|
||||
if verbose_level >= 2:
|
||||
print("Property: Name=%s, %s" % (item.Name, val_type))
|
||||
nprop = nprop + 1
|
||||
elif item_class == "syntax":
|
||||
data_type = vt_map.get(item.OleAutoDataType, "<unknown type>")
|
||||
if verbose_level >= 2:
|
||||
print("Syntax: Name=%s, Datatype = %s" % (item.Name, data_type))
|
||||
nsyntax = nsyntax + 1
|
||||
if verbose_level >= 1:
|
||||
print("Processed", nclass, "classes")
|
||||
print("Processed", nprop, "properties")
|
||||
print("Processed", nsyntax, "syntax items")
|
||||
|
||||
|
||||
def DumpGC():
|
||||
"Dumps the GC: object (whatever that is!)"
|
||||
ob = ADsGetObject("GC:", IID_IADsContainer)
|
||||
for sub_ob in ob:
|
||||
print("GC ob: %s (%s)" % (sub_ob.Name, sub_ob.ADsPath))
|
||||
|
||||
|
||||
def DumpLocalUsers():
|
||||
"Dumps the local machine users"
|
||||
path = "WinNT://%s,computer" % (local_name,)
|
||||
ob = ADsGetObject(path, IID_IADsContainer)
|
||||
ob.put_Filter(["User", "Group"])
|
||||
for sub_ob in ob:
|
||||
print("User/Group: %s (%s)" % (sub_ob.Name, sub_ob.ADsPath))
|
||||
|
||||
|
||||
def DumpLocalGroups():
|
||||
"Dumps the local machine groups"
|
||||
path = "WinNT://%s,computer" % (local_name,)
|
||||
ob = ADsGetObject(path, IID_IADsContainer)
|
||||
|
||||
ob.put_Filter(["Group"])
|
||||
for sub_ob in ob:
|
||||
print("Group: %s (%s)" % (sub_ob.Name, sub_ob.ADsPath))
|
||||
# get the members
|
||||
members = sub_ob.Members()
|
||||
for member in members:
|
||||
print(" Group member: %s (%s)" % (member.Name, member.ADsPath))
|
||||
|
||||
|
||||
def usage(tests):
|
||||
import os
|
||||
|
||||
print("Usage: %s [-s server ] [-v] [Test ...]" % os.path.basename(sys.argv[0]))
|
||||
print(" -v : Verbose - print more information")
|
||||
print(" -s : server - execute the tests against the named server")
|
||||
print("where Test is one of:")
|
||||
for t in tests:
|
||||
print(t.__name__, ":", t.__doc__)
|
||||
print()
|
||||
print("If not tests are specified, all tests are run")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def main():
|
||||
import getopt, traceback
|
||||
|
||||
tests = []
|
||||
for ob in globals().values():
|
||||
if type(ob) == type(main) and ob.__doc__:
|
||||
tests.append(ob)
|
||||
opts, args = getopt.getopt(sys.argv[1:], "s:hv")
|
||||
for opt, val in opts:
|
||||
if opt == "-s":
|
||||
if val[-1] not in "\\/":
|
||||
val = val + "/"
|
||||
global server
|
||||
server = val
|
||||
if opt == "-h":
|
||||
usage(tests)
|
||||
if opt == "-v":
|
||||
global verbose_level
|
||||
verbose_level = verbose_level + 1
|
||||
|
||||
if len(args) == 0:
|
||||
print("Running all tests - use '-h' to see command-line options...")
|
||||
dotests = tests
|
||||
else:
|
||||
dotests = []
|
||||
for arg in args:
|
||||
for t in tests:
|
||||
if t.__name__ == arg:
|
||||
dotests.append(t)
|
||||
break
|
||||
else:
|
||||
print("Test '%s' unknown - skipping" % arg)
|
||||
if not len(dotests):
|
||||
print("Nothing to do!")
|
||||
usage(tests)
|
||||
for test in dotests:
|
||||
try:
|
||||
test()
|
||||
except:
|
||||
print("Test %s failed" % test.__name__)
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Reference in New Issue
Block a user