diff --git a/Lib/site-packages/adodbapi/__init__.py b/Lib/site-packages/adodbapi/__init__.py new file mode 100644 index 0000000..a5eca81 --- /dev/null +++ b/Lib/site-packages/adodbapi/__init__.py @@ -0,0 +1,56 @@ +"""adodbapi - A python DB API 2.0 (PEP 249) interface to Microsoft ADO + +Copyright (C) 2002 Henrik Ekelund, version 2.1 by Vernon Cole +* http://sourceforge.net/projects/adodbapi +""" +import sys +import time + +if sys.version_info < (3,0): # in Python 2, define all symbols, just like the bad old way + from apibase import * + VariantConversionMap = MultiMap # old name. Should use apibase.MultiMap + from .ado_consts import * + _makeByteBuffer = buffer +else: + # but if the user is running Python 3, then keep the dictionary clean + from .apibase import apilevel, threadsafety, paramstyle + from .apibase import Warning, Error, InterfaceError, DatabaseError, DataError, OperationalError, IntegrityError + from .apibase import InternalError, ProgrammingError, NotSupportedError, FetchFailedError + from .apibase import NUMBER, STRING, BINARY, DATETIME, ROWID + _makeByteBuffer = bytes + +from .adodbapi import connect, Connection, __version__, dateconverter, Cursor + +def Binary(aString): + """This function constructs an object capable of holding a binary (long) string value. """ + return _makeByteBuffer(aString) + +def Date(year,month,day): + "This function constructs an object holding a date value. " + return dateconverter.Date(year,month,day) + +def Time(hour,minute,second): + "This function constructs an object holding a time value. " + return dateconverter.Time(hour,minute,second) + +def Timestamp(year,month,day,hour,minute,second): + "This function constructs an object holding a time stamp value. " + return dateconverter.Timestamp(year,month,day,hour,minute,second) + +def DateFromTicks(ticks): + """This function constructs an object holding a date value from the given ticks value + (number of seconds since the epoch; see the documentation of the standard Python time module for details). """ + return Date(*time.gmtime(ticks)[:3]) + +def TimeFromTicks(ticks): + """This function constructs an object holding a time value from the given ticks value + (number of seconds since the epoch; see the documentation of the standard Python time module for details). """ + return Time(*time.gmtime(ticks)[3:6]) + +def TimestampFromTicks(ticks): + """This function constructs an object holding a time stamp value from the given + ticks value (number of seconds since the epoch; + see the documentation of the standard Python time module for details). """ + return Timestamp(*time.gmtime(ticks)[:6]) + +version = 'adodbapi v' + __version__ diff --git a/Lib/site-packages/adodbapi/ado_consts.py b/Lib/site-packages/adodbapi/ado_consts.py new file mode 100644 index 0000000..5ecf735 --- /dev/null +++ b/Lib/site-packages/adodbapi/ado_consts.py @@ -0,0 +1,276 @@ +# ADO enumerated constants documented on MSDN: +# http://msdn.microsoft.com/en-us/library/ms678353(VS.85).aspx + +# IsolationLevelEnum +adXactUnspecified = -1 +adXactBrowse = 0x100 +adXactChaos = 0x10 +adXactCursorStability = 0x1000 +adXactIsolated = 0x100000 +adXactReadCommitted = 0x1000 +adXactReadUncommitted = 0x100 +adXactRepeatableRead = 0x10000 +adXactSerializable = 0x100000 + +# CursorLocationEnum +adUseClient = 3 +adUseServer = 2 + +# CursorTypeEnum +adOpenDynamic = 2 +adOpenForwardOnly = 0 +adOpenKeyset = 1 +adOpenStatic = 3 +adOpenUnspecified = -1 + +# CommandTypeEnum +adCmdText = 1 +adCmdStoredProc = 4 +adSchemaTables = 20 + +# ParameterDirectionEnum +adParamInput = 1 +adParamInputOutput = 3 +adParamOutput = 2 +adParamReturnValue = 4 +adParamUnknown = 0 +directions = { + 0: 'Unknown', + 1: 'Input', + 2: 'Output', + 3: 'InputOutput', + 4: 'Return', + } +def ado_direction_name(ado_dir): + try: + return 'adParam' + directions[ado_dir] + except: + return 'unknown direction ('+str(ado_dir)+')' + +# ObjectStateEnum +adStateClosed = 0 +adStateOpen = 1 +adStateConnecting = 2 +adStateExecuting = 4 +adStateFetching = 8 + +# FieldAttributeEnum +adFldMayBeNull = 0x40 + +# ConnectModeEnum +adModeUnknown = 0 +adModeRead = 1 +adModeWrite = 2 +adModeReadWrite = 3 +adModeShareDenyRead = 4 +adModeShareDenyWrite = 8 +adModeShareExclusive = 12 +adModeShareDenyNone = 16 +adModeRecursive = 0x400000 + +# XactAttributeEnum +adXactCommitRetaining = 131072 +adXactAbortRetaining = 262144 + +ado_error_TIMEOUT = -2147217871 + +# DataTypeEnum - ADO Data types documented at: +# http://msdn2.microsoft.com/en-us/library/ms675318.aspx +adArray = 0x2000 +adEmpty = 0x0 +adBSTR = 0x8 +adBigInt = 0x14 +adBinary = 0x80 +adBoolean = 0xb +adChapter = 0x88 +adChar = 0x81 +adCurrency = 0x6 +adDBDate = 0x85 +adDBTime = 0x86 +adDBTimeStamp = 0x87 +adDate = 0x7 +adDecimal = 0xe +adDouble = 0x5 +adError = 0xa +adFileTime = 0x40 +adGUID = 0x48 +adIDispatch = 0x9 +adIUnknown = 0xd +adInteger = 0x3 +adLongVarBinary = 0xcd +adLongVarChar = 0xc9 +adLongVarWChar = 0xcb +adNumeric = 0x83 +adPropVariant = 0x8a +adSingle = 0x4 +adSmallInt = 0x2 +adTinyInt = 0x10 +adUnsignedBigInt = 0x15 +adUnsignedInt = 0x13 +adUnsignedSmallInt = 0x12 +adUnsignedTinyInt = 0x11 +adUserDefined = 0x84 +adVarBinary = 0xCC +adVarChar = 0xC8 +adVarNumeric = 0x8B +adVarWChar = 0xCA +adVariant = 0xC +adWChar = 0x82 +# Additional constants used by introspection but not ADO itself +AUTO_FIELD_MARKER = -1000 + +adTypeNames = { + adBSTR: 'adBSTR', + adBigInt: 'adBigInt', + adBinary: 'adBinary', + adBoolean: 'adBoolean', + adChapter: 'adChapter', + adChar: 'adChar', + adCurrency: 'adCurrency', + adDBDate: 'adDBDate', + adDBTime: 'adDBTime', + adDBTimeStamp: 'adDBTimeStamp', + adDate: 'adDate', + adDecimal: 'adDecimal', + adDouble: 'adDouble', + adEmpty: 'adEmpty', + adError: 'adError', + adFileTime: 'adFileTime', + adGUID: 'adGUID', + adIDispatch: 'adIDispatch', + adIUnknown: 'adIUnknown', + adInteger: 'adInteger', + adLongVarBinary: 'adLongVarBinary', + adLongVarChar: 'adLongVarChar', + adLongVarWChar: 'adLongVarWChar', + adNumeric: 'adNumeric', + adPropVariant: 'adPropVariant', + adSingle: 'adSingle', + adSmallInt: 'adSmallInt', + adTinyInt: 'adTinyInt', + adUnsignedBigInt: 'adUnsignedBigInt', + adUnsignedInt: 'adUnsignedInt', + adUnsignedSmallInt: 'adUnsignedSmallInt', + adUnsignedTinyInt: 'adUnsignedTinyInt', + adUserDefined: 'adUserDefined', + adVarBinary: 'adVarBinary', + adVarChar: 'adVarChar', + adVarNumeric: 'adVarNumeric', + adVarWChar: 'adVarWChar', + adVariant: 'adVariant', + adWChar: 'adWChar', + } + +def ado_type_name(ado_type): + return adTypeNames.get(ado_type, 'unknown type ('+str(ado_type)+')') + +# here in decimal, sorted by value +#adEmpty 0 Specifies no value (DBTYPE_EMPTY). +#adSmallInt 2 Indicates a two-byte signed integer (DBTYPE_I2). +#adInteger 3 Indicates a four-byte signed integer (DBTYPE_I4). +#adSingle 4 Indicates a single-precision floating-point value (DBTYPE_R4). +#adDouble 5 Indicates a double-precision floating-point value (DBTYPE_R8). +#adCurrency 6 Indicates a currency value (DBTYPE_CY). Currency is a fixed-point number +# with four digits to the right of the decimal point. It is stored in an eight-byte signed integer scaled by 10,000. +#adDate 7 Indicates a date value (DBTYPE_DATE). A date is stored as a double, the whole part of which is +# the number of days since December 30, 1899, and the fractional part of which is the fraction of a day. +#adBSTR 8 Indicates a null-terminated character string (Unicode) (DBTYPE_BSTR). +#adIDispatch 9 Indicates a pointer to an IDispatch interface on a COM object (DBTYPE_IDISPATCH). +#adError 10 Indicates a 32-bit error code (DBTYPE_ERROR). +#adBoolean 11 Indicates a boolean value (DBTYPE_BOOL). +#adVariant 12 Indicates an Automation Variant (DBTYPE_VARIANT). +#adIUnknown 13 Indicates a pointer to an IUnknown interface on a COM object (DBTYPE_IUNKNOWN). +#adDecimal 14 Indicates an exact numeric value with a fixed precision and scale (DBTYPE_DECIMAL). +#adTinyInt 16 Indicates a one-byte signed integer (DBTYPE_I1). +#adUnsignedTinyInt 17 Indicates a one-byte unsigned integer (DBTYPE_UI1). +#adUnsignedSmallInt 18 Indicates a two-byte unsigned integer (DBTYPE_UI2). +#adUnsignedInt 19 Indicates a four-byte unsigned integer (DBTYPE_UI4). +#adBigInt 20 Indicates an eight-byte signed integer (DBTYPE_I8). +#adUnsignedBigInt 21 Indicates an eight-byte unsigned integer (DBTYPE_UI8). +#adFileTime 64 Indicates a 64-bit value representing the number of 100-nanosecond intervals since +# January 1, 1601 (DBTYPE_FILETIME). +#adGUID 72 Indicates a globally unique identifier (GUID) (DBTYPE_GUID). +#adBinary 128 Indicates a binary value (DBTYPE_BYTES). +#adChar 129 Indicates a string value (DBTYPE_STR). +#adWChar 130 Indicates a null-terminated Unicode character string (DBTYPE_WSTR). +#adNumeric 131 Indicates an exact numeric value with a fixed precision and scale (DBTYPE_NUMERIC). +# adUserDefined 132 Indicates a user-defined variable (DBTYPE_UDT). +#adUserDefined 132 Indicates a user-defined variable (DBTYPE_UDT). +#adDBDate 133 Indicates a date value (yyyymmdd) (DBTYPE_DBDATE). +#adDBTime 134 Indicates a time value (hhmmss) (DBTYPE_DBTIME). +#adDBTimeStamp 135 Indicates a date/time stamp (yyyymmddhhmmss plus a fraction in billionths) (DBTYPE_DBTIMESTAMP). +#adChapter 136 Indicates a four-byte chapter value that identifies rows in a child rowset (DBTYPE_HCHAPTER). +#adPropVariant 138 Indicates an Automation PROPVARIANT (DBTYPE_PROP_VARIANT). +#adVarNumeric 139 Indicates a numeric value (Parameter object only). +#adVarChar 200 Indicates a string value (Parameter object only). +#adLongVarChar 201 Indicates a long string value (Parameter object only). +#adVarWChar 202 Indicates a null-terminated Unicode character string (Parameter object only). +#adLongVarWChar 203 Indicates a long null-terminated Unicode string value (Parameter object only). +#adVarBinary 204 Indicates a binary value (Parameter object only). +#adLongVarBinary 205 Indicates a long binary value (Parameter object only). +#adArray (Does not apply to ADOX.) 0x2000 A flag value, always combined with another data type constant, +# that indicates an array of that other data type. + +# Error codes to names +adoErrors= { + 0xe7b :'adErrBoundToCommand', + 0xe94 :'adErrCannotComplete', + 0xea4 :'adErrCantChangeConnection', + 0xc94 :'adErrCantChangeProvider', + 0xe8c :'adErrCantConvertvalue', + 0xe8d :'adErrCantCreate', + 0xea3 :'adErrCatalogNotSet', + 0xe8e :'adErrColumnNotOnThisRow', + 0xd5d :'adErrDataConversion', + 0xe89 :'adErrDataOverflow', + 0xe9a :'adErrDelResOutOfScope', + 0xea6 :'adErrDenyNotSupported', + 0xea7 :'adErrDenyTypeNotSupported', + 0xcb3 :'adErrFeatureNotAvailable', + 0xea5 :'adErrFieldsUpdateFailed', + 0xc93 :'adErrIllegalOperation', + 0xcae :'adErrInTransaction', + 0xe87 :'adErrIntegrityViolation', + 0xbb9 :'adErrInvalidArgument', + 0xe7d :'adErrInvalidConnection', + 0xe7c :'adErrInvalidParamInfo', + 0xe82 :'adErrInvalidTransaction', + 0xe91 :'adErrInvalidURL', + 0xcc1 :'adErrItemNotFound', + 0xbcd :'adErrNoCurrentRecord', + 0xe83 :'adErrNotExecuting', + 0xe7e :'adErrNotReentrant', + 0xe78 :'adErrObjectClosed', + 0xd27 :'adErrObjectInCollection', + 0xd5c :'adErrObjectNotSet', + 0xe79 :'adErrObjectOpen', + 0xbba :'adErrOpeningFile', + 0xe80 :'adErrOperationCancelled', + 0xe96 :'adErrOutOfSpace', + 0xe88 :'adErrPermissionDenied', + 0xe9e :'adErrPropConflicting', + 0xe9b :'adErrPropInvalidColumn', + 0xe9c :'adErrPropInvalidOption', + 0xe9d :'adErrPropInvalidValue', + 0xe9f :'adErrPropNotAllSettable', + 0xea0 :'adErrPropNotSet', + 0xea1 :'adErrPropNotSettable', + 0xea2 :'adErrPropNotSupported', + 0xbb8 :'adErrProviderFailed', + 0xe7a :'adErrProviderNotFound', + 0xbbb :'adErrReadFile', + 0xe93 :'adErrResourceExists', + 0xe92 :'adErrResourceLocked', + 0xe97 :'adErrResourceOutOfScope', + 0xe8a :'adErrSchemaViolation', + 0xe8b :'adErrSignMismatch', + 0xe81 :'adErrStillConnecting', + 0xe7f :'adErrStillExecuting', + 0xe90 :'adErrTreePermissionDenied', + 0xe8f :'adErrURLDoesNotExist', + 0xe99 :'adErrURLNamedRowDoesNotExist', + 0xe98 :'adErrUnavailable', + 0xe84 :'adErrUnsafeOperation', + 0xe95 :'adErrVolumeNotFound', + 0xbbc :'adErrWriteFile' + } diff --git a/Lib/site-packages/adodbapi/adodbapi.py b/Lib/site-packages/adodbapi/adodbapi.py new file mode 100644 index 0000000..0100df7 --- /dev/null +++ b/Lib/site-packages/adodbapi/adodbapi.py @@ -0,0 +1,1010 @@ +"""adodbapi - A python DB API 2.0 (PEP 249) interface to Microsoft ADO + +Copyright (C) 2002 Henrik Ekelund, versions 2.1 and later by Vernon Cole +* http://sourceforge.net/projects/pywin32 +* http://sourceforge.net/projects/adodbapi + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + django adaptations and refactoring by Adam Vandenberg + +DB-API 2.0 specification: http://www.python.org/dev/peps/pep-0249/ + +This module source should run correctly in CPython versions 2.5 and later, +or IronPython version 2.6 and later, +or, after running through 2to3.py, CPython 3.0 or later. +""" +__version__ = '2.6.0.6' +version = 'adodbapi v' + __version__ + +import sys +import copy +import decimal +import os + +import process_connect_string +from . import ado_consts as adc +import apibase as api + +try: + verbose = int(os.environ['ADODBAPI_VERBOSE']) +except: + verbose = False +if verbose: + print(version) + +# --- define objects to smooth out IronPython <-> CPython differences +onWin32 = False # assume the worst +if api.onIronPython: + from System import Activator, Type, DBNull, DateTime, Array, Byte + from System import Decimal as SystemDecimal + from clr import Reference + def Dispatch(dispatch): + type = Type.GetTypeFromProgID(dispatch) + return Activator.CreateInstance(type) + def getIndexedValue(obj,index): + return obj.Item[index] +else: # try pywin32 + try: + import win32com.client + import pythoncom + import pywintypes + onWin32 = True + def Dispatch(dispatch): + return win32com.client.Dispatch(dispatch) + except ImportError: + import warnings + warnings.warn("pywin32 package (or IronPython) required for adodbapi.",ImportWarning) + def getIndexedValue(obj,index): + return obj(index) + +try: + from collections import Mapping +except ImportError: # Python 2.5 + Mapping = dict # this will handle the most common case + +# --- define objects to smooth out Python3000 <-> Python 2.x differences +unicodeType = str #this line will be altered by 2to3.py to '= str' +longType = int #this line will be altered by 2to3.py to '= int' +if sys.version_info >= (3,0): #python 3.x + StringTypes = str + maxint = sys.maxsize +else: #python 2.x + StringTypes = (str,str) # will be messed up by 2to3 but never used + maxint = sys.maxint + +# ----------------- The .connect method ----------------- +def make_COM_connecter(): + try: + if onWin32: + pythoncom.CoInitialize() #v2.1 Paj + c = Dispatch('ADODB.Connection') #connect _after_ CoIninialize v2.1.1 adamvan + except: + raise api.InterfaceError ("Windows COM Error: Dispatch('ADODB.Connection') failed.") + return c + +def connect(*args, **kwargs): # --> a db-api connection object + """Connect to a database. + + call using: + :connection_string -- An ADODB formatted connection string, see: + * http://www.connectionstrings.com + * http://www.asp101.com/articles/john/connstring/default.asp + :timeout -- A command timeout value, in seconds (default 30 seconds) + """ + co = Connection() # make an empty connection object + + kwargs = process_connect_string.process(args, kwargs, True) + + try: # connect to the database, using the connection information in kwargs + co.connect(kwargs) + return co + except (Exception) as e: + message = 'Error opening connection to "%s"' % co.connection_string + raise api.OperationalError(e, message) + +# so you could use something like: +# myConnection.paramstyle = 'named' +# The programmer may also change the default. +# For example, if I were using django, I would say: +# import adodbapi as Database +# Database.adodbapi.paramstyle = 'format' + +# ------- other module level defaults -------- +defaultIsolationLevel = adc.adXactReadCommitted +# Set defaultIsolationLevel on module level before creating the connection. +# For example: +# import adodbapi, ado_consts +# adodbapi.adodbapi.defaultIsolationLevel=ado_consts.adXactBrowse" +# +# Set defaultCursorLocation on module level before creating the connection. +# It may be one of the "adUse..." consts. +defaultCursorLocation = adc.adUseClient # changed from adUseServer as of v 2.3.0 + +dateconverter = api.pythonDateTimeConverter() # default + +def format_parameters(ADOparameters, show_value=False): + """Format a collection of ADO Command Parameters. + + Used by error reporting in _execute_command. + """ + try: + if show_value: + desc = [ + "Name: %s, Dir.: %s, Type: %s, Size: %s, Value: \"%s\", Precision: %s, NumericScale: %s" %\ + (p.Name, adc.directions[p.Direction], adc.adTypeNames.get(p.Type, str(p.Type)+' (unknown type)'), p.Size, p.Value, p.Precision, p.NumericScale) + for p in ADOparameters ] + else: + desc = [ + "Name: %s, Dir.: %s, Type: %s, Size: %s, Precision: %s, NumericScale: %s" %\ + (p.Name, adc.directions[p.Direction], adc.adTypeNames.get(p.Type, str(p.Type)+' (unknown type)'), p.Size, p.Precision, p.NumericScale) + for p in ADOparameters ] + return '[' + '\n'.join(desc) + ']' + except: + return '[]' + +def _configure_parameter(p, value, adotype, settings_known): + """Configure the given ADO Parameter 'p' with the Python 'value'.""" + + if adotype in api.adoBinaryTypes: + p.Size = len(value) + p.AppendChunk(value) + + elif isinstance(value,StringTypes): #v2.1 Jevon + L = len(value) + if adotype in api.adoStringTypes: #v2.2.1 Cole + if settings_known: L = min(L,p.Size) #v2.1 Cole limit data to defined size + p.Value = value[:L] #v2.1 Jevon & v2.1 Cole + else: + p.Value = value # dont limit if db column is numeric + if L>0: #v2.1 Cole something does not like p.Size as Zero + p.Size = L #v2.1 Jevon + + elif isinstance(value, decimal.Decimal): + if api.onIronPython: + s = str(value) + p.Value = s + p.Size = len(s) + else: + p.Value = value + exponent = value.as_tuple()[2] + digit_count = len(value.as_tuple()[1]) + p.Precision = digit_count + if exponent == 0: + p.NumericScale = 0 + elif exponent < 0: + p.NumericScale = -exponent + if p.Precision < p.NumericScale: + p.Precision = p.NumericScale + else: # exponent > 0: + p.NumericScale = 0 + p.Precision = digit_count + exponent + + elif type(value) in dateconverter.types: + if settings_known and adotype in api.adoDateTimeTypes: + p.Value = dateconverter.COMDate(value) + else: #probably a string + # provide the date as a string in the format 'YYYY-MM-dd' + s = dateconverter.DateObjectToIsoFormatString(value) + p.Value = s + p.Size = len(s) + + elif api.onIronPython and isinstance(value, longType): # Iron Python Long + s = str(value) # feature workaround for IPy 2.0 + p.Value = s + + elif adotype == adc.adEmpty: # ADO will not let you specify a null column + p.Type = adc.adInteger # so we will fake it to be an integer (just to have something) + p.Value = None # and pass in a Null *value* + + # For any other type, set the value and let pythoncom do the right thing. + else: + p.Value = value + + +def counter(): + i = 0 + while True: + yield i + i += 1 + +# # # # # ----- the Class that defines a connection ----- # # # # # +class Connection(object): + # include connection attributes as class attributes required by api definition. + Warning = api.Warning + Error = api.Error + InterfaceError = api.InterfaceError + DataError = api.DataError + DatabaseError = api.DatabaseError + OperationalError = api.OperationalError + IntegrityError = api.IntegrityError + InternalError = api.InternalError + NotSupportedError = api.NotSupportedError + ProgrammingError = api.ProgrammingError + FetchFailedError = api.FetchFailedError # (special for django) + # ...class attributes... (can be overridden by instance attributes) + verbose = api.verbose + + @property + def dbapi(self): # a proposed db-api version 3 extension. + "Return a reference to the DBAPI module for this Connection." + return api + + def __init__(self): # now define the instance attributes + self.connector = None + self.paramstyle = api.paramstyle + self.supportsTransactions = False + self.connection_string = '' + self.cursors = {} + self.cursor_counter = counter() + self.dbms_name = '' + self.dbms_version = '' + self.errorhandler = None # use the standard error handler for this instance + self.transaction_level = 0 # 0 == Not in a transaction, at the top level + self._autocommit = False + + def connect(self, kwargs, connection_maker=make_COM_connecter): + if verbose > 9: + print(('kwargs=', repr(kwargs))) + try: + self.connection_string = kwargs['connection_string'] % kwargs # insert keyword arguments + except (Exception) as e: + self._raiseConnectionError(KeyError,'Python string format error in connection string->') + self.timeout = kwargs.get('timeout', 30) + self.kwargs = kwargs + if verbose: + print('%s attempting: "%s"' % (version, self.connection_string)) + self.connector = connection_maker() + self.connector.ConnectionTimeout = self.timeout + self.connector.ConnectionString = self.connection_string + + try: + self.connector.Open() # Open the ADO connection + except api.Error: + self._raiseConnectionError(api.DatabaseError, 'ADO error trying to Open=%s' % self.connection_string) + + if getIndexedValue(self.connector.Properties,'Transaction DDL').Value != 0: + self.supportsTransactions=True + self.dbms_name = getIndexedValue(self.connector.Properties,'DBMS Name').Value + self.dbms_version = getIndexedValue(self.connector.Properties,'DBMS Version').Value + self.connector.CursorLocation = defaultCursorLocation #v2.1 Rose + if self.supportsTransactions: + self.connector.IsolationLevel=defaultIsolationLevel + self._autocommit = bool(kwargs.get('autocommit', False)) + if not self._autocommit: + self.transaction_level = self.connector.BeginTrans() #Disables autocommit & inits transaction_level + else: + self._autocommit = True + if 'paramstyle' in kwargs: + self.paramstyle = kwargs['paramstyle'] # let setattr do the error checking + self.messages=[] + if verbose: + print('adodbapi New connection at %X' % id(self)) + + def _raiseConnectionError(self, errorclass, errorvalue): + eh = self.errorhandler + if eh is None: + eh = api.standardErrorHandler + eh(self, None, errorclass, errorvalue) + + def _closeAdoConnection(self): #all v2.1 Rose + """close the underlying ADO Connection object, + rolling it back first if it supports transactions.""" + if self.connector is None: + return + if not self._autocommit: + if self.transaction_level: + try: self.connector.RollbackTrans() + except: pass + self.connector.Close() + if verbose: + print('adodbapi Closed connection at %X' % id(self)) + + def close(self): + """Close the connection now (rather than whenever __del__ is called). + + The connection will be unusable from this point forward; + an Error (or subclass) exception will be raised if any operation is attempted with the connection. + The same applies to all cursor objects trying to use the connection. + """ + for crsr in list(self.cursors.values())[:]: # copy the list, then close each one + crsr.close(dont_tell_me=True) + self.messages=[] + try: + self._closeAdoConnection() #v2.1 Rose + except (Exception) as e: + self._raiseConnectionError(sys.exc_info()[0], sys.exc_info()[1]) + + self.connector = None #v2.4.2.2 fix subtle timeout bug + # per M.Hammond: "I expect the benefits of uninitializing are probably fairly small, + # so never uninitializing will probably not cause any problems." + + def commit(self): + """Commit any pending transaction to the database. + + Note that if the database supports an auto-commit feature, + this must be initially off. An interface method may be provided to turn it back on. + Database modules that do not support transactions should implement this method with void functionality. + """ + self.messages = [] + if not self.supportsTransactions: + return + + try: + self.transaction_level = self.connector.CommitTrans() + if verbose > 1: + print('commit done on connection at %X' % id(self)) + if not (self._autocommit or (self.connector.Attributes & adc.adXactAbortRetaining)): + #If attributes has adXactCommitRetaining it performs retaining commits that is, + #calling CommitTrans automatically starts a new transaction. Not all providers support this. + #If not, we will have to start a new transaction by this command: + self.transaction_level = self.connector.BeginTrans() + except Exception as e: + self._raiseConnectionError(api.ProgrammingError, e) + + def _rollback(self): + """In case a database does provide transactions this method causes the the database to roll back to + the start of any pending transaction. Closing a connection without committing the changes first will + cause an implicit rollback to be performed. + + If the database does not support the functionality required by the method, the interface should + throw an exception in case the method is used. + The preferred approach is to not implement the method and thus have Python generate + an AttributeError in case the method is requested. This allows the programmer to check for database + capabilities using the standard hasattr() function. + + For some dynamically configured interfaces it may not be appropriate to require dynamically making + the method available. These interfaces should then raise a NotSupportedError to indicate the + non-ability to perform the roll back when the method is invoked. + """ + self.messages=[] + if self.transaction_level: # trying to roll back with no open transaction causes an error + try: + self.transaction_level = self.connector.RollbackTrans() + if verbose > 1: + print('rollback done on connection at %X' % id(self)) + if not self._autocommit and not(self.connector.Attributes & adc.adXactAbortRetaining): + #If attributes has adXactAbortRetaining it performs retaining aborts that is, + #calling RollbackTrans automatically starts a new transaction. Not all providers support this. + #If not, we will have to start a new transaction by this command: + if self.transaction_level == 0: + self.transaction_level = self.connector.BeginTrans() + except Exception as e: + self._raiseConnectionError(api.ProgrammingError, e) + + def __setattr__(self, name, value): + if name == 'autocommit': # extension: allow user to turn autocommit on or off + if self.supportsTransactions: + object.__setattr__(self, '_autocommit', bool(value)) + try: self._rollback() # must clear any outstanding transactions + except: pass + return + elif name == 'paramstyle': + if value not in api.accepted_paramstyles: + self._raiseConnectionError(api.NotSupportedError, + 'paramstyle="%s" not in:%s' % (value, repr(api.accepted_paramstyles))) + elif name == 'variantConversions': + value = copy.copy(value) # make a new copy -- no changes in the default, please + object.__setattr__(self, name, value) + + def __getattr__(self, item): + if item == 'rollback': # the rollback method only appears if the database supports transactions + if self.supportsTransactions: + return self._rollback # return the rollback method so the caller can execute it. + else: + raise AttributeError ('this data provider does not support Rollback') + elif item == 'autocommit': + return self._autocommit + else: + raise AttributeError('no such attribute in ADO connection object as="%s"' % item) + + def cursor(self): + "Return a new Cursor Object using the connection." + self.messages = [] + c = Cursor(self) + return c + + def _i_am_here(self, crsr): + "message from a new cursor proclaiming its existence" + i = next(self.cursor_counter) + self.cursors[i] = crsr + crsr.id = i + + def _i_am_closing(self,crsr): + "message from a cursor giving connection a chance to clean up" + try: + del self.cursors[crsr.id] + except: + pass + + def printADOerrors(self): + j=self.connector.Errors.Count + if j: + print('ADO Errors:(%i)' % j) + for e in self.connector.Errors: + print('Description: %s' % e.Description) + print('Error: %s %s ' % (e.Number, adc.adoErrors.get(e.Number, "unknown"))) + if e.Number == adc.ado_error_TIMEOUT: + print('Timeout Error: Try using adodbpi.connect(constr,timeout=Nseconds)') + print('Source: %s' % e.Source) + print('NativeError: %s' % e.NativeError) + print('SQL State: %s' % e.SQLState) + + def _suggest_error_class(self): + """Introspect the current ADO Errors and determine an appropriate error class. + + Error.SQLState is a SQL-defined error condition, per the SQL specification: + http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt + + The 23000 class of errors are integrity errors. + Error 40002 is a transactional integrity error. + """ + if self.connector is not None: + for e in self.connector.Errors: + state = str(e.SQLState) + if state.startswith('23') or state=='40002': + return api.IntegrityError + return api.DatabaseError + + def __del__(self): + try: + self._closeAdoConnection() #v2.1 Rose + except: + pass + self.connector = None + + def __enter__(self): # Connections are context managers + return(self) + + def __exit__(self, exc_type, exc_val, exc_tb): + if exc_type: + self._rollback() #automatic rollback on errors + else: + self.commit() + + def get_table_names(self): + schema = self.connector.OpenSchema(20) # constant = adSchemaTables + + tables = [] + while not schema.EOF: + name = getIndexedValue(schema.Fields,'TABLE_NAME').Value + tables.append(name) + schema.MoveNext() + del schema + return tables + +# # # # # ----- the Class that defines a cursor ----- # # # # # +class Cursor(object): +## ** api required attributes: +## description... +## This read-only attribute is a sequence of 7-item sequences. +## Each of these sequences contains information describing one result column: +## (name, type_code, display_size, internal_size, precision, scale, null_ok). +## This attribute will be None for operations that do not return rows or if the +## cursor has not had an operation invoked via the executeXXX() method yet. +## The type_code can be interpreted by comparing it to the Type Objects specified in the section below. +## rowcount... +## This read-only attribute specifies the number of rows that the last executeXXX() produced +## (for DQL statements like select) or affected (for DML statements like update or insert). +## The attribute is -1 in case no executeXXX() has been performed on the cursor or +## the rowcount of the last operation is not determinable by the interface.[7] +## arraysize... +## This read/write attribute specifies the number of rows to fetch at a time with fetchmany(). +## It defaults to 1 meaning to fetch a single row at a time. +## Implementations must observe this value with respect to the fetchmany() method, +## but are free to interact with the database a single row at a time. +## It may also be used in the implementation of executemany(). +## ** extension attributes: +## paramstyle... +## allows the programmer to override the connection's default paramstyle +## errorhandler... +## allows the programmer to override the connection's default error handler + + def __init__(self,connection): + self.command = None + self._ado_prepared = False + self.messages=[] + self.connection = connection + self.paramstyle = connection.paramstyle # used for overriding the paramstyle + self._parameter_names = [] + self.recordset_is_remote = False + self.rs = None # the ADO recordset for this cursor + self.converters = [] # conversion function for each column + self.columnNames = {} # names of columns {lowercase name : number,...} + self.numberOfColumns = 0 + self._description = None + self.rowcount = -1 + self.errorhandler = connection.errorhandler + self.arraysize = 1 + connection._i_am_here(self) + if verbose: + print('%s New cursor at %X on conn %X' % (version, id(self), id(self.connection))) + + def __iter__(self): # [2.1 Zamarev] + return iter(self.fetchone, None) # [2.1 Zamarev] + + def prepare(self, operation): + self.command = operation + self._description = None + self._ado_prepared = 'setup' + + def __next__(self): + r = self.fetchone() + if r: + return r + raise StopIteration + + def __enter__(self): + "Allow database cursors to be used with context managers." + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + "Allow database cursors to be used with context managers." + self.close() + + def _raiseCursorError(self, errorclass, errorvalue): + eh = self.errorhandler + if eh is None: + eh = api.standardErrorHandler + eh(self.connection, self, errorclass, errorvalue) + + def build_column_info(self, recordset): + self.converters = [] # convertion function for each column + self.columnNames = {} # names of columns {lowercase name : number,...} + self._description = None + + # if EOF and BOF are true at the same time, there are no records in the recordset + if (recordset is None) or (recordset.State == adc.adStateClosed): + self.rs = None + self.numberOfColumns = 0 + return + self.rs = recordset #v2.1.1 bkline + self.recordset_format = api.RS_ARRAY if api.onIronPython else api.RS_WIN_32 + self.numberOfColumns = recordset.Fields.Count + try: + varCon = self.connection.variantConversions + except AttributeError: + varCon = api.variantConversions + for i in range(self.numberOfColumns): + f = getIndexedValue(self.rs.Fields, i) + try: + self.converters.append(varCon[f.Type]) # conversion function for this column + except KeyError: + self._raiseCursorError(api.InternalError, 'Data column of Unknown ADO type=%s' % f.Type) + self.columnNames[f.Name.lower()] = i # columnNames lookup + + def _makeDescriptionFromRS(self): + # Abort if closed or no recordset. + if self.rs is None: + self._description = None + return + desc = [] + for i in range(self.numberOfColumns): + f = getIndexedValue(self.rs.Fields, i) + if self.rs.EOF or self.rs.BOF: + display_size=None + else: + display_size=f.ActualSize #TODO: Is this the correct defintion according to the DB API 2 Spec ? + null_ok= bool(f.Attributes & adc.adFldMayBeNull) #v2.1 Cole + desc.append((f.Name, f.Type, display_size, f.DefinedSize, f.Precision, f.NumericScale, null_ok)) + self._description = desc + + def get_description(self): + if not self._description: + self._makeDescriptionFromRS() + return self._description + + def __getattr__(self, item): + if item == 'description': + return self.get_description() + getattr(self, item) # may get here on Remote attribute calls for existing attributes + + def format_description(self,d): + """Format db_api description tuple for printing.""" + if self.description is None: + self._makeDescriptionFromRS() + if isinstance(d,int): + d = self.description[d] + desc = "Name= %s, Type= %s, DispSize= %s, IntSize= %s, Precision= %s, Scale= %s NullOK=%s" % \ + (d[0], adc.adTypeNames.get(d[1], str(d[1])+' (unknown type)'), + d[2], d[3], d[4], d[5], d[6]) + return desc + + def close(self, dont_tell_me=False): + """Close the cursor now (rather than whenever __del__ is called). + The cursor will be unusable from this point forward; an Error (or subclass) + exception will be raised if any operation is attempted with the cursor. + """ + if self.connection is None: + return + if not dont_tell_me: + self.connection._i_am_closing(self) # take me off the connection's cursors list + self.messages = [] + if self.rs and self.rs.State != adc.adStateClosed: # rs exists and is open #v2.1 Rose + self.rs.Close() #v2.1 Rose + self.rs = None # let go of the recordset so ADO will let it be disposed #v2.1 Rose + self.connection = None #this will make all future method calls on me throw an exception + if verbose: + print('adodbapi Closed cursor at %X' % id(self)) + + def __del__(self): + try: + self.close() + except: + pass + + def _new_command(self, command_text, command_type=adc.adCmdText): + self.cmd = None + self.messages = [] + + if self.connection is None: + self._raiseCursorError(api.InterfaceError, None) + return + try: + self.cmd = Dispatch("ADODB.Command") + self.cmd.ActiveConnection = self.connection.connector + self.cmd.CommandTimeout = self.connection.timeout + self.cmd.CommandType = command_type + self.cmd.CommandText = command_text + self.cmd.Prepared = bool(self._ado_prepared) + except: + self._raiseCursorError(api.DatabaseError, + 'Error creating new ADODB.Command object for "%s"' % repr(command_text)) + + def _execute_command(self): + # Stored procedures may have an integer return value + self.return_value = None + recordset = None + count = -1 #default value + if verbose: + print('Executing command="%s"'%self.command) + try: + # ----- the actual SQL is executed here --- + if api.onIronPython: + ra = Reference[int]() + recordset = self.cmd.Execute(ra) + count = ra.Value + else: #pywin32 + recordset, count = self.cmd.Execute() + # ----- ------------------------------- --- + except (Exception) as e: + _message = "" + if hasattr(e, 'args'): _message += str(e.args)+"\n" + _message += "Command:\n%s\nParameters:\n%s" % (self.cmd.CommandText, + format_parameters(self.cmd.Parameters, True)) + klass = self.connection._suggest_error_class() + self._raiseCursorError(klass, _message) + try: + self.rowcount = recordset.RecordCount + except: + self.rowcount = count + self.build_column_info(recordset) + + # The ADO documentation hints that obtaining the recordcount may be timeconsuming + # "If the Recordset object does not support approximate positioning, this property + # may be a significant drain on resources # [ekelund] + # Therefore, COM will not return rowcount for server-side cursors. [Cole] + # Client-side cursors (the default since v2.8) will force a static + # cursor, and rowcount will then be set accurately [Cole] + def get_rowcount(self): + return self.rowcount + + def get_returned_parameters(self): + """with some providers, returned parameters and the .return_value are not available until + after the last recordset has been read. In that case, you must coll nextset() until it + returns None, then call this method to get your returned information.""" + + retLst=[] # store procedures may return altered parameters, including an added "return value" item + for p in tuple(self.cmd.Parameters): + if verbose > 2: + print('Returned=Name: %s, Dir.: %s, Type: %s, Size: %s, Value: "%s",' \ + " Precision: %s, NumericScale: %s" % \ + (p.Name, adc.directions[p.Direction], + adc.adTypeNames.get(p.Type, str(p.Type)+' (unknown type)'), + p.Size, p.Value, p.Precision, p.NumericScale)) + pyObject = api.convert_to_python(p.Value, api.variantConversions[p.Type]) + if p.Direction == adc.adParamReturnValue: + self.returnValue = pyObject # also load the undocumented attribute (Vernon's Error!) + self.return_value = pyObject + else: + retLst.append(pyObject) + return retLst # return the parameter list to the caller + + def callproc(self, procname, parameters=None): + """Call a stored database procedure with the given name. + The sequence of parameters must contain one entry for each + argument that the sproc expects. The result of the + call is returned as modified copy of the input + sequence. Input parameters are left untouched, output and + input/output parameters replaced with possibly new values. + + The sproc may also provide a result set as output, + which is available through the standard .fetch*() methods. + Extension: A "return_value" property may be set on the + cursor if the sproc defines an integer return value. + """ + self._parameter_names = [] + self._new_command(procname, command_type=adc.adCmdStoredProc) + self._buildADOparameterList(parameters, sproc=True) + if verbose > 2: + print('Calling Stored Proc with Params=', format_parameters(self.cmd.Parameters, True)) + self._execute_command() + return self.get_returned_parameters() + + def _reformat_operation(self, operation, parameters): + if self.paramstyle in ('format', 'pyformat'): # convert %s to ? + operation, self._parameter_names = api.changeFormatToQmark(operation) + elif self.paramstyle == 'named' or (self.paramstyle == 'dynamic' and isinstance(parameters, Mapping)): + operation, self._parameter_names = api.changeNamedToQmark(operation) # convert :name to ? + return operation + + def _buildADOparameterList(self, parameters, sproc=False): + self.parameters = parameters + if parameters is None: + parameters = [] + + parameters_known = False + if sproc: # needed only if we are calling a stored procedure + try: # attempt to use ADO's parameter list + self.cmd.Parameters.Refresh() + if verbose > 2: + print('ADO detected Params=', format_parameters(self.cmd.Parameters, True)) + print('Program Parameters=', repr(parameters)) + parameters_known = True + except api.Error: + if verbose: + print('ADO Parameter Refresh failed') + pass + else: + if len(parameters) != self.cmd.Parameters.Count - 1: + raise api.ProgrammingError('You must supply %d parameters for this stored procedure' % \ + (self.cmd.Parameters.Count - 1)) + if sproc or parameters != []: + i = 0 + if parameters_known: # use ado parameter list + if self._parameter_names: # named parameters + for i, pm_name in enumerate(self._parameter_names): + p = getIndexedValue(self.cmd.Parameters, i) + try: + _configure_parameter(p, parameters[pm_name], p.Type, parameters_known) + except (Exception) as e: + _message = 'Error Converting Parameter %s: %s, %s <- %s\n' % \ + (p.Name, adc.ado_type_name(p.Type), p.Value, repr(parameters[pm_name])) + self._raiseCursorError(api.DataError, _message+'->'+repr(e.args)) + else: # regular sequence of parameters + for value in parameters: + p = getIndexedValue(self.cmd.Parameters,i) + if p.Direction == adc.adParamReturnValue: # this is an extra parameter added by ADO + i += 1 # skip the extra + p=getIndexedValue(self.cmd.Parameters,i) + try: + _configure_parameter(p, value, p.Type, parameters_known) + except (Exception) as e: + _message = 'Error Converting Parameter %s: %s, %s <- %s\n' % \ + (p.Name, adc.ado_type_name(p.Type), p.Value, repr(value)) + self._raiseCursorError(api.DataError, _message+'->'+repr(e.args)) + i += 1 + else: #-- build own parameter list + if self._parameter_names: # we expect a dictionary of parameters, this is the list of expected names + for parm_name in self._parameter_names: + elem = parameters[parm_name] + adotype = api.pyTypeToADOType(elem) + p = self.cmd.CreateParameter(parm_name, adotype, adc.adParamInput) + _configure_parameter(p, elem, adotype, parameters_known) + try: + self.cmd.Parameters.Append(p) + except (Exception) as e: + _message = 'Error Building Parameter %s: %s, %s <- %s\n' % \ + (p.Name, adc.ado_type_name(p.Type), p.Value, repr(elem)) + self._raiseCursorError(api.DataError, _message+'->'+repr(e.args)) + else : # expecting the usual sequence of parameters + if sproc: + p = self.cmd.CreateParameter('@RETURN_VALUE', adc.adInteger, adc.adParamReturnValue) + self.cmd.Parameters.Append(p) + + for elem in parameters: + name='p%i' % i + adotype = api.pyTypeToADOType(elem) + p=self.cmd.CreateParameter(name, adotype, adc.adParamInput) # Name, Type, Direction, Size, Value + _configure_parameter(p, elem, adotype, parameters_known) + try: + self.cmd.Parameters.Append(p) + except (Exception) as e: + _message = 'Error Building Parameter %s: %s, %s <- %s\n' % \ + (p.Name, adc.ado_type_name(p.Type), p.Value, repr(elem)) + self._raiseCursorError(api.DataError, _message+'->'+repr(e.args)) + i += 1 + if self._ado_prepared == 'setup': + self._ado_prepared = True # parameters will be known next loop + + def execute(self, operation, parameters=None): + """Prepare and execute a database operation (query or command). + + Parameters may be provided as sequence or mapping and will be bound to variables in the operation. + Variables are specified in a database-specific notation + (see the module's paramstyle attribute for details). [5] + A reference to the operation will be retained by the cursor. + If the same operation object is passed in again, then the cursor + can optimize its behavior. This is most effective for algorithms + where the same operation is used, but different parameters are bound to it (many times). + + For maximum efficiency when reusing an operation, it is best to use + the setinputsizes() method to specify the parameter types and sizes ahead of time. + It is legal for a parameter to not match the predefined information; + the implementation should compensate, possibly with a loss of efficiency. + + The parameters may also be specified as list of tuples to e.g. insert multiple rows in + a single operation, but this kind of usage is depreciated: executemany() should be used instead. + + Return value is not defined. + + [5] The module will use the __getitem__ method of the parameters object to map either positions + (integers) or names (strings) to parameter values. This allows for both sequences and mappings + to be used as input. + The term "bound" refers to the process of binding an input value to a database execution buffer. + In practical terms, this means that the input value is directly used as a value in the operation. + The client should not be required to "escape" the value so that it can be used -- the value + should be equal to the actual database value. """ + if self.command is not operation or self._ado_prepared == 'setup': + if self.command is not operation: + self._ado_prepared = False + self.command = operation + self._parameter_names = [] + if parameters and self.paramstyle != 'qmark': + operation = self._reformat_operation(operation, parameters) # if 'named' will set self._parameter_names + self._new_command(operation) + self._buildADOparameterList(parameters) + if verbose > 3: + print('Params=', format_parameters(self.cmd.Parameters, True)) + self._execute_command() + + def executemany(self, operation, seq_of_parameters): + """Prepare a database operation (query or command) + and then execute it against all parameter sequences or mappings found in the sequence seq_of_parameters. + + Return values are not defined. + """ + self.messages = list() + total_recordcount = 0 + + self.prepare(operation) + for params in seq_of_parameters: + self.execute(self.command, params) + if self.rowcount == -1: + total_recordcount = -1 + if total_recordcount != -1: + total_recordcount += self.rowcount + self.rowcount = total_recordcount + + def _fetch(self, limit=None): + """Fetch rows from the current recordset. + + limit -- Number of rows to fetch, or None (default) to fetch all rows. + """ + if self.connection is None or self.rs is None: + self._raiseCursorError(api.FetchFailedError, 'fetch() on closed connection or empty query set') + return + + if self.rs.State == adc.adStateClosed or self.rs.BOF or self.rs.EOF: + return list() + if limit: # limit number of rows retrieved + ado_results = self.rs.GetRows(limit) + else: # get all rows + ado_results = self.rs.GetRows() + if self.recordset_format == api.RS_ARRAY: # result of GetRows is a two-dimension array + length = len(ado_results) // self.numberOfColumns # length of first dimension + else: #pywin32 + length = len(ado_results[0]) #result of GetRows is tuples in a tuple + fetchObject = api.SQLrows(ado_results, length, self) # new object to hold the results of the fetch + return fetchObject + + def fetchone(self): + """ Fetch the next row of a query result set, returning a single sequence, + or None when no more data is available. + + An Error (or subclass) exception is raised if the previous call to executeXXX() + did not produce any result set or no call was issued yet. + """ + self.messages = [] + result = self._fetch(1) + if result: # return record (not list of records) + return result[0] + return None + + def fetchmany(self, size=None): + """Fetch the next set of rows of a query result, returning a list of tuples. An empty sequence is returned when no more rows are available. + + The number of rows to fetch per call is specified by the parameter. + If it is not given, the cursor's arraysize determines the number of rows to be fetched. + The method should try to fetch as many rows as indicated by the size parameter. + If this is not possible due to the specified number of rows not being available, + fewer rows may be returned. + + An Error (or subclass) exception is raised if the previous call to executeXXX() + did not produce any result set or no call was issued yet. + + Note there are performance considerations involved with the size parameter. + For optimal performance, it is usually best to use the arraysize attribute. + If the size parameter is used, then it is best for it to retain the same value from + one fetchmany() call to the next. + """ + self.messages=[] + if size is None: + size = self.arraysize + return self._fetch(size) + + def fetchall(self): + """Fetch all (remaining) rows of a query result, returning them as a sequence of sequences (e.g. a list of tuples). + + Note that the cursor's arraysize attribute + can affect the performance of this operation. + An Error (or subclass) exception is raised if the previous call to executeXXX() + did not produce any result set or no call was issued yet. + """ + self.messages=[] + return self._fetch() + + def nextset(self): + """Skip to the next available recordset, discarding any remaining rows from the current recordset. + + If there are no more sets, the method returns None. Otherwise, it returns a true + value and subsequent calls to the fetch methods will return rows from the next result set. + + An Error (or subclass) exception is raised if the previous call to executeXXX() + did not produce any result set or no call was issued yet. + """ + self.messages=[] + if self.connection is None or self.rs is None: + self._raiseCursorError(api.OperationalError, ('nextset() on closed connection or empty query set')) + return None + + if api.onIronPython: + try: + recordset = self.rs.NextRecordset() + except TypeError: + recordset = None + except api.Error as exc: + self._raiseCursorError(api.NotSupportedError, exc.args) + else: #pywin32 + try: #[begin 2.1 ekelund] + rsTuple=self.rs.NextRecordset() # + except pywintypes.com_error as exc: # return appropriate error + self._raiseCursorError(api.NotSupportedError, exc.args)#[end 2.1 ekelund] + recordset = rsTuple[0] + if recordset is None: + return None + self.build_column_info(recordset) + return True + + def setinputsizes(self,sizes): + pass + + def setoutputsize(self, size, column=None): + pass + + def _last_query(self): # let the programmer see what query we actually used + try: + if self.parameters == None: + ret = self.cmd.CommandText + else: + ret = "%s,parameters=%s" % (self.cmd.CommandText,repr(self.parameters)) + except: + ret = None + return ret + query = property(_last_query, None, None, + "returns the last query executed") + +if __name__ == '__main__': + raise api.ProgrammingError(version + ' cannot be run as a main program.') diff --git a/Lib/site-packages/adodbapi/examples/db_print.py b/Lib/site-packages/adodbapi/examples/db_print.py new file mode 100644 index 0000000..338c042 --- /dev/null +++ b/Lib/site-packages/adodbapi/examples/db_print.py @@ -0,0 +1,70 @@ +""" db_print.py -- a simple demo for ADO database reads.""" +from __future__ import with_statement #needed for Python 2.5 + +import sys +import adodbapi.ado_consts as adc + +cmd_args = ('proxy_host', 'proxy_port', 'filename', 'table_name') +if 'help' in sys.argv: + print(('possible settings keywords are:',cmd_args)) + sys.exit() + +kw_args = {} # pick up filename and proxy address from command line (optionally) +for arg in sys.argv: + s = arg.split("=") + if len(s) > 1: + if s[0] in cmd_args: + kw_args[s[0]] = s[1] + +kw_args.setdefault('filename', "test.mdb") # assumes server is running from examples folder +kw_args.setdefault('table_name', 'Products') # the name of the demo table + +# the server needs to select the provider based on his Python installation +provider_switch = ['provider', 'Microsoft.ACE.OLEDB.12.0', "Microsoft.Jet.OLEDB.4.0"] + +# ------------------------ START HERE ------------------------------------- +#create the connection +constr = "Provider=%(provider)s;Data Source=%(filename)s" +if 'proxy_host' in kw_args: + import adodbapi.remote as db +else: + import adodbapi as db +con = db.connect(constr, kw_args, macro_is64bit=provider_switch) + +if kw_args['table_name'] == '?': + print('The tables in your database are:') + for name in con.get_table_names(): + print(name) +else: +#make a cursor on the connection + with con.cursor() as c: + + #run an SQL statement on the cursor + sql = 'select * from %s' % kw_args['table_name'] + print(('performing query="%s"' % sql)) + c.execute(sql) + + #check the results + print(('result rowcount shows as= %d. (Note: -1 means "not known")' \ + % (c.rowcount,))) + print('') + print('result data description is:') + print(' NAME Type DispSize IntrnlSz Prec Scale Null?') + for d in c.description: + print((('%16s %-12s %8s %8d %4d %5d %s') % \ + (d[0], adc.adTypeNames[d[1]], d[2], d[3], d[4],d[5], bool(d[6])))) + print('') + print('str() of first five records are...') + + #get the results + db = c.fetchmany(5) + + #print them + for rec in db: + print(rec) + + print('') + print('repr() of next row is...') + print((repr(c.fetchone()))) + print('') +con.close() diff --git a/Lib/site-packages/adodbapi/examples/db_table_names.py b/Lib/site-packages/adodbapi/examples/db_table_names.py new file mode 100644 index 0000000..f93de0e --- /dev/null +++ b/Lib/site-packages/adodbapi/examples/db_table_names.py @@ -0,0 +1,19 @@ +""" db_table_names.py -- a simple demo for ADO database table listing.""" +import sys +import adodbapi + +try: + databasename = sys.argv[1] +except IndexError: + databasename = "test.mdb" + +provider = ['prv', "Microsoft.ACE.OLEDB.12.0", "Microsoft.Jet.OLEDB.4.0"] +constr = "Provider=%(prv)s;Data Source=%(db)s" + +#create the connection +con = adodbapi.connect(constr, db=databasename, macro_is64bit=provider) + +print(('Table names in= %s' % databasename)) + +for table in con.get_table_names(): + print(table) diff --git a/Lib/site-packages/adodbapi/examples/xls_read.py b/Lib/site-packages/adodbapi/examples/xls_read.py new file mode 100644 index 0000000..59fdba5 --- /dev/null +++ b/Lib/site-packages/adodbapi/examples/xls_read.py @@ -0,0 +1,38 @@ +import sys +import adodbapi +try: + import adodbapi.is64bit as is64bit + is64 = is64bit.Python() +except ImportError: + is64 = False + +if is64: + driver = "Microsoft.ACE.OLEDB.12.0" +else: + driver = "Microsoft.Jet.OLEDB.4.0" +extended = 'Extended Properties="Excel 8.0;HDR=Yes;IMEX=1;"' + +try: # first command line argument will be xls file name -- default to the one written by xls_write.py + filename = sys.argv[1] +except IndexError: + filename = 'xx.xls' + +constr = "Provider=%s;Data Source=%s;%s" % (driver, filename, extended) + +conn = adodbapi.connect(constr) + +try: # second command line argument will be worksheet name -- default to first worksheet + sheet = sys.argv[2] +except IndexError: + # use ADO feature to get the name of the first worksheet + sheet = conn.get_table_names()[0] + +print(('Shreadsheet=%s Worksheet=%s' % (filename, sheet))) +print('------------------------------------------------------------') +crsr = conn.cursor() +sql = "SELECT * from [%s]" % sheet +crsr.execute(sql) +for row in crsr.fetchmany(10): + print((repr(row))) +crsr.close() +conn.close() diff --git a/Lib/site-packages/adodbapi/examples/xls_write.py b/Lib/site-packages/adodbapi/examples/xls_write.py new file mode 100644 index 0000000..66ca5b2 --- /dev/null +++ b/Lib/site-packages/adodbapi/examples/xls_write.py @@ -0,0 +1,32 @@ +from __future__ import with_statement # needed only if running Python 2.5 +import adodbapi +try: + import adodbapi.is64bit as is64bit + is64 = is64bit.Python() +except ImportError: + is64 = False # in case the user has an old version of adodbapi +if is64: + driver = "Microsoft.ACE.OLEDB.12.0" +else: + driver = "Microsoft.Jet.OLEDB.4.0" +filename = 'xx.xls' # file will be created if it does not exist +extended = 'Extended Properties="Excel 8.0;Readonly=False;"' + +constr = "Provider=%s;Data Source=%s;%s" % (driver, filename, extended) + +conn = adodbapi.connect(constr) +with conn: # will auto commit if no errors + with conn.cursor() as crsr: + try: crsr.execute('drop table SheetOne') + except: pass # just is case there is one already there + + # create the sheet and the header row and set the types for the columns + crsr.execute('create table SheetOne (Header1 text, Header2 text, Header3 text, Header4 text, Header5 text)') + + sql = "INSERT INTO SheetOne (Header1, Header2 ,Header3, Header4, Header5) values (?,?,?,?,?)" + + data = (1, 2, 3, 4, 5) + crsr.execute(sql, data) # write the first row of data + crsr.execute(sql, (6, 7, 8, 9, 10)) # another row of data +conn.close() +print(('Created spreadsheet=%s worksheet=%s' % (filename, 'SheetOne'))) diff --git a/Lib/site-packages/adodbapi/is64bit.py b/Lib/site-packages/adodbapi/is64bit.py new file mode 100644 index 0000000..bb60360 --- /dev/null +++ b/Lib/site-packages/adodbapi/is64bit.py @@ -0,0 +1,33 @@ +"""is64bit.Python() --> boolean value of detected Python word size. is64bit.os() --> os build version""" +import sys + +def Python(): + if sys.platform == 'cli': #IronPython + import System + return System.IntPtr.Size == 8 + else: + try: + return sys.maxsize > 2147483647 + except AttributeError: + return sys.maxint > 2147483647 + +def os(): + import platform + pm = platform.machine() + if pm != '..' and pm.endswith('64'): # recent Python (not Iron) + return True + else: + import os + if 'PROCESSOR_ARCHITEW6432' in os.environ: + return True # 32 bit program running on 64 bit Windows + try: + return os.environ['PROCESSOR_ARCHITECTURE'].endswith('64') # 64 bit Windows 64 bit program + except IndexError: + pass # not Windows + try: + return '64' in platform.architecture()[0] # this often works in Linux + except: + return False # is an older version of Python, assume also an older os (best we can guess) + +if __name__ == "__main__": + print(("is64bit.Python() =", Python(), "is64bit.os() =", os())) diff --git a/Lib/site-packages/adodbapi/license.txt b/Lib/site-packages/adodbapi/license.txt new file mode 100644 index 0000000..c255f4a --- /dev/null +++ b/Lib/site-packages/adodbapi/license.txt @@ -0,0 +1,506 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + diff --git a/Lib/site-packages/adodbapi/readme.txt b/Lib/site-packages/adodbapi/readme.txt new file mode 100644 index 0000000..23cdf39 --- /dev/null +++ b/Lib/site-packages/adodbapi/readme.txt @@ -0,0 +1,92 @@ +Project +------- +adodbapi + +A Python DB-API 2.0 (PEP-249) module that makes it easy to use Microsoft ADO +for connecting with databases and other data sources +using either CPython or IronPython. + +Home page: + +Features: +* 100% DB-API 2.0 (PEP-249) compliant (including most extensions and recommendations). +* Includes pyunit testcases that describe how to use the module. +* Fully implemented in Python. -- runs in Python 2.5+ Python 3.0+ and IronPython 2.6+ +* Licensed under the LGPL license, which means that it can be used freely even in commercial programs subject to certain restrictions. +* Includes SERVER and REMOTE modules so that a Windows proxy can serve ADO databases to a Linux client using PyRO. +* The user can choose between paramstyles: 'qmark' 'named' 'format' 'pyformat' 'dynamic' +* Supports data retrieval by column name e.g.: + for row in myCurser.execute("select name,age from students"): + print("Student", row.name, "is", row.age, "years old.") +* Supports user-definable system-to-Python data conversion functions (selected by ADO data type, or by column) + +Prerequisites: +* C Python 2.5 or higher + and pywin32 (Mark Hammond's python for windows extensions.) +or + Iron Python 2.6 or higher. (works in IPy2.0 for all data types except BUFFER) + +Installation: +* (C-Python on Windows): Download pywin32 from http://sf.net/projects/pywin32 and install from .msi (adodbapi is included) +* ((to use Windows as a server, also download and install Pyro4 (requires Python 2.6 or later))) https://pypi.python.org/pypi/Pyro4 +* (IronPython on Windows): Download adodbapi from http://sf.net/projects/adodbapi. Unpack the zip. + Open a command window as an administrator. CD to the folder containing the unzipped files. + Run "setup.py install" using the IronPython of your choice. +* (Linux, as a client): download and install from PyPi: "pip install adodbapi Pyro4" + +NOTE: ........... +If you do not like the new default operation of returning Numeric columns as decimal.Decimal, +you can select other options by the user defined conversion feature. +Try: + adodbapi.apibase.variantConversions[adodbapi.ado_consts.adNumeric] = adodbapi.apibase.cvtString +or: + adodbapi.apibase.variantConversions[adodbapi.ado_consts.adNumeric] = adodbapi.apibase.cvtFloat +or: + adodbapi.apibase.variantConversions[adodbapi.ado_consts.adNumeric] = write_your_own_convertion_function + ............ +whats new in version 2.6 + A cursor.prepare() method and support for prepared SQL statements. + Lots of refactoring, especially of the Remote and Server modules (still to be treated as Beta code). + The quick start document 'quick_reference.odt' will export as a nice-looking pdf. + Added paramstyles 'pyformat' and 'dynamic'. If your 'paramstyle' is 'named' you _must_ pass a dictionary of + parameters to your .execute() method. If your 'paramstyle' is 'format' 'pyformat' or 'dynamic', you _may_ + pass a dictionary of parameters -- provided your SQL operation string is formatted correctly. + +whats new in version 2.5 + Remote module: (works on Linux!) allows a Windows computer to serve ADO databases via PyRO + Server module: PyRO server for ADO. Run using a command like= C:>python -m adodbapi.server + (server has simple connection string macros: is64bit, getuser, sql_provider, auto_security) + Brief documentation included. See adodbapi/examples folder adodbapi.rtf + New connection method conn.get_table_names() --> list of names of tables in database + + Vastly refactored. Data conversion things have been moved to the new adodbapi.apibase module. + Many former module-level attributes are now class attributes. (Should be more thread-safe) + Connection objects are now context managers for transactions and will commit or rollback. + Cursor objects are context managers and will automatically close themselves. + Autocommit can be switched on and off. + Keyword and positional arguments on the connect() method work as documented in PEP 249. + Keyword arguments from the connect call can be formatted into the connection string. + New keyword arguments defined, such as: autocommit, paramstyle, remote_proxy, remote_port. + *** Breaking change: variantConversion lookups are simplified: the following will raise KeyError: + oldconverter=adodbapi.variantConversions[adodbapi.adoStringTypes] + Refactor as: oldconverter=adodbapi.variantConversions[adodbapi.adoStringTypes[0]] + +(( More information like this in older_whatsnew.txt )) + +License +------- +LGPL, see http://www.opensource.org/licenses/lgpl-license.php + +Documentation +------------- +Start with: + +http://www.python.org/topics/database/DatabaseAPI-2.0.html +read the examples in adodbapi/examples +and look at the test cases in adodbapi/test directory. + +Mailing lists +------------- +The adodbapi mailing lists have been deactivated. Submit comments to the +pywin32 or IronPython mailing lists. + -- the bug tracker on sourceforge.net/projects/adodbapi will be checked, (infrequently). diff --git a/Lib/site-packages/adodbapi/schema_table.py b/Lib/site-packages/adodbapi/schema_table.py new file mode 100644 index 0000000..5667b9c --- /dev/null +++ b/Lib/site-packages/adodbapi/schema_table.py @@ -0,0 +1,14 @@ +"""call using an open ADO connection --> list of table names""" +from . import adodbapi + +def names(connection_object): + ado = connection_object.adoConn + schema = ado.OpenSchema(20) # constant = adSchemaTables + + tables = [] + while not schema.EOF: + name = adodbapi.getIndexedValue(schema.Fields,'TABLE_NAME').Value + tables.append(name) + schema.MoveNext() + del schema + return tables diff --git a/Lib/site-packages/adodbapi/test/adodbapitest.py b/Lib/site-packages/adodbapi/test/adodbapitest.py new file mode 100644 index 0000000..637c3ce --- /dev/null +++ b/Lib/site-packages/adodbapi/test/adodbapitest.py @@ -0,0 +1,1348 @@ +""" Unit tests version 2.6.0.6 for adodbapi""" +from __future__ import with_statement +# when Python 2.5 is retired, change that to: from __future__ import print_function +""" + adodbapi - A python DB API 2.0 interface to Microsoft ADO + + Copyright (C) 2002 Henrik Ekelund + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Updates by Vernon Cole +""" + +import unittest +import sys +import datetime +import decimal +import copy + +try: + import win32com.client + win32 = True +except ImportError: + win32 = False + +# run the configuration module. +import adodbapitestconfig as config # will set sys.path to find correct version of adodbapi +# in our code below, all our switches are from config.whatever + +import adodbapi +import adodbapi.apibase as api + + +try: + import adodbapi.ado_consts as ado_consts +except ImportError: #we are doing a shortcut import as a module -- so + try: + import ado_consts + except ImportError: + from adodbapi import ado_consts + +if sys.version_info >= (3,0): + import tryconnection3 as tryconnection + def str2bytes(sval): + return sval.encode("latin1") + str = str + long = int +else: + import tryconnection2 as tryconnection + def str2bytes(sval): + if isinstance(sval, str): + return sval + return sval.encode("latin1") +try: + bytes +except NameError: + bytes = str + +class CommonDBTests(unittest.TestCase): + "Self contained super-simple tests in easy syntax, should work on everything between mySQL and Oracle" + + def setUp(self): + self.engine = 'unknown' + + def getEngine(self): + return self.engine + + def getConnection(self): + raise NotImplementedError #"This method must be overriden by a subclass" + + def getCursor(self): + return self.getConnection().cursor() + + def testConnection(self): + crsr=self.getCursor() + assert crsr.__class__.__name__ == 'Cursor' + + def testErrorHandlerInherits(self): + if not self.remote: + conn=self.getConnection() + mycallable=lambda connection,cursor,errorclass,errorvalue: 1 + conn.errorhandler=mycallable + crsr=conn.cursor() + assert crsr.errorhandler==mycallable,"Error handler on crsr should be same as on connection" + + def testDefaultErrorHandlerConnection(self): + if not self.remote: + conn=self.getConnection() + del conn.messages[:] + try: + conn.close() + conn.commit() #Should not be able to use connection after it is closed + except: + assert len(conn.messages)==1 + assert len(conn.messages[0])==2 + assert conn.messages[0][0]==api.ProgrammingError + + def testOwnErrorHandlerConnection(self): + if self.remote: # ToDo: use "skip" + return + mycallable=lambda connection,cursor,errorclass,errorvalue: 1 #does not raise anything + conn=self.getConnection() + conn.errorhandler=mycallable + conn.close() + conn.commit() #Should not be able to use connection after it is closed + assert len(conn.messages)==0 + + conn.errorhandler=None #This should bring back the standard error handler + try: + conn.close() + conn.commit() #Should not be able to use connection after it is closed + except: + pass + #The Standard errorhandler appends error to messages attribute + assert len(conn.messages)>0,"Setting errorhandler to none should bring back the standard error handler" + + + def testDefaultErrorHandlerCursor(self): + crsr=self.getConnection().cursor() + if not self.remote: + del crsr.messages[:] + try: + crsr.execute("SELECT abbtytddrf FROM dasdasd") + except: + assert len(crsr.messages)==1 + assert len(crsr.messages[0])==2 + assert crsr.messages[0][0]==api.DatabaseError + + def testOwnErrorHandlerCursor(self): + if self.remote: # ToDo: should be a "skip" + return + mycallable=lambda connection,cursor,errorclass,errorvalue: 1 #does not raise anything + crsr=self.getConnection().cursor() + crsr.errorhandler=mycallable + crsr.execute("SELECT abbtytddrf FROM dasdasd") + assert len(crsr.messages)==0 + + crsr.errorhandler=None #This should bring back the standard error handler + try: + crsr.execute("SELECT abbtytddrf FROM dasdasd") + except: + pass + #The Standard errorhandler appends error to messages attribute + assert len(crsr.messages)>0,"Setting errorhandler to none should bring back the standard error handler" + + + def testUserDefinedConversions(self): + if self.remote: ## Todo: should be a "skip" + return + try: + duplicatingConverter=lambda aStringField: aStringField*2 + assert duplicatingConverter('gabba') == 'gabbagabba' + + self.helpForceDropOnTblTemp() + conn=self.getConnection() + # the variantConversions attribute should not exist on a normal connection object + self.assertRaises(AttributeError, lambda x:conn.variantConversions[x],[2]) + if not self.remote: + # create a variantConversions attribute on the connection + conn.variantConversions = copy.copy(api.variantConversions) + crsr=conn.cursor() + tabdef = "CREATE TABLE xx_%s (fldData VARCHAR(100) NOT NULL, fld2 VARCHAR(20))" % config.tmp + crsr.execute(tabdef) + crsr.execute("INSERT INTO xx_%s(fldData,fld2) VALUES('gabba','booga')" % config.tmp) + crsr.execute("INSERT INTO xx_%s(fldData,fld2) VALUES('hey','yo')" % config.tmp) + # change converter for ALL adoStringTypes columns + conn.variantConversions[api.adoStringTypes]=duplicatingConverter + crsr.execute("SELECT fldData,fld2 FROM xx_%s ORDER BY fldData" % config.tmp) + + rows=crsr.fetchall() + row = rows[0] + self.assertEquals(row[0],'gabbagabba') + row = rows[1] + self.assertEquals(row[0],'heyhey') + self.assertEquals(row[1],'yoyo') + + upcaseConverter=lambda aStringField: aStringField.upper() + assert upcaseConverter('upThis') == 'UPTHIS' + + # now use a single column converter + rows.converters[1] = upcaseConverter # convert second column + self.assertEquals(row[0],'heyhey') # first will be unchanged + self.assertEquals(row[1],'YO') # second will convert to upper case + + finally: + try: + del conn.variantConversions #Restore the default + except: pass + self.helpRollbackTblTemp() + + def testUserDefinedConversionForExactNumericTypes(self): + # variantConversions is a dictionary of conversion functions + # held internally in adodbapi.apibase + # + # !!! this test intentionally alters the value of what should be constant in the module + # !!! no new code should use this example, to is only a test to see that the + # !!! deprecated way of doing this still works. (use connection.variantConversions) + # + if not self.remote and sys.version_info < (3,0): ### Py3 need different test + oldconverter = adodbapi.variantConversions[ado_consts.adNumeric] #keep old function to restore later + # By default decimal and "numbers" are returned as decimals. + # Instead, make numbers return as floats + try: + adodbapi.variantConversions[ado_consts.adNumeric] = adodbapi.cvtFloat + self.helpTestDataType("decimal(18,2)",'NUMBER',3.45,compareAlmostEqual=1) + self.helpTestDataType("numeric(18,2)",'NUMBER',3.45,compareAlmostEqual=1) + # now return strings + adodbapi.variantConversions[ado_consts.adNumeric] = adodbapi.cvtString + self.helpTestDataType("numeric(18,2)",'NUMBER','3.45') + # now a completly weird user defined convertion + adodbapi.variantConversions[ado_consts.adNumeric] = lambda x: '!!This function returns a funny unicode string %s!!'%x + self.helpTestDataType("numeric(18,2)",'NUMBER','3.45', + allowedReturnValues=['!!This function returns a funny unicode string 3.45!!']) + finally: + # now reset the converter to its original function + adodbapi.variantConversions[ado_consts.adNumeric]=oldconverter #Restore the original convertion function + + def helpTestDataType(self,sqlDataTypeString, + DBAPIDataTypeString, + pyData, + pyDataInputAlternatives=None, + compareAlmostEqual=None, + allowedReturnValues=None): + self.helpForceDropOnTblTemp() + conn=self.getConnection() + crsr=conn.cursor() + tabdef= """ + CREATE TABLE xx_%s ( + fldId integer NOT NULL, + fldData """ % config.tmp + sqlDataTypeString + ")\n" + + crsr.execute(tabdef) + + #Test Null values mapped to None + crsr.execute("INSERT INTO xx_%s (fldId) VALUES (1)" % config.tmp) + + crsr.execute("SELECT fldId,fldData FROM xx_%s" % config.tmp) + rs=crsr.fetchone() + self.assertEquals(rs[1],None) #Null should be mapped to None + assert rs[0]==1 + + #Test description related + descTuple=crsr.description[1] + assert descTuple[0] in ['fldData','flddata'], 'was "%s" expected "%s"'%(descTuple[0],'fldData') + + if DBAPIDataTypeString=='STRING': + assert descTuple[1] == api.STRING, 'was "%s" expected "%s"'%(descTuple[1],api.STRING.values) + elif DBAPIDataTypeString == 'NUMBER': + assert descTuple[1] == api.NUMBER, 'was "%s" expected "%s"'%(descTuple[1],api.NUMBER.values) + elif DBAPIDataTypeString == 'BINARY': + assert descTuple[1] == api.BINARY, 'was "%s" expected "%s"'%(descTuple[1],api.BINARY.values) + elif DBAPIDataTypeString == 'DATETIME': + assert descTuple[1] == api.DATETIME, 'was "%s" expected "%s"'%(descTuple[1],api.DATETIME.values) + elif DBAPIDataTypeString == 'ROWID': + assert descTuple[1] == api.ROWID, 'was "%s" expected "%s"'%(descTuple[1],api.ROWID.values) + elif DBAPIDataTypeString == 'UUID': + assert descTuple[1] == api.OTHER, 'was "%s" expected "%s"'%(descTuple[1],api.OTHER.values) + else: + raise NotImplementedError #"DBAPIDataTypeString not provided" + + #Test data binding + inputs=[pyData] + if pyDataInputAlternatives: + inputs.extend(pyDataInputAlternatives) + if str is str: + inputs = set(inputs) # removes redundant string==unicode tests + fldId=1 + for inParam in inputs: + fldId+=1 + try: + crsr.execute("INSERT INTO xx_%s (fldId,fldData) VALUES (?,?)" % config.tmp, (fldId, inParam)) + except: + if self.remote: + for message in crsr.messages: + print(message) + else: + conn.printADOerrors() + raise + crsr.execute("SELECT fldData FROM xx_%s WHERE ?=fldID" % config.tmp, [fldId]) + rs=crsr.fetchone() + if allowedReturnValues: + allowedTypes = tuple([type(aRV) for aRV in allowedReturnValues]) + assert isinstance(rs[0],allowedTypes), \ + 'result type "%s" must be one of %s'%(type(rs[0]),allowedTypes) + else: + assert isinstance(rs[0] ,type(pyData)), \ + 'result type "%s" must be instance of %s'%(type(rs[0]),type(pyData)) + + if compareAlmostEqual and DBAPIDataTypeString == 'DATETIME': + iso1=adodbapi.dateconverter.DateObjectToIsoFormatString(rs[0]) + iso2=adodbapi.dateconverter.DateObjectToIsoFormatString(pyData) + self.assertEquals(iso1, iso2) + elif compareAlmostEqual: + s = float(pyData) + v = float(rs[0]) + assert abs(v-s)/s < 0.00001, \ + "Values not almost equal recvd=%s, expected=%f" %(rs[0],s) + else: + if allowedReturnValues: + ok=False + self.assertTrue(rs[0] in allowedReturnValues, + 'Value "%s" not in %s' % (repr(rs[0]), allowedReturnValues)) + else: + self.assertEquals(rs[0], pyData, + 'Values are not equal recvd="%s", expected="%s"' %(rs[0],pyData)) + + def testDataTypeFloat(self): + self.helpTestDataType("real",'NUMBER',3.45,compareAlmostEqual=True) + self.helpTestDataType("float",'NUMBER',1.79e37,compareAlmostEqual=True) + + def testDataTypeDecmal(self): + self.helpTestDataType("decimal(18,2)",'NUMBER',3.45, + allowedReturnValues=['3.45','3,45',decimal.Decimal('3.45')]) + self.helpTestDataType("numeric(18,2)",'NUMBER',3.45, + allowedReturnValues=['3.45','3,45',decimal.Decimal('3.45')]) + self.helpTestDataType("decimal(20,2)",'NUMBER',444444444444444444, + allowedReturnValues=['444444444444444444.00', '444444444444444444,00', + decimal.Decimal('444444444444444444')]) + if self.getEngine() == 'MSSQL': + self.helpTestDataType("uniqueidentifier",'UUID','{71A4F49E-39F3-42B1-A41E-48FF154996E6}', + allowedReturnValues=['{71A4F49E-39F3-42B1-A41E-48FF154996E6}']) + + def testDataTypeMoney(self): #v2.1 Cole -- use decimal for money + if self.getEngine() == 'MySQL': + self.helpTestDataType("DECIMAL(20,4)",'NUMBER',decimal.Decimal('-922337203685477.5808')) + elif self.getEngine() == 'PostgreSQL': + self.helpTestDataType("money",'NUMBER',decimal.Decimal('-922337203685477.5808'), + compareAlmostEqual=True, + allowedReturnValues=[-922337203685477.5808, + decimal.Decimal('-922337203685477.5808')]) + else: + self.helpTestDataType("smallmoney",'NUMBER',decimal.Decimal('214748.02')) + self.helpTestDataType("money",'NUMBER',decimal.Decimal('-922337203685477.5808')) + + def testDataTypeInt(self): + if self.getEngine() != 'PostgreSQL': + self.helpTestDataType("tinyint",'NUMBER',115) + self.helpTestDataType("smallint",'NUMBER',-32768) + if self.getEngine() not in ['ACCESS','PostgreSQL']: + self.helpTestDataType("bit",'NUMBER',1) #Does not work correctly with access + if self.getEngine() in ['MSSQL','PostgreSQL']: + self.helpTestDataType("bigint",'NUMBER',3000000000, + allowedReturnValues=[3000000000, int(3000000000)]) + self.helpTestDataType("int",'NUMBER',2147483647) + + def testDataTypeChar(self): + for sqlDataType in ("char(6)","nchar(6)"): + self.helpTestDataType(sqlDataType,'STRING','spam ',allowedReturnValues=['spam','spam','spam ','spam ']) + + def testDataTypeVarChar(self): + if self.getEngine() == 'MySQL': + stringKinds = ["varchar(10)","text"] + elif self.getEngine() == 'PostgreSQL': + stringKinds = ["varchar(10)","text","character varying"] + else: + stringKinds = ["varchar(10)","nvarchar(10)","text","ntext"] #,"varchar(max)"] + + for sqlDataType in stringKinds: + self.helpTestDataType(sqlDataType,'STRING','spam',['spam']) + + def testDataTypeDate(self): + if self.getEngine() == 'PostgreSQL': + dt = "timestamp" + else: + dt = "datetime" + self.helpTestDataType(dt,'DATETIME',adodbapi.Date(2002,10,28), + compareAlmostEqual=True) + if self.getEngine() not in ['MySQL','PostgreSQL']: + self.helpTestDataType("smalldatetime",'DATETIME',adodbapi.Date(2002,10,28), + compareAlmostEqual=True) + if tag != 'pythontime' and self.getEngine() not in ['MySQL','PostgreSQL']: # fails when using pythonTime + self.helpTestDataType(dt,'DATETIME', adodbapi.Timestamp(2002,10,28,12,15,1), + compareAlmostEqual=True) + + def testDataTypeBinary(self): + binfld = str2bytes('\x07\x00\xE2\x40*') + arv = [binfld, adodbapi.Binary(binfld), bytes(binfld)] + if self.getEngine() == 'PostgreSQL': + self.helpTestDataType("bytea",'BINARY',adodbapi.Binary(binfld), + allowedReturnValues=arv) + else: + self.helpTestDataType("binary(5)",'BINARY',adodbapi.Binary(binfld), + allowedReturnValues=arv) + self.helpTestDataType("varbinary(100)",'BINARY',adodbapi.Binary(binfld), + allowedReturnValues=arv) + if self.getEngine() != 'MySQL': + self.helpTestDataType("image",'BINARY',adodbapi.Binary(binfld), + allowedReturnValues=arv) + + def helpRollbackTblTemp(self): + self.helpForceDropOnTblTemp() + + def helpForceDropOnTblTemp(self): + conn=self.getConnection() + with conn.cursor() as crsr: + try: + crsr.execute("DROP TABLE xx_%s" % config.tmp) + if not conn.autocommit: + conn.commit() + except: + pass + + def helpCreateAndPopulateTableTemp(self,crsr): + tabdef= """ + CREATE TABLE xx_%s ( + fldData INTEGER + ) + """ % config.tmp + try: #EAFP + crsr.execute(tabdef) + except api.DatabaseError: # was not dropped before + self.helpForceDropOnTblTemp() # so drop it now + crsr.execute(tabdef) + for i in range(9): # note: this poor SQL code, but a valid test + crsr.execute("INSERT INTO xx_%s (fldData) VALUES (%i)" % (config.tmp, i)) + # NOTE: building the test table without using parameter substitution + + def testFetchAll(self): + crsr=self.getCursor() + self.helpCreateAndPopulateTableTemp(crsr) + crsr.execute("SELECT fldData FROM xx_%s" % config.tmp) + rs=crsr.fetchall() + assert len(rs)==9 + #test slice of rows + i = 3 + for row in rs[3:-2]: #should have rowid 3..6 + assert row[0]==i + i+=1 + self.helpRollbackTblTemp() + + def testPreparedStatement(self): + crsr=self.getCursor() + self.helpCreateAndPopulateTableTemp(crsr) + crsr.prepare("SELECT fldData FROM xx_%s" % config.tmp) + crsr.execute(crsr.command) + rs=crsr.fetchall() + assert len(rs)==9 + assert rs[2][0]==2 + self.helpRollbackTblTemp() + + def testWrongPreparedStatement(self): + crsr=self.getCursor() + self.helpCreateAndPopulateTableTemp(crsr) + crsr.prepare("SELECT * FROM nowhere") + crsr.execute("SELECT fldData FROM xx_%s" % config.tmp) + rs=crsr.fetchall() + assert len(rs)==9 + assert rs[2][0]==2 + self.helpRollbackTblTemp() + def testIterator(self): + crsr=self.getCursor() + self.helpCreateAndPopulateTableTemp(crsr) + crsr.execute("SELECT fldData FROM xx_%s" % config.tmp) + for i,row in enumerate(crsr): # using cursor rather than fetchxxx + assert row[0]==i + self.helpRollbackTblTemp() + + def testExecuteMany(self): + crsr=self.getCursor() + self.helpCreateAndPopulateTableTemp(crsr) + seq_of_values = [ (111,) , (222,) ] + crsr.executemany("INSERT INTO xx_%s (fldData) VALUES (?)" % config.tmp, seq_of_values) + if crsr.rowcount==-1: + print((self.getEngine()+" Provider does not support rowcount (on .executemany())")) + else: + self.assertEquals( crsr.rowcount,2) + crsr.execute("SELECT fldData FROM xx_%s" % config.tmp) + rs=crsr.fetchall() + assert len(rs)==11 + self.helpRollbackTblTemp() + + + def testRowCount(self): + crsr=self.getCursor() + self.helpCreateAndPopulateTableTemp(crsr) + crsr.execute("SELECT fldData FROM xx_%s" % config.tmp) + if crsr.rowcount == -1: + #print("provider does not support rowcount on select") + pass + else: + self.assertEquals( crsr.rowcount,9) + self.helpRollbackTblTemp() + + def testRowCountNoRecordset(self): + crsr=self.getCursor() + self.helpCreateAndPopulateTableTemp(crsr) + crsr.execute("DELETE FROM xx_%s WHERE fldData >= 5" % config.tmp) + if crsr.rowcount==-1: + print((self.getEngine()+" Provider does not support rowcount (on DELETE)")) + else: + self.assertEquals( crsr.rowcount,4) + self.helpRollbackTblTemp() + + def testFetchMany(self): + crsr=self.getCursor() + self.helpCreateAndPopulateTableTemp(crsr) + crsr.execute("SELECT fldData FROM xx_%s" % config.tmp) + rs=crsr.fetchmany(3) + assert len(rs)==3 + rs=crsr.fetchmany(5) + assert len(rs)==5 + rs=crsr.fetchmany(5) + assert len(rs)==1 #Ask for five, but there is only one left + self.helpRollbackTblTemp() + + def testFetchManyWithArraySize(self): + crsr=self.getCursor() + self.helpCreateAndPopulateTableTemp(crsr) + crsr.execute("SELECT fldData FROM xx_%s" % config.tmp) + rs=crsr.fetchmany() + assert len(rs)==1 #arraysize Defaults to one + crsr.arraysize=4 + rs=crsr.fetchmany() + assert len(rs)==4 + rs=crsr.fetchmany() + assert len(rs)==4 + rs=crsr.fetchmany() + assert len(rs)==0 + self.helpRollbackTblTemp() + + def testErrorConnect(self): + conn = self.getConnection() + kw = {} + if 'proxy_host' in conn.kwargs: + kw['proxy_host'] = conn.kwargs['proxy_host'] + conn.close() + self.assertRaises(api.DatabaseError, self.db, 'not a valid connect string', kw) + + def testRowIterator(self): + self.helpForceDropOnTblTemp() + conn=self.getConnection() + crsr=conn.cursor() + tabdef= """ + CREATE TABLE xx_%s ( + fldId integer NOT NULL, + fldTwo integer, + fldThree integer, + fldFour integer) + """ % config.tmp + crsr.execute(tabdef) + + inputs = [(2,3,4),(102,103,104)] + fldId=1 + for inParam in inputs: + fldId+=1 + try: + crsr.execute("INSERT INTO xx_%s (fldId,fldTwo,fldThree,fldFour) VALUES (?,?,?,?)" % config.tmp, + (fldId,inParam[0],inParam[1],inParam[2])) + except: + if self.remote: + for message in crsr.messages: + print(message) + else: + conn.printADOerrors() + raise + crsr.execute("SELECT fldTwo,fldThree,fldFour FROM xx_%s WHERE ?=fldID" % config.tmp, [fldId]) + rec = crsr.fetchone() + # check that stepping through an emulated row works + for j in range(len(inParam)): + assert rec[j] == inParam[j], 'returned value:"%s" != test value:"%s"'%(rec[j],inParam[j]) + # check that we can get a complete tuple from a row + assert tuple(rec) == inParam, 'returned value:"%s" != test value:"%s"'%(repr(rec),repr(inParam)) + # test that slices of rows work + slice1 = tuple(rec[:-1]) + slice2 = tuple(inParam[0:2]) + assert slice1 == slice2, 'returned value:"%s" != test value:"%s"'%(repr(slice1),repr(slice2)) + # now test named column retrieval + assert rec['fldTwo'] == inParam[0] + assert rec.fldThree == inParam[1] + assert rec.fldFour == inParam[2] + # test array operation + # note that the fields vv vv vv are out of order + crsr.execute("select fldThree,fldFour,fldTwo from xx_%s" % config.tmp) + recs = crsr.fetchall() + assert recs[1][0] == 103 + assert recs[0][1] == 4 + assert recs[1]['fldFour'] == 104 + assert recs[0,0] == 3 + assert recs[0,'fldTwo'] == 2 + assert recs[1,2] == 102 + for i in range(1): + for j in range(2): + assert recs[i][j] == recs[i,j] + + def testFormatParamstyle(self): + self.helpForceDropOnTblTemp() + conn=self.getConnection() + conn.paramstyle = 'format' #test nonstandard use of paramstyle + crsr=conn.cursor() + tabdef= """ + CREATE TABLE xx_%s ( + fldId integer NOT NULL, + fldData varchar(10), + fldConst varchar(30)) + """ % config.tmp + crsr.execute(tabdef) + + inputs = ['one','two','three'] + fldId=2 + for inParam in inputs: + fldId+=1 + sql = "INSERT INTO xx_" + \ + config.tmp + \ + " (fldId,fldConst,fldData) VALUES (%s,'thi%s :may cause? trouble', %s)" + try: + crsr.execute(sql, (fldId,inParam)) + except: + if self.remote: + for message in crsr.messages: + print(message) + else: + conn.printADOerrors() + raise + crsr.execute("SELECT fldData, fldConst FROM xx_" + config.tmp + " WHERE %s=fldID", [fldId]) + rec = crsr.fetchone() + self.assertEqual(rec[0], inParam, 'returned value:"%s" != test value:"%s"' % (rec[0],inParam)) + self.assertEqual(rec[1], "thi%s :may cause? trouble") + + # now try an operation with a "%s" as part of a literal + sel = "insert into xx_" + config.tmp + " (fldId,fldData) VALUES (%s,'four%sfive')" + params = (20,) + crsr.execute(sel,params) + + #test the .query implementation + assert '(?,' in crsr.query, 'expected:"%s" in "%s"'%('(?,',crsr.query) + #test the .command attribute + assert crsr.command == sel + #test the .parameters attribute + if not self.remote: # parameter list will be altered in transit + self.assertEqual(crsr.parameters, params) + #now make sure the data made it + crsr.execute("SELECT fldData FROM xx_%s WHERE fldID=20" % config.tmp) + rec = crsr.fetchone() + self.assertEqual(rec[0], 'four%sfive') + + def testNamedParamstyle(self): + self.helpForceDropOnTblTemp() + conn=self.getConnection() + crsr=conn.cursor() + crsr.paramstyle = 'named' #test nonstandard use of paramstyle + tabdef= """ + CREATE TABLE xx_%s ( + fldId integer NOT NULL, + fldData varchar(10)) + """ % config.tmp + crsr.execute(tabdef) + + inputs = ['four','five','six'] + fldId=10 + for inParam in inputs: + fldId+=1 + try: + crsr.execute("INSERT INTO xx_%s (fldId,fldData) VALUES (:Id,:f_Val)" % config.tmp, + {"f_Val":inParam,'Id':fldId}) + except: + if self.remote: + for message in crsr.messages: + print(message) + else: + conn.printADOerrors() + raise + crsr.execute("SELECT fldData FROM xx_%s WHERE :Id=fldID" % config.tmp, {'Id':fldId}) + rec = crsr.fetchone() + self.assertEqual(rec[0], inParam, 'returned value:"%s" != test value:"%s"'%(rec[0],inParam)) + # now a test with a ":" as part of a literal + crsr.execute("insert into xx_%s (fldId,fldData) VALUES (:xyz,'six:five')" % config.tmp,{'xyz':30}) + crsr.execute("SELECT fldData FROM xx_%s WHERE fldID=30" % config.tmp) + rec = crsr.fetchone() + self.assertEqual(rec[0], 'six:five') + + + def testPyformatParamstyle(self): + self.helpForceDropOnTblTemp() + conn=self.getConnection() + crsr=conn.cursor() + crsr.paramstyle = 'pyformat' #test nonstandard use of paramstyle + tabdef= """ + CREATE TABLE xx_%s ( + fldId integer NOT NULL, + fldData varchar(10)) + """ % config.tmp + crsr.execute(tabdef) + + inputs = ['four', 'five', 'six'] + fldId=10 + for inParam in inputs: + fldId+=1 + try: + crsr.execute("INSERT INTO xx_%s (fldId,fldData) VALUES (%%(Id)s,%%(f_Val)s)" % config.tmp, + {"f_Val": inParam, 'Id': fldId}) + except: + if self.remote: + for message in crsr.messages: + print(message) + else: + conn.printADOerrors() + raise + crsr.execute("SELECT fldData FROM xx_%s WHERE %%(Id)s=fldID" % config.tmp, {'Id':fldId}) + rec = crsr.fetchone() + self.assertEqual(rec[0], inParam, 'returned value:"%s" != test value:"%s"'%(rec[0],inParam)) + # now a test with a "%" as part of a literal + crsr.execute("insert into xx_%s (fldId,fldData) VALUES (%%(xyz)s,'six%%five')" % config.tmp,{'xyz': 30}) + crsr.execute("SELECT fldData FROM xx_%s WHERE fldID=30" % config.tmp) + rec = crsr.fetchone() + self.assertEqual(rec[0], 'six%five') + + def testAutomaticParamstyle(self): + self.helpForceDropOnTblTemp() + conn=self.getConnection() + conn.paramstyle = 'dynamic' #test nonstandard use of paramstyle + crsr=conn.cursor() + tabdef= """ + CREATE TABLE xx_%s ( + fldId integer NOT NULL, + fldData varchar(10), + fldConst varchar(30)) + """ % config.tmp + crsr.execute(tabdef) + inputs = ['one', 'two', 'three'] + fldId=2 + for inParam in inputs: + fldId+=1 + try: + crsr.execute("INSERT INTO xx_" + config.tmp + \ + " (fldId,fldConst,fldData) VALUES (?,'thi%s :may cause? troub:1e', ?)", (fldId,inParam)) + except: + if self.remote: + for message in crsr.messages: + print(message) + else: + conn.printADOerrors() + raise + trouble = 'thi%s :may cause? troub:1e' + crsr.execute("SELECT fldData, fldConst FROM xx_" + config.tmp + " WHERE ?=fldID", [fldId]) + rec = crsr.fetchone() + self.assertEqual(rec[0], inParam, 'returned value:"%s" != test value:"%s"'%(rec[0],inParam)) + self.assertEqual(rec[1], trouble) + # inputs = [u'four',u'five',u'six'] + fldId=10 + for inParam in inputs: + fldId+=1 + try: + crsr.execute("INSERT INTO xx_%s (fldId,fldData) VALUES (:Id,:f_Val)" % config.tmp, + {"f_Val":inParam,'Id':fldId}) + except: + if self.remote: + for message in crsr.messages: + print(message) + else: + conn.printADOerrors() + raise + crsr.execute("SELECT fldData FROM xx_%s WHERE :Id=fldID" % config.tmp, {'Id':fldId}) + rec = crsr.fetchone() + self.assertEqual(rec[0], inParam, 'returned value:"%s" != test value:"%s"'%(rec[0],inParam)) + # now a test with a ":" as part of a literal -- and use a prepared query + crsr.prepare("insert into xx_%s (fldId,fldData) VALUES (:xyz,'six:five')" % config.tmp) + crsr.execute(crsr.command, {'xyz':30}) + crsr.execute("SELECT fldData FROM xx_%s WHERE fldID=30" % config.tmp) + rec = crsr.fetchone() + self.assertEqual(rec[0], 'six:five') + + def testRollBack(self): + conn = self.getConnection() + crsr = conn.cursor() + assert not crsr.connection.autocommit, 'Unexpected beginning condition' + self.helpCreateAndPopulateTableTemp(crsr) + crsr.connection.commit() # commit the first bunch + + crsr.execute("INSERT INTO xx_%s (fldData) VALUES(100)" % config.tmp) + + selectSql = "SELECT fldData FROM xx_%s WHERE fldData=100" % config.tmp + crsr.execute(selectSql) + rs = crsr.fetchall() + assert len(rs) == 1 + self.conn.rollback() + crsr.execute(selectSql) + assert crsr.fetchone() == None, 'cursor.fetchone should return None if a query retrieves no rows' + crsr.execute('SELECT fldData from xx_%s' % config.tmp) + rs = crsr.fetchall() + assert len(rs) == 9, 'the original records should still be present' + self.helpRollbackTblTemp() + + + def testCommit(self): + try: + con2 = self.getAnotherConnection() + except NotImplementedError: + return # should be "SKIP" for ACCESS + assert not con2.autocommit, 'default should be manual commit' + crsr = con2.cursor() + self.helpCreateAndPopulateTableTemp(crsr) + + crsr.execute("INSERT INTO xx_%s (fldData) VALUES(100)" % config.tmp) + con2.commit() + + selectSql = "SELECT fldData FROM xx_%s WHERE fldData=100" % config.tmp + crsr.execute(selectSql) + rs = crsr.fetchall() + assert len(rs) == 1 + crsr.close() + con2.close() + conn = self.getConnection() + crsr = self.getCursor() + with conn.cursor() as crsr: + crsr.execute(selectSql) + rs = crsr.fetchall() + assert len(rs) == 1 + assert rs[0][0] == 100 + self.helpRollbackTblTemp() + + + def testAutoRollback(self): + try: + con2 = self.getAnotherConnection() + except NotImplementedError: + return # should be "SKIP" for ACCESS + assert not con2.autocommit, 'unexpected beginning condition' + crsr = con2.cursor() + self.helpCreateAndPopulateTableTemp(crsr) + crsr.execute("INSERT INTO xx_%s (fldData) VALUES(100)" % config.tmp) + selectSql = "SELECT fldData FROM xx_%s WHERE fldData=100" % config.tmp + crsr.execute(selectSql) + rs = crsr.fetchall() + assert len(rs) == 1 + crsr.close() + con2.close() + crsr = self.getCursor() + try: + crsr.execute(selectSql) # closing the connection should have forced rollback + row = crsr.fetchone() + except api.DatabaseError: + row = None # if the entire table disappeared the rollback was perfect and the test passed + assert row == None, 'cursor.fetchone should return None if a query retrieves no rows. Got %s' % repr(row) + self.helpRollbackTblTemp() + + def testAutoCommit(self): + try: + ac_conn = self.getAnotherConnection({'autocommit': True}) + except NotImplementedError: + return # should be "SKIP" for ACCESS + crsr = ac_conn.cursor() + self.helpCreateAndPopulateTableTemp(crsr) + crsr.execute("INSERT INTO xx_%s (fldData) VALUES(100)" % config.tmp) + crsr.close() + with self.getCursor() as crsr: + selectSql = 'SELECT fldData from xx_%s' % config.tmp + crsr.execute(selectSql) # closing the connection should _not_ have forced rollback + rs = crsr.fetchall() + assert len(rs) == 10, 'all records should still be present' + ac_conn.close() + self.helpRollbackTblTemp() + + def testSwitchedAutoCommit(self): + try: + ac_conn = self.getAnotherConnection() + except NotImplementedError: + return # should be "SKIP" for ACCESS + ac_conn.autocommit = True + crsr = ac_conn.cursor() + self.helpCreateAndPopulateTableTemp(crsr) + crsr.execute("INSERT INTO xx_%s (fldData) VALUES(100)" % config.tmp) + crsr.close() + conn = self.getConnection() + ac_conn.close() + with self.getCursor() as crsr: + selectSql = 'SELECT fldData from xx_%s' % config.tmp + crsr.execute(selectSql) # closing the connection should _not_ have forced rollback + rs = crsr.fetchall() + assert len(rs) == 10, 'all records should still be present' + self.helpRollbackTblTemp() + +class TestADOwithSQLServer(CommonDBTests): + def setUp(self): + self.conn = config.dbSqlServerconnect(*config.connStrSQLServer[0], **config.connStrSQLServer[1]) + self.conn.timeout = 30 # turn timeout back up + self.engine = 'MSSQL' + self.db = config.dbSqlServerconnect + self.remote = config.connStrSQLServer[2] + + def tearDown(self): + try: + self.conn.rollback() + except: + pass + try: + self.conn.close() + except: + pass + self.conn=None + + def getConnection(self): + return self.conn + + def getAnotherConnection(self, addkeys=None): + keys = dict(config.connStrSQLServer[1]) + if addkeys: + keys.update(addkeys) + return config.dbSqlServerconnect(*config.connStrSQLServer[0], **keys) + + def testVariableReturningStoredProcedure(self): + crsr=self.conn.cursor() + spdef= """ + CREATE PROCEDURE sp_DeleteMeOnlyForTesting + @theInput varchar(50), + @theOtherInput varchar(50), + @theOutput varchar(100) OUTPUT + AS + SET @theOutput=@theInput+@theOtherInput + """ + try: + crsr.execute("DROP PROCEDURE sp_DeleteMeOnlyForTesting") + self.conn.commit() + except: #Make sure it is empty + pass + crsr.execute(spdef) + + retvalues=crsr.callproc('sp_DeleteMeOnlyForTesting',('Dodsworth','Anne',' ')) + assert retvalues[0]=='Dodsworth', '%s is not "Dodsworth"'%repr(retvalues[0]) + assert retvalues[1]=='Anne','%s is not "Anne"'%repr(retvalues[1]) + assert retvalues[2]=='DodsworthAnne','%s is not "DodsworthAnne"'%repr(retvalues[2]) + self.conn.rollback() + + def testMultipleSetReturn(self): + crsr=self.getCursor() + self.helpCreateAndPopulateTableTemp(crsr) + + spdef= """ + CREATE PROCEDURE sp_DeleteMe_OnlyForTesting + AS + SELECT fldData FROM xx_%s ORDER BY fldData ASC + SELECT fldData From xx_%s where fldData = -9999 + SELECT fldData FROM xx_%s ORDER BY fldData DESC + """ % (config.tmp, config.tmp, config.tmp) + try: + crsr.execute("DROP PROCEDURE sp_DeleteMe_OnlyForTesting") + self.conn.commit() + except: #Make sure it is empty + pass + crsr.execute(spdef) + + retvalues=crsr.callproc('sp_DeleteMe_OnlyForTesting') + row=crsr.fetchone() + self.assertEquals(row[0], 0) + assert crsr.nextset() == True, 'Operation should succeed' + assert not crsr.fetchall(), 'Should be an empty second set' + assert crsr.nextset() == True, 'third set should be present' + rowdesc=crsr.fetchall() + self.assertEquals(rowdesc[0][0],8) + assert crsr.nextset() == None,'No more return sets, should return None' + + self.helpRollbackTblTemp() + + + def testDatetimeProcedureParameter(self): + crsr=self.conn.cursor() + spdef= """ + CREATE PROCEDURE sp_DeleteMeOnlyForTesting + @theInput DATETIME, + @theOtherInput varchar(50), + @theOutput varchar(100) OUTPUT + AS + SET @theOutput = CONVERT(CHARACTER(20), @theInput, 0) + @theOtherInput + """ + try: + crsr.execute("DROP PROCEDURE sp_DeleteMeOnlyForTesting") + self.conn.commit() + except: #Make sure it is empty + pass + crsr.execute(spdef) + + result = crsr.callproc('sp_DeleteMeOnlyForTesting', [adodbapi.Timestamp(2014,12,25,0,1,0), 'Beep', ' ' * 30]) + + assert result[2] == 'Dec 25 2014 12:01AM Beep', 'value was="%s"' % result[2] + self.conn.rollback() + + def testIncorrectStoredProcedureParameter(self): + crsr=self.conn.cursor() + spdef= """ + CREATE PROCEDURE sp_DeleteMeOnlyForTesting + @theInput DATETIME, + @theOtherInput varchar(50), + @theOutput varchar(100) OUTPUT + AS + SET @theOutput = CONVERT(CHARACTER(20), @theInput) + @theOtherInput + """ + try: + crsr.execute("DROP PROCEDURE sp_DeleteMeOnlyForTesting") + self.conn.commit() + except: #Make sure it is empty + pass + crsr.execute(spdef) + + # calling the sproc with a string for the first parameter where a DateTime is expected + result = tryconnection.try_operation_with_expected_exception( + (api.DataError,api.DatabaseError), + crsr.callproc, + ['sp_DeleteMeOnlyForTesting'], + {'parameters': ['this is wrong', 'Anne', 'not Alice']} + ) + if result[0]: # the expected exception was raised + assert '@theInput' in str(result[1]) or 'DatabaseError' in str(result), \ + 'Identifies the wrong erroneous parameter' + else: + assert result[0], result[1] # incorrect or no exception + self.conn.rollback() + +class TestADOwithAccessDB(CommonDBTests): + def setUp(self): + self.conn = config.dbAccessconnect(*config.connStrAccess[0], **config.connStrAccess[1]) + self.conn.timeout = 30 # turn timeout back up + self.engine = 'ACCESS' + self.db = config.dbAccessconnect + self.remote = config.connStrAccess[2] + + def tearDown(self): + try: + self.conn.rollback() + except: + pass + try: + self.conn.close() + except: + pass + self.conn=None + + def getConnection(self): + return self.conn + + def getAnotherConnection(self, addkeys=None): + raise NotImplementedError('Jet cannot use a second connection to the database') + + def testOkConnect(self): + c = self.db(*config.connStrAccess[0], **config.connStrAccess[1]) + assert c != None + c.close() + +class TestADOwithMySql(CommonDBTests): + def setUp(self): + self.conn = config.dbMySqlconnect(*config.connStrMySql[0], **config.connStrMySql[1]) + self.conn.timeout = 30 # turn timeout back up + self.engine = 'MySQL' + self.db = config.dbMySqlconnect + self.remote = config.connStrMySql[2] + + def tearDown(self): + try: + self.conn.rollback() + except: + pass + try: + self.conn.close() + except: + pass + self.conn=None + + def getConnection(self): + return self.conn + + def getAnotherConnection(self, addkeys=None): + keys = dict(config.connStrMySql[1]) + if addkeys: + keys.update(addkeys) + return config.dbMySqlconnect(*config.connStrMySql[0], **keys) + + def testOkConnect(self): + c = self.db(*config.connStrMySql[0], **config.connStrMySql[1]) + assert c != None + + # def testStoredProcedure(self): + # crsr=self.conn.cursor() + # try: + # crsr.execute("DROP PROCEDURE DeleteMeOnlyForTesting") + # self.conn.commit() + # except: #Make sure it is empty + # pass + # spdef= """ + # DELIMITER $$ + # CREATE PROCEDURE DeleteMeOnlyForTesting (onein CHAR(10), twoin CHAR(10), OUT theout CHAR(20)) + # DETERMINISTIC + # BEGIN + # SET theout = onein //|| twoin; + # /* (SELECT 'a small string' as result; */ + # END $$ + # """ + # + # crsr.execute(spdef) + # + # retvalues=crsr.callproc('DeleteMeOnlyForTesting',('Dodsworth','Anne',' ')) + # print 'return value (mysql)=',repr(crsr.returnValue) ### + # assert retvalues[0]=='Dodsworth', '%s is not "Dodsworth"'%repr(retvalues[0]) + # assert retvalues[1]=='Anne','%s is not "Anne"'%repr(retvalues[1]) + # assert retvalues[2]=='DodsworthAnne','%s is not "DodsworthAnne"'%repr(retvalues[2]) + # + # try: + # crsr.execute("DROP PROCEDURE, DeleteMeOnlyForTesting") + # self.conn.commit() + # except: #Make sure it is empty + # pass + +class TestADOwithPostgres(CommonDBTests): + def setUp(self): + self.conn = config.dbPostgresConnect(*config.connStrPostgres[0], **config.connStrPostgres[1]) + self.conn.timeout = 30 # turn timeout back up + self.engine = 'PostgreSQL' + self.db = config.dbPostgresConnect + self.remote = config.connStrPostgres[2] + + def tearDown(self): + try: + self.conn.rollback() + except: + pass + try: + self.conn.close() + except: + pass + self.conn=None + + def getConnection(self): + return self.conn + + def getAnotherConnection(self, addkeys=None): + keys = dict(config.connStrPostgres[1]) + if addkeys: + keys.update(addkeys) + return config.dbPostgresConnect(*config.connStrPostgres[0], **keys) + + def testOkConnect(self): + c = self.db(*config.connStrPostgres[0], **config.connStrPostgres[1]) + assert c != None + + # def testStoredProcedure(self): + # crsr=self.conn.cursor() + # spdef= """ + # CREATE OR REPLACE FUNCTION DeleteMeOnlyForTesting (text, text) + # RETURNS text AS $funk$ + # BEGIN + # RETURN $1 || $2; + # END; + # $funk$ + # LANGUAGE SQL; + # """ + # + # crsr.execute(spdef) + # retvalues = crsr.callproc('DeleteMeOnlyForTesting',('Dodsworth','Anne',' ')) + # ### print 'return value (pg)=',repr(crsr.returnValue) ### + # assert retvalues[0]=='Dodsworth', '%s is not "Dodsworth"'%repr(retvalues[0]) + # assert retvalues[1]=='Anne','%s is not "Anne"'%repr(retvalues[1]) + # assert retvalues[2]=='Dodsworth Anne','%s is not "Dodsworth Anne"'%repr(retvalues[2]) + # self.conn.rollback() + # try: + # crsr.execute("DROP PROCEDURE, DeleteMeOnlyForTesting") + # self.conn.commit() + # except: #Make sure it is empty + # pass + +class TimeConverterInterfaceTest(unittest.TestCase): + def testIDate(self): + assert self.tc.Date(1990,2,2) + + def testITime(self): + assert self.tc.Time(13,2,2) + + def testITimestamp(self): + assert self.tc.Timestamp(1990,2,2,13,2,1) + + def testIDateObjectFromCOMDate(self): + assert self.tc.DateObjectFromCOMDate(37435.7604282) + + def testICOMDate(self): + assert hasattr(self.tc,'COMDate') + + def testExactDate(self): + d=self.tc.Date(1994,11,15) + comDate=self.tc.COMDate(d) + correct=34653.0 + assert comDate == correct,comDate + + def testExactTimestamp(self): + d=self.tc.Timestamp(1994,11,15,12,0,0) + comDate=self.tc.COMDate(d) + correct=34653.5 + self.assertEquals( comDate ,correct) + + d=self.tc.Timestamp(2003,5,6,14,15,17) + comDate=self.tc.COMDate(d) + correct=37747.593946759262 + self.assertEquals( comDate ,correct) + + def testIsoFormat(self): + d=self.tc.Timestamp(1994,11,15,12,3,10) + iso=self.tc.DateObjectToIsoFormatString(d) + self.assertEquals(str(iso[:19]) , '1994-11-15 12:03:10') + + dt=self.tc.Date(2003,5,2) + iso=self.tc.DateObjectToIsoFormatString(dt) + self.assertEquals(str(iso[:10]), '2003-05-02') + +if config.doMxDateTimeTest: + import mx.DateTime +class TestMXDateTimeConverter(TimeConverterInterfaceTest): + def setUp(self): + self.tc = api.mxDateTimeConverter() + + def testCOMDate(self): + t=mx.DateTime.DateTime(2002,6,28,18,15,2) + cmd=self.tc.COMDate(t) + assert cmd == t.COMDate() + + def testDateObjectFromCOMDate(self): + cmd=self.tc.DateObjectFromCOMDate(37435.7604282) + t=mx.DateTime.DateTime(2002,6,28,18,15,0) + t2=mx.DateTime.DateTime(2002,6,28,18,15,2) + assert t2>cmd>t + + def testDate(self): + assert mx.DateTime.Date(1980,11,4)==self.tc.Date(1980,11,4) + + def testTime(self): + assert mx.DateTime.Time(13,11,4)==self.tc.Time(13,11,4) + + def testTimestamp(self): + t=mx.DateTime.DateTime(2002,6,28,18,15,1) + obj=self.tc.Timestamp(2002,6,28,18,15,1) + assert t == obj + +import time +class TestPythonTimeConverter(TimeConverterInterfaceTest): + def setUp(self): + self.tc=api.pythonTimeConverter() + + def testCOMDate(self): + mk = time.mktime((2002,6,28,18,15,1, 4,31+28+31+30+31+28,-1)) + t=time.localtime(mk) + # Fri, 28 Jun 2002 18:15:01 +0000 + cmd=self.tc.COMDate(t) + assert abs(cmd - 37435.7604282) < 1.0/24,"%f more than an hour wrong" % cmd + + def testDateObjectFromCOMDate(self): + cmd=self.tc.DateObjectFromCOMDate(37435.7604282) + t1=time.gmtime(time.mktime((2002,6,28,0,14,1, 4,31+28+31+30+31+28,-1))) + #there are errors in the implementation of gmtime which we ignore + t2=time.gmtime(time.mktime((2002,6,29,12,14,2, 4,31+28+31+30+31+28,-1))) + assert t1= (3,0): + import tryconnection3 as tryconnection +else: + import tryconnection2 as tryconnection + +print((sys.version)) +node = platform.node() +try: print(('node=%s: is64bit.os()= %s, is64bit.Python()= %s' % (node, is64bit.os(), is64bit.Python()))) +except: pass + +try: + onWindows = bool(sys.getwindowsversion()) # seems to work on all versions of Python +except: + onWindows = False + +# create a random name for temporary table names +_alphabet = "PYFGCRLAOEUIDHTNTQJKXBMWVZ1234567890" # yes, I do use a dvorak keyboard! +tmp = ''.join([random.choice(_alphabet) for x in range(9)]) +mdb_name = 'xx_' + tmp + '.mdb' +testfolder = setuptestframework.maketemp() + +if '--package' in sys.argv: + pth = setuptestframework.makeadopackage(testfolder) +else: + pth = setuptestframework.find_ado_path() +if pth not in sys.path: + sys.path.insert(1,pth) + +# function to clean up the temporary folder -- calling program must run this function before exit. +cleanup = setuptestframework.getcleanupfunction() + +import adodbapi # will (hopefully) be imported using the "pth" discovered above + +try: + print((adodbapi.version)) # show version +except: + print('"adodbapi.version" not present or not working.') +print(__doc__) + +verbose = False +for a in sys.argv: + if a.startswith('--verbose'): + arg = True + try: arg = int(a.split("=")[1]) + except IndexError: pass + adodbapi.adodbapi.verbose = arg + verbose = arg + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # start your environment setup here v v v +SQL_HOST_NODE = 'Vpad' +doAllTests = '--all' in sys.argv +doAccessTest = not ('--nojet' in sys.argv) +doSqlServerTest = node == SQL_HOST_NODE or '--mssql' in sys.argv or doAllTests +doMySqlTest = '--mysql' in sys.argv or doAllTests +doPostgresTest = '--pg' in sys.argv or doAllTests +iterateOverTimeTests = ('--time' in sys.argv or doAllTests) and onWindows + +THE_PROXY_HOST = '25.44.77.176' if node != SQL_HOST_NODE or not onWindows else '::1' # -- change this + +try: #If mx extensions are installed, use mxDateTime + import mx.DateTime + doMxDateTimeTest=True +except: + doMxDateTimeTest=False #Requires eGenixMXExtensions + +doTimeTest = True # obsolete python time format + +if doAccessTest: + if onWindows and (node == SQL_HOST_NODE or not is64bit.Python()): + c = {'mdb': setuptestframework.makemdb(testfolder, mdb_name)} + else: + c = {'macro_find_temp_test_path' : ['mdb', 'server_test.mdb'], + 'proxy_host' : THE_PROXY_HOST} + + + # macro definition for keyword "driver" using macro "is64bit" -- see documentation + c['macro_is64bit'] = ['driver', "Microsoft.ACE.OLEDB.12.0", "Microsoft.Jet.OLEDB.4.0"] + connStrAccess = "Provider=%(driver)s;Data Source=%(mdb)s" + print(' ...Testing ACCESS connection...') + doAccessTest, connStrAccess, dbAccessconnect = tryconnection.try_connection(verbose, connStrAccess, 10, **c) + +if doSqlServerTest: + c = {'macro_getnode' : ['host', r"%s\SQLExpress"], # name of computer with SQL Server + #'host':'25.44.77.176;' # Network Library=dbmssocn', + 'database': "adotest", + 'user' : 'adotestuser', # None implies Windows security + 'password' : "12345678", + # macro definition for keyword "security" using macro "auto_security" + 'macro_auto_security' : 'security', + 'provider' : 'SQLNCLI11; MARS Connection=True' + } + connStr = "Provider=%(provider)s; Initial Catalog=%(database)s; Data Source=%(host)s; %(security)s;" + + if node != SQL_HOST_NODE: + if THE_PROXY_HOST: + c["proxy_host"] = THE_PROXY_HOST # the SQL server runs a proxy for this test + else: + c["pyro_connection"] = "PYRONAME:ado.connection" + print(' ...Testing MS-SQL login...') + doSqlServerTest, connStrSQLServer, dbSqlServerconnect = tryconnection.try_connection(verbose, connStr, 30, **c) + +if doMySqlTest: + c = {'host' : "25.223.161.222", + 'database' : 'test', + 'user' : 'adotest', + 'password' : '12345678', + 'driver' : "MySQL ODBC 5.3 Unicode Driver"} # or _driver="MySQL ODBC 3.51 Driver + + if not onWindows: + if THE_PROXY_HOST: + c["proxy_host"] = THE_PROXY_HOST + else: + c["pyro_connection"] = "PYRONAME:ado.connection" + + c['macro_is64bit'] = ['provider', 'Provider=MSDASQL;'] + cs = '%(provider)sDriver={%(driver)s};Server=%(host)s;Port=3306;' + \ + 'Database=%(database)s;user=%(user)s;password=%(password)s;Option=3;' + print(' ...Testing MySql login...') + doMySqlTest, connStrMySql, dbMySqlconnect = tryconnection.try_connection(verbose, cs, 5, **c) + +if doPostgresTest: + _computername = "25.223.161.222" + _databasename='adotest' + _username = 'adotestuser' + _password = '12345678' + kws = {'timeout' : 4} + kws['macro_is64bit'] = ['prov_drv', 'Provider=MSDASQL;Driver={PostgreSQL Unicode(x64)}', + 'Driver=PostgreSQL Unicode'] + if not onWindows: + if THE_PROXY_HOST: + kws['proxy_host'] = THE_PROXY_HOST + else: + kws['pyro_connection'] = 'PYRONAME:ado.connection' + # get driver from http://www.postgresql.org/ftp/odbc/versions/ + # test using positional and keyword arguments (bad example for real code) + print(' ...Testing PostgreSQL login...') + doPostgresTest, connStrPostgres, dbPostgresConnect = tryconnection.try_connection(verbose, + '%(prov_drv)s;Server=%(host)s;Database=%(database)s;uid=%(user)s;pwd=%(password)s;', + _username, _password, _computername, _databasename, **kws) + +assert doAccessTest or doSqlServerTest or doMySqlTest or doPostgresTest, 'No database engine found for testing' diff --git a/Lib/site-packages/adodbapi/test/dbapi20.py b/Lib/site-packages/adodbapi/test/dbapi20.py new file mode 100644 index 0000000..a3fcd59 --- /dev/null +++ b/Lib/site-packages/adodbapi/test/dbapi20.py @@ -0,0 +1,899 @@ +#!/usr/bin/env python +''' Python DB API 2.0 driver compliance unit test suite. + + This software is Public Domain and may be used without restrictions. + + "Now we have booze and barflies entering the discussion, plus rumours of + DBAs on drugs... and I won't tell you what flashes through my mind each + time I read the subject line with 'Anal Compliance' in it. All around + this is turning out to be a thoroughly unwholesome unit test." + + -- Ian Bicking +''' + +__version__ = '$Revision: 1.14.3 $'[11:-2] +__author__ = 'Stuart Bishop ' + +import unittest +import time +import sys + +if sys.version[0] >= '3': #python 3.x + _BaseException = Exception + def _failUnless(self, expr, msg=None): + self.assertTrue(expr, msg) +else: #python 2.x + from exceptions import Exception as _BaseException + def _failUnless(self, expr, msg=None): + self.failUnless(expr, msg) ## deprecated since Python 2.6 + +# set this to "True" to follow API 2.0 to the letter +TEST_FOR_NON_IDEMPOTENT_CLOSE = True + +# Revision 1.14 2013/05/20 11:02:05 kf7xm +# Add a literal string to the format insertion test to catch trivial re-format algorithms + +# Revision 1.13 2013/05/08 14:31:50 kf7xm +# Quick switch to Turn off IDEMPOTENT_CLOSE test. Also: Silence teardown failure + +# Revision 1.12 2009/02/06 03:35:11 kf7xm +# Tested okay with Python 3.0, includes last minute patches from Mark H. +# +# Revision 1.1.1.1.2.1 2008/09/20 19:54:59 rupole +# Include latest changes from main branch +# Updates for py3k +# +# Revision 1.11 2005/01/02 02:41:01 zenzen +# Update author email address +# +# Revision 1.10 2003/10/09 03:14:14 zenzen +# Add test for DB API 2.0 optional extension, where database exceptions +# are exposed as attributes on the Connection object. +# +# Revision 1.9 2003/08/13 01:16:36 zenzen +# Minor tweak from Stefan Fleiter +# +# Revision 1.8 2003/04/10 00:13:25 zenzen +# Changes, as per suggestions by M.-A. Lemburg +# - Add a table prefix, to ensure namespace collisions can always be avoided +# +# Revision 1.7 2003/02/26 23:33:37 zenzen +# Break out DDL into helper functions, as per request by David Rushby +# +# Revision 1.6 2003/02/21 03:04:33 zenzen +# Stuff from Henrik Ekelund: +# added test_None +# added test_nextset & hooks +# +# Revision 1.5 2003/02/17 22:08:43 zenzen +# Implement suggestions and code from Henrik Eklund - test that cursor.arraysize +# defaults to 1 & generic cursor.callproc test added +# +# Revision 1.4 2003/02/15 00:16:33 zenzen +# Changes, as per suggestions and bug reports by M.-A. Lemburg, +# Matthew T. Kromer, Federico Di Gregorio and Daniel Dittmar +# - Class renamed +# - Now a subclass of TestCase, to avoid requiring the driver stub +# to use multiple inheritance +# - Reversed the polarity of buggy test in test_description +# - Test exception heirarchy correctly +# - self.populate is now self._populate(), so if a driver stub +# overrides self.ddl1 this change propogates +# - VARCHAR columns now have a width, which will hopefully make the +# DDL even more portible (this will be reversed if it causes more problems) +# - cursor.rowcount being checked after various execute and fetchXXX methods +# - Check for fetchall and fetchmany returning empty lists after results +# are exhausted (already checking for empty lists if select retrieved +# nothing +# - Fix bugs in test_setoutputsize_basic and test_setinputsizes +# +def str2bytes(sval): + if sys.version_info < (3,0) and isinstance(sval, str): + sval = sval.decode("latin1") + return sval.encode("latin1") #python 3 make unicode into bytes + +class DatabaseAPI20Test(unittest.TestCase): + ''' Test a database self.driver for DB API 2.0 compatibility. + This implementation tests Gadfly, but the TestCase + is structured so that other self.drivers can subclass this + test case to ensure compiliance with the DB-API. It is + expected that this TestCase may be expanded in the future + if ambiguities or edge conditions are discovered. + + The 'Optional Extensions' are not yet being tested. + + self.drivers should subclass this test, overriding setUp, tearDown, + self.driver, connect_args and connect_kw_args. Class specification + should be as follows: + + import dbapi20 + class mytest(dbapi20.DatabaseAPI20Test): + [...] + + Don't 'import DatabaseAPI20Test from dbapi20', or you will + confuse the unit tester - just 'import dbapi20'. + ''' + + # The self.driver module. This should be the module where the 'connect' + # method is to be found + driver = None + connect_args = () # List of arguments to pass to connect + connect_kw_args = {} # Keyword arguments for connect + table_prefix = 'dbapi20test_' # If you need to specify a prefix for tables + + ddl1 = 'create table %sbooze (name varchar(20))' % table_prefix + ddl2 = 'create table %sbarflys (name varchar(20), drink varchar(30))' % table_prefix + xddl1 = 'drop table %sbooze' % table_prefix + xddl2 = 'drop table %sbarflys' % table_prefix + + lowerfunc = 'lower' # Name of stored procedure to convert string->lowercase + + # Some drivers may need to override these helpers, for example adding + # a 'commit' after the execute. + def executeDDL1(self,cursor): + cursor.execute(self.ddl1) + + def executeDDL2(self,cursor): + cursor.execute(self.ddl2) + + def setUp(self): + ''' self.drivers should override this method to perform required setup + if any is necessary, such as creating the database. + ''' + pass + + def tearDown(self): + ''' self.drivers should override this method to perform required cleanup + if any is necessary, such as deleting the test database. + The default drops the tables that may be created. + ''' + try: + con = self._connect() + try: + cur = con.cursor() + for ddl in (self.xddl1,self.xddl2): + try: + cur.execute(ddl) + con.commit() + except self.driver.Error: + # Assume table didn't exist. Other tests will check if + # execute is busted. + pass + finally: + con.close() + except _BaseException: + pass + + def _connect(self): + try: + r = self.driver.connect( + *self.connect_args,**self.connect_kw_args + ) + except AttributeError: + self.fail("No connect method found in self.driver module") + return r + + def test_connect(self): + con = self._connect() + con.close() + + def test_apilevel(self): + try: + # Must exist + apilevel = self.driver.apilevel + # Must equal 2.0 + self.assertEqual(apilevel,'2.0') + except AttributeError: + self.fail("Driver doesn't define apilevel") + + def test_threadsafety(self): + try: + # Must exist + threadsafety = self.driver.threadsafety + # Must be a valid value + _failUnless(self, threadsafety in (0,1,2,3)) + except AttributeError: + self.fail("Driver doesn't define threadsafety") + + def test_paramstyle(self): + try: + # Must exist + paramstyle = self.driver.paramstyle + # Must be a valid value + _failUnless(self, paramstyle in ( + 'qmark','numeric','named','format','pyformat' + )) + except AttributeError: + self.fail("Driver doesn't define paramstyle") + + def test_Exceptions(self): + # Make sure required exceptions exist, and are in the + # defined heirarchy. + if sys.version[0] == '3': #under Python 3 StardardError no longer exists + self.assertTrue(issubclass(self.driver.Warning,Exception)) + self.assertTrue(issubclass(self.driver.Error,Exception)) + else: + self.failUnless(issubclass(self.driver.Warning,Exception)) + self.failUnless(issubclass(self.driver.Error,Exception)) + + _failUnless(self, + issubclass(self.driver.InterfaceError,self.driver.Error) + ) + _failUnless(self, + issubclass(self.driver.DatabaseError,self.driver.Error) + ) + _failUnless(self, + issubclass(self.driver.OperationalError,self.driver.Error) + ) + _failUnless(self, + issubclass(self.driver.IntegrityError,self.driver.Error) + ) + _failUnless(self, + issubclass(self.driver.InternalError,self.driver.Error) + ) + _failUnless(self, + issubclass(self.driver.ProgrammingError,self.driver.Error) + ) + _failUnless(self, + issubclass(self.driver.NotSupportedError,self.driver.Error) + ) + + def test_ExceptionsAsConnectionAttributes(self): + # OPTIONAL EXTENSION + # Test for the optional DB API 2.0 extension, where the exceptions + # are exposed as attributes on the Connection object + # I figure this optional extension will be implemented by any + # driver author who is using this test suite, so it is enabled + # by default. + con = self._connect() + drv = self.driver + _failUnless(self,con.Warning is drv.Warning) + _failUnless(self,con.Error is drv.Error) + _failUnless(self,con.InterfaceError is drv.InterfaceError) + _failUnless(self,con.DatabaseError is drv.DatabaseError) + _failUnless(self,con.OperationalError is drv.OperationalError) + _failUnless(self,con.IntegrityError is drv.IntegrityError) + _failUnless(self,con.InternalError is drv.InternalError) + _failUnless(self,con.ProgrammingError is drv.ProgrammingError) + _failUnless(self,con.NotSupportedError is drv.NotSupportedError) + + + def test_commit(self): + con = self._connect() + try: + # Commit must work, even if it doesn't do anything + con.commit() + finally: + con.close() + + def test_rollback(self): + con = self._connect() + # If rollback is defined, it should either work or throw + # the documented exception + if hasattr(con,'rollback'): + try: + con.rollback() + except self.driver.NotSupportedError: + pass + + def test_cursor(self): + con = self._connect() + try: + cur = con.cursor() + finally: + con.close() + + def test_cursor_isolation(self): + con = self._connect() + try: + # Make sure cursors created from the same connection have + # the documented transaction isolation level + cur1 = con.cursor() + cur2 = con.cursor() + self.executeDDL1(cur1) + cur1.execute("insert into %sbooze values ('Victoria Bitter')" % ( + self.table_prefix + )) + cur2.execute("select name from %sbooze" % self.table_prefix) + booze = cur2.fetchall() + self.assertEqual(len(booze),1) + self.assertEqual(len(booze[0]),1) + self.assertEqual(booze[0][0],'Victoria Bitter') + finally: + con.close() + + def test_description(self): + con = self._connect() + try: + cur = con.cursor() + self.executeDDL1(cur) + self.assertEqual(cur.description,None, + 'cursor.description should be none after executing a ' + 'statement that can return no rows (such as DDL)' + ) + cur.execute('select name from %sbooze' % self.table_prefix) + self.assertEqual(len(cur.description),1, + 'cursor.description describes too many columns' + ) + self.assertEqual(len(cur.description[0]),7, + 'cursor.description[x] tuples must have 7 elements' + ) + self.assertEqual(cur.description[0][0].lower(),'name', + 'cursor.description[x][0] must return column name' + ) + self.assertEqual(cur.description[0][1],self.driver.STRING, + 'cursor.description[x][1] must return column type. Got %r' + % cur.description[0][1] + ) + + # Make sure self.description gets reset + self.executeDDL2(cur) + self.assertEqual(cur.description,None, + 'cursor.description not being set to None when executing ' + 'no-result statements (eg. DDL)' + ) + finally: + con.close() + + def test_rowcount(self): + con = self._connect() + try: + cur = con.cursor() + self.executeDDL1(cur) + _failUnless(self,cur.rowcount in (-1,0), # Bug #543885 + 'cursor.rowcount should be -1 or 0 after executing no-result ' + 'statements' + ) + cur.execute("insert into %sbooze values ('Victoria Bitter')" % ( + self.table_prefix + )) + _failUnless(self,cur.rowcount in (-1,1), + 'cursor.rowcount should == number or rows inserted, or ' + 'set to -1 after executing an insert statement' + ) + cur.execute("select name from %sbooze" % self.table_prefix) + _failUnless(self,cur.rowcount in (-1,1), + 'cursor.rowcount should == number of rows returned, or ' + 'set to -1 after executing a select statement' + ) + self.executeDDL2(cur) + self.assertEqual(cur.rowcount,-1, + 'cursor.rowcount not being reset to -1 after executing ' + 'no-result statements' + ) + finally: + con.close() + + lower_func = 'lower' + def test_callproc(self): + con = self._connect() + try: + cur = con.cursor() + if self.lower_func and hasattr(cur,'callproc'): + r = cur.callproc(self.lower_func,('FOO',)) + self.assertEqual(len(r),1) + self.assertEqual(r[0],'FOO') + r = cur.fetchall() + self.assertEqual(len(r),1,'callproc produced no result set') + self.assertEqual(len(r[0]),1, + 'callproc produced invalid result set' + ) + self.assertEqual(r[0][0],'foo', + 'callproc produced invalid results' + ) + finally: + con.close() + + def test_close(self): + con = self._connect() + try: + cur = con.cursor() + finally: + con.close() + + # cursor.execute should raise an Error if called after connection + # closed + self.assertRaises(self.driver.Error,self.executeDDL1,cur) + + # connection.commit should raise an Error if called after connection' + # closed.' + self.assertRaises(self.driver.Error,con.commit) + + # connection.close should raise an Error if called more than once + #!!! reasonable persons differ about the usefulness of this test and this feature !!! + if TEST_FOR_NON_IDEMPOTENT_CLOSE: + self.assertRaises(self.driver.Error,con.close) + + def test_execute(self): + con = self._connect() + try: + cur = con.cursor() + self._paraminsert(cur) + finally: + con.close() + + def _paraminsert(self,cur): + self.executeDDL2(cur) + cur.execute("insert into %sbarflys values ('Victoria Bitter', 'thi%%s :may ca%%(u)se? troub:1e')" % ( + self.table_prefix + )) + _failUnless(self,cur.rowcount in (-1,1)) + + if self.driver.paramstyle == 'qmark': + cur.execute( + "insert into %sbarflys values (?, 'thi%%s :may ca%%(u)se? troub:1e')" % self.table_prefix, + ("Cooper's",) + ) + elif self.driver.paramstyle == 'numeric': + cur.execute( + "insert into %sbarflys values (:1, 'thi%%s :may ca%%(u)se? troub:1e')" % self.table_prefix, + ("Cooper's",) + ) + elif self.driver.paramstyle == 'named': + cur.execute( + "insert into %sbarflys values (:beer, 'thi%%s :may ca%%(u)se? troub:1e')" % self.table_prefix, + {'beer':"Cooper's"} + ) + elif self.driver.paramstyle == 'format': + cur.execute( + "insert into %sbarflys values (%%s, 'thi%%s :may ca%%(u)se? troub:1e')" % self.table_prefix, + ("Cooper's",) + ) + elif self.driver.paramstyle == 'pyformat': + cur.execute( + "insert into %sbarflys values (%%(beer)s, 'thi%%s :may ca%%(u)se? troub:1e')" % self.table_prefix, + {'beer':"Cooper's"} + ) + else: + self.fail('Invalid paramstyle') + _failUnless(self,cur.rowcount in (-1,1)) + + cur.execute('select name, drink from %sbarflys' % self.table_prefix) + res = cur.fetchall() + self.assertEqual(len(res),2,'cursor.fetchall returned too few rows') + beers = [res[0][0],res[1][0]] + beers.sort() + self.assertEqual(beers[0],"Cooper's", + 'cursor.fetchall retrieved incorrect data, or data inserted ' + 'incorrectly' + ) + self.assertEqual(beers[1],"Victoria Bitter", + 'cursor.fetchall retrieved incorrect data, or data inserted ' + 'incorrectly' + ) + trouble = "thi%s :may ca%(u)se? troub:1e" + self.assertEqual(res[0][1], trouble, + 'cursor.fetchall retrieved incorrect data, or data inserted ' + 'incorrectly. Got=%s, Expected=%s' % (repr(res[0][1]), repr(trouble))) + self.assertEqual(res[1][1], trouble, + 'cursor.fetchall retrieved incorrect data, or data inserted ' + 'incorrectly. Got=%s, Expected=%s' % (repr(res[1][1]), repr(trouble) + )) + + def test_executemany(self): + con = self._connect() + try: + cur = con.cursor() + self.executeDDL1(cur) + largs = [ ("Cooper's",) , ("Boag's",) ] + margs = [ {'beer': "Cooper's"}, {'beer': "Boag's"} ] + if self.driver.paramstyle == 'qmark': + cur.executemany( + 'insert into %sbooze values (?)' % self.table_prefix, + largs + ) + elif self.driver.paramstyle == 'numeric': + cur.executemany( + 'insert into %sbooze values (:1)' % self.table_prefix, + largs + ) + elif self.driver.paramstyle == 'named': + cur.executemany( + 'insert into %sbooze values (:beer)' % self.table_prefix, + margs + ) + elif self.driver.paramstyle == 'format': + cur.executemany( + 'insert into %sbooze values (%%s)' % self.table_prefix, + largs + ) + elif self.driver.paramstyle == 'pyformat': + cur.executemany( + 'insert into %sbooze values (%%(beer)s)' % ( + self.table_prefix + ), + margs + ) + else: + self.fail('Unknown paramstyle') + _failUnless(self,cur.rowcount in (-1,2), + 'insert using cursor.executemany set cursor.rowcount to ' + 'incorrect value %r' % cur.rowcount + ) + cur.execute('select name from %sbooze' % self.table_prefix) + res = cur.fetchall() + self.assertEqual(len(res),2, + 'cursor.fetchall retrieved incorrect number of rows' + ) + beers = [res[0][0],res[1][0]] + beers.sort() + self.assertEqual(beers[0],"Boag's",'incorrect data "%s" retrieved' % beers[0]) + self.assertEqual(beers[1],"Cooper's",'incorrect data retrieved') + finally: + con.close() + + def test_fetchone(self): + con = self._connect() + try: + cur = con.cursor() + + # cursor.fetchone should raise an Error if called before + # executing a select-type query + self.assertRaises(self.driver.Error,cur.fetchone) + + # cursor.fetchone should raise an Error if called after + # executing a query that cannnot return rows + self.executeDDL1(cur) + self.assertRaises(self.driver.Error,cur.fetchone) + + cur.execute('select name from %sbooze' % self.table_prefix) + self.assertEqual(cur.fetchone(),None, + 'cursor.fetchone should return None if a query retrieves ' + 'no rows' + ) + _failUnless(self,cur.rowcount in (-1,0)) + + # cursor.fetchone should raise an Error if called after + # executing a query that cannnot return rows + cur.execute("insert into %sbooze values ('Victoria Bitter')" % ( + self.table_prefix + )) + self.assertRaises(self.driver.Error,cur.fetchone) + + cur.execute('select name from %sbooze' % self.table_prefix) + r = cur.fetchone() + self.assertEqual(len(r),1, + 'cursor.fetchone should have retrieved a single row' + ) + self.assertEqual(r[0],'Victoria Bitter', + 'cursor.fetchone retrieved incorrect data' + ) + self.assertEqual(cur.fetchone(),None, + 'cursor.fetchone should return None if no more rows available' + ) + _failUnless(self,cur.rowcount in (-1,1)) + finally: + con.close() + + samples = [ + 'Carlton Cold', + 'Carlton Draft', + 'Mountain Goat', + 'Redback', + 'Victoria Bitter', + 'XXXX' + ] + + def _populate(self): + ''' Return a list of sql commands to setup the DB for the fetch + tests. + ''' + populate = [ + "insert into %sbooze values ('%s')" % (self.table_prefix,s) + for s in self.samples + ] + return populate + + def test_fetchmany(self): + con = self._connect() + try: + cur = con.cursor() + + # cursor.fetchmany should raise an Error if called without + #issuing a query + self.assertRaises(self.driver.Error,cur.fetchmany,4) + + self.executeDDL1(cur) + for sql in self._populate(): + cur.execute(sql) + + cur.execute('select name from %sbooze' % self.table_prefix) + r = cur.fetchmany() + self.assertEqual(len(r),1, + 'cursor.fetchmany retrieved incorrect number of rows, ' + 'default of arraysize is one.' + ) + cur.arraysize=10 + r = cur.fetchmany(3) # Should get 3 rows + self.assertEqual(len(r),3, + 'cursor.fetchmany retrieved incorrect number of rows' + ) + r = cur.fetchmany(4) # Should get 2 more + self.assertEqual(len(r),2, + 'cursor.fetchmany retrieved incorrect number of rows' + ) + r = cur.fetchmany(4) # Should be an empty sequence + self.assertEqual(len(r),0, + 'cursor.fetchmany should return an empty sequence after ' + 'results are exhausted' + ) + _failUnless(self,cur.rowcount in (-1,6)) + + # Same as above, using cursor.arraysize + cur.arraysize=4 + cur.execute('select name from %sbooze' % self.table_prefix) + r = cur.fetchmany() # Should get 4 rows + self.assertEqual(len(r),4, + 'cursor.arraysize not being honoured by fetchmany' + ) + r = cur.fetchmany() # Should get 2 more + self.assertEqual(len(r),2) + r = cur.fetchmany() # Should be an empty sequence + self.assertEqual(len(r),0) + _failUnless(self,cur.rowcount in (-1,6)) + + cur.arraysize=6 + cur.execute('select name from %sbooze' % self.table_prefix) + rows = cur.fetchmany() # Should get all rows + _failUnless(self,cur.rowcount in (-1,6)) + self.assertEqual(len(rows),6) + self.assertEqual(len(rows),6) + rows = [r[0] for r in rows] + rows.sort() + + # Make sure we get the right data back out + for i in range(0,6): + self.assertEqual(rows[i],self.samples[i], + 'incorrect data retrieved by cursor.fetchmany' + ) + + rows = cur.fetchmany() # Should return an empty list + self.assertEqual(len(rows),0, + 'cursor.fetchmany should return an empty sequence if ' + 'called after the whole result set has been fetched' + ) + _failUnless(self,cur.rowcount in (-1,6)) + + self.executeDDL2(cur) + cur.execute('select name from %sbarflys' % self.table_prefix) + r = cur.fetchmany() # Should get empty sequence + self.assertEqual(len(r),0, + 'cursor.fetchmany should return an empty sequence if ' + 'query retrieved no rows' + ) + _failUnless(self,cur.rowcount in (-1,0)) + + finally: + con.close() + + def test_fetchall(self): + con = self._connect() + try: + cur = con.cursor() + # cursor.fetchall should raise an Error if called + # without executing a query that may return rows (such + # as a select) + self.assertRaises(self.driver.Error, cur.fetchall) + + self.executeDDL1(cur) + for sql in self._populate(): + cur.execute(sql) + + # cursor.fetchall should raise an Error if called + # after executing a a statement that cannot return rows + self.assertRaises(self.driver.Error,cur.fetchall) + + cur.execute('select name from %sbooze' % self.table_prefix) + rows = cur.fetchall() + _failUnless(self,cur.rowcount in (-1,len(self.samples))) + self.assertEqual(len(rows),len(self.samples), + 'cursor.fetchall did not retrieve all rows' + ) + rows = [r[0] for r in rows] + rows.sort() + for i in range(0,len(self.samples)): + self.assertEqual(rows[i],self.samples[i], + 'cursor.fetchall retrieved incorrect rows' + ) + rows = cur.fetchall() + self.assertEqual( + len(rows),0, + 'cursor.fetchall should return an empty list if called ' + 'after the whole result set has been fetched' + ) + _failUnless(self,cur.rowcount in (-1,len(self.samples))) + + self.executeDDL2(cur) + cur.execute('select name from %sbarflys' % self.table_prefix) + rows = cur.fetchall() + _failUnless(self,cur.rowcount in (-1,0)) + self.assertEqual(len(rows),0, + 'cursor.fetchall should return an empty list if ' + 'a select query returns no rows' + ) + + finally: + con.close() + + def test_mixedfetch(self): + con = self._connect() + try: + cur = con.cursor() + self.executeDDL1(cur) + for sql in self._populate(): + cur.execute(sql) + + cur.execute('select name from %sbooze' % self.table_prefix) + rows1 = cur.fetchone() + rows23 = cur.fetchmany(2) + rows4 = cur.fetchone() + rows56 = cur.fetchall() + _failUnless(self,cur.rowcount in (-1,6)) + self.assertEqual(len(rows23),2, + 'fetchmany returned incorrect number of rows' + ) + self.assertEqual(len(rows56),2, + 'fetchall returned incorrect number of rows' + ) + + rows = [rows1[0]] + rows.extend([rows23[0][0],rows23[1][0]]) + rows.append(rows4[0]) + rows.extend([rows56[0][0],rows56[1][0]]) + rows.sort() + for i in range(0,len(self.samples)): + self.assertEqual(rows[i],self.samples[i], + 'incorrect data retrieved or inserted' + ) + finally: + con.close() + + def help_nextset_setUp(self,cur): + ''' Should create a procedure called deleteme + that returns two result sets, first the + number of rows in booze then "name from booze" + ''' + raise NotImplementedError('Helper not implemented') + #sql=""" + # create procedure deleteme as + # begin + # select count(*) from booze + # select name from booze + # end + #""" + #cur.execute(sql) + + def help_nextset_tearDown(self,cur): + 'If cleaning up is needed after nextSetTest' + raise NotImplementedError('Helper not implemented') + #cur.execute("drop procedure deleteme") + + def test_nextset(self): + con = self._connect() + try: + cur = con.cursor() + if not hasattr(cur,'nextset'): + return + + try: + self.executeDDL1(cur) + sql=self._populate() + for sql in self._populate(): + cur.execute(sql) + + self.help_nextset_setUp(cur) + + cur.callproc('deleteme') + numberofrows=cur.fetchone() + assert numberofrows[0]== len(self.samples) + assert cur.nextset() + names=cur.fetchall() + assert len(names) == len(self.samples) + s=cur.nextset() + assert s == None,'No more return sets, should return None' + finally: + self.help_nextset_tearDown(cur) + + finally: + con.close() + + def test_nextset(self): + raise NotImplementedError('Drivers need to override this test') + + def test_arraysize(self): + # Not much here - rest of the tests for this are in test_fetchmany + con = self._connect() + try: + cur = con.cursor() + _failUnless(self,hasattr(cur,'arraysize'), + 'cursor.arraysize must be defined' + ) + finally: + con.close() + + def test_setinputsizes(self): + con = self._connect() + try: + cur = con.cursor() + cur.setinputsizes( (25,) ) + self._paraminsert(cur) # Make sure cursor still works + finally: + con.close() + + def test_setoutputsize_basic(self): + # Basic test is to make sure setoutputsize doesn't blow up + con = self._connect() + try: + cur = con.cursor() + cur.setoutputsize(1000) + cur.setoutputsize(2000,0) + self._paraminsert(cur) # Make sure the cursor still works + finally: + con.close() + + def test_setoutputsize(self): + # Real test for setoutputsize is driver dependant + raise NotImplementedError('Driver needed to override this test') + + def test_None(self): + con = self._connect() + try: + cur = con.cursor() + self.executeDDL1(cur) + cur.execute('insert into %sbooze values (NULL)' % self.table_prefix) + cur.execute('select name from %sbooze' % self.table_prefix) + r = cur.fetchall() + self.assertEqual(len(r),1) + self.assertEqual(len(r[0]),1) + self.assertEqual(r[0][0],None,'NULL value not returned as None') + finally: + con.close() + + def test_Date(self): + d1 = self.driver.Date(2002,12,25) + d2 = self.driver.DateFromTicks(time.mktime((2002,12,25,0,0,0,0,0,0))) + # Can we assume this? API doesn't specify, but it seems implied + # self.assertEqual(str(d1),str(d2)) + + def test_Time(self): + t1 = self.driver.Time(13,45,30) + t2 = self.driver.TimeFromTicks(time.mktime((2001,1,1,13,45,30,0,0,0))) + # Can we assume this? API doesn't specify, but it seems implied + # self.assertEqual(str(t1),str(t2)) + + def test_Timestamp(self): + t1 = self.driver.Timestamp(2002,12,25,13,45,30) + t2 = self.driver.TimestampFromTicks( + time.mktime((2002,12,25,13,45,30,0,0,0)) + ) + # Can we assume this? API doesn't specify, but it seems implied + # self.assertEqual(str(t1),str(t2)) + + def test_Binary(self): + b = self.driver.Binary(str2bytes('Something')) + b = self.driver.Binary(str2bytes('')) + + def test_STRING(self): + _failUnless(self, hasattr(self.driver,'STRING'), + 'module.STRING must be defined' + ) + + def test_BINARY(self): + _failUnless(self, hasattr(self.driver,'BINARY'), + 'module.BINARY must be defined.' + ) + + def test_NUMBER(self): + _failUnless(self, hasattr(self.driver,'NUMBER'), + 'module.NUMBER must be defined.' + ) + + def test_DATETIME(self): + _failUnless(self, hasattr(self.driver,'DATETIME'), + 'module.DATETIME must be defined.' + ) + + def test_ROWID(self): + _failUnless(self, hasattr(self.driver,'ROWID'), + 'module.ROWID must be defined.' + ) diff --git a/Lib/site-packages/adodbapi/test/is64bit.py b/Lib/site-packages/adodbapi/test/is64bit.py new file mode 100644 index 0000000..bb60360 --- /dev/null +++ b/Lib/site-packages/adodbapi/test/is64bit.py @@ -0,0 +1,33 @@ +"""is64bit.Python() --> boolean value of detected Python word size. is64bit.os() --> os build version""" +import sys + +def Python(): + if sys.platform == 'cli': #IronPython + import System + return System.IntPtr.Size == 8 + else: + try: + return sys.maxsize > 2147483647 + except AttributeError: + return sys.maxint > 2147483647 + +def os(): + import platform + pm = platform.machine() + if pm != '..' and pm.endswith('64'): # recent Python (not Iron) + return True + else: + import os + if 'PROCESSOR_ARCHITEW6432' in os.environ: + return True # 32 bit program running on 64 bit Windows + try: + return os.environ['PROCESSOR_ARCHITECTURE'].endswith('64') # 64 bit Windows 64 bit program + except IndexError: + pass # not Windows + try: + return '64' in platform.architecture()[0] # this often works in Linux + except: + return False # is an older version of Python, assume also an older os (best we can guess) + +if __name__ == "__main__": + print(("is64bit.Python() =", Python(), "is64bit.os() =", os())) diff --git a/Lib/site-packages/adodbapi/test/setuptestframework.py b/Lib/site-packages/adodbapi/test/setuptestframework.py new file mode 100644 index 0000000..b5859e2 --- /dev/null +++ b/Lib/site-packages/adodbapi/test/setuptestframework.py @@ -0,0 +1,113 @@ +#!/usr/bin/python2 +# Configure this in order to run the testcases. +"setuptestframework.py v 2.5.0.c9" + +import os +import sys +import tempfile +import shutil + +try: + OSErrors = (WindowsError, OSError) +except NameError: # not running on Windows + OSErrors = OSError + +def maketemp(): + temphome = tempfile.gettempdir() + tempdir = os.path.join(temphome, 'adodbapi_test') + ## try: ## if running simultanous test, don't erase the other thread's work + ## shutil.rmtree(tempdir) # kill off an old copy + ## except: pass + try: os.mkdir(tempdir) + except: pass + return tempdir + +def _cleanup_function(testfolder, mdb_name): + try: os.unlink(os.path.join(testfolder, mdb_name)) + except: pass # mdb database not present + try: shutil.rmtree(os.path.join(testfolder, 'adodbapi')) + except: pass # test package not present + +def getcleanupfunction(): + return _cleanup_function + +def find_ado_path(): + adoName = os.path.normpath(os.getcwd() + '/../../adodbapi.py') + adoPackage = os.path.dirname(adoName) + return adoPackage + +# make a new package directory for the test copy of ado +def makeadopackage(testfolder): + adoName = os.path.normpath(os.getcwd() + '/../adodbapi.py') + adoPath = os.path.dirname(adoName) + if os.path.exists(adoName): + newpackage = os.path.join(testfolder,'adodbapi') + try: + os.mkdir(newpackage) + except OSErrors: + print('*Note: temporary adodbapi package already exists: may be two versions running?') + for f in os.listdir(adoPath): + if f.endswith('.py'): + shutil.copy(os.path.join(adoPath, f), newpackage) + if sys.version_info >= (3,0): # only when running Py3.n + save = sys.stdout + sys.stdout = None + from lib2to3.main import main # use 2to3 to make test package + main("lib2to3.fixes",args=['-n','-w', newpackage]) + sys.stdout = save + return testfolder + else: + raise EnvironmentError('Connot find source of adodbapi to test.') + +def makemdb(testfolder, mdb_name): + # following setup code borrowed from pywin32 odbc test suite + # kindly contributed by Frank Millman. + import os + + _accessdatasource = os.path.join(testfolder, mdb_name) + if not os.path.isfile(_accessdatasource): + try: + from win32com.client.gencache import EnsureDispatch + from win32com.client import constants + win32 = True + except ImportError: #perhaps we are running IronPython + win32 = False #iron Python + try: + from System import Activator, Type + except: + pass + + # Create a brand-new database - what is the story with these? + dbe = None + for suffix in (".36", ".35", ".30"): + try: + if win32: + dbe = EnsureDispatch("DAO.DBEngine" + suffix) + else: + type= Type.GetTypeFromProgID("DAO.DBEngine" + suffix) + dbe = Activator.CreateInstance(type) + break + except: + pass + if dbe: + print((' ...Creating ACCESS db at '+_accessdatasource)) + if win32: + workspace = dbe.Workspaces(0) + newdb = workspace.CreateDatabase(_accessdatasource, + constants.dbLangGeneral, + constants.dbEncrypt) + else: + newdb = dbe.CreateDatabase(_accessdatasource,';LANGID=0x0409;CP=1252;COUNTRY=0') + newdb.Close() + else: + print((' ...copying test ACCESS db to '+_accessdatasource)) + mdbName = os.path.normpath(os.getcwd() + '/../examples/test.mdb') + import shutil + shutil.copy(mdbName, _accessdatasource) + + return _accessdatasource + +if __name__ == "__main__": + print('Setting up a Jet database for server to use for remote testing...') + temp = maketemp() + makemdb(temp, 'server_test.mdb') diff --git a/Lib/site-packages/adodbapi/test/test_adodbapi_dbapi20.py b/Lib/site-packages/adodbapi/test/test_adodbapi_dbapi20.py new file mode 100644 index 0000000..89362c8 --- /dev/null +++ b/Lib/site-packages/adodbapi/test/test_adodbapi_dbapi20.py @@ -0,0 +1,181 @@ +print("This module depends on the dbapi20 compliance tests created by Stuart Bishop") +print("(see db-sig mailing list history for info)") +import platform +import unittest +import sys + +import dbapi20 +import setuptestframework + +testfolder = setuptestframework.maketemp() +if '--package' in sys.argv: + pth = setuptestframework.makeadopackage(testfolder) + sys.argv.remove('--package') +else: + pth = setuptestframework.find_ado_path() +if pth not in sys.path: + sys.path.insert(1,pth) +# function to clean up the temporary folder -- calling program must run this function before exit. +cleanup = setuptestframework.getcleanupfunction() + +import adodbapi +import adodbapi.is64bit as is64bit +db = adodbapi + +if '--verbose' in sys.argv: + db.adodbapi.verbose = 3 + +print((adodbapi.version)) +print(("Tested with dbapi20 %s" % dbapi20.__version__)) + +try: + onWindows = bool(sys.getwindowsversion()) # seems to work on all versions of Python +except: + onWindows = False + +node = platform.node() + +conn_kws = {} +host = None # if None, will use macro to fill in node name +instance = r'%s\SQLExpress' +conn_kws['name'] = 'adotest' + +if host is None: + conn_kws['macro_getnode'] = ['host', instance] +else: + conn_kws['host'] = host + +conn_kws['provider'] = 'Provider=SQLNCLI11;DataTypeCompatibility=80;MARS Connection=True;' +connStr = "%(provider)s; Integrated Security=SSPI; Initial Catalog=%(name)s;Data Source=%(host)s" + +if onWindows and node != "z-PC": + pass # default should make a local SQL Server connection +elif node == "xxx": # try Postgres database + _computername = "25.223.161.222" + _databasename='adotest' + _username = 'adotestuser' + _password = '12345678' + _driver="PostgreSQL Unicode" + _provider = '' + connStr = '%sDriver={%s};Server=%s;Database=%s;uid=%s;pwd=%s;' % \ + (_provider,_driver,_computername,_databasename,_username,_password) +elif node == "yyy": # ACCESS data base is known to fail some tests. + if is64bit.Python(): + driver = "Microsoft.ACE.OLEDB.12.0" + else: + driver = "Microsoft.Jet.OLEDB.4.0" + testmdb = setuptestframework.makemdb(testfolder) + connStr = r"Provider=%s;Data Source=%s" % (driver, testmdb) +else: # try a remote connection to an SQL server + conn_kws['proxy_host'] = '25.44.77.176' + import adodbapi.remote + db = adodbapi.remote + +print(('Using Connection String like=%s' % connStr)) +print(('Keywords=%s' % repr(conn_kws))) + +class test_adodbapi(dbapi20.DatabaseAPI20Test): + driver = db + connect_args = (connStr,) + connect_kw_args = conn_kws + + def __init__(self,arg): + dbapi20.DatabaseAPI20Test.__init__(self,arg) + + def testMethodName(self): + return self.id().split('.')[-1] + + def setUp(self): + # Call superclass setUp In case this does something in the + # future + dbapi20.DatabaseAPI20Test.setUp(self) + if self.testMethodName()=='test_callproc': + con = self._connect() + engine = con.dbms_name + ## print('Using database Engine=%s' % engine) ## + if engine != 'MS Jet': + sql=""" + create procedure templower + @theData varchar(50) + as + select lower(@theData) + """ + else: # Jet + sql=""" + create procedure templower + (theData varchar(50)) + as + select lower(theData); + """ + cur = con.cursor() + try: + cur.execute(sql) + con.commit() + except: + pass + cur.close() + con.close() + self.lower_func='templower' + + + def tearDown(self): + if self.testMethodName()=='test_callproc': + con = self._connect() + cur = con.cursor() + try: + cur.execute("drop procedure templower") + except: + pass + con.commit() + dbapi20.DatabaseAPI20Test.tearDown(self) + + + def help_nextset_setUp(self,cur): + 'Should create a procedure called deleteme ' + 'that returns two result sets, first the number of rows in booze then "name from booze"' + sql=""" + create procedure deleteme as + begin + select count(*) from %sbooze + select name from %sbooze + end + """ %(self.table_prefix,self.table_prefix) + cur.execute(sql) + + def help_nextset_tearDown(self,cur): + 'If cleaning up is needed after nextSetTest' + try: + cur.execute("drop procedure deleteme") + except: + pass + + def test_nextset(self): + con = self._connect() + try: + cur = con.cursor() + + stmts=[self.ddl1] + self._populate() + for sql in stmts: + cur.execute(sql) + + self.help_nextset_setUp(cur) + + cur.callproc('deleteme') + numberofrows=cur.fetchone() + assert numberofrows[0]== 6 + assert cur.nextset() + names=cur.fetchall() + assert len(names) == len(self.samples) + s=cur.nextset() + assert s == None,'No more return sets, should return None' + finally: + try: + self.help_nextset_tearDown(cur) + finally: + con.close() + + def test_setoutputsize(self): pass + +if __name__ == '__main__': + unittest.main() + cleanup(testfolder, None) diff --git a/Lib/site-packages/adodbapi/test/tryconnection2.py b/Lib/site-packages/adodbapi/test/tryconnection2.py new file mode 100644 index 0000000..fa0b8b9 --- /dev/null +++ b/Lib/site-packages/adodbapi/test/tryconnection2.py @@ -0,0 +1,46 @@ +# This module may be retired as soon as Python 2.5 support is dropped. +# +# It exists only to allow trapping exceptions using the "except [exception list], e" format +# which is a syntax error in Python 3 + +def try_connection(verbose, *args, **kwargs): + import adodbapi + + if "proxy_host" in kwargs or 'pyro_connection' in kwargs or 'proxy_host' in args: + import adodbapi.remote + import Pyro4 + pyroError = Pyro4.errors.PyroError + dbconnect = adodbapi.remote.connect + remote = True + else: + dbconnect = adodbapi.connect + pyroError = NotImplementedError # (will not occur) + remote = False + try: + s = dbconnect(*args, **kwargs) # connect to server + if verbose: + print('Connected to:', s.connection_string) + print('which has tables:', s.get_table_names()) + s.close() # thanks, it worked, goodbye + except (adodbapi.DatabaseError, pyroError) as inst: + print(inst.args[0]) # should be the error message + print('***Failed getting connection using=', repr(args), repr(kwargs)) + if remote: + print('** Is your Python2 ado.connection server running?') + print('* Have you run "setuptestframework.py" to create server_test.mdb?') + return False, (args, kwargs), None + + if remote: + print(" (remote)", end=' ') + print(" (successful)") + + return True, (args, kwargs, remote), dbconnect + +def try_operation_with_expected_exception(expected_exceptions, some_function, args, kwargs): + try: + some_function(*args, **kwargs) + except expected_exceptions as e: + return True, e + except: + raise # an exception other than the expected occurred + return False, 'The expected exception did not occur' diff --git a/Lib/site-packages/adodbapi/test/tryconnection3.py b/Lib/site-packages/adodbapi/test/tryconnection3.py new file mode 100644 index 0000000..7871174 --- /dev/null +++ b/Lib/site-packages/adodbapi/test/tryconnection3.py @@ -0,0 +1,48 @@ +from __future__ import print_function +# This module may be retired as soon as Python 2.5 support is dropped. +# +# It exists only to allow trapping exceptions using the "except [exception list] as e" format +# which is a syntax error in Python 2.5 + +def try_connection(verbose, *args, **kwargs): + import adodbapi + + if "proxy_host" in kwargs or "pyro_connection" in kwargs or "proxy_host" in args: + import adodbapi.remote + import Pyro4 + pyroError = Pyro4.errors.PyroError + dbconnect = adodbapi.remote.connect + remote = True + else: + dbconnect = adodbapi.connect + pyroError = NotImplementedError # (will not occur) + remote = False + try: + s = dbconnect(*args, **kwargs) # connect to server + if verbose: + print('Connected to:', s.connection_string) + print('which has tables:', s.get_table_names()) + s.close() # thanks, it worked, goodbye + except adodbapi.DatabaseError as inst: + print(inst.args[0]) # should be the error message + print('***Failed getting connection using=',repr(args),repr(kwargs)) + if remote: + print('** Are you running a *Python3* ado.connection server? **') + print('* Have you run "setuptestframework.py" to create server_test.mdb?') + return False, (args, kwargs), None + + if remote: + print(" (remote)",end="") + print(" (successful)") + + return True, (args, kwargs, remote), dbconnect + + +def try_operation_with_expected_exception(expected_exception_list, some_function, *args, **kwargs): + try: + some_function(*args, **kwargs) + except expected_exception_list as e: + return True, e + except: + raise # an exception other than the expected occurred + return False, 'The expected exception did not occur' diff --git a/Lib/site-packages/isapi/PyISAPI_loader.dll b/Lib/site-packages/isapi/PyISAPI_loader.dll new file mode 100644 index 0000000..d289453 Binary files /dev/null and b/Lib/site-packages/isapi/PyISAPI_loader.dll differ diff --git a/Lib/site-packages/isapi/README.txt b/Lib/site-packages/isapi/README.txt new file mode 100644 index 0000000..e65feb9 --- /dev/null +++ b/Lib/site-packages/isapi/README.txt @@ -0,0 +1,7 @@ +A Python ISAPI extension. Contributed by Phillip Frantz, and is +Copyright 2002-2003 by Blackdog Software Pty Ltd. + +See the 'samples' directory, and particularly samples\README.txt + +You can find documentation in the PyWin32.chm file that comes with pywin32 - +you can open this from Pythonwin->Help, or from the start menu. \ No newline at end of file diff --git a/Lib/site-packages/isapi/__init__.py b/Lib/site-packages/isapi/__init__.py new file mode 100644 index 0000000..c4778ce --- /dev/null +++ b/Lib/site-packages/isapi/__init__.py @@ -0,0 +1,33 @@ +# The Python ISAPI package. + +# Exceptions thrown by the DLL framework. +class ISAPIError(Exception): + def __init__(self, errno, strerror = None, funcname = None): + # named attributes match IOError etc. + self.errno = errno + self.strerror = strerror + self.funcname = funcname + Exception.__init__(self, errno, strerror, funcname) + def __str__(self): + if self.strerror is None: + try: + import win32api + self.strerror = win32api.FormatMessage(self.errno).strip() + except: + self.strerror = "no error message is available" + # str() looks like a win32api error. + return str( (self.errno, self.strerror, self.funcname) ) + +class FilterError(ISAPIError): + pass + +class ExtensionError(ISAPIError): + pass + +# A little development aid - a filter or extension callback function can +# raise one of these exceptions, and the handler module will be reloaded. +# This means you can change your code without restarting IIS. +# After a reload, your filter/extension will have the GetFilterVersion/ +# GetExtensionVersion function called, but with None as the first arg. +class InternalReloadException(Exception): + pass diff --git a/Lib/site-packages/isapi/doc/isapi.html b/Lib/site-packages/isapi/doc/isapi.html new file mode 100644 index 0000000..4662c5c --- /dev/null +++ b/Lib/site-packages/isapi/doc/isapi.html @@ -0,0 +1,92 @@ + + + +Introduction to Python ISAPI support + +

Introduction to Python ISAPI support

+ +

See also

+ +

Note: if you are viewing this documentation directly from disk, +most links in this document will fail - you can also find this document in the +CHM file that comes with pywin32, where the links will work + +

Introduction

+This documents Python support for hosting ISAPI exensions and filters inside +Microsoft Internet Information Server (IIS). It assumes a basic understanding +of the ISAPI filter and extension mechanism. +

+In summary, to implement a filter or extension, you provide a Python module +which defines a Filter and/or Extension class. Once your class has been +loaded, IIS/ISAPI will, via an extension DLL, call methods on your class. +

+A filter and a class instance need only provide 3 methods - for filters they +are called GetFilterVersion, HttpFilterProc and +TerminateFilter. For extensions they +are named GetExtensionVersion, HttpExtensionProc and +TerminateExtension. If you are familiar with writing ISAPI +extensions in C/C++, these names and their purpose will be familiar. +

+Most of the work is done in the HttpFilterProc and +HttpExtensionProc methods. These both take a single +parameter - an HTTP_FILTER_CONTEXT and +EXTENSION_CONTROL_BLOCK +object respectively. +

+In addition to these components, there is an 'isapi' package, containing +support facilities (base-classes, exceptions, etc) which can be leveraged +by the extension. + +

Base classes

+There are a number of base classes provided to make writing extensions a little +simpler. Of particular note is isapi.threaded_extension.ThreadPoolExtension. +This implements a thread-pool and informs IIS that the request is progressing +in the background. Your sub-class need only provide a Dispatch +method, which is called on one of the worker threads rather than the thread +that the request came in on. +

+There is base-class for a filter in isapi.simple, but there is no +equivilent threaded filter - filters work under a different model, where +background processing is not possible. +

Samples

+Please see the isapi/samples directory for some sample filters +and extensions. + +

Implementation

+A Python ISAPI filter extension consists of 2 main components: +
    +
  • A DLL used by ISAPI to interface with Python.
  • +
  • A Python script used by that DLL to implement the filter or extension +functionality
  • +
+ +

Extension DLL

+The DLL is usually managed automatically by the isapi.install module. As the +Python script for the extension is installed, a generic DLL provided with +the isapi package is installed next to the script, and IIS configured to +use this DLL. +

+The name of the DLL always has the same base name as the Python script, but +with a leading underscore (_), and an extension of .dll. For example, the +sample "redirector.py" will, when installed, have "_redirector.dll" created +in the same directory. +

+The Python script may provide 2 entry points - methods named __FilterFactory__ +and __ExtensionFactory__, both taking no arguments and returning a filter or +extension object. + +

Using py2exe and the isapi package

+You can instruct py2exe to create a 'frozen' Python ISAPI filter/extension. +In this case, py2exe will create a package with everything you need in one +directory, and the Python source file embedded in the .zip file. +

+In general, you will want to build a seperate installation executable along +with the ISAPI extension. This executable will be built from the same script. +See the ISAPI sample in the py2exe distribution. diff --git a/Lib/site-packages/isapi/install.py b/Lib/site-packages/isapi/install.py new file mode 100644 index 0000000..b68d039 --- /dev/null +++ b/Lib/site-packages/isapi/install.py @@ -0,0 +1,730 @@ +"""Installation utilities for Python ISAPI filters and extensions.""" + +# this code adapted from "Tomcat JK2 ISAPI redirector", part of Apache +# Created July 2004, Mark Hammond. +import sys, os, imp, shutil, stat +import operator +from win32com.client import GetObject, Dispatch +from win32com.client.gencache import EnsureModule, EnsureDispatch +import win32api +import pythoncom +import winerror +import traceback + +_APP_INPROC = 0 +_APP_OUTPROC = 1 +_APP_POOLED = 2 +_IIS_OBJECT = "IIS://LocalHost/W3SVC" +_IIS_SERVER = "IIsWebServer" +_IIS_WEBDIR = "IIsWebDirectory" +_IIS_WEBVIRTUALDIR = "IIsWebVirtualDir" +_IIS_FILTERS = "IIsFilters" +_IIS_FILTER = "IIsFilter" + +_DEFAULT_SERVER_NAME = "Default Web Site" +_DEFAULT_HEADERS = "X-Powered-By: Python" +_DEFAULT_PROTECTION = _APP_POOLED + +# Default is for 'execute' only access - ie, only the extension +# can be used. This can be overridden via your install script. +_DEFAULT_ACCESS_EXECUTE = True +_DEFAULT_ACCESS_READ = False +_DEFAULT_ACCESS_WRITE = False +_DEFAULT_ACCESS_SCRIPT = False +_DEFAULT_CONTENT_INDEXED = False +_DEFAULT_ENABLE_DIR_BROWSING = False +_DEFAULT_ENABLE_DEFAULT_DOC = False + +_extensions = [ext for ext, _, _ in imp.get_suffixes()] +is_debug_build = '_d.pyd' in _extensions + +this_dir = os.path.abspath(os.path.dirname(__file__)) + +class FilterParameters: + Name = None + Description = None + Path = None + Server = None + # Params that control if/how AddExtensionFile is called. + AddExtensionFile = True + AddExtensionFile_Enabled = True + AddExtensionFile_GroupID = None # defaults to Name + AddExtensionFile_CanDelete = True + AddExtensionFile_Description = None # defaults to Description. + + def __init__(self, **kw): + self.__dict__.update(kw) + +class VirtualDirParameters: + Name = None # Must be provided. + Description = None # defaults to Name + AppProtection = _DEFAULT_PROTECTION + Headers = _DEFAULT_HEADERS + Path = None # defaults to WWW root. + Type = _IIS_WEBVIRTUALDIR + AccessExecute = _DEFAULT_ACCESS_EXECUTE + AccessRead = _DEFAULT_ACCESS_READ + AccessWrite = _DEFAULT_ACCESS_WRITE + AccessScript = _DEFAULT_ACCESS_SCRIPT + ContentIndexed = _DEFAULT_CONTENT_INDEXED + EnableDirBrowsing = _DEFAULT_ENABLE_DIR_BROWSING + EnableDefaultDoc = _DEFAULT_ENABLE_DEFAULT_DOC + DefaultDoc = None # Only set in IIS if not None + ScriptMaps = [] + ScriptMapUpdate = "end" # can be 'start', 'end', 'replace' + Server = None + + def __init__(self, **kw): + self.__dict__.update(kw) + + def is_root(self): + "This virtual directory is a root directory if parent and name are blank" + parent, name = self.split_path() + return not parent and not name + + def split_path(self): + return split_path(self.Name) + +class ScriptMapParams: + Extension = None + Module = None + Flags = 5 + Verbs = "" + # Params that control if/how AddExtensionFile is called. + AddExtensionFile = True + AddExtensionFile_Enabled = True + AddExtensionFile_GroupID = None # defaults to Name + AddExtensionFile_CanDelete = True + AddExtensionFile_Description = None # defaults to Description. + def __init__(self, **kw): + self.__dict__.update(kw) + + def __str__(self): + "Format this parameter suitable for IIS" + items = [self.Extension, self.Module, self.Flags] + # IIS gets upset if there is a trailing verb comma, but no verbs + if self.Verbs: + items.append(self.Verbs) + items = [str(item) for item in items] + return ','.join(items) + +class ISAPIParameters: + ServerName = _DEFAULT_SERVER_NAME + # Description = None + Filters = [] + VirtualDirs = [] + def __init__(self, **kw): + self.__dict__.update(kw) + +verbose = 1 # The level - 0 is quiet. +def log(level, what): + if verbose >= level: + print(what) + +# Convert an ADSI COM exception to the Win32 error code embedded in it. +def _GetWin32ErrorCode(com_exc): + hr = com_exc.hresult + # If we have more details in the 'excepinfo' struct, use it. + if com_exc.excepinfo: + hr = com_exc.excepinfo[-1] + if winerror.HRESULT_FACILITY(hr) != winerror.FACILITY_WIN32: + raise + return winerror.SCODE_CODE(hr) + +class InstallationError(Exception): pass +class ItemNotFound(InstallationError): pass +class ConfigurationError(InstallationError): pass + +def FindPath(options, server, name): + if name.lower().startswith("iis://"): + return name + else: + if name and name[0] != "/": + name = "/"+name + return FindWebServer(options, server)+"/ROOT"+name + +def LocateWebServerPath(description): + """ + Find an IIS web server whose name or comment matches the provided + description (case-insensitive). + + >>> LocateWebServerPath('Default Web Site') # doctest: +SKIP + + or + + >>> LocateWebServerPath('1') #doctest: +SKIP + """ + assert len(description) >= 1, "Server name or comment is required" + iis = GetObject(_IIS_OBJECT) + description = description.lower().strip() + for site in iis: + # Name is generally a number, but no need to assume that. + site_attributes = [getattr(site, attr, "").lower().strip() + for attr in ("Name", "ServerComment")] + if description in site_attributes: + return site.AdsPath + msg = "No web sites match the description '%s'" % description + raise ItemNotFound(msg) + +def GetWebServer(description = None): + """ + Load the web server instance (COM object) for a given instance + or description. + If None is specified, the default website is retrieved (indicated + by the identifier 1. + """ + description = description or "1" + path = LocateWebServerPath(description) + server = LoadWebServer(path) + return server + +def LoadWebServer(path): + try: + server = GetObject(path) + except pythoncom.com_error as details: + msg = details.strerror + if exc.excepinfo and exc.excepinfo[2]: + msg = exc.excepinfo[2] + msg = "WebServer %s: %s" % (path, msg) + raise ItemNotFound(msg) + return server + +def FindWebServer(options, server_desc): + """ + Legacy function to allow options to define a .server property + to override the other parameter. Use GetWebServer instead. + """ + # options takes precedence + server_desc = options.server or server_desc + # make sure server_desc is unicode (could be mbcs if passed in + # sys.argv). + if server_desc and not isinstance(server_desc, str): + server_desc = server_desc.decode('mbcs') + + # get the server (if server_desc is None, the default site is acquired) + server = GetWebServer(server_desc) + return server.adsPath + +def split_path(path): + """ + Get the parent path and basename. + + >>> split_path('/') + ['', ''] + + >>> split_path('') + ['', ''] + + >>> split_path('foo') + ['', 'foo'] + + >>> split_path('/foo') + ['', 'foo'] + + >>> split_path('/foo/bar') + ['/foo', 'bar'] + + >>> split_path('foo/bar') + ['/foo', 'bar'] + """ + + if not path.startswith('/'): path = '/' + path + return path.rsplit('/', 1) + +def _CreateDirectory(iis_dir, name, params): + # We used to go to lengths to keep an existing virtual directory + # in place. However, in some cases the existing directories got + # into a bad state, and an update failed to get them working. + # So we nuke it first. If this is a problem, we could consider adding + # a --keep-existing option. + try: + # Also seen the Class change to a generic IISObject - so nuke + # *any* existing object, regardless of Class + assert name.strip("/"), "mustn't delete the root!" + iis_dir.Delete('', name) + log(2, "Deleted old directory '%s'" % (name,)) + except pythoncom.com_error: + pass + + newDir = iis_dir.Create(params.Type, name) + log(2, "Creating new directory '%s' in %s..." % (name,iis_dir.Name)) + + friendly = params.Description or params.Name + newDir.AppFriendlyName = friendly + + # Note that the new directory won't be visible in the IIS UI + # unless the directory exists on the filesystem. + try: + path = params.Path or iis_dir.Path + newDir.Path = path + except AttributeError: + # If params.Type is IIS_WEBDIRECTORY, an exception is thrown + pass + newDir.AppCreate2(params.AppProtection) + # XXX - note that these Headers only work in IIS6 and earlier. IIS7 + # only supports them on the w3svc node - not even on individial sites, + # let alone individual extensions in the site! + if params.Headers: + newDir.HttpCustomHeaders = params.Headers + + log(2, "Setting directory options...") + newDir.AccessExecute = params.AccessExecute + newDir.AccessRead = params.AccessRead + newDir.AccessWrite = params.AccessWrite + newDir.AccessScript = params.AccessScript + newDir.ContentIndexed = params.ContentIndexed + newDir.EnableDirBrowsing = params.EnableDirBrowsing + newDir.EnableDefaultDoc = params.EnableDefaultDoc + if params.DefaultDoc is not None: + newDir.DefaultDoc = params.DefaultDoc + newDir.SetInfo() + return newDir + + +def CreateDirectory(params, options): + _CallHook(params, "PreInstall", options) + if not params.Name: + raise ConfigurationError("No Name param") + parent, name = params.split_path() + target_dir = GetObject(FindPath(options, params.Server, parent)) + + if not params.is_root(): + target_dir = _CreateDirectory(target_dir, name, params) + + AssignScriptMaps(params.ScriptMaps, target_dir, params.ScriptMapUpdate) + + _CallHook(params, "PostInstall", options, target_dir) + log(1, "Configured Virtual Directory: %s" % (params.Name,)) + return target_dir + +def AssignScriptMaps(script_maps, target, update='replace'): + """Updates IIS with the supplied script map information. + + script_maps is a list of ScriptMapParameter objects + + target is an IIS Virtual Directory to assign the script maps to + + update is a string indicating how to update the maps, one of ('start', + 'end', or 'replace') + """ + # determine which function to use to assign script maps + script_map_func = '_AssignScriptMaps' + update.capitalize() + try: + script_map_func = eval(script_map_func) + except NameError: + msg = "Unknown ScriptMapUpdate option '%s'" % update + raise ConfigurationError(msg) + # use the str method to format the script maps for IIS + script_maps = [str(s) for s in script_maps] + # call the correct function + script_map_func(target, script_maps) + target.SetInfo() + +def get_unique_items(sequence, reference): + "Return items in sequence that can't be found in reference." + return tuple([item for item in sequence if item not in reference]) + +def _AssignScriptMapsReplace(target, script_maps): + target.ScriptMaps = script_maps + +def _AssignScriptMapsEnd(target, script_maps): + unique_new_maps = get_unique_items(script_maps, target.ScriptMaps) + target.ScriptMaps = target.ScriptMaps + unique_new_maps + +def _AssignScriptMapsStart(target, script_maps): + unique_new_maps = get_unique_items(script_maps, target.ScriptMaps) + target.ScriptMaps = unique_new_maps + target.ScriptMaps + +def CreateISAPIFilter(filterParams, options): + server = FindWebServer(options, filterParams.Server) + _CallHook(filterParams, "PreInstall", options) + try: + filters = GetObject(server+"/Filters") + except pythoncom.com_error as exc: + # Brand new sites don't have the '/Filters' collection - create it. + # Any errors other than 'not found' we shouldn't ignore. + if winerror.HRESULT_FACILITY(exc.hresult) != winerror.FACILITY_WIN32 or \ + winerror.HRESULT_CODE(exc.hresult) != winerror.ERROR_PATH_NOT_FOUND: + raise + server_ob = GetObject(server) + filters = server_ob.Create(_IIS_FILTERS, "Filters") + filters.FilterLoadOrder = "" + filters.SetInfo() + + # As for VirtualDir, delete an existing one. + assert filterParams.Name.strip("/"), "mustn't delete the root!" + try: + filters.Delete(_IIS_FILTER, filterParams.Name) + log(2, "Deleted old filter '%s'" % (filterParams.Name,)) + except pythoncom.com_error: + pass + newFilter = filters.Create(_IIS_FILTER, filterParams.Name) + log(2, "Created new ISAPI filter...") + assert os.path.isfile(filterParams.Path) + newFilter.FilterPath = filterParams.Path + newFilter.FilterDescription = filterParams.Description + newFilter.SetInfo() + load_order = [b.strip() for b in filters.FilterLoadOrder.split(",") if b] + if filterParams.Name not in load_order: + load_order.append(filterParams.Name) + filters.FilterLoadOrder = ",".join(load_order) + filters.SetInfo() + _CallHook(filterParams, "PostInstall", options, newFilter) + log (1, "Configured Filter: %s" % (filterParams.Name,)) + return newFilter + +def DeleteISAPIFilter(filterParams, options): + _CallHook(filterParams, "PreRemove", options) + server = FindWebServer(options, filterParams.Server) + ob_path = server+"/Filters" + try: + filters = GetObject(ob_path) + except pythoncom.com_error as details: + # failure to open the filters just means a totally clean IIS install + # (IIS5 at least has no 'Filters' key when freshly installed). + log(2, "ISAPI filter path '%s' did not exist." % (ob_path,)) + return + try: + assert filterParams.Name.strip("/"), "mustn't delete the root!" + filters.Delete(_IIS_FILTER, filterParams.Name) + log(2, "Deleted ISAPI filter '%s'" % (filterParams.Name,)) + except pythoncom.com_error as details: + rc = _GetWin32ErrorCode(details) + if rc != winerror.ERROR_PATH_NOT_FOUND: + raise + log(2, "ISAPI filter '%s' did not exist." % (filterParams.Name,)) + # Remove from the load order + load_order = [b.strip() for b in filters.FilterLoadOrder.split(",") if b] + if filterParams.Name in load_order: + load_order.remove(filterParams.Name) + filters.FilterLoadOrder = ",".join(load_order) + filters.SetInfo() + _CallHook(filterParams, "PostRemove", options) + log (1, "Deleted Filter: %s" % (filterParams.Name,)) + +def _AddExtensionFile(module, def_groupid, def_desc, params, options): + group_id = params.AddExtensionFile_GroupID or def_groupid + desc = params.AddExtensionFile_Description or def_desc + try: + ob = GetObject(_IIS_OBJECT) + ob.AddExtensionFile(module, + params.AddExtensionFile_Enabled, + group_id, + params.AddExtensionFile_CanDelete, + desc) + log(2, "Added extension file '%s' (%s)" % (module, desc)) + except (pythoncom.com_error, AttributeError) as details: + # IIS5 always fails. Probably should upgrade this to + # complain more loudly if IIS6 fails. + log(2, "Failed to add extension file '%s': %s" % (module, details)) + +def AddExtensionFiles(params, options): + """Register the modules used by the filters/extensions as a trusted + 'extension module' - required by the default IIS6 security settings.""" + # Add each module only once. + added = {} + for vd in params.VirtualDirs: + for smp in vd.ScriptMaps: + if smp.Module not in added and smp.AddExtensionFile: + _AddExtensionFile(smp.Module, vd.Name, vd.Description, smp, + options) + added[smp.Module] = True + + for fd in params.Filters: + if fd.Path not in added and fd.AddExtensionFile: + _AddExtensionFile(fd.Path, fd.Name, fd.Description, fd, options) + added[fd.Path] = True + +def _DeleteExtensionFileRecord(module, options): + try: + ob = GetObject(_IIS_OBJECT) + ob.DeleteExtensionFileRecord(module) + log(2, "Deleted extension file record for '%s'" % module) + except (pythoncom.com_error, AttributeError) as details: + log(2, "Failed to remove extension file '%s': %s" % (module, details)) + +def DeleteExtensionFileRecords(params, options): + deleted = {} # only remove each .dll once. + for vd in params.VirtualDirs: + for smp in vd.ScriptMaps: + if smp.Module not in deleted and smp.AddExtensionFile: + _DeleteExtensionFileRecord(smp.Module, options) + deleted[smp.Module] = True + + for filter_def in params.Filters: + if filter_def.Path not in deleted and filter_def.AddExtensionFile: + _DeleteExtensionFileRecord(filter_def.Path, options) + deleted[filter_def.Path] = True + +def CheckLoaderModule(dll_name): + suffix = "" + if is_debug_build: suffix = "_d" + template = os.path.join(this_dir, + "PyISAPI_loader" + suffix + ".dll") + if not os.path.isfile(template): + raise ConfigurationError( + "Template loader '%s' does not exist" % (template,)) + # We can't do a simple "is newer" check, as the DLL is specific to the + # Python version. So we check the date-time and size are identical, + # and skip the copy in that case. + src_stat = os.stat(template) + try: + dest_stat = os.stat(dll_name) + except os.error: + same = 0 + else: + same = src_stat[stat.ST_SIZE]==dest_stat[stat.ST_SIZE] and \ + src_stat[stat.ST_MTIME]==dest_stat[stat.ST_MTIME] + if not same: + log(2, "Updating %s->%s" % (template, dll_name)) + shutil.copyfile(template, dll_name) + shutil.copystat(template, dll_name) + else: + log(2, "%s is up to date." % (dll_name,)) + +def _CallHook(ob, hook_name, options, *extra_args): + func = getattr(ob, hook_name, None) + if func is not None: + args = (ob,options) + extra_args + func(*args) + +def Install(params, options): + _CallHook(params, "PreInstall", options) + for vd in params.VirtualDirs: + CreateDirectory(vd, options) + + for filter_def in params.Filters: + CreateISAPIFilter(filter_def, options) + + AddExtensionFiles(params, options) + + _CallHook(params, "PostInstall", options) + +def RemoveDirectory(params, options): + if params.is_root(): + return + try: + directory = GetObject(FindPath(options, params.Server, params.Name)) + except pythoncom.com_error as details: + rc = _GetWin32ErrorCode(details) + if rc != winerror.ERROR_PATH_NOT_FOUND: + raise + log(2, "VirtualDirectory '%s' did not exist" % params.Name) + directory = None + if directory is not None: + # Be robust should IIS get upset about unloading. + try: + directory.AppUnLoad() + except: + exc_val = sys.exc_info()[1] + log(2, "AppUnLoad() for %s failed: %s" % (params.Name, exc_val)) + # Continue trying to delete it. + try: + parent = GetObject(directory.Parent) + parent.Delete(directory.Class, directory.Name) + log (1, "Deleted Virtual Directory: %s" % (params.Name,)) + except: + exc_val = sys.exc_info()[1] + log(1, "Failed to remove directory %s: %s" % (params.Name, exc_val)) + +def RemoveScriptMaps(vd_params, options): + "Remove script maps from the already installed virtual directory" + parent, name = vd_params.split_path() + target_dir = GetObject(FindPath(options, vd_params.Server, parent)) + installed_maps = list(target_dir.ScriptMaps) + for _map in map(str, vd_params.ScriptMaps): + if _map in installed_maps: + installed_maps.remove(_map) + target_dir.ScriptMaps = installed_maps + target_dir.SetInfo() + +def Uninstall(params, options): + _CallHook(params, "PreRemove", options) + + DeleteExtensionFileRecords(params, options) + + for vd in params.VirtualDirs: + _CallHook(vd, "PreRemove", options) + + RemoveDirectory(vd, options) + if vd.is_root(): + # if this is installed to the root virtual directory, we can't delete it + # so remove the script maps. + RemoveScriptMaps(vd, options) + + _CallHook(vd, "PostRemove", options) + + for filter_def in params.Filters: + DeleteISAPIFilter(filter_def, options) + _CallHook(params, "PostRemove", options) + +# Patch up any missing module names in the params, replacing them with +# the DLL name that hosts this extension/filter. +def _PatchParamsModule(params, dll_name, file_must_exist = True): + if file_must_exist: + if not os.path.isfile(dll_name): + raise ConfigurationError("%s does not exist" % (dll_name,)) + + # Patch up all references to the DLL. + for f in params.Filters: + if f.Path is None: f.Path = dll_name + for d in params.VirtualDirs: + for sm in d.ScriptMaps: + if sm.Module is None: sm.Module = dll_name + +def GetLoaderModuleName(mod_name, check_module = None): + # find the name of the DLL hosting us. + # By default, this is "_{module_base_name}.dll" + if hasattr(sys, "frozen"): + # What to do? The .dll knows its name, but this is likely to be + # executed via a .exe, which does not know. + base, ext = os.path.splitext(mod_name) + path, base = os.path.split(base) + # handle the common case of 'foo.exe'/'foow.exe' + if base.endswith('w'): + base = base[:-1] + # For py2exe, we have '_foo.dll' as the standard pyisapi loader - but + # 'foo.dll' is what we use (it just delegates). + # So no leading '_' on the installed name. + dll_name = os.path.abspath(os.path.join(path, base + ".dll")) + else: + base, ext = os.path.splitext(mod_name) + path, base = os.path.split(base) + dll_name = os.path.abspath(os.path.join(path, "_" + base + ".dll")) + # Check we actually have it. + if check_module is None: check_module = not hasattr(sys, "frozen") + if check_module: + CheckLoaderModule(dll_name) + return dll_name + +# Note the 'log' params to these 'builtin' args - old versions of pywin32 +# didn't log at all in this function (by intent; anyone calling this was +# responsible). So existing code that calls this function with the old +# signature (ie, without a 'log' param) still gets the same behaviour as +# before... + +def InstallModule(conf_module_name, params, options, log=lambda *args:None): + "Install the extension" + if not hasattr(sys, "frozen"): + conf_module_name = os.path.abspath(conf_module_name) + if not os.path.isfile(conf_module_name): + raise ConfigurationError("%s does not exist" % (conf_module_name,)) + + loader_dll = GetLoaderModuleName(conf_module_name) + _PatchParamsModule(params, loader_dll) + Install(params, options) + log(1, "Installation complete.") + +def UninstallModule(conf_module_name, params, options, log=lambda *args:None): + "Remove the extension" + loader_dll = GetLoaderModuleName(conf_module_name, False) + _PatchParamsModule(params, loader_dll, False) + Uninstall(params, options) + log(1, "Uninstallation complete.") + +standard_arguments = { + "install" : InstallModule, + "remove" : UninstallModule, +} + +def build_usage(handler_map): + docstrings = [handler.__doc__ for handler in handler_map.values()] + all_args = dict(zip(iter(handler_map.keys()), docstrings)) + arg_names = "|".join(iter(all_args.keys())) + usage_string = "%prog [options] [" + arg_names + "]\n" + usage_string += "commands:\n" + for arg, desc in all_args.items(): + usage_string += " %-10s: %s" % (arg, desc) + "\n" + return usage_string[:-1] + +def MergeStandardOptions(options, params): + """ + Take an options object generated by the command line and merge + the values into the IISParameters object. + """ + pass + + +# We support 2 ways of extending our command-line/install support. +# * Many of the installation items allow you to specify "PreInstall", +# "PostInstall", "PreRemove" and "PostRemove" hooks +# All hooks are called with the 'params' object being operated on, and +# the 'optparser' options for this session (ie, the command-line options) +# PostInstall for VirtualDirectories and Filters both have an additional +# param - the ADSI object just created. +# * You can pass your own option parser for us to use, and/or define a map +# with your own custom arg handlers. It is a map of 'arg'->function. +# The function is called with (options, log_fn, arg). The function's +# docstring is used in the usage output. +def HandleCommandLine(params, argv=None, conf_module_name = None, + default_arg = "install", + opt_parser = None, custom_arg_handlers = {}): + """Perform installation or removal of an ISAPI filter or extension. + + This module handles standard command-line options and configuration + information, and installs, removes or updates the configuration of an + ISAPI filter or extension. + + You must pass your configuration information in params - all other + arguments are optional, and allow you to configure the installation + process. + """ + global verbose + from optparse import OptionParser + + argv = argv or sys.argv + if not conf_module_name: + conf_module_name = sys.argv[0] + # convert to a long name so that if we were somehow registered with + # the "short" version but unregistered with the "long" version we + # still work (that will depend on exactly how the installer was + # started) + try: + conf_module_name = win32api.GetLongPathName(conf_module_name) + except win32api.error as exc: + log(2, "Couldn't determine the long name for %r: %s" % + (conf_module_name, exc)) + + if opt_parser is None: + # Build our own parser. + parser = OptionParser(usage='') + else: + # The caller is providing their own filter, presumably with their + # own options all setup. + parser = opt_parser + + # build a usage string if we don't have one. + if not parser.get_usage(): + all_handlers = standard_arguments.copy() + all_handlers.update(custom_arg_handlers) + parser.set_usage(build_usage(all_handlers)) + + # allow the user to use uninstall as a synonym for remove if it wasn't + # defined by the custom arg handlers. + all_handlers.setdefault('uninstall', all_handlers['remove']) + + parser.add_option("-q", "--quiet", + action="store_false", dest="verbose", default=True, + help="don't print status messages to stdout") + parser.add_option("-v", "--verbosity", action="count", + dest="verbose", default=1, + help="increase the verbosity of status messages") + parser.add_option("", "--server", action="store", + help="Specifies the IIS server to install/uninstall on." \ + " Default is '%s/1'" % (_IIS_OBJECT,)) + + (options, args) = parser.parse_args(argv[1:]) + MergeStandardOptions(options, params) + verbose = options.verbose + if not args: + args = [default_arg] + try: + for arg in args: + handler = all_handlers[arg] + handler(conf_module_name, params, options, log) + except (ItemNotFound, InstallationError) as details: + if options.verbose > 1: + traceback.print_exc() + print("%s: %s" % (details.__class__.__name__, details)) + except KeyError: + parser.error("Invalid arg '%s'" % arg) diff --git a/Lib/site-packages/isapi/isapicon.py b/Lib/site-packages/isapi/isapicon.py new file mode 100644 index 0000000..79dd479 --- /dev/null +++ b/Lib/site-packages/isapi/isapicon.py @@ -0,0 +1,120 @@ +"""Constants needed by ISAPI filters and extensions.""" +# ====================================================================== +# Copyright 2002-2003 by Blackdog Software Pty Ltd. +# +# All Rights Reserved +# +# Permission to use, copy, modify, and distribute this software and +# its documentation for any purpose and without fee is hereby +# granted, provided that the above copyright notice appear in all +# copies and that both that copyright notice and this permission +# notice appear in supporting documentation, and that the name of +# Blackdog Software not be used in advertising or publicity pertaining to +# distribution of the software without specific, written prior +# permission. +# +# BLACKDOG SOFTWARE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN +# NO EVENT SHALL BLACKDOG SOFTWARE BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# ====================================================================== + +# HTTP reply codes + +HTTP_CONTINUE = 100 +HTTP_SWITCHING_PROTOCOLS = 101 +HTTP_PROCESSING = 102 +HTTP_OK = 200 +HTTP_CREATED = 201 +HTTP_ACCEPTED = 202 +HTTP_NON_AUTHORITATIVE = 203 +HTTP_NO_CONTENT = 204 +HTTP_RESET_CONTENT = 205 +HTTP_PARTIAL_CONTENT = 206 +HTTP_MULTI_STATUS = 207 +HTTP_MULTIPLE_CHOICES = 300 +HTTP_MOVED_PERMANENTLY = 301 +HTTP_MOVED_TEMPORARILY = 302 +HTTP_SEE_OTHER = 303 +HTTP_NOT_MODIFIED = 304 +HTTP_USE_PROXY = 305 +HTTP_TEMPORARY_REDIRECT = 307 +HTTP_BAD_REQUEST = 400 +HTTP_UNAUTHORIZED = 401 +HTTP_PAYMENT_REQUIRED = 402 +HTTP_FORBIDDEN = 403 +HTTP_NOT_FOUND = 404 +HTTP_METHOD_NOT_ALLOWED = 405 +HTTP_NOT_ACCEPTABLE = 406 +HTTP_PROXY_AUTHENTICATION_REQUIRED= 407 +HTTP_REQUEST_TIME_OUT = 408 +HTTP_CONFLICT = 409 +HTTP_GONE = 410 +HTTP_LENGTH_REQUIRED = 411 +HTTP_PRECONDITION_FAILED = 412 +HTTP_REQUEST_ENTITY_TOO_LARGE = 413 +HTTP_REQUEST_URI_TOO_LARGE = 414 +HTTP_UNSUPPORTED_MEDIA_TYPE = 415 +HTTP_RANGE_NOT_SATISFIABLE = 416 +HTTP_EXPECTATION_FAILED = 417 +HTTP_UNPROCESSABLE_ENTITY = 422 +HTTP_INTERNAL_SERVER_ERROR = 500 +HTTP_NOT_IMPLEMENTED = 501 +HTTP_BAD_GATEWAY = 502 +HTTP_SERVICE_UNAVAILABLE = 503 +HTTP_GATEWAY_TIME_OUT = 504 +HTTP_VERSION_NOT_SUPPORTED = 505 +HTTP_VARIANT_ALSO_VARIES = 506 + +HSE_STATUS_SUCCESS = 1 +HSE_STATUS_SUCCESS_AND_KEEP_CONN = 2 +HSE_STATUS_PENDING = 3 +HSE_STATUS_ERROR = 4 + +SF_NOTIFY_SECURE_PORT = 0x00000001 +SF_NOTIFY_NONSECURE_PORT = 0x00000002 +SF_NOTIFY_READ_RAW_DATA = 0x00008000 +SF_NOTIFY_PREPROC_HEADERS = 0x00004000 +SF_NOTIFY_AUTHENTICATION = 0x00002000 +SF_NOTIFY_URL_MAP = 0x00001000 +SF_NOTIFY_ACCESS_DENIED = 0x00000800 +SF_NOTIFY_SEND_RESPONSE = 0x00000040 +SF_NOTIFY_SEND_RAW_DATA = 0x00000400 +SF_NOTIFY_LOG = 0x00000200 +SF_NOTIFY_END_OF_REQUEST = 0x00000080 +SF_NOTIFY_END_OF_NET_SESSION = 0x00000100 + +SF_NOTIFY_ORDER_HIGH = 0x00080000 +SF_NOTIFY_ORDER_MEDIUM = 0x00040000 +SF_NOTIFY_ORDER_LOW = 0x00020000 +SF_NOTIFY_ORDER_DEFAULT = SF_NOTIFY_ORDER_LOW + +SF_NOTIFY_ORDER_MASK = (SF_NOTIFY_ORDER_HIGH | \ + SF_NOTIFY_ORDER_MEDIUM | \ + SF_NOTIFY_ORDER_LOW) + +SF_STATUS_REQ_FINISHED = 134217728 # 0x8000000 +SF_STATUS_REQ_FINISHED_KEEP_CONN = 134217728 + 1 +SF_STATUS_REQ_NEXT_NOTIFICATION = 134217728 + 2 +SF_STATUS_REQ_HANDLED_NOTIFICATION = 134217728 + 3 +SF_STATUS_REQ_ERROR = 134217728 + 4 +SF_STATUS_REQ_READ_NEXT = 134217728 + 5 + +HSE_IO_SYNC = 0x00000001 # for WriteClient +HSE_IO_ASYNC = 0x00000002 # for WriteClient/TF/EU +HSE_IO_DISCONNECT_AFTER_SEND = 0x00000004 # for TF +HSE_IO_SEND_HEADERS = 0x00000008 # for TF +HSE_IO_NODELAY = 0x00001000 # turn off nagling +# These two are only used by VectorSend +HSE_IO_FINAL_SEND = 0x00000010 +HSE_IO_CACHE_RESPONSE = 0x00000020 + +HSE_EXEC_URL_NO_HEADERS = 0x02 +HSE_EXEC_URL_IGNORE_CURRENT_INTERCEPTOR = 0x04 +HSE_EXEC_URL_IGNORE_VALIDATION_AND_RANGE = 0x10 +HSE_EXEC_URL_DISABLE_CUSTOM_ERROR = 0x20 +HSE_EXEC_URL_SSI_CMD = 0x40 +HSE_EXEC_URL_HTTP_CACHE_ELIGIBLE = 0x80 diff --git a/Lib/site-packages/isapi/samples/README.txt b/Lib/site-packages/isapi/samples/README.txt new file mode 100644 index 0000000..5024b10 --- /dev/null +++ b/Lib/site-packages/isapi/samples/README.txt @@ -0,0 +1,20 @@ +In this directory you will find examples of ISAPI filters and extensions. + +The filter loading mechanism works like this: +* IIS loads the special Python "loader" DLL. This DLL will generally have a + leading underscore as part of its name. +* This loader DLL looks for a Python module, by removing the first letter of + the DLL base name. + +This means that an ISAPI extension module consists of 2 key files - the loader +DLL (eg, "_MyIISModule.dll", and a Python module (which for this example +would be "MyIISModule.py") + +When you install an ISAPI extension, the installation code checks to see if +there is a loader DLL for your implementation file - if one does not exist, +or the standard loader is different, it is copied and renamed accordingly. + +We use this mechanism to provide the maximum separation between different +Python extensions installed on the same server - otherwise filter order and +other tricky IIS semantics would need to be replicated. Also, each filter +gets its own thread-pool, etc. diff --git a/Lib/site-packages/isapi/samples/advanced.py b/Lib/site-packages/isapi/samples/advanced.py new file mode 100644 index 0000000..f08586d --- /dev/null +++ b/Lib/site-packages/isapi/samples/advanced.py @@ -0,0 +1,196 @@ +# This extension demonstrates some advanced features of the Python ISAPI +# framework. +# We demonstrate: +# * Reloading your Python module without shutting down IIS (eg, when your +# .py implementation file changes.) +# * Custom command-line handling - both additional options and commands. +# * Using a query string - any part of the URL after a '?' is assumed to +# be "variable names" separated by '&' - we will print the values of +# these server variables. +# * If the tail portion of the URL is "ReportUnhealthy", IIS will be +# notified we are unhealthy via a HSE_REQ_REPORT_UNHEALTHY request. +# Whether this is acted upon depends on if the IIS health-checking +# tools are installed, but you should always see the reason written +# to the Windows event log - see the IIS documentation for more. + +from isapi import isapicon +from isapi.simple import SimpleExtension +import sys, os, stat + +if hasattr(sys, "isapidllhandle"): + import win32traceutil + +# Notes on reloading +# If your HttpFilterProc or HttpExtensionProc functions raises +# 'isapi.InternalReloadException', the framework will not treat it +# as an error but instead will terminate your extension, reload your +# extension module, re-initialize the instance, and re-issue the request. +# The Initialize functions are called with None as their param. The +# return code from the terminate function is ignored. +# +# This is all the framework does to help you. It is up to your code +# when you raise this exception. This sample uses a Win32 "find +# notification". Whenever windows tells us one of the files in the +# directory has changed, we check if the time of our source-file has +# changed, and set a flag. Next imcoming request, we check the flag and +# raise the special exception if set. +# +# The end result is that the module is automatically reloaded whenever +# the source-file changes - you need take no further action to see your +# changes reflected in the running server. + +# The framework only reloads your module - if you have libraries you +# depend on and also want reloaded, you must arrange for this yourself. +# One way of doing this would be to special case the import of these +# modules. Eg: +# -- +# try: +# my_module = reload(my_module) # module already imported - reload it +# except NameError: +# import my_module # first time around - import it. +# -- +# When your module is imported for the first time, the NameError will +# be raised, and the module imported. When the ISAPI framework reloads +# your module, the existing module will avoid the NameError, and allow +# you to reload that module. + +from isapi import InternalReloadException +import win32event, win32file, winerror, win32con, threading + +try: + reload_counter += 1 +except NameError: + reload_counter = 0 + +# A watcher thread that checks for __file__ changing. +# When it detects it, it simply sets "change_detected" to true. +class ReloadWatcherThread(threading.Thread): + def __init__(self): + self.change_detected = False + self.filename = __file__ + if self.filename.endswith("c") or self.filename.endswith("o"): + self.filename = self.filename[:-1] + self.handle = win32file.FindFirstChangeNotification( + os.path.dirname(self.filename), + False, # watch tree? + win32con.FILE_NOTIFY_CHANGE_LAST_WRITE) + threading.Thread.__init__(self) + + def run(self): + last_time = os.stat(self.filename)[stat.ST_MTIME] + while 1: + try: + rc = win32event.WaitForSingleObject(self.handle, + win32event.INFINITE) + win32file.FindNextChangeNotification(self.handle) + except win32event.error as details: + # handle closed - thread should terminate. + if details.winerror != winerror.ERROR_INVALID_HANDLE: + raise + break + this_time = os.stat(self.filename)[stat.ST_MTIME] + if this_time != last_time: + print("Detected file change - flagging for reload.") + self.change_detected = True + last_time = this_time + + def stop(self): + win32file.FindCloseChangeNotification(self.handle) + +# The ISAPI extension - handles requests in our virtual dir, and sends the +# response to the client. +class Extension(SimpleExtension): + "Python advanced sample Extension" + def __init__(self): + self.reload_watcher = ReloadWatcherThread() + self.reload_watcher.start() + + def HttpExtensionProc(self, ecb): + # NOTE: If you use a ThreadPoolExtension, you must still perform + # this check in HttpExtensionProc - raising the exception from + # The "Dispatch" method will just cause the exception to be + # rendered to the browser. + if self.reload_watcher.change_detected: + print("Doing reload") + raise InternalReloadException + + url = ecb.GetServerVariable("UNICODE_URL") + if url.endswith("ReportUnhealthy"): + ecb.ReportUnhealthy("I'm a little sick") + + ecb.SendResponseHeaders("200 OK", "Content-Type: text/html\r\n\r\n", 0) + print("", file=ecb) + + qs = ecb.GetServerVariable("QUERY_STRING") + if qs: + queries = qs.split("&") + print("

", file=ecb)
+            for q in queries:
+                val = ecb.GetServerVariable(q, '<no such variable>')
+                print("%s=%r" % (q, val), file=ecb)
+            print("

", file=ecb) + + print("This module has been imported", file=ecb) + print("%d times" % (reload_counter,), file=ecb) + print("", file=ecb) + ecb.close() + return isapicon.HSE_STATUS_SUCCESS + + def TerminateExtension(self, status): + self.reload_watcher.stop() + +# The entry points for the ISAPI extension. +def __ExtensionFactory__(): + return Extension() + +# Our special command line customization. +# Pre-install hook for our virtual directory. +def PreInstallDirectory(params, options): + # If the user used our special '--description' option, + # then we override our default. + if options.description: + params.Description = options.description + +# Post install hook for our entire script +def PostInstall(params, options): + print() + print("The sample has been installed.") + print("Point your browser to /AdvancedPythonSample") + print("If you modify the source file and reload the page,") + print("you should see the reload counter increment") + +# Handler for our custom 'status' argument. +def status_handler(options, log, arg): + "Query the status of something" + print("Everything seems to be fine!") + +custom_arg_handlers = {"status": status_handler} + +if __name__=='__main__': + # If run from the command-line, install ourselves. + from isapi.install import * + params = ISAPIParameters(PostInstall = PostInstall) + # Setup the virtual directories - this is a list of directories our + # extension uses - in this case only 1. + # Each extension has a "script map" - this is the mapping of ISAPI + # extensions. + sm = [ + ScriptMapParams(Extension="*", Flags=0) + ] + vd = VirtualDirParameters(Name="AdvancedPythonSample", + Description = Extension.__doc__, + ScriptMaps = sm, + ScriptMapUpdate = "replace", + # specify the pre-install hook. + PreInstall = PreInstallDirectory + ) + params.VirtualDirs = [vd] + # Setup our custom option parser. + from optparse import OptionParser + parser = OptionParser('') # blank usage, so isapi sets it. + parser.add_option("", "--description", + action="store", + help="custom description to use for the virtual directory") + + HandleCommandLine(params, opt_parser=parser, + custom_arg_handlers = custom_arg_handlers) diff --git a/Lib/site-packages/isapi/samples/redirector.py b/Lib/site-packages/isapi/samples/redirector.py new file mode 100644 index 0000000..99c5d88 --- /dev/null +++ b/Lib/site-packages/isapi/samples/redirector.py @@ -0,0 +1,109 @@ +# This is a sample ISAPI extension written in Python. +# +# Please see README.txt in this directory, and specifically the +# information about the "loader" DLL - installing this sample will create +# "_redirector.dll" in the current directory. The readme explains this. + +# Executing this script (or any server config script) will install the extension +# into your web server. As the server executes, the PyISAPI framework will load +# this module and create your Extension and Filter objects. + +# This is the simplest possible redirector (or proxy) we can write. The +# extension installs with a mask of '*' in the root of the site. +# As an added bonus though, we optionally show how, on IIS6 and later, we +# can use HSE_ERQ_EXEC_URL to ignore certain requests - in IIS5 and earlier +# we can only do this with an ISAPI filter - see redirector_with_filter for +# an example. If this sample is run on IIS5 or earlier it simply ignores +# any excludes. + +from isapi import isapicon, threaded_extension +import sys +import traceback +try: + from urllib.request import urlopen +except ImportError: + # py3k spelling... + from urllib.request import urlopen +import win32api + +# sys.isapidllhandle will exist when we are loaded by the IIS framework. +# In this case we redirect our output to the win32traceutil collector. +if hasattr(sys, "isapidllhandle"): + import win32traceutil + +# The site we are proxying. +proxy = "http://www.python.org" + +# Urls we exclude (ie, allow IIS to handle itself) - all are lowered, +# and these entries exist by default on Vista... +excludes = ["/iisstart.htm", "/welcome.png"] + +# An "io completion" function, called when ecb.ExecURL completes... +def io_callback(ecb, url, cbIO, errcode): + # Get the status of our ExecURL + httpstatus, substatus, win32 = ecb.GetExecURLStatus() + print("ExecURL of %r finished with http status %d.%d, win32 status %d (%s)" % ( + url, httpstatus, substatus, win32, win32api.FormatMessage(win32).strip())) + # nothing more to do! + ecb.DoneWithSession() + +# The ISAPI extension - handles all requests in the site. +class Extension(threaded_extension.ThreadPoolExtension): + "Python sample Extension" + def Dispatch(self, ecb): + # Note that our ThreadPoolExtension base class will catch exceptions + # in our Dispatch method, and write the traceback to the client. + # That is perfect for this sample, so we don't catch our own. + #print 'IIS dispatching "%s"' % (ecb.GetServerVariable("URL"),) + url = ecb.GetServerVariable("URL").decode("ascii") + for exclude in excludes: + if url.lower().startswith(exclude): + print("excluding %s" % url) + if ecb.Version < 0x60000: + print("(but this is IIS5 or earlier - can't do 'excludes')") + else: + ecb.IOCompletion(io_callback, url) + ecb.ExecURL(None, None, None, None, None, isapicon.HSE_EXEC_URL_IGNORE_CURRENT_INTERCEPTOR) + return isapicon.HSE_STATUS_PENDING + + new_url = proxy + url + print("Opening %s" % new_url) + fp = urlopen(new_url) + headers = fp.info() + # subtle py3k breakage: in py3k, str(headers) has normalized \r\n + # back to \n and also stuck an extra \n term. py2k leaves the + # \r\n from the server in tact and finishes with a single term. + if sys.version_info < (3,0): + header_text = str(headers) + "\r\n" + else: + # take *all* trailing \n off, replace remaining with + # \r\n, then add the 2 trailing \r\n. + header_text = str(headers).rstrip('\n').replace('\n', '\r\n') + '\r\n\r\n' + ecb.SendResponseHeaders("200 OK", header_text, False) + ecb.WriteClient(fp.read()) + ecb.DoneWithSession() + print("Returned data from '%s'" % (new_url,)) + return isapicon.HSE_STATUS_SUCCESS + +# The entry points for the ISAPI extension. +def __ExtensionFactory__(): + return Extension() + +if __name__=='__main__': + # If run from the command-line, install ourselves. + from isapi.install import * + params = ISAPIParameters() + # Setup the virtual directories - this is a list of directories our + # extension uses - in this case only 1. + # Each extension has a "script map" - this is the mapping of ISAPI + # extensions. + sm = [ + ScriptMapParams(Extension="*", Flags=0) + ] + vd = VirtualDirParameters(Name="/", + Description = Extension.__doc__, + ScriptMaps = sm, + ScriptMapUpdate = "replace" + ) + params.VirtualDirs = [vd] + HandleCommandLine(params) diff --git a/Lib/site-packages/isapi/samples/redirector_asynch.py b/Lib/site-packages/isapi/samples/redirector_asynch.py new file mode 100644 index 0000000..bdd9908 --- /dev/null +++ b/Lib/site-packages/isapi/samples/redirector_asynch.py @@ -0,0 +1,78 @@ +# This is a sample ISAPI extension written in Python. + +# This is like the other 'redirector' samples, but uses asnch IO when writing +# back to the client (it does *not* use asynch io talking to the remote +# server!) + +from isapi import isapicon, threaded_extension +import sys +import traceback +import urllib.request, urllib.parse, urllib.error + +# sys.isapidllhandle will exist when we are loaded by the IIS framework. +# In this case we redirect our output to the win32traceutil collector. +if hasattr(sys, "isapidllhandle"): + import win32traceutil + +# The site we are proxying. +proxy = "http://www.python.org" + +# We synchronously read chunks of this size then asynchronously write them. +CHUNK_SIZE=8192 + +# The callback made when IIS completes the asynch write. +def io_callback(ecb, fp, cbIO, errcode): + print("IO callback", ecb, fp, cbIO, errcode) + chunk = fp.read(CHUNK_SIZE) + if chunk: + ecb.WriteClient(chunk, isapicon.HSE_IO_ASYNC) + # and wait for the next callback to say this chunk is done. + else: + # eof - say we are complete. + fp.close() + ecb.DoneWithSession() + +# The ISAPI extension - handles all requests in the site. +class Extension(threaded_extension.ThreadPoolExtension): + "Python sample proxy server - asynch version." + def Dispatch(self, ecb): + print('IIS dispatching "%s"' % (ecb.GetServerVariable("URL"),)) + url = ecb.GetServerVariable("URL") + + new_url = proxy + url + print("Opening %s" % new_url) + fp = urllib.request.urlopen(new_url) + headers = fp.info() + ecb.SendResponseHeaders("200 OK", str(headers) + "\r\n", False) + # now send the first chunk asynchronously + ecb.ReqIOCompletion(io_callback, fp) + chunk = fp.read(CHUNK_SIZE) + if chunk: + ecb.WriteClient(chunk, isapicon.HSE_IO_ASYNC) + return isapicon.HSE_STATUS_PENDING + # no data - just close things now. + ecb.DoneWithSession() + return isapicon.HSE_STATUS_SUCCESS + +# The entry points for the ISAPI extension. +def __ExtensionFactory__(): + return Extension() + +if __name__=='__main__': + # If run from the command-line, install ourselves. + from isapi.install import * + params = ISAPIParameters() + # Setup the virtual directories - this is a list of directories our + # extension uses - in this case only 1. + # Each extension has a "script map" - this is the mapping of ISAPI + # extensions. + sm = [ + ScriptMapParams(Extension="*", Flags=0) + ] + vd = VirtualDirParameters(Name="/", + Description = Extension.__doc__, + ScriptMaps = sm, + ScriptMapUpdate = "replace" + ) + params.VirtualDirs = [vd] + HandleCommandLine(params) diff --git a/Lib/site-packages/isapi/samples/redirector_with_filter.py b/Lib/site-packages/isapi/samples/redirector_with_filter.py new file mode 100644 index 0000000..3b2afaf --- /dev/null +++ b/Lib/site-packages/isapi/samples/redirector_with_filter.py @@ -0,0 +1,155 @@ +# This is a sample configuration file for an ISAPI filter and extension +# written in Python. +# +# Please see README.txt in this directory, and specifically the +# information about the "loader" DLL - installing this sample will create +# "_redirector_with_filter.dll" in the current directory. The readme explains +# this. + +# Executing this script (or any server config script) will install the extension +# into your web server. As the server executes, the PyISAPI framework will load +# this module and create your Extension and Filter objects. + +# This sample provides sample redirector: +# It is implemented by a filter and an extension, so that some requests can +# be ignored. Compare with 'redirector_simple' which avoids the filter, but +# is unable to selectively ignore certain requests. +# The process is sample uses is: +# * The filter is installed globally, as all filters are. +# * A Virtual Directory named "python" is setup. This dir has our ISAPI +# extension as the only application, mapped to file-extension '*'. Thus, our +# extension handles *all* requests in this directory. +# The basic process is that the filter does URL rewriting, redirecting every +# URL to our Virtual Directory. Our extension then handles this request, +# forwarding the data from the proxied site. +# For example: +# * URL of "index.html" comes in. +# * Filter rewrites this to "/python/index.html" +# * Our extension sees the full "/python/index.html", removes the leading +# portion, and opens and forwards the remote URL. + + +# This sample is very small - it avoid most error handling, etc. It is for +# demonstration purposes only. + +from isapi import isapicon, threaded_extension +from isapi.simple import SimpleFilter +import sys +import traceback +import urllib.request, urllib.parse, urllib.error + +# sys.isapidllhandle will exist when we are loaded by the IIS framework. +# In this case we redirect our output to the win32traceutil collector. +if hasattr(sys, "isapidllhandle"): + import win32traceutil + +# The site we are proxying. +proxy = "http://www.python.org" +# The name of the virtual directory we install in, and redirect from. +virtualdir = "/python" + +# The key feature of this redirector over the simple redirector is that it +# can choose to ignore certain responses by having the filter not rewrite them +# to our virtual dir. For this sample, we just exclude the IIS help directory. + +# The ISAPI extension - handles requests in our virtual dir, and sends the +# response to the client. +class Extension(threaded_extension.ThreadPoolExtension): + "Python sample Extension" + def Dispatch(self, ecb): + # Note that our ThreadPoolExtension base class will catch exceptions + # in our Dispatch method, and write the traceback to the client. + # That is perfect for this sample, so we don't catch our own. + #print 'IIS dispatching "%s"' % (ecb.GetServerVariable("URL"),) + url = ecb.GetServerVariable("URL") + if url.startswith(virtualdir): + new_url = proxy + url[len(virtualdir):] + print("Opening", new_url) + fp = urllib.request.urlopen(new_url) + headers = fp.info() + ecb.SendResponseHeaders("200 OK", str(headers) + "\r\n", False) + ecb.WriteClient(fp.read()) + ecb.DoneWithSession() + print("Returned data from '%s'!" % (new_url,)) + else: + # this should never happen - we should only see requests that + # start with our virtual directory name. + print("Not proxying '%s'" % (url,)) + + +# The ISAPI filter. +class Filter(SimpleFilter): + "Sample Python Redirector" + filter_flags = isapicon.SF_NOTIFY_PREPROC_HEADERS | \ + isapicon.SF_NOTIFY_ORDER_DEFAULT + + def HttpFilterProc(self, fc): + #print "Filter Dispatch" + nt = fc.NotificationType + if nt != isapicon.SF_NOTIFY_PREPROC_HEADERS: + return isapicon.SF_STATUS_REQ_NEXT_NOTIFICATION + + pp = fc.GetData() + url = pp.GetHeader("url") + #print "URL is '%s'" % (url,) + prefix = virtualdir + if not url.startswith(prefix): + new_url = prefix + url + print("New proxied URL is '%s'" % (new_url,)) + pp.SetHeader("url", new_url) + # For the sake of demonstration, show how the FilterContext + # attribute is used. It always starts out life as None, and + # any assignments made are automatically decref'd by the + # framework during a SF_NOTIFY_END_OF_NET_SESSION notification. + if fc.FilterContext is None: + fc.FilterContext = 0 + fc.FilterContext += 1 + print("This is request number %d on this connection" % fc.FilterContext) + return isapicon.SF_STATUS_REQ_HANDLED_NOTIFICATION + else: + print("Filter ignoring URL '%s'" % (url,)) + + # Some older code that handled SF_NOTIFY_URL_MAP. + #~ print "Have URL_MAP notify" + #~ urlmap = fc.GetData() + #~ print "URI is", urlmap.URL + #~ print "Path is", urlmap.PhysicalPath + #~ if urlmap.URL.startswith("/UC/"): + #~ # Find the /UC/ in the physical path, and nuke it (except + #~ # as the path is physical, it is \) + #~ p = urlmap.PhysicalPath + #~ pos = p.index("\\UC\\") + #~ p = p[:pos] + p[pos+3:] + #~ p = r"E:\src\pyisapi\webroot\PyTest\formTest.htm" + #~ print "New path is", p + #~ urlmap.PhysicalPath = p + +# The entry points for the ISAPI extension. +def __FilterFactory__(): + return Filter() +def __ExtensionFactory__(): + return Extension() + +if __name__=='__main__': + # If run from the command-line, install ourselves. + from isapi.install import * + params = ISAPIParameters() + # Setup all filters - these are global to the site. + params.Filters = [ + FilterParameters(Name="PythonRedirector", + Description=Filter.__doc__), + ] + # Setup the virtual directories - this is a list of directories our + # extension uses - in this case only 1. + # Each extension has a "script map" - this is the mapping of ISAPI + # extensions. + sm = [ + ScriptMapParams(Extension="*", Flags=0) + ] + vd = VirtualDirParameters(Name=virtualdir[1:], + Description = Extension.__doc__, + ScriptMaps = sm, + ScriptMapUpdate = "replace" + ) + params.VirtualDirs = [vd] + HandleCommandLine(params) diff --git a/Lib/site-packages/isapi/samples/test.py b/Lib/site-packages/isapi/samples/test.py new file mode 100644 index 0000000..5b595cb --- /dev/null +++ b/Lib/site-packages/isapi/samples/test.py @@ -0,0 +1,154 @@ +# This extension is used mainly for testing purposes - it is not +# designed to be a simple sample, but instead is a hotch-potch of things +# that attempts to exercise the framework. + +from isapi import isapicon +from isapi.simple import SimpleExtension +import sys, os, stat + +if hasattr(sys, "isapidllhandle"): + import win32traceutil + +# We use the same reload support as 'advanced.py' demonstrates. +from isapi import InternalReloadException +import win32event, win32file, winerror, win32con, threading + +# A watcher thread that checks for __file__ changing. +# When it detects it, it simply sets "change_detected" to true. +class ReloadWatcherThread(threading.Thread): + def __init__(self): + self.change_detected = False + self.filename = __file__ + if self.filename.endswith("c") or self.filename.endswith("o"): + self.filename = self.filename[:-1] + self.handle = win32file.FindFirstChangeNotification( + os.path.dirname(self.filename), + False, # watch tree? + win32con.FILE_NOTIFY_CHANGE_LAST_WRITE) + threading.Thread.__init__(self) + + def run(self): + last_time = os.stat(self.filename)[stat.ST_MTIME] + while 1: + try: + rc = win32event.WaitForSingleObject(self.handle, + win32event.INFINITE) + win32file.FindNextChangeNotification(self.handle) + except win32event.error as details: + # handle closed - thread should terminate. + if details.winerror != winerror.ERROR_INVALID_HANDLE: + raise + break + this_time = os.stat(self.filename)[stat.ST_MTIME] + if this_time != last_time: + print("Detected file change - flagging for reload.") + self.change_detected = True + last_time = this_time + + def stop(self): + win32file.FindCloseChangeNotification(self.handle) + +def TransmitFileCallback(ecb, hFile, cbIO, errCode): + print("Transmit complete!") + ecb.close() + +# The ISAPI extension - handles requests in our virtual dir, and sends the +# response to the client. +class Extension(SimpleExtension): + "Python test Extension" + def __init__(self): + self.reload_watcher = ReloadWatcherThread() + self.reload_watcher.start() + + def HttpExtensionProc(self, ecb): + # NOTE: If you use a ThreadPoolExtension, you must still perform + # this check in HttpExtensionProc - raising the exception from + # The "Dispatch" method will just cause the exception to be + # rendered to the browser. + if self.reload_watcher.change_detected: + print("Doing reload") + raise InternalReloadException + + if ecb.GetServerVariable("UNICODE_URL").endswith("test.py"): + file_flags = win32con.FILE_FLAG_SEQUENTIAL_SCAN | win32con.FILE_FLAG_OVERLAPPED + hfile = win32file.CreateFile(__file__, win32con.GENERIC_READ, + 0, None, win32con.OPEN_EXISTING, + file_flags, None) + flags = isapicon.HSE_IO_ASYNC | isapicon.HSE_IO_DISCONNECT_AFTER_SEND | \ + isapicon.HSE_IO_SEND_HEADERS + # We pass hFile to the callback simply as a way of keeping it alive + # for the duration of the transmission + try: + ecb.TransmitFile(TransmitFileCallback, hfile, + int(hfile), + "200 OK", + 0, 0, None, None, flags) + except: + # Errors keep this source file open! + hfile.Close() + raise + else: + # default response + ecb.SendResponseHeaders("200 OK", "Content-Type: text/html\r\n\r\n", 0) + print("", file=ecb) + print("The root of this site is at", ecb.MapURLToPath("/"), file=ecb) + print("", file=ecb) + ecb.close() + return isapicon.HSE_STATUS_SUCCESS + + def TerminateExtension(self, status): + self.reload_watcher.stop() + +# The entry points for the ISAPI extension. +def __ExtensionFactory__(): + return Extension() + +# Our special command line customization. +# Pre-install hook for our virtual directory. +def PreInstallDirectory(params, options): + # If the user used our special '--description' option, + # then we override our default. + if options.description: + params.Description = options.description + +# Post install hook for our entire script +def PostInstall(params, options): + print() + print("The sample has been installed.") + print("Point your browser to /PyISAPITest") + +# Handler for our custom 'status' argument. +def status_handler(options, log, arg): + "Query the status of something" + print("Everything seems to be fine!") + +custom_arg_handlers = {"status": status_handler} + +if __name__=='__main__': + # If run from the command-line, install ourselves. + from isapi.install import * + params = ISAPIParameters(PostInstall = PostInstall) + # Setup the virtual directories - this is a list of directories our + # extension uses - in this case only 1. + # Each extension has a "script map" - this is the mapping of ISAPI + # extensions. + sm = [ + ScriptMapParams(Extension="*", Flags=0) + ] + vd = VirtualDirParameters(Name="PyISAPITest", + Description = Extension.__doc__, + ScriptMaps = sm, + ScriptMapUpdate = "replace", + # specify the pre-install hook. + PreInstall = PreInstallDirectory + ) + params.VirtualDirs = [vd] + # Setup our custom option parser. + from optparse import OptionParser + parser = OptionParser('') # blank usage, so isapi sets it. + parser.add_option("", "--description", + action="store", + help="custom description to use for the virtual directory") + + HandleCommandLine(params, opt_parser=parser, + custom_arg_handlers = custom_arg_handlers) diff --git a/Lib/site-packages/isapi/simple.py b/Lib/site-packages/isapi/simple.py new file mode 100644 index 0000000..3c653c7 --- /dev/null +++ b/Lib/site-packages/isapi/simple.py @@ -0,0 +1,68 @@ +"""Simple base-classes for extensions and filters. + +None of the filter and extension functions are considered 'optional' by the +framework. These base-classes provide simple implementations for the +Initialize and Terminate functions, allowing you to omit them, + +It is not necessary to use these base-classes - but if you don't, you +must ensure each of the required methods are implemented. +""" + +class SimpleExtension: + "Base class for a simple ISAPI extension" + def __init__(self): + pass + + def GetExtensionVersion(self, vi): + """Called by the ISAPI framework to get the extension version + + The default implementation uses the classes docstring to + set the extension description.""" + # nod to our reload capability - vi is None when we are reloaded. + if vi is not None: + vi.ExtensionDesc = self.__doc__ + + def HttpExtensionProc(self, control_block): + """Called by the ISAPI framework for each extension request. + + sub-classes must provide an implementation for this method. + """ + raise NotImplementedError("sub-classes should override HttpExtensionProc") + + def TerminateExtension(self, status): + """Called by the ISAPI framework as the extension terminates. + """ + pass + +class SimpleFilter: + "Base class for a a simple ISAPI filter" + filter_flags = None + def __init__(self): + pass + + def GetFilterVersion(self, fv): + """Called by the ISAPI framework to get the extension version + + The default implementation uses the classes docstring to + set the extension description, and uses the classes + filter_flags attribute to set the ISAPI filter flags - you + must specify filter_flags in your class. + """ + if self.filter_flags is None: + raise RuntimeError("You must specify the filter flags") + # nod to our reload capability - fv is None when we are reloaded. + if fv is not None: + fv.Flags = self.filter_flags + fv.FilterDesc = self.__doc__ + + def HttpFilterProc(self, fc): + """Called by the ISAPI framework for each filter request. + + sub-classes must provide an implementation for this method. + """ + raise NotImplementedError("sub-classes should override HttpExtensionProc") + + def TerminateFilter(self, status): + """Called by the ISAPI framework as the filter terminates. + """ + pass diff --git a/Lib/site-packages/isapi/test/README.txt b/Lib/site-packages/isapi/test/README.txt new file mode 100644 index 0000000..b4356a7 --- /dev/null +++ b/Lib/site-packages/isapi/test/README.txt @@ -0,0 +1,3 @@ +This is a directory for tests of the PyISAPI framework. + +For demos, please see the pyisapi 'samples' directory. \ No newline at end of file diff --git a/Lib/site-packages/isapi/test/extension_simple.py b/Lib/site-packages/isapi/test/extension_simple.py new file mode 100644 index 0000000..991e491 --- /dev/null +++ b/Lib/site-packages/isapi/test/extension_simple.py @@ -0,0 +1,111 @@ +# This is an ISAPI extension purely for testing purposes. It is NOT +# a 'demo' (even though it may be useful!) +# +# Install this extension, then point your browser to: +# "http://localhost/pyisapi_test/test1" +# This will execute the method 'test1' below. See below for the list of +# test methods that are acceptable. + +from isapi import isapicon, threaded_extension, ExtensionError +from isapi.simple import SimpleFilter +import traceback +import urllib.request, urllib.parse, urllib.error +import winerror + +# If we have no console (eg, am running from inside IIS), redirect output +# somewhere useful - in this case, the standard win32 trace collector. +import win32api +try: + win32api.GetConsoleTitle() +except win32api.error: + # No console - redirect + import win32traceutil + +# The ISAPI extension - handles requests in our virtual dir, and sends the +# response to the client. +class Extension(threaded_extension.ThreadPoolExtension): + "Python ISAPI Tester" + def Dispatch(self, ecb): + print('Tester dispatching "%s"' % (ecb.GetServerVariable("URL"),)) + url = ecb.GetServerVariable("URL") + test_name = url.split("/")[-1] + meth = getattr(self, test_name, None) + if meth is None: + raise AttributeError("No test named '%s'" % (test_name,)) + result = meth(ecb) + if result is None: + # This means the test finalized everything + return + ecb.SendResponseHeaders("200 OK", "Content-type: text/html\r\n\r\n", + False) + print("Finished running test ", test_name, "", file=ecb) + print("

", file=ecb)
+        print(result, file=ecb)
+        print("
", file=ecb) + print("", file=ecb) + ecb.DoneWithSession() + + def test1(self, ecb): + try: + ecb.GetServerVariable("foo bar") + raise RuntimeError("should have failed!") + except ExtensionError as err: + assert err.errno == winerror.ERROR_INVALID_INDEX, err + return "worked!" + + def test_long_vars(self, ecb): + qs = ecb.GetServerVariable("QUERY_STRING") + # Our implementation has a default buffer size of 8k - so we test + # the code that handles an overflow by ensuring there are more + # than 8k worth of chars in the URL. + expected_query = ('x' * 8500) + if len(qs)==0: + # Just the URL with no query part - redirect to myself, but with + # a huge query portion. + me = ecb.GetServerVariable("URL") + headers = "Location: " + me + "?" + expected_query + "\r\n\r\n" + ecb.SendResponseHeaders("301 Moved", headers) + ecb.DoneWithSession() + return None + if qs == expected_query: + return "Total length of variable is %d - test worked!" % (len(qs),) + else: + return "Unexpected query portion! Got %d chars, expected %d" % \ + (len(qs), len(expected_query)) + + def test_unicode_vars(self, ecb): + # We need to check that we are running IIS6! This seems the only + # effective way from an extension. + ver = float(ecb.GetServerVariable("SERVER_SOFTWARE").split('/')[1]) + if ver < 6.0: + return "This is IIS version %g - unicode only works in IIS6 and later" % ver + + us = ecb.GetServerVariable("UNICODE_SERVER_NAME") + if not isinstance(us, str): + raise RuntimeError("unexpected type!") + if us != str(ecb.GetServerVariable("SERVER_NAME")): + raise RuntimeError("Unicode and non-unicode values were not the same") + return "worked!" + +# The entry points for the ISAPI extension. +def __ExtensionFactory__(): + return Extension() + +if __name__=='__main__': + # If run from the command-line, install ourselves. + from isapi.install import * + params = ISAPIParameters() + # Setup the virtual directories - this is a list of directories our + # extension uses - in this case only 1. + # Each extension has a "script map" - this is the mapping of ISAPI + # extensions. + sm = [ + ScriptMapParams(Extension="*", Flags=0) + ] + vd = VirtualDirParameters(Name="pyisapi_test", + Description = Extension.__doc__, + ScriptMaps = sm, + ScriptMapUpdate = "replace" + ) + params.VirtualDirs = [vd] + HandleCommandLine(params) diff --git a/Lib/site-packages/isapi/threaded_extension.py b/Lib/site-packages/isapi/threaded_extension.py new file mode 100644 index 0000000..79743ac --- /dev/null +++ b/Lib/site-packages/isapi/threaded_extension.py @@ -0,0 +1,171 @@ +"""An ISAPI extension base class implemented using a thread-pool.""" +# $Id$ + +import sys +import time +from isapi import isapicon, ExtensionError +import isapi.simple +from win32file import GetQueuedCompletionStatus, CreateIoCompletionPort, \ + PostQueuedCompletionStatus, CloseHandle +from win32security import SetThreadToken +from win32event import INFINITE +from pywintypes import OVERLAPPED + +import threading +import traceback + +ISAPI_REQUEST = 1 +ISAPI_SHUTDOWN = 2 + +class WorkerThread(threading.Thread): + def __init__(self, extension, io_req_port): + self.running = False + self.io_req_port = io_req_port + self.extension = extension + threading.Thread.__init__(self) + # We wait 15 seconds for a thread to terminate, but if it fails to, + # we don't want the process to hang at exit waiting for it... + self.setDaemon(True) + + def run(self): + self.running = True + while self.running: + errCode, bytes, key, overlapped = \ + GetQueuedCompletionStatus(self.io_req_port, INFINITE) + if key == ISAPI_SHUTDOWN and overlapped is None: + break + + # Let the parent extension handle the command. + dispatcher = self.extension.dispatch_map.get(key) + if dispatcher is None: + raise RuntimeError("Bad request '%s'" % (key,)) + + dispatcher(errCode, bytes, key, overlapped) + + def call_handler(self, cblock): + self.extension.Dispatch(cblock) + +# A generic thread-pool based extension, using IO Completion Ports. +# Sub-classes can override one method to implement a simple extension, or +# may leverage the CompletionPort to queue their own requests, and implement a +# fully asynch extension. +class ThreadPoolExtension(isapi.simple.SimpleExtension): + "Base class for an ISAPI extension based around a thread-pool" + max_workers = 20 + worker_shutdown_wait = 15000 # 15 seconds for workers to quit... + def __init__(self): + self.workers = [] + # extensible dispatch map, for sub-classes that need to post their + # own requests to the completion port. + # Each of these functions is called with the result of + # GetQueuedCompletionStatus for our port. + self.dispatch_map = { + ISAPI_REQUEST: self.DispatchConnection, + } + + def GetExtensionVersion(self, vi): + isapi.simple.SimpleExtension.GetExtensionVersion(self, vi) + # As per Q192800, the CompletionPort should be created with the number + # of processors, even if the number of worker threads is much larger. + # Passing 0 means the system picks the number. + self.io_req_port = CreateIoCompletionPort(-1, None, 0, 0) + # start up the workers + self.workers = [] + for i in range(self.max_workers): + worker = WorkerThread(self, self.io_req_port) + worker.start() + self.workers.append(worker) + + def HttpExtensionProc(self, control_block): + overlapped = OVERLAPPED() + overlapped.object = control_block + PostQueuedCompletionStatus(self.io_req_port, 0, ISAPI_REQUEST, overlapped) + return isapicon.HSE_STATUS_PENDING + + def TerminateExtension(self, status): + for worker in self.workers: + worker.running = False + for worker in self.workers: + PostQueuedCompletionStatus(self.io_req_port, 0, ISAPI_SHUTDOWN, None) + # wait for them to terminate - pity we aren't using 'native' threads + # as then we could do a smart wait - but now we need to poll.... + end_time = time.time() + self.worker_shutdown_wait/1000 + alive = self.workers + while alive: + if time.time() > end_time: + # xxx - might be nice to log something here. + break + time.sleep(0.2) + alive = [w for w in alive if w.isAlive()] + self.dispatch_map = {} # break circles + CloseHandle(self.io_req_port) + + # This is the one operation the base class supports - a simple + # Connection request. We setup the thread-token, and dispatch to the + # sub-class's 'Dispatch' method. + def DispatchConnection(self, errCode, bytes, key, overlapped): + control_block = overlapped.object + # setup the correct user for this request + hRequestToken = control_block.GetImpersonationToken() + SetThreadToken(None, hRequestToken) + try: + try: + self.Dispatch(control_block) + except: + self.HandleDispatchError(control_block) + finally: + # reset the security context + SetThreadToken(None, None) + + def Dispatch(self, ecb): + """Overridden by the sub-class to handle connection requests. + + This class creates a thread-pool using a Windows completion port, + and dispatches requests via this port. Sub-classes can generally + implement each connection request using blocking reads and writes, and + the thread-pool will still provide decent response to the end user. + + The sub-class can set a max_workers attribute (default is 20). Note + that this generally does *not* mean 20 threads will all be concurrently + running, via the magic of Windows completion ports. + + There is no default implementation - sub-classes must implement this. + """ + raise NotImplementedError("sub-classes should override Dispatch") + + def HandleDispatchError(self, ecb): + """Handles errors in the Dispatch method. + + When a Dispatch method call fails, this method is called to handle + the exception. The default implementation formats the traceback + in the browser. + """ + ecb.HttpStatusCode = isapicon.HSE_STATUS_ERROR + #control_block.LogData = "we failed!" + exc_typ, exc_val, exc_tb = sys.exc_info() + limit = None + try: + try: + import cgi + ecb.SendResponseHeaders("200 OK", "Content-type: text/html\r\n\r\n", + False) + print(file=ecb) + print("

Traceback (most recent call last):

", file=ecb) + list = traceback.format_tb(exc_tb, limit) + \ + traceback.format_exception_only(exc_typ, exc_val) + print("
%s%s
" % ( + cgi.escape("".join(list[:-1])), cgi.escape(list[-1]),), file=ecb) + except ExtensionError: + # The client disconnected without reading the error body - + # its probably not a real browser at the other end, ignore it. + pass + except: + print("FAILED to render the error message!") + traceback.print_exc() + print("ORIGINAL extension error:") + traceback.print_exception(exc_typ, exc_val, exc_tb) + finally: + # holding tracebacks in a local of a frame that may itself be + # part of a traceback used to be evil and cause leaks! + exc_tb = None + ecb.DoneWithSession() diff --git a/Lib/site-packages/pythoncom.py b/Lib/site-packages/pythoncom.py new file mode 100644 index 0000000..7c3c044 --- /dev/null +++ b/Lib/site-packages/pythoncom.py @@ -0,0 +1,3 @@ +# Magic utility that "redirects" to pythoncomxx.dll +import pywintypes +pywintypes.__import_pywin32_system_module__("pythoncom", globals()) diff --git a/Lib/site-packages/pythonwin/Pythonwin.exe b/Lib/site-packages/pythonwin/Pythonwin.exe new file mode 100644 index 0000000..26ff116 Binary files /dev/null and b/Lib/site-packages/pythonwin/Pythonwin.exe differ diff --git a/Lib/site-packages/pythonwin/dde.pyd b/Lib/site-packages/pythonwin/dde.pyd new file mode 100644 index 0000000..cdcf48a Binary files /dev/null and b/Lib/site-packages/pythonwin/dde.pyd differ diff --git a/Lib/site-packages/pythonwin/license.txt b/Lib/site-packages/pythonwin/license.txt new file mode 100644 index 0000000..c9c0361 --- /dev/null +++ b/Lib/site-packages/pythonwin/license.txt @@ -0,0 +1,30 @@ +Unless stated in the specfic source file, this work is +Copyright (c) 1994-2008, Mark Hammond +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +Neither name of Mark Hammond nor the name of contributors may be used +to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS +IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Lib/site-packages/pythonwin/mfc140u.dll b/Lib/site-packages/pythonwin/mfc140u.dll new file mode 100644 index 0000000..62aad59 Binary files /dev/null and b/Lib/site-packages/pythonwin/mfc140u.dll differ diff --git a/Lib/site-packages/pythonwin/mfcm140u.dll b/Lib/site-packages/pythonwin/mfcm140u.dll new file mode 100644 index 0000000..ae10245 Binary files /dev/null and b/Lib/site-packages/pythonwin/mfcm140u.dll differ diff --git a/Lib/site-packages/pythonwin/pywin/Demos/app/basictimerapp.py b/Lib/site-packages/pythonwin/pywin/Demos/app/basictimerapp.py new file mode 100644 index 0000000..7a5183a --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/app/basictimerapp.py @@ -0,0 +1,221 @@ +# basictimerapp - a really simple timer application. +# This should be run using the command line: +# pythonwin /app demos\basictimerapp.py +import win32ui +import win32api +import win32con +import sys +from pywin.framework import app, cmdline, dlgappcore, cmdline +import timer +import time +import string + +class TimerAppDialog(dlgappcore.AppDialog): + softspace=1 + def __init__(self, appName = ""): + dlgappcore.AppDialog.__init__(self, win32ui.IDD_GENERAL_STATUS) + self.timerAppName = appName + self.argOff = 0 + if len(self.timerAppName)==0: + if len(sys.argv)>1 and sys.argv[1][0]!='/': + self.timerAppName = sys.argv[1] + self.argOff = 1 + + def PreDoModal(self): +# sys.stderr = sys.stdout + pass + + def ProcessArgs(self, args): + for arg in args: + if arg=="/now": + self.OnOK() + + def OnInitDialog(self): + win32ui.SetProfileFileName('pytimer.ini') + self.title = win32ui.GetProfileVal(self.timerAppName, "Title", "Remote System Timer") + self.buildTimer = win32ui.GetProfileVal(self.timerAppName, "Timer", "EachMinuteIntervaler()") + self.doWork = win32ui.GetProfileVal(self.timerAppName, "Work", "DoDemoWork()") + # replace "\n" with real \n. + self.doWork = self.doWork.replace('\\n','\n') + dlgappcore.AppDialog.OnInitDialog(self) + + self.SetWindowText(self.title) + self.prompt1 = self.GetDlgItem(win32ui.IDC_PROMPT1) + self.prompt2 = self.GetDlgItem(win32ui.IDC_PROMPT2) + self.prompt3 = self.GetDlgItem(win32ui.IDC_PROMPT3) + self.butOK = self.GetDlgItem(win32con.IDOK) + self.butCancel = self.GetDlgItem(win32con.IDCANCEL) + self.prompt1.SetWindowText("Python Timer App") + self.prompt2.SetWindowText("") + self.prompt3.SetWindowText("") + self.butOK.SetWindowText("Do it now") + self.butCancel.SetWindowText("Close") + + self.timerManager = TimerManager(self) + self.ProcessArgs(sys.argv[self.argOff:]) + self.timerManager.go() + return 1 + + def OnDestroy(self,msg): + dlgappcore.AppDialog.OnDestroy(self, msg) + self.timerManager.stop() + def OnOK(self): + # stop the timer, then restart after setting special boolean + self.timerManager.stop() + self.timerManager.bConnectNow = 1 + self.timerManager.go() + return +# def OnCancel(self): default behaviour - cancel == close. +# return + +class TimerManager: + def __init__(self, dlg): + self.dlg = dlg + self.timerId = None + self.intervaler = eval(self.dlg.buildTimer) + self.bConnectNow = 0 + self.bHaveSetPrompt1 = 0 + def CaptureOutput(self): + self.oldOut = sys.stdout + self.oldErr = sys.stderr + sys.stdout = sys.stderr = self + self.bHaveSetPrompt1 = 0 + def ReleaseOutput(self): + sys.stdout = self.oldOut + sys.stderr = self.oldErr + def write(self, str): + s = str.strip() + if len(s): + if self.bHaveSetPrompt1: + dest = self.dlg.prompt3 + else: + dest = self.dlg.prompt1 + self.bHaveSetPrompt1 = 1 + dest.SetWindowText(s) + def go(self): + self.OnTimer(None,None) + def stop(self): + if self.timerId: timer.kill_timer (self.timerId) + self.timerId = None + + def OnTimer(self, id, timeVal): + if id: timer.kill_timer (id) + if self.intervaler.IsTime() or self.bConnectNow : + # do the work. + try: + self.dlg.SetWindowText(self.dlg.title + " - Working...") + self.dlg.butOK.EnableWindow(0) + self.dlg.butCancel.EnableWindow(0) + self.CaptureOutput() + try: + exec(self.dlg.doWork) + print("The last operation completed successfully.") + except: + t, v, tb = sys.exc_info() + str = "Failed: %s: %s" % (t, repr(v)) + print(str) + self.oldErr.write(str) + tb = None # Prevent cycle + finally: + self.ReleaseOutput() + self.dlg.butOK.EnableWindow() + self.dlg.butCancel.EnableWindow() + self.dlg.SetWindowText(self.dlg.title) + else: + now = time.time() + nextTime = self.intervaler.GetNextTime() + if nextTime: + timeDiffSeconds = nextTime - now + timeDiffMinutes = int(timeDiffSeconds / 60) + timeDiffSeconds = timeDiffSeconds % 60 + timeDiffHours = int(timeDiffMinutes / 60) + timeDiffMinutes = timeDiffMinutes % 60 + self.dlg.prompt1.SetWindowText("Next connection due in %02d:%02d:%02d" % (timeDiffHours,timeDiffMinutes,timeDiffSeconds)) + self.timerId = timer.set_timer (self.intervaler.GetWakeupInterval(), self.OnTimer) + self.bConnectNow = 0 + +class TimerIntervaler: + def __init__(self): + self.nextTime = None + self.wakeUpInterval = 2000 + def GetWakeupInterval(self): + return self.wakeUpInterval + def GetNextTime(self): + return self.nextTime + def IsTime(self): + now = time.time() + if self.nextTime is None: + self.nextTime = self.SetFirstTime(now) + ret = 0 + if now >= self.nextTime: + ret = 1 + self.nextTime = self.SetNextTime(self.nextTime, now) + # do the work. + return ret + +class EachAnyIntervaler(TimerIntervaler): + def __init__(self, timeAt, timePos, timeAdd, wakeUpInterval = None): + TimerIntervaler.__init__(self) + self.timeAt = timeAt + self.timePos = timePos + self.timeAdd = timeAdd + if wakeUpInterval: + self.wakeUpInterval = wakeUpInterval + def SetFirstTime(self, now): + timeTup = time.localtime(now) + lst = [] + for item in timeTup: + lst.append(item) + bAdd = timeTup[self.timePos] > self.timeAt + lst[self.timePos] = self.timeAt + for pos in range(self.timePos+1, 6): + lst[pos]=0 + ret = time.mktime(tuple(lst)) + if (bAdd): + ret = ret + self.timeAdd + return ret; + + def SetNextTime(self, lastTime, now): + return lastTime + self.timeAdd + +class EachMinuteIntervaler(EachAnyIntervaler): + def __init__(self, at=0): + EachAnyIntervaler.__init__(self, at, 5, 60, 2000) + +class EachHourIntervaler(EachAnyIntervaler): + def __init__(self, at=0): + EachAnyIntervaler.__init__(self, at, 4, 3600, 10000) + +class EachDayIntervaler(EachAnyIntervaler): + def __init__(self,at=0): + EachAnyIntervaler.__init__(self, at, 3, 86400, 10000) + +class TimerDialogApp(dlgappcore.DialogApp): + def CreateDialog(self): + return TimerAppDialog() + +def DoDemoWork(): + print("Doing the work...") + print("About to connect") + win32api.MessageBeep(win32con.MB_ICONASTERISK) + win32api.Sleep(2000) + print("Doing something else...") + win32api.MessageBeep(win32con.MB_ICONEXCLAMATION) + win32api.Sleep(2000) + print("More work.") + win32api.MessageBeep(win32con.MB_ICONHAND) + win32api.Sleep(2000) + print("The last bit.") + win32api.MessageBeep(win32con.MB_OK) + win32api.Sleep(2000) + +app = TimerDialogApp() + +def t(): + t = TimerAppDialog("Test Dialog") + t.DoModal() + return t + +if __name__=='__main__': + import demoutils + demoutils.NeedApp() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/app/customprint.py b/Lib/site-packages/pythonwin/pywin/Demos/app/customprint.py new file mode 100644 index 0000000..3ad36bd --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/app/customprint.py @@ -0,0 +1,194 @@ +# A demo of an Application object that has some custom print functionality. + +# If you desire, you can also run this from inside Pythonwin, in which +# case it will do the demo inside the Pythonwin environment. + +# This sample was contributed by Roger Burnham. + +from pywin.mfc import docview, dialog, afxres +from pywin.framework import app + +import win32con +import win32ui +import win32api + +PRINTDLGORD = 1538 +IDC_PRINT_MAG_EDIT = 1010 + + +class PrintDemoTemplate(docview.DocTemplate): + def _SetupSharedMenu_(self): + pass + +class PrintDemoView(docview.ScrollView): + + def OnInitialUpdate(self): + ret = self._obj_.OnInitialUpdate() + self.colors = {'Black' : (0x00<<0) + (0x00<<8) + (0x00<<16), + 'Red' : (0xff<<0) + (0x00<<8) + (0x00<<16), + 'Green' : (0x00<<0) + (0xff<<8) + (0x00<<16), + 'Blue' : (0x00<<0) + (0x00<<8) + (0xff<<16), + 'Cyan' : (0x00<<0) + (0xff<<8) + (0xff<<16), + 'Magenta': (0xff<<0) + (0x00<<8) + (0xff<<16), + 'Yellow' : (0xff<<0) + (0xff<<8) + (0x00<<16), + } + self.pens = {} + for name, color in self.colors.items(): + self.pens[name] = win32ui.CreatePen(win32con.PS_SOLID, + 5, color) + self.pen = None + self.size = (128,128) + self.SetScaleToFitSize(self.size) + self.HookCommand(self.OnFilePrint, afxres.ID_FILE_PRINT) + self.HookCommand(self.OnFilePrintPreview, + win32ui.ID_FILE_PRINT_PREVIEW) + return ret + + def OnDraw(self, dc): + oldPen = None + x,y = self.size + delta = 2 + colors = list(self.colors.keys()) + colors.sort() + colors = colors*2 + for color in colors: + if oldPen is None: + oldPen = dc.SelectObject(self.pens[color]) + else: + dc.SelectObject(self.pens[color]) + dc.MoveTo(( delta, delta)) + dc.LineTo((x-delta, delta)) + dc.LineTo((x-delta, y-delta)) + dc.LineTo(( delta, y-delta)) + dc.LineTo(( delta, delta)) + delta = delta + 4 + if x-delta <= 0 or y-delta <= 0: + break + dc.SelectObject(oldPen) + + def OnPrepareDC (self, dc, pInfo): + if dc.IsPrinting(): + mag = self.prtDlg['mag'] + dc.SetMapMode(win32con.MM_ANISOTROPIC); + dc.SetWindowOrg((0, 0)) + dc.SetWindowExt((1, 1)) + dc.SetViewportOrg((0, 0)) + dc.SetViewportExt((mag, mag)) + + def OnPreparePrinting(self, pInfo): + flags = (win32ui.PD_USEDEVMODECOPIES| + win32ui.PD_PAGENUMS| + win32ui.PD_NOPAGENUMS| + win32ui.PD_NOSELECTION) + self.prtDlg = ImagePrintDialog(pInfo, PRINTDLGORD, flags) + pInfo.SetPrintDialog(self.prtDlg) + pInfo.SetMinPage(1) + pInfo.SetMaxPage(1) + pInfo.SetFromPage(1) + pInfo.SetToPage(1) + ret = self.DoPreparePrinting(pInfo) + return ret + + def OnBeginPrinting(self, dc, pInfo): + return self._obj_.OnBeginPrinting(dc, pInfo) + + def OnEndPrinting(self, dc, pInfo): + del self.prtDlg + return self._obj_.OnEndPrinting(dc, pInfo) + + def OnFilePrintPreview(self, *arg): + self._obj_.OnFilePrintPreview() + + def OnFilePrint(self, *arg): + self._obj_.OnFilePrint() + + def OnPrint(self, dc, pInfo): + doc = self.GetDocument() + metrics = dc.GetTextMetrics() + cxChar = metrics['tmAveCharWidth'] + cyChar = metrics['tmHeight'] + left, top, right, bottom = pInfo.GetDraw() + dc.TextOut(0, 2*cyChar, doc.GetTitle()) + top = top + (7*cyChar)/2 + dc.MoveTo(left, top) + dc.LineTo(right, top) + top = top + cyChar + # this seems to have not effect... + # get what I want with the dc.SetWindowOrg calls + pInfo.SetDraw((left, top, right, bottom)) + dc.SetWindowOrg((0, -top)) + + self.OnDraw(dc) + dc.SetTextAlign(win32con.TA_LEFT|win32con.TA_BOTTOM) + + rect = self.GetWindowRect() + rect = self.ScreenToClient(rect) + height = (rect[3]-rect[1]) + dc.SetWindowOrg((0, -(top+height+cyChar))) + dc.MoveTo(left, 0) + dc.LineTo(right, 0) + + x = 0 + y = (3*cyChar)/2 + + dc.TextOut(x, y, doc.GetTitle()) + y = y + cyChar + + +class PrintDemoApp(app.CApp): + def __init__(self): + app.CApp.__init__(self) + + def InitInstance(self): + template = PrintDemoTemplate(None, None, + None, PrintDemoView) + self.AddDocTemplate(template) + self._obj_.InitMDIInstance() + self.LoadMainFrame() + doc = template.OpenDocumentFile(None) + doc.SetTitle('Custom Print Document') + + +class ImagePrintDialog(dialog.PrintDialog): + + sectionPos = 'Image Print Demo' + + def __init__(self, pInfo, dlgID, flags=win32ui.PD_USEDEVMODECOPIES): + dialog.PrintDialog.__init__(self, pInfo, dlgID, flags=flags) + mag = win32ui.GetProfileVal(self.sectionPos, + 'Document Magnification', + 0) + if mag <= 0: + mag = 2 + win32ui.WriteProfileVal(self.sectionPos, + 'Document Magnification', + mag) + + self['mag'] = mag + + def OnInitDialog(self): + self.magCtl = self.GetDlgItem(IDC_PRINT_MAG_EDIT) + self.magCtl.SetWindowText(repr(self['mag'])) + return dialog.PrintDialog.OnInitDialog(self) + def OnOK(self): + dialog.PrintDialog.OnOK(self) + strMag = self.magCtl.GetWindowText() + try: + self['mag'] = int(strMag) + except: + pass + win32ui.WriteProfileVal(self.sectionPos, + 'Document Magnification', + self['mag']) + + +if __name__=='__main__': + # Running under Pythonwin + def test(): + template = PrintDemoTemplate(None, None, + None, PrintDemoView) + template.OpenDocumentFile(None) + test() +else: + app = PrintDemoApp() + diff --git a/Lib/site-packages/pythonwin/pywin/Demos/app/demoutils.py b/Lib/site-packages/pythonwin/pywin/Demos/app/demoutils.py new file mode 100644 index 0000000..70bdbdb --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/app/demoutils.py @@ -0,0 +1,52 @@ +# Utilities for the demos + +import sys, win32api, win32con, win32ui + +NotScriptMsg = """\ +This demo program is not designed to be run as a Script, but is +probably used by some other test program. Please try another demo. +""" + +NeedGUIMsg = """\ +This demo program can only be run from inside of Pythonwin + +You must start Pythonwin, and select 'Run' from the toolbar or File menu +""" + + +NeedAppMsg = """\ +This demo program is a 'Pythonwin Application'. + +It is more demo code than an example of Pythonwin's capabilities. + +To run it, you must execute the command: +pythonwin.exe /app "%s" + +Would you like to execute it now? +""" + +def NotAScript(): + import win32ui + win32ui.MessageBox(NotScriptMsg, "Demos") + +def NeedGoodGUI(): + from pywin.framework.app import HaveGoodGUI + rc = HaveGoodGUI() + if not rc: + win32ui.MessageBox(NeedGUIMsg, "Demos") + return rc + +def NeedApp(): + import win32ui + rc = win32ui.MessageBox(NeedAppMsg % sys.argv[0], "Demos", win32con.MB_YESNO) + if rc==win32con.IDYES: + try: + parent = win32ui.GetMainFrame().GetSafeHwnd() + win32api.ShellExecute(parent, None, 'pythonwin.exe', '/app "%s"' % sys.argv[0], None, 1) + except win32api.error as details: + win32ui.MessageBox("Error executing command - %s" % (details), "Demos") + + +if __name__=='__main__': + import demoutils + demoutils.NotAScript() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/app/dlgappdemo.py b/Lib/site-packages/pythonwin/pywin/Demos/app/dlgappdemo.py new file mode 100644 index 0000000..4341d02 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/app/dlgappdemo.py @@ -0,0 +1,46 @@ +# dlgappdemo - a demo of a dialog application. +# This is a demonstration of both a custom "application" module, +# and a Python program in a dialog box. +# +# NOTE: You CAN NOT import this module from either PythonWin or Python. +# This module must be specified on the commandline to PythonWin only. +# eg, PythonWin /app dlgappdemo.py + +from pywin.framework import dlgappcore, app +import win32ui +import sys + +class TestDialogApp(dlgappcore.DialogApp): + def CreateDialog(self): + return TestAppDialog() + + +class TestAppDialog(dlgappcore.AppDialog): + def __init__(self): + self.edit = None + dlgappcore.AppDialog.__init__(self, win32ui.IDD_LARGE_EDIT) + def OnInitDialog(self): + self.SetWindowText('Test dialog application') + self.edit = self.GetDlgItem(win32ui.IDC_EDIT1) + print("Hello from Python") + print("args are:", end=' ') + for arg in sys.argv: + print(arg) + return 1 + + def PreDoModal(self): + sys.stdout = sys.stderr = self + + def write(self, str): + if self.edit: + self.edit.SetSel(-2) + # translate \n to \n\r + self.edit.ReplaceSel(str.replace('\n','\r\n')) + else: + win32ui.OutputDebug("dlgapp - no edit control! >>\n%s\n<<\n" % str ) + +app.AppBuilder = TestDialogApp + +if __name__=='__main__': + import demoutils + demoutils.NeedApp() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/app/dojobapp.py b/Lib/site-packages/pythonwin/pywin/Demos/app/dojobapp.py new file mode 100644 index 0000000..b73f794 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/app/dojobapp.py @@ -0,0 +1,62 @@ +# dojobapp - do a job, show the result in a dialog, and exit. +# +# Very simple - faily minimal dialog based app. +# +# This should be run using the command line: +# pythonwin /app demos\dojobapp.py + +import win32ui +import win32api +import win32con +import sys +from pywin.framework import app, dlgappcore +import string + +class DoJobAppDialog(dlgappcore.AppDialog): + softspace=1 + def __init__(self, appName = ""): + self.appName = appName + dlgappcore.AppDialog.__init__(self, win32ui.IDD_GENERAL_STATUS) + + def PreDoModal(self): + pass + + def ProcessArgs(self, args): + pass + + def OnInitDialog(self): + self.SetWindowText(self.appName) + butCancel = self.GetDlgItem(win32con.IDCANCEL) + butCancel.ShowWindow(win32con.SW_HIDE) + p1 = self.GetDlgItem(win32ui.IDC_PROMPT1) + p2 = self.GetDlgItem(win32ui.IDC_PROMPT2) + + # Do something here! + + p1.SetWindowText("Hello there") + p2.SetWindowText("from the demo") + def OnDestroy(self,msg): + pass +# def OnOK(self): +# pass +# def OnCancel(self): default behaviour - cancel == close. +# return + +class DoJobDialogApp(dlgappcore.DialogApp): + def CreateDialog(self): + return DoJobAppDialog("Do Something") + +class CopyToDialogApp(DoJobDialogApp): + def __init__(self): + DoJobDialogApp.__init__(self) + +app.AppBuilder = DoJobDialogApp + +def t(): + t = DoJobAppDialog("Copy To") + t.DoModal() + return t + +if __name__=='__main__': + import demoutils + demoutils.NeedApp() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/app/helloapp.py b/Lib/site-packages/pythonwin/pywin/Demos/app/helloapp.py new file mode 100644 index 0000000..0324a16 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/app/helloapp.py @@ -0,0 +1,45 @@ +## +## helloapp.py +## +## +## A nice, small 'hello world' Pythonwin application. +## NOT an MDI application - just a single, normal, top-level window. +## +## MUST be run with the command line "pythonwin.exe /app helloapp.py" +## (or if you are really keen, rename "pythonwin.exe" to something else, then +## using MSVC or similar, edit the string section in the .EXE to name this file) +## +## Originally by Willy Heineman + + +import win32con +import win32ui +from pywin.mfc import window, dialog, afxres +from pywin.mfc.thread import WinApp + +# The main frame. +# Does almost nothing at all - doesnt even create a child window! +class HelloWindow(window.Wnd): + def __init__(self): + # The window.Wnd ctor creates a Window object, and places it in + # self._obj_. Note the window object exists, but the window itself + # does not! + window.Wnd.__init__(self, win32ui.CreateWnd()) + + # Now we ask the window object to create the window itself. + self._obj_.CreateWindowEx(win32con.WS_EX_CLIENTEDGE, \ + win32ui.RegisterWndClass(0, 0, win32con.COLOR_WINDOW + 1), \ + 'Hello World!', win32con.WS_OVERLAPPEDWINDOW, \ + (100, 100, 400, 300), None, 0, None) + +# The application object itself. +class HelloApp(WinApp): + + def InitInstance(self): + self.frame = HelloWindow() + self.frame.ShowWindow(win32con.SW_SHOWNORMAL) + # We need to tell MFC what our main frame is. + self.SetMainFrame(self.frame) + +# Now create the application object itself! +app = HelloApp() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/cmdserver.py b/Lib/site-packages/pythonwin/pywin/Demos/cmdserver.py new file mode 100644 index 0000000..0b3f7e0 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/cmdserver.py @@ -0,0 +1,108 @@ +# cmdserver.py + +# Demo code that is not Pythonwin related, but too good to throw away... + +import win32api +import sys +from pywin.framework import winout + +import _thread, sys + +import traceback + +class ThreadWriter: + "Assign an instance to sys.stdout for per-thread printing objects - Courtesy Guido!" + def __init__(self): + "Constructor -- initialize the table of writers" + self.writers = {} + self.origStdOut = None + def register(self, writer): + "Register the writer for the current thread" + self.writers[_thread.get_ident()] = writer + if self.origStdOut is None: + self.origStdOut = sys.stdout + sys.stdout = self + + def unregister(self): + "Remove the writer for the current thread, if any" + try: + del self.writers[_thread.get_ident()] + except KeyError: + pass + if len(self.writers)==0: + sys.stdout = self.origStdOut + self.origStdOut = None + + def getwriter(self): + "Return the current thread's writer, default sys.stdout" + try: + return self.writers[_thread.get_ident()] + except KeyError: + return self.origStdOut + + def write(self, str): + "Write to the current thread's writer, default sys.stdout" + self.getwriter().write(str) + +def Test(): + num=1 + while num<1000: + print('Hello there no ' + str(num)) + win32api.Sleep(50) + num = num + 1 + +class flags: + SERVER_BEST = 0 + SERVER_IMMEDIATE = 1 + SERVER_THREAD = 2 + SERVER_PROCESS = 3 + +def StartServer( cmd, title=None, bCloseOnEnd=0, serverFlags = flags.SERVER_BEST ): + out = winout.WindowOutput( title, None, winout.flags.WQ_IDLE ) + if not title: + title=cmd + out.Create(title) +# ServerThread((out, cmd, title, bCloseOnEnd)) +# out = sys.stdout + _thread.start_new_thread( ServerThread, (out, cmd, title, bCloseOnEnd) ) + +def ServerThread(myout, cmd, title, bCloseOnEnd): + try: + writer.register(myout) + print('Executing "%s"\n' % cmd) + bOK = 1 + try: + import __main__ + exec (cmd+'\n', __main__.__dict__) + except: + bOK = 0 + if bOK: + print("Command terminated without errors.") + else: + t, v, tb = sys.exc_info() + print(t, ': ', v) + traceback.print_tb(tb) + tb = None # prevent a cycle + print("Command terminated with an unhandled exception") + writer.unregister() + if bOK and bCloseOnEnd: + myout.frame.DestroyWindow() + + # Unhandled exception of any kind in a thread kills the gui! + except: + t, v, tb = sys.exc_info() + print(t, ': ', v) + traceback.print_tb(tb) + tb = None + print("Thread failed") + +# assist for reloading (when debugging) - use only 1 tracer object, +# else a large chain of tracer objects will exist. +#try: +# writer +#except NameError: +# writer=ThreadWriter() +if __name__=='__main__': + import demoutils + demoutils.NotAScript() + diff --git a/Lib/site-packages/pythonwin/pywin/Demos/createwin.py b/Lib/site-packages/pythonwin/pywin/Demos/createwin.py new file mode 100644 index 0000000..78f3c94 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/createwin.py @@ -0,0 +1,98 @@ +# +# Window creation example +# +# This example creates a minimal "control" that just fills in its +# window with red. To make your own control, subclass Control and +# write your own OnPaint() method. See PyCWnd.HookMessage for what +# the parameters to OnPaint are. +# + +from pywin.mfc import dialog, window +import win32ui +import win32con +import win32api + +class Control(window.Wnd): + """Generic control class""" + def __init__ (self): + window.Wnd.__init__(self, win32ui.CreateWnd ()) + + def OnPaint (self): + dc, paintStruct = self.BeginPaint() + self.DoPaint(dc) + self.EndPaint(paintStruct) + + def DoPaint (self, dc): # Override this! + pass + +class RedBox (Control): + def DoPaint (self, dc): + dc.FillSolidRect (self.GetClientRect(), win32api.RGB(255,0,0)) + + +class RedBoxWithPie (RedBox): + def DoPaint (self, dc): + RedBox.DoPaint(self, dc) + r = self.GetClientRect() + dc.Pie(r[0], r[1], r[2], r[3], 0,0,r[2], r[3]//2) + +def MakeDlgTemplate(): + style = (win32con.DS_MODALFRAME | + win32con.WS_POPUP | + win32con.WS_VISIBLE | + win32con.WS_CAPTION | + win32con.WS_SYSMENU | + win32con.DS_SETFONT) + cs = (win32con.WS_CHILD | + win32con.WS_VISIBLE) + + w = 64 + h = 64 + + dlg = [["Red box", + (0, 0, w, h), + style, + None, + (8, "MS Sans Serif")], + ] + + s = win32con.WS_TABSTOP | cs + + dlg.append([128, + "Cancel", + win32con.IDCANCEL, + (7, h - 18, 50, 14), s | win32con.BS_PUSHBUTTON]) + + return dlg + +class TestDialog(dialog.Dialog): + def OnInitDialog(self): + rc = dialog.Dialog.OnInitDialog(self) + self.redbox = RedBox () + self.redbox.CreateWindow (None, "RedBox", + win32con.WS_CHILD | + win32con.WS_VISIBLE, + (5, 5, 90, 68), + self, 1003) + return rc + +class TestPieDialog(dialog.Dialog): + def OnInitDialog(self): + rc = dialog.Dialog.OnInitDialog(self) + self.control = RedBoxWithPie() + self.control.CreateWindow (None, "RedBox with Pie", + win32con.WS_CHILD | + win32con.WS_VISIBLE, + (5, 5, 90, 68), + self, 1003) + +def demo(modal=0): + d = TestPieDialog (MakeDlgTemplate()) + if modal: + d.DoModal() + else: + d.CreateWindow() + +if __name__=='__main__': + demo(1) + diff --git a/Lib/site-packages/pythonwin/pywin/Demos/demoutils.py b/Lib/site-packages/pythonwin/pywin/Demos/demoutils.py new file mode 100644 index 0000000..8f7d5f6 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/demoutils.py @@ -0,0 +1,54 @@ +# Utilities for the demos + +import sys, win32api, win32con, win32ui + +NotScriptMsg = """\ +This demo program is not designed to be run as a Script, but is +probably used by some other test program. Please try another demo. +""" + +NeedGUIMsg = """\ +This demo program can only be run from inside of Pythonwin + +You must start Pythonwin, and select 'Run' from the toolbar or File menu +""" + + +NeedAppMsg = """\ +This demo program is a 'Pythonwin Application'. + +It is more demo code than an example of Pythonwin's capabilities. + +To run it, you must execute the command: +pythonwin.exe /app "%s" + +Would you like to execute it now? +""" + +def NotAScript(): + import win32ui + win32ui.MessageBox(NotScriptMsg, "Demos") + +def NeedGoodGUI(): + from pywin.framework.app import HaveGoodGUI + rc = HaveGoodGUI() + if not rc: + win32ui.MessageBox(NeedGUIMsg, "Demos") + return rc + +def NeedApp(): + import win32ui + rc = win32ui.MessageBox(NeedAppMsg % sys.argv[0], "Demos", win32con.MB_YESNO) + if rc==win32con.IDYES: + try: + parent = win32ui.GetMainFrame().GetSafeHwnd() + win32api.ShellExecute(parent, None, 'pythonwin.exe', '/app "%s"' % sys.argv[0], None, 1) + except win32api.error as details: + win32ui.MessageBox("Error executing command - %s" % (details), "Demos") + + +from pywin.framework.app import HaveGoodGUI + +if __name__=='__main__': + import demoutils + demoutils.NotAScript() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/dibdemo.py b/Lib/site-packages/pythonwin/pywin/Demos/dibdemo.py new file mode 100644 index 0000000..fe28653 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/dibdemo.py @@ -0,0 +1,69 @@ +# A demo which creates a view and a frame which displays a PPM format bitmap +# +# This hasnnt been run in a while, as I dont have many of that format around! +import win32ui +import win32con +import win32api +import string + +class DIBView: + def __init__(self, doc, dib): + self.dib = dib + self.view = win32ui.CreateView(doc) + self.width = self.height = 0 + # set up message handlers +# self.view.OnPrepareDC = self.OnPrepareDC + self.view.HookMessage (self.OnSize, win32con.WM_SIZE) + + def OnSize (self, params): + lParam = params[3] + self.width = win32api.LOWORD(lParam) + self.height = win32api.HIWORD(lParam) + + def OnDraw (self, ob, dc): + # set sizes used for "non strecth" mode. + self.view.SetScrollSizes(win32con.MM_TEXT, self.dib.GetSize()) + dibSize = self.dib.GetSize() + dibRect = (0,0,dibSize[0], dibSize[1]) + # stretch BMP. + #self.dib.Paint(dc, (0,0,self.width, self.height),dibRect) + # non stretch. + self.dib.Paint(dc) + +class DIBDemo: + def __init__(self, filename, * bPBM): + # init data members + f = open(filename, 'rb') + dib=win32ui.CreateDIBitmap() + if len(bPBM)>0: + magic=f.readline() + if magic != "P6\n": + print("The file is not a PBM format file") + raise ValueError("Failed - The file is not a PBM format file") + # check magic? + rowcollist=f.readline().split() + cols=int(rowcollist[0]) + rows=int(rowcollist[1]) + f.readline() # whats this one? + dib.LoadPBMData(f,(cols,rows)) + else: + dib.LoadWindowsFormatFile(f) + f.close() + # create doc/view + self.doc = win32ui.CreateDoc() + self.dibView = DIBView( self.doc, dib ) + self.frame = win32ui.CreateMDIFrame() + self.frame.LoadFrame() # this will force OnCreateClient + self.doc.SetTitle ('DIB Demo') + self.frame.ShowWindow() + + # display the sucka + self.frame.ActivateFrame() + + def OnCreateClient( self, createparams, context ): + self.dibView.view.CreateWindow(self.frame) + return 1 + +if __name__=='__main__': + import demoutils + demoutils.NotAScript() \ No newline at end of file diff --git a/Lib/site-packages/pythonwin/pywin/Demos/dlgtest.py b/Lib/site-packages/pythonwin/pywin/Demos/dlgtest.py new file mode 100644 index 0000000..1e7d10e --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/dlgtest.py @@ -0,0 +1,137 @@ +# A Demo of Pythonwin's Dialog and Property Page support. + +################### +# +# First demo - use the built-in to Pythonwin "Tab Stop" dialog, but +# customise it heavily. +# +# ID's for the tabstop dialog - out test. +# +from win32ui import IDD_SET_TABSTOPS +from win32ui import IDC_EDIT_TABS +from win32ui import IDC_PROMPT_TABS +from win32con import IDOK +from win32con import IDCANCEL + +import win32ui +import win32con + +from pywin.mfc import dialog + +class TestDialog(dialog.Dialog): + def __init__(self, modal=1): + dialog.Dialog.__init__(self, IDD_SET_TABSTOPS) + self.counter=0 + if modal: + self.DoModal() + else: + self.CreateWindow() + + def OnInitDialog(self): + # Set the caption of the dialog itself. + self.SetWindowText("Used to be Tab Stops!") + # Get a child control, remember it, and change its text. + self.edit=self.GetDlgItem(IDC_EDIT_TABS) # the text box. + self.edit.SetWindowText("Test") + # Hook a Windows message for the dialog. + self.edit.HookMessage(self.KillFocus, win32con.WM_KILLFOCUS) + # Get the prompt control, and change its next. + prompt=self.GetDlgItem(IDC_PROMPT_TABS) # the prompt box. + prompt.SetWindowText("Prompt") + # And the same for the button.. + cancel=self.GetDlgItem(IDCANCEL) # the cancel button + cancel.SetWindowText("&Kill me") + + # And just for demonstration purposes, we hook the notify message for the dialog. + # This allows us to be notified when the Edit Control text changes. + self.HookCommand(self.OnNotify, IDC_EDIT_TABS) + + def OnNotify(self, controlid, code): + if code==win32con.EN_CHANGE: + print("Edit text changed!") + return 1 # I handled this, so no need to call defaults! + + # kill focus for the edit box. + # Simply increment the value in the text box. + def KillFocus(self,msg): + self.counter=self.counter+1 + if self.edit != None: + self.edit.SetWindowText(str(self.counter)) + + # Called when the dialog box is terminating... + def OnDestroy(self,msg): + del self.edit + del self.counter + +# A very simply Property Sheet. +# We only make a new class for demonstration purposes. +class TestSheet(dialog.PropertySheet): + def __init__(self, title): + dialog.PropertySheet.__init__(self, title) + self.HookMessage(self.OnActivate, win32con.WM_ACTIVATE) + def OnActivate(self, msg): + pass + +# A very simply Property Page, which will be "owned" by the above +# Property Sheet. +# We create a new class, just so we can hook a control notification. +class TestPage(dialog.PropertyPage): + def OnInitDialog(self): + # We use the HookNotify function to allow Python to respond to + # Windows WM_NOTIFY messages. + # In this case, we are interested in BN_CLICKED messages. + self.HookNotify(self.OnNotify, win32con.BN_CLICKED) + def OnNotify(self, std, extra): + print("OnNotify", std, extra) + +# Some code that actually uses these objects. +def demo(modal = 0): + TestDialog(modal) + + # property sheet/page demo + ps=win32ui.CreatePropertySheet('Property Sheet/Page Demo') + # Create a completely standard PropertyPage. + page1=win32ui.CreatePropertyPage(win32ui.IDD_PROPDEMO1) + # Create our custom property page. + page2=TestPage(win32ui.IDD_PROPDEMO2) + ps.AddPage(page1) + ps.AddPage(page2) + if modal: + ps.DoModal() + else: + style = win32con.WS_SYSMENU|win32con.WS_POPUP|win32con.WS_CAPTION|win32con.DS_MODALFRAME|win32con.WS_VISIBLE + styleex = win32con.WS_EX_DLGMODALFRAME | win32con.WS_EX_PALETTEWINDOW + ps.CreateWindow(win32ui.GetMainFrame(), style, styleex) + + +def test(modal=1): + +# dlg=dialog.Dialog(1010) +# dlg.CreateWindow() +# dlg.EndDialog(0) +# del dlg +# return + # property sheet/page demo + ps=TestSheet('Property Sheet/Page Demo') + page1=win32ui.CreatePropertyPage(win32ui.IDD_PROPDEMO1) + page2=win32ui.CreatePropertyPage(win32ui.IDD_PROPDEMO2) + ps.AddPage(page1) + ps.AddPage(page2) + del page1 + del page2 + if modal: + ps.DoModal() + else: + ps.CreateWindow(win32ui.GetMainFrame()) + return ps + +def d(): + dlg = win32ui.CreateDialog(win32ui.IDD_DEBUGGER) + dlg.datalist.append((win32ui.IDC_DBG_RADIOSTACK, "radio")) + print("data list is ", dlg.datalist) + dlg.data['radio']=1 + dlg.DoModal() + print(dlg.data['radio']) + +if __name__=='__main__': + demo(1) diff --git a/Lib/site-packages/pythonwin/pywin/Demos/dyndlg.py b/Lib/site-packages/pythonwin/pywin/Demos/dyndlg.py new file mode 100644 index 0000000..4b920f5 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/dyndlg.py @@ -0,0 +1,73 @@ +# dyndlg.py +# contributed by Curt Hagenlocher + +# Dialog Template params: +# Parameter 0 - Window caption +# Parameter 1 - Bounds (rect tuple) +# Parameter 2 - Window style +# Parameter 3 - Extended style +# Parameter 4 - Font tuple +# Parameter 5 - Menu name +# Parameter 6 - Window class +# Dialog item params: +# Parameter 0 - Window class +# Parameter 1 - Text +# Parameter 2 - ID +# Parameter 3 - Bounds +# Parameter 4 - Style +# Parameter 5 - Extended style +# Parameter 6 - Extra data + + +import win32ui +import win32con +from pywin.mfc import dialog, window + +def MakeDlgTemplate(): + style = win32con.DS_MODALFRAME | win32con.WS_POPUP | win32con.WS_VISIBLE | win32con.WS_CAPTION | win32con.WS_SYSMENU | win32con.DS_SETFONT + cs = win32con.WS_CHILD | win32con.WS_VISIBLE + dlg = [ ["Select Warehouse", (0, 0, 177, 93), style, None, (8, "MS Sans Serif")], ] + dlg.append([130, "Current Warehouse:", -1, (7, 7, 69, 9), cs | win32con.SS_LEFT]) + dlg.append([130, "ASTORIA", 128, (16, 17, 99, 7), cs | win32con.SS_LEFT]) + dlg.append([130, "New &Warehouse:", -1, (7, 29, 69, 9), cs | win32con.SS_LEFT]) + s = win32con.WS_TABSTOP | cs +# dlg.append([131, None, 130, (5, 40, 110, 48), +# s | win32con.LBS_NOTIFY | win32con.LBS_SORT | win32con.LBS_NOINTEGRALHEIGHT | win32con.WS_VSCROLL | win32con.WS_BORDER]) + dlg.append(["{8E27C92B-1264-101C-8A2F-040224009C02}", None, 131, (5, 40, 110, 48),win32con.WS_TABSTOP]) + + dlg.append([128, "OK", win32con.IDOK, (124, 5, 50, 14), s | win32con.BS_DEFPUSHBUTTON]) + s = win32con.BS_PUSHBUTTON | s + dlg.append([128, "Cancel", win32con.IDCANCEL, (124, 22, 50, 14), s]) + dlg.append([128, "&Help", 100, (124, 74, 50, 14), s]) + + return dlg + +def test1(): + win32ui.CreateDialogIndirect( MakeDlgTemplate() ).DoModal() + +def test2(): + dialog.Dialog( MakeDlgTemplate() ).DoModal() + +def test3(): + dlg = win32ui.LoadDialogResource(win32ui.IDD_SET_TABSTOPS) + dlg[0][0] = 'New Dialog Title' + dlg[0][1] = (80, 20, 161, 60) + dlg[1][1] = '&Confusion:' + cs = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_TABSTOP | win32con.BS_PUSHBUTTON + dlg.append([128, "&Help", 100, (111, 41, 40, 14), cs]) + dialog.Dialog( dlg ).DoModal() + +def test4(): + page1=dialog.PropertyPage(win32ui.LoadDialogResource(win32ui.IDD_PROPDEMO1)) + page2=dialog.PropertyPage(win32ui.LoadDialogResource(win32ui.IDD_PROPDEMO2)) + ps=dialog.PropertySheet('Property Sheet/Page Demo', None, [page1, page2]) + ps.DoModal() + +def testall(): + test1() + test2() + test3() + test4() + +if __name__=='__main__': + testall() \ No newline at end of file diff --git a/Lib/site-packages/pythonwin/pywin/Demos/fontdemo.py b/Lib/site-packages/pythonwin/pywin/Demos/fontdemo.py new file mode 100644 index 0000000..f2a212c --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/fontdemo.py @@ -0,0 +1,79 @@ +# Demo of Generic document windows, DC, and Font usage +# by Dave Brennan (brennan@hal.com) + +# usage examples: + +# >>> from fontdemo import * +# >>> d = FontDemo('Hello, Python') +# >>> f1 = { 'name':'Arial', 'height':36, 'weight':win32con.FW_BOLD} +# >>> d.SetFont(f1) +# >>> f2 = {'name':'Courier New', 'height':24, 'italic':1} +# >>> d.SetFont (f2) + +import win32ui +import win32con +import win32api + +from pywin.mfc import docview + + +# font is a dictionary in which the following elements matter: +# (the best matching font to supplied parameters is returned) +# name string name of the font as known by Windows +# size point size of font in logical units +# weight weight of font (win32con.FW_NORMAL, win32con.FW_BOLD) +# italic boolean; true if set to anything but None +# underline boolean; true if set to anything but None + +class FontView(docview.ScrollView): + def __init__(self, doc, text = 'Python Rules!', font_spec = {'name':'Arial', 'height':42}): + docview.ScrollView.__init__(self, doc) + self.font = win32ui.CreateFont (font_spec) + self.text = text + self.width = self.height = 0 + # set up message handlers + self.HookMessage (self.OnSize, win32con.WM_SIZE) + def OnAttachedObjectDeath(self): + docview.ScrollView.OnAttachedObjectDeath(self) + del self.font + + def SetFont (self, new_font): + # Change font on the fly + self.font = win32ui.CreateFont (new_font) + # redraw the entire client window + selfInvalidateRect (None) + def OnSize (self, params): + lParam = params[3] + self.width = win32api.LOWORD(lParam) + self.height = win32api.HIWORD(lParam) + + def OnPrepareDC (self, dc, printinfo): + # Set up the DC for forthcoming OnDraw call + self.SetScrollSizes(win32con.MM_TEXT, (100,100)) + dc.SetTextColor (win32api.RGB(0,0,255)) + dc.SetBkColor (win32api.GetSysColor (win32con.COLOR_WINDOW)) + dc.SelectObject (self.font) + dc.SetTextAlign (win32con.TA_CENTER | win32con.TA_BASELINE) + + def OnDraw (self, dc): + if (self.width == 0 and self.height == 0): + left, top, right, bottom = self.GetClientRect() + self.width = right - left + self.height = bottom - top + x, y = self.width // 2, self.height // 2 + dc.TextOut (x, y, self.text) + +def FontDemo(): + # create doc/view + template = docview.DocTemplate(win32ui.IDR_PYTHONTYPE, None, None, FontView) + doc=template.OpenDocumentFile(None) + doc.SetTitle ('Font Demo') +# print "template is ", template, "obj is", template._obj_ + template.close() +# print "closed" +# del template + +if __name__=='__main__': + import demoutils + if demoutils.NeedGoodGUI(): + FontDemo() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/guidemo.py b/Lib/site-packages/pythonwin/pywin/Demos/guidemo.py new file mode 100644 index 0000000..56be8ab --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/guidemo.py @@ -0,0 +1,68 @@ +# GUI Demo - just a worker script to invoke all the other demo/test scripts. +import win32ui +import __main__ +import sys +import regutil +import win32api + +demos = [ \ +# ('Font', 'import fontdemo;fontdemo.FontDemo()'), + ('Open GL Demo', 'import openGLDemo;openGLDemo.test()'), + ('Threaded GUI', 'import threadedgui;threadedgui.ThreadedDemo()'), + ('Tree View Demo', 'import hiertest;hiertest.demoboth()'), + ('3-Way Splitter Window', 'import splittst;splittst.demo()'), + ('Custom Toolbars and Tooltips', 'import toolbar;toolbar.test()'), + ('Progress Bar', 'import progressbar;progressbar.demo()'), + ('Slider Control', 'import sliderdemo;sliderdemo.demo()'), + ('Dynamic window creation', 'import createwin;createwin.demo()'), + ('Various Dialog demos', 'import dlgtest;dlgtest.demo()'), + ('OCX Control Demo', 'from ocx import ocxtest;ocxtest.demo()'), + ('OCX Serial Port Demo', 'from ocx import ocxserialtest; ocxserialtest.test()'), + ('IE4 Control Demo', 'from ocx import webbrowser; webbrowser.Demo("http://www.python.org")'), +] + +def demo(): + try: + # seeif I can locate the demo files. + import fontdemo + except ImportError: + # else put the demos direectory on the path (if not already) + try: + instPath = regutil.GetRegistryDefaultValue(regutil.BuildDefaultPythonKey() + "\\InstallPath") + except win32api.error: + print("The InstallPath can not be located, and the Demos directory is not on the path") + instPath="." + + demosDir = win32ui.FullPath(instPath + "\\Demos") + for path in sys.path: + if win32ui.FullPath(path)==demosDir: + break + else: + sys.path.append(demosDir) + import fontdemo + + import sys + if "/go" in sys.argv: + for name, cmd in demos: + try: + exec(cmd) + except: + print("Demo of %s failed - %s:%s" % (cmd,sys.exc_info()[0], sys.exc_info()[1])) + return + # Otherwise allow the user to select the demo to run + + import pywin.dialogs.list + while 1: + rc = pywin.dialogs.list.SelectFromLists( "Select a Demo", demos, ['Demo Title'] ) + if rc is None: + break + title, cmd = demos[rc] + try: + exec(cmd) + except: + print("Demo of %s failed - %s:%s" % (title,sys.exc_info()[0], sys.exc_info()[1])) + +if __name__==__main__.__name__: + import demoutils + if demoutils.NeedGoodGUI(): + demo() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/hiertest.py b/Lib/site-packages/pythonwin/pywin/Demos/hiertest.py new file mode 100644 index 0000000..58bc0b2 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/hiertest.py @@ -0,0 +1,104 @@ +import win32ui +import os +import commctrl + +from pywin.tools import hierlist +from pywin.mfc import docview, window + +# directory listbox +# This has obvious limitations - doesnt track subdirs, etc. Demonstrates +# simple use of Python code for querying the tree as needed. +# Only use strings, and lists of strings (from curdir()) +class DirHierList(hierlist.HierList): + def __init__(self, root, listBoxID = win32ui.IDC_LIST1): + hierlist.HierList.__init__(self, root, win32ui.IDB_HIERFOLDERS, listBoxID) + def GetText(self, item): + return os.path.basename(item) + def GetSubList(self, item): + if os.path.isdir(item): + ret = [os.path.join(item, fname) for fname in os.listdir(item)] + else: + ret = None + return ret + # if the item is a dir, it is expandable. + def IsExpandable(self, item): + return os.path.isdir(item) + def GetSelectedBitmapColumn(self, item): + return self.GetBitmapColumn(item)+6 # Use different color for selection + +class TestDocument(docview.Document): + def __init__(self, template): + docview.Document.__init__(self, template) + self.hierlist = hierlist.HierListWithItems(HLIFileDir("\\"), win32ui.IDB_HIERFOLDERS, win32ui.AFX_IDW_PANE_FIRST) + +class HierListView(docview.TreeView): + def OnInitialUpdate(self): + rc = self._obj_.OnInitialUpdate() + self.hierList = self.GetDocument().hierlist + self.hierList.HierInit(self.GetParent()) + self.hierList.SetStyle(commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS) + return rc + +class HierListFrame(window.MDIChildWnd): + pass + +def GetTestRoot(): + tree1 = ('Tree 1',[('Item 1','Item 1 data'),'Item 2',3]) + tree2 = ('Tree 2',[('Item 2.1','Item 2 data'),'Item 2.2',2.3]) + return ('Root',[tree1,tree2,'Item 3']) + +def demoboth(): + template = docview.DocTemplate(win32ui.IDR_PYTHONTYPE, TestDocument, HierListFrame, HierListView) + template.OpenDocumentFile(None).SetTitle("Hierlist demo") + + demomodeless() + +def demomodeless(): + testList2=DirHierList("\\") + dlg=hierlist.HierDialog('hier list test',testList2) + dlg.CreateWindow() + +def demodlg (): + testList2=DirHierList("\\") + dlg=hierlist.HierDialog('hier list test',testList2) + dlg.DoModal() + +def demo(): + template = docview.DocTemplate(win32ui.IDR_PYTHONTYPE, TestDocument, HierListFrame, HierListView) + template.OpenDocumentFile(None).SetTitle("Hierlist demo") + +# +# Demo/Test for HierList items. +# +# Easy to make a better directory program. +# +class HLIFileDir(hierlist.HierListItem): + def __init__( self, filename ): + self.filename = filename + hierlist.HierListItem.__init__(self) + def GetText(self): + try: + return "%-20s %d bytes" % (os.path.basename(self.filename), os.stat(self.filename)[6]) + except os.error as details: + return "%-20s - %s" % (self.filename, details[1]) + + def IsExpandable(self): + return os.path.isdir(self.filename) + def GetSubList(self): + ret = [] + for newname in os.listdir(self.filename): + if newname not in ['.', '..']: + ret.append( HLIFileDir( os.path.join(self.filename,newname ) ) ) + return ret + + +def demohli(): + template = docview.DocTemplate(win32ui.IDR_PYTHONTYPE, TestDocument, hierlist.HierListFrame, hierlist.HierListView) + template.OpenDocumentFile(None).SetTitle("Hierlist demo") + +if __name__=='__main__': + import demoutils + if demoutils.HaveGoodGUI(): + demoboth() + else: + demodlg() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/menutest.py b/Lib/site-packages/pythonwin/pywin/Demos/menutest.py new file mode 100644 index 0000000..366b42f --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/menutest.py @@ -0,0 +1,12 @@ +# Run this as a python script, to gray "close" off the edit window system menu. +from pywin.framework import interact +import win32con + +if __name__=='__main__': + import demoutils + if demoutils.NeedGoodGUI(): + win=interact.edit.currentView.GetParent() + menu=win.GetSystemMenu() + id=menu.GetMenuItemID(6) + menu.EnableMenuItem(id,win32con.MF_BYCOMMAND|win32con.MF_GRAYED) + print("The interactive window's 'Close' menu item is now disabled.") diff --git a/Lib/site-packages/pythonwin/pywin/Demos/objdoc.py b/Lib/site-packages/pythonwin/pywin/Demos/objdoc.py new file mode 100644 index 0000000..10cca4f --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/objdoc.py @@ -0,0 +1,49 @@ +# This is a sample file, and shows the basic framework for using an "Object" based +# document, rather than a "filename" based document. +# This is referenced by the Pythonwin .html documentation. + +# In the example below, the OpenObject() method is used instead of OpenDocumentFile, +# and all the core MFC document open functionality is retained. + +import win32ui +from pywin.mfc import docview + +class object_template (docview.DocTemplate): + def __init__(self): + docview.DocTemplate.__init__(self, None, None, None, object_view) + def OpenObject(self, object): # Use this instead of OpenDocumentFile. + # Look for existing open document + for doc in self.GetDocumentList(): + print("document is ", doc) + if doc.object is object: + doc.GetFirstView().ActivateFrame() + return doc + # not found - new one. + doc = object_document(self, object) + frame = self.CreateNewFrame(doc) + doc.OnNewDocument() + doc.SetTitle(str(object)) + self.InitialUpdateFrame(frame, doc) + return doc + +class object_document (docview.Document): + def __init__(self, template, object): + docview.Document.__init__(self, template) + self.object = object + def OnOpenDocument (self, name): + raise RuntimeError("Should not be called if template strings set up correctly") + return 0 + +class object_view (docview.EditView): + def OnInitialUpdate (self): + self.ReplaceSel("Object is %s" % repr(self.GetDocument().object)) + +def demo (): + t = object_template() + d = t.OpenObject(win32ui) + return (t, d) + +if __name__=='__main__': + import demoutils + if demoutils.NeedGoodGUI(): + demo() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/ocx/__init__.py b/Lib/site-packages/pythonwin/pywin/Demos/ocx/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Lib/site-packages/pythonwin/pywin/Demos/ocx/demoutils.py b/Lib/site-packages/pythonwin/pywin/Demos/ocx/demoutils.py new file mode 100644 index 0000000..8f7d5f6 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/ocx/demoutils.py @@ -0,0 +1,54 @@ +# Utilities for the demos + +import sys, win32api, win32con, win32ui + +NotScriptMsg = """\ +This demo program is not designed to be run as a Script, but is +probably used by some other test program. Please try another demo. +""" + +NeedGUIMsg = """\ +This demo program can only be run from inside of Pythonwin + +You must start Pythonwin, and select 'Run' from the toolbar or File menu +""" + + +NeedAppMsg = """\ +This demo program is a 'Pythonwin Application'. + +It is more demo code than an example of Pythonwin's capabilities. + +To run it, you must execute the command: +pythonwin.exe /app "%s" + +Would you like to execute it now? +""" + +def NotAScript(): + import win32ui + win32ui.MessageBox(NotScriptMsg, "Demos") + +def NeedGoodGUI(): + from pywin.framework.app import HaveGoodGUI + rc = HaveGoodGUI() + if not rc: + win32ui.MessageBox(NeedGUIMsg, "Demos") + return rc + +def NeedApp(): + import win32ui + rc = win32ui.MessageBox(NeedAppMsg % sys.argv[0], "Demos", win32con.MB_YESNO) + if rc==win32con.IDYES: + try: + parent = win32ui.GetMainFrame().GetSafeHwnd() + win32api.ShellExecute(parent, None, 'pythonwin.exe', '/app "%s"' % sys.argv[0], None, 1) + except win32api.error as details: + win32ui.MessageBox("Error executing command - %s" % (details), "Demos") + + +from pywin.framework.app import HaveGoodGUI + +if __name__=='__main__': + import demoutils + demoutils.NotAScript() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/ocx/flash.py b/Lib/site-packages/pythonwin/pywin/Demos/ocx/flash.py new file mode 100644 index 0000000..4aa93f6 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/ocx/flash.py @@ -0,0 +1,84 @@ +# By Bradley Schatz +# simple flash/python application demonstrating bidirectional +# communicaion between flash and python. Click the sphere to see +# behavior. Uses Bounce.swf from FlashBounce.zip, available from +# http://pages.cpsc.ucalgary.ca/~saul/vb_examples/tutorial12/ + +# Update to the path of the .swf file (note it could be a true URL) +flash_url = "c:\\bounce.swf" + +import win32ui, win32con, win32api, regutil +from pywin.mfc import window, activex +from win32com.client import gencache +import sys + +FlashModule = gencache.EnsureModule("{D27CDB6B-AE6D-11CF-96B8-444553540000}", 0, 1, 0) + +if FlashModule is None: + raise ImportError("Flash does not appear to be installed.") + +class MyFlashComponent(activex.Control, FlashModule.ShockwaveFlash): + def __init__(self): + activex.Control.__init__(self) + FlashModule.ShockwaveFlash.__init__(self) + self.x = 50 + self.y = 50 + self.angle = 30 + self.started = 0 + + def OnFSCommand(self, command, args): + print("FSCommend" , command, args) + self.x = self.x + 20 + self.y = self.y + 20 + self.angle = self.angle + 20 + if self.x > 200 or self.y > 200: + self.x = 0 + self.y = 0 + if self.angle > 360: + self.angle = 0 + self.SetVariable("xVal", self.x) + self.SetVariable("yVal", self.y) + self.SetVariable("angle", self.angle) + self.TPlay("_root.mikeBall") + + def OnProgress(self, percentDone): + print("PercentDone", percentDone) + def OnReadyStateChange(self, newState): + # 0=Loading, 1=Uninitialized, 2=Loaded, 3=Interactive, 4=Complete + print("State", newState) + + +class BrowserFrame(window.MDIChildWnd): + def __init__(self, url = None): + if url is None: + self.url = regutil.GetRegisteredHelpFile("Main Python Documentation") + else: + self.url = url + pass # Dont call base class doc/view version... + def Create(self, title, rect = None, parent = None): + style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_OVERLAPPEDWINDOW + self._obj_ = win32ui.CreateMDIChild() + self._obj_.AttachObject(self) + self._obj_.CreateWindow(None, title, style, rect, parent) + rect = self.GetClientRect() + rect = (0,0,rect[2]-rect[0], rect[3]-rect[1]) + self.ocx = MyFlashComponent() + self.ocx.CreateControl("Flash Player", win32con.WS_VISIBLE | win32con.WS_CHILD, rect, self, 1000) + self.ocx.LoadMovie(0,flash_url) + self.ocx.Play() + self.HookMessage (self.OnSize, win32con.WM_SIZE) + + def OnSize (self, params): + rect = self.GetClientRect() + rect = (0,0,rect[2]-rect[0], rect[3]-rect[1]) + self.ocx.SetWindowPos(0, rect, 0) + +def Demo(): + url = None + if len(sys.argv)>1: + url = win32api.GetFullPathName(sys.argv[1]) + f = BrowserFrame(url) + f.Create("Flash Player") + +if __name__=='__main__': + Demo() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/ocx/msoffice.py b/Lib/site-packages/pythonwin/pywin/Demos/ocx/msoffice.py new file mode 100644 index 0000000..4502363 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/ocx/msoffice.py @@ -0,0 +1,127 @@ +# This demo uses some of the Microsoft Office components. +# +# It was taken from an MSDN article showing how to embed excel. +# It is not comlpete yet, but it _does_ show an Excel spreadsheet in a frame! +# + +import win32ui, win32uiole, win32con, regutil +from pywin.mfc import window, activex, object, docview +from win32com.client import gencache + +#WordModule = gencache.EnsureModule('{00020905-0000-0000-C000-000000000046}', 1033, 8, 0) +#if WordModule is None: +# raise ImportError, "Microsoft Word version 8 does not appear to be installed." + + +class OleClientItem(object.CmdTarget): + def __init__(self, doc): + object.CmdTarget.__init__(self, win32uiole.CreateOleClientItem(doc)) + + def OnGetItemPosition(self): + # For now return a hard-coded rect. + return (10, 10, 210, 210) + + def OnActivate(self): + # Allow only one inplace activate item per frame + view = self.GetActiveView() + item = self.GetDocument().GetInPlaceActiveItem(view) + if item is not None and item._obj_ != self._obj_: + item.Close() + self._obj_.OnActivate() + + def OnChange(self, oleNotification, dwParam): + self._obj_.OnChange(oleNotification, dwParam) + self.GetDocument().UpdateAllViews(None) + + def OnChangeItemPosition(self, rect): + # During in-place activation CEmbed_ExcelCntrItem::OnChangeItemPosition + # is called by the server to change the position of the in-place + # window. Usually, this is a result of the data in the server + # document changing such that the extent has changed or as a result + # of in-place resizing. + # + # The default here is to call the base class, which will call + # COleClientItem::SetItemRects to move the item + # to the new position. + if not self._obj_.OnChangeItemPosition(self, rect): + return 0 + + # TODO: update any cache you may have of the item's rectangle/extent + return 1 + +class OleDocument(object.CmdTarget): + def __init__(self, template): + object.CmdTarget.__init__(self, win32uiole.CreateOleDocument(template)) + self.EnableCompoundFile() + +class ExcelView(docview.ScrollView): + def OnInitialUpdate(self): + self.HookMessage(self.OnSetFocus, win32con.WM_SETFOCUS) + self.HookMessage (self.OnSize, win32con.WM_SIZE) + + self.SetScrollSizes(win32con.MM_TEXT, (100, 100)) + rc = self._obj_.OnInitialUpdate() + self.EmbedExcel() + return rc + + def EmbedExcel(self): + doc = self.GetDocument() + self.clientItem = OleClientItem(doc) + self.clientItem.CreateNewItem("Excel.Sheet") + self.clientItem.DoVerb(-1, self) + doc.UpdateAllViews(None) + + def OnDraw(self, dc): + doc = self.GetDocument() + pos = doc.GetStartPosition() + clientItem, pos = doc.GetNextItem(pos) + clientItem.Draw(dc, (10, 10, 210, 210) ) + + # Special handling of OnSetFocus and OnSize are required for a container + # when an object is being edited in-place. + def OnSetFocus(self, msg): + item = self.GetDocument().GetInPlaceActiveItem(self) + if item is not None and item.GetItemState()==win32uiole.COleClientItem_activeUIState: + wnd = item.GetInPlaceWindow() + if wnd is not None: + wnd.SetFocus() + return 0 # Dont get the base version called. + return 1 # Call the base version. + + def OnSize (self, params): + item = self.GetDocument().GetInPlaceActiveItem(self) + if item is not None: + item.SetItemRects() + return 1 # do call the base! + +class OleTemplate(docview.DocTemplate): + def __init__(self, resourceId=None, MakeDocument=None, MakeFrame=None, MakeView=None): + if MakeDocument is None: MakeDocument = OleDocument + if MakeView is None: MakeView = ExcelView + docview.DocTemplate.__init__(self, resourceId, MakeDocument, MakeFrame, MakeView) + +class WordFrame(window.MDIChildWnd): + def __init__(self, doc = None): + self._obj_ = win32ui.CreateMDIChild() + self._obj_.AttachObject(self) + # Dont call base class doc/view version... + def Create(self, title, rect = None, parent = None): + style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_OVERLAPPEDWINDOW + self._obj_.CreateWindow(None, title, style, rect, parent) + + rect = self.GetClientRect() + rect = (0,0,rect[2]-rect[0], rect[3]-rect[1]) + self.ocx = MyWordControl() + self.ocx.CreateControl("Microsoft Word", win32con.WS_VISIBLE | win32con.WS_CHILD, rect, self, 20000) + +def Demo(): + import sys, win32api + docName = None + if len(sys.argv)>1: + docName = win32api.GetFullPathName(sys.argv[1]) + OleTemplate().OpenDocumentFile(None) +# f = WordFrame(docName) +# f.Create("Microsoft Office") + +if __name__=='__main__': + Demo() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/ocx/ocxserialtest.py b/Lib/site-packages/pythonwin/pywin/Demos/ocx/ocxserialtest.py new file mode 100644 index 0000000..ed2aa0b --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/ocx/ocxserialtest.py @@ -0,0 +1,101 @@ +# ocxserialtest.py +# +# Sample that uses the mscomm OCX to talk to a serial +# device. + +# Very simple - queries a modem for ATI responses + +import win32ui, win32uiole +import win32con +from pywin.mfc import dialog, activex +from win32com.client import gencache +import pythoncom + +SERIAL_SETTINGS = '19200,n,8,1' +SERIAL_PORT = 2 + +win32ui.DoWaitCursor(1) +serialModule = gencache.EnsureModule("{648A5603-2C6E-101B-82B6-000000000014}", 0, 1, 1) +win32ui.DoWaitCursor(0) +if serialModule is None: + raise ImportError("MS COMM Control does not appear to be installed on the PC") + + +def MakeDlgTemplate(): + style = win32con.DS_MODALFRAME | win32con.WS_POPUP \ + | win32con.WS_VISIBLE | win32con.WS_CAPTION \ + | win32con.WS_SYSMENU | win32con.DS_SETFONT + cs = win32con.WS_CHILD | win32con.WS_VISIBLE + dlg = [ ["Very Basic Terminal", + (0, 0, 350, 180), style, None, (8, "MS Sans Serif")], ] + s = win32con.WS_TABSTOP | cs + dlg.append(["RICHEDIT", None, 132, (5, 5, 340, 170),s | win32con.ES_WANTRETURN | win32con.ES_MULTILINE | win32con.ES_AUTOVSCROLL | win32con.WS_VSCROLL]) + return dlg + + +#################################### +# +# Serial Control +# +class MySerialControl(activex.Control, serialModule.MSComm): + def __init__(self, parent): + activex.Control.__init__(self) + serialModule.MSComm.__init__(self) + self.parent = parent + def OnComm(self): + self.parent.OnComm() + +class TestSerDialog(dialog.Dialog): + def __init__(self, *args): + dialog.Dialog.__init__(*(self,)+args) + self.olectl = None + def OnComm(self): + event = self.olectl.CommEvent + if event == serialModule.OnCommConstants.comEvReceive: + self.editwindow.ReplaceSel(self.olectl.Input) + + def OnKey(self, key): + if self.olectl: + self.olectl.Output = chr(key) + + def OnInitDialog(self): + rc = dialog.Dialog.OnInitDialog(self) + self.editwindow = self.GetDlgItem(132) + self.editwindow.HookAllKeyStrokes(self.OnKey) + + self.olectl = MySerialControl(self) + try: + self.olectl.CreateControl("OCX", + win32con.WS_TABSTOP | win32con.WS_VISIBLE, + (7,43,500,300), self._obj_, 131) + except win32ui.error: + self.MessageBox("The Serial Control could not be created") + self.olectl = None + self.EndDialog(win32con.IDCANCEL) + if self.olectl: + self.olectl.Settings = SERIAL_SETTINGS + self.olectl.CommPort = SERIAL_PORT + self.olectl.RThreshold = 1 + try: + self.olectl.PortOpen = 1 + except pythoncom.com_error as details: + print("Could not open the specified serial port - %s" % (details.excepinfo[2])) + self.EndDialog(win32con.IDCANCEL) + return rc + + def OnDestroy(self, msg): + if self.olectl: + try: + self.olectl.PortOpen = 0 + except pythoncom.com_error as details: + print("Error closing port - %s" % (details.excepinfo[2])) + return dialog.Dialog.OnDestroy(self, msg) + +def test(): + d = TestSerDialog(MakeDlgTemplate() ) + d.DoModal() + +if __name__ == "__main__": + import demoutils + if demoutils.NeedGoodGUI(): + test() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/ocx/ocxtest.py b/Lib/site-packages/pythonwin/pywin/Demos/ocx/ocxtest.py new file mode 100644 index 0000000..6d20add --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/ocx/ocxtest.py @@ -0,0 +1,186 @@ +# OCX Tester for Pythonwin +# +# This file _is_ ready to run. All that is required is that the OCXs being tested +# are installed on your machine. +# +# The .py files behind the OCXs will be automatically generated and imported. + +from pywin.mfc import dialog, window, activex +import win32ui, win32uiole +import win32con +import os, sys, win32api, glob +from win32com.client import gencache + + +def MakeDlgTemplate(): + style = win32con.DS_MODALFRAME | win32con.WS_POPUP | win32con.WS_VISIBLE | win32con.WS_CAPTION | win32con.WS_SYSMENU | win32con.DS_SETFONT + cs = win32con.WS_CHILD | win32con.WS_VISIBLE + dlg = [ ["OCX Demos", (0, 0, 350, 350), style, None, (8, "MS Sans Serif")], ] + s = win32con.WS_TABSTOP | cs +# dlg.append([131, None, 130, (5, 40, 110, 48), +# s | win32con.LBS_NOTIFY | win32con.LBS_SORT | win32con.LBS_NOINTEGRALHEIGHT | win32con.WS_VSCROLL | win32con.WS_BORDER]) +# dlg.append(["{8E27C92B-1264-101C-8A2F-040224009C02}", None, 131, (5, 40, 110, 48),win32con.WS_TABSTOP]) + + dlg.append([128, "About", win32con.IDOK, (124, 5, 50, 14), s | win32con.BS_DEFPUSHBUTTON]) + s = win32con.BS_PUSHBUTTON | s + dlg.append([128, "Close", win32con.IDCANCEL, (124, 22, 50, 14), s]) + + return dlg + +#################################### +# +# Calendar test code +# + +def GetTestCalendarClass(): + global calendarParentModule + win32ui.DoWaitCursor(1) + calendarParentModule = gencache.EnsureModule("{8E27C92E-1264-101C-8A2F-040224009C02}", 0, 7, 0) + win32ui.DoWaitCursor(0) + if calendarParentModule is None: + return None + + class TestCalDialog(dialog.Dialog): + def OnInitDialog(self): + + class MyCal(activex.Control, calendarParentModule.Calendar): + def OnAfterUpdate(self): + print("OnAfterUpdate") + def OnClick(self): + print("OnClick") + def OnDblClick(self): + print("OnDblClick") + def OnKeyDown(self, KeyCode, Shift): + print("OnKeyDown", KeyCode, Shift) + def OnKeyPress(self, KeyAscii): + print("OnKeyPress", KeyAscii) + def OnKeyUp(self, KeyCode, Shift): + print("OnKeyUp", KeyCode, Shift) + def OnBeforeUpdate(self, Cancel): + print("OnBeforeUpdate", Cancel) + def OnNewMonth(self): + print("OnNewMonth") + def OnNewYear(self): + print("OnNewYear") + + rc = dialog.Dialog.OnInitDialog(self) + self.olectl = MyCal() + try: + self.olectl.CreateControl("OCX", win32con.WS_TABSTOP | win32con.WS_VISIBLE, (7,43,500,300), self._obj_, 131) + except win32ui.error: + self.MessageBox("The Calendar Control could not be created") + self.olectl = None + self.EndDialog(win32con.IDCANCEL) + + return rc + def OnOK(self): + self.olectl.AboutBox() + + return TestCalDialog + + +#################################### +# +# Video Control +# +def GetTestVideoModule(): + global videoControlModule, videoControlFileName + win32ui.DoWaitCursor(1) + videoControlModule = gencache.EnsureModule("{05589FA0-C356-11CE-BF01-00AA0055595A}", 0, 2, 0) + win32ui.DoWaitCursor(0) + if videoControlModule is None: + return None + fnames = glob.glob(os.path.join(win32api.GetWindowsDirectory(), "*.avi")) + if not fnames: + print("No AVI files available in system directory") + return None + videoControlFileName = fnames[0] + return videoControlModule + +def GetTestVideoDialogClass(): + if GetTestVideoModule() is None: + return None + class TestVideoDialog(dialog.Dialog): + def OnInitDialog(self): + rc = dialog.Dialog.OnInitDialog(self) + try: + self.olectl = activex.MakeControlInstance(videoControlModule.ActiveMovie) + self.olectl.CreateControl("", win32con.WS_TABSTOP | win32con.WS_VISIBLE, (7,43,500,300), self._obj_, 131) + except win32ui.error: + self.MessageBox("The Video Control could not be created") + self.olectl = None + self.EndDialog(win32con.IDCANCEL) + return + + self.olectl.FileName = videoControlFileName +# self.olectl.Run() + return rc + def OnOK(self): + self.olectl.AboutBox() + return TestVideoDialog + +############### +# +# An OCX in an MDI Frame +# +class OCXFrame(window.MDIChildWnd): + def __init__(self): + pass # Dont call base class doc/view version... + def Create(self, controlClass, title, rect = None, parent = None): + style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_OVERLAPPEDWINDOW + self._obj_ = win32ui.CreateMDIChild() + self._obj_.AttachObject(self) + self._obj_.CreateWindow(None, title, style, rect, parent) + + rect = self.GetClientRect() + rect = (0,0,rect[2]-rect[0], rect[3]-rect[1]) + self.ocx = controlClass() + self.ocx.CreateControl("", win32con.WS_VISIBLE | win32con.WS_CHILD, rect, self, 1000) + +def MDITest(): + calendarParentModule = gencache.EnsureModule("{8E27C92E-1264-101C-8A2F-040224009C02}", 0, 7, 0) + class MyCal(activex.Control, calendarParentModule.Calendar): + def OnAfterUpdate(self): + print("OnAfterUpdate") + def OnClick(self): + print("OnClick") + + f = OCXFrame() + f.Create(MyCal, "Calendar Test") + + +def test1(): + klass = GetTestCalendarClass() + if klass is None: + print("Can not test the MSAccess Calendar control - it does not appear to be installed") + return + + d = klass(MakeDlgTemplate() ) + d.DoModal() + +def test2(): + klass = GetTestVideoDialogClass() + if klass is None: + print("Can not test the Video OCX - it does not appear to be installed,") + print("or no AVI files can be found.") + return + d = klass(MakeDlgTemplate() ) + d.DoModal() + d = None + +def test3(): + d = TestCOMMDialog(MakeDlgTemplate() ) + d.DoModal() + d = None + +def testall(): + test1() + test2() + +def demo(): + testall() + +if __name__=='__main__': + import demoutils + if demoutils.NeedGoodGUI(): + testall() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/ocx/webbrowser.py b/Lib/site-packages/pythonwin/pywin/Demos/ocx/webbrowser.py new file mode 100644 index 0000000..db44187 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/ocx/webbrowser.py @@ -0,0 +1,55 @@ +# This demo uses the IE4 Web Browser control. + +# It catches an "OnNavigate" event, and updates the frame title. +# (event stuff by Neil Hodgson) + +import win32ui, win32con, win32api, regutil +from pywin.mfc import window, activex +from win32com.client import gencache +import sys + +WebBrowserModule = gencache.EnsureModule("{EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}", 0, 1, 1) +if WebBrowserModule is None: + raise ImportError("IE4 does not appear to be installed.") + +class MyWebBrowser(activex.Control, WebBrowserModule.WebBrowser): + def OnBeforeNavigate2(self, pDisp, URL, Flags, TargetFrameName, PostData, Headers, Cancel): + self.GetParent().OnNavigate(URL) + #print "BeforeNavigate2", pDisp, URL, Flags, TargetFrameName, PostData, Headers, Cancel + +class BrowserFrame(window.MDIChildWnd): + def __init__(self, url = None): + if url is None: + self.url = regutil.GetRegisteredHelpFile("Main Python Documentation") + if self.url is None: + self.url = "http://www.python.org" + else: + self.url = url + pass # Dont call base class doc/view version... + def Create(self, title, rect = None, parent = None): + style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_OVERLAPPEDWINDOW + self._obj_ = win32ui.CreateMDIChild() + self._obj_.AttachObject(self) + self._obj_.CreateWindow(None, title, style, rect, parent) + rect = self.GetClientRect() + rect = (0,0,rect[2]-rect[0], rect[3]-rect[1]) + self.ocx = MyWebBrowser() + self.ocx.CreateControl("Web Browser", win32con.WS_VISIBLE | win32con.WS_CHILD, rect, self, 1000) + self.ocx.Navigate(self.url) + self.HookMessage (self.OnSize, win32con.WM_SIZE) + def OnSize (self, params): + rect = self.GetClientRect() + rect = (0,0,rect[2]-rect[0], rect[3]-rect[1]) + self.ocx.SetWindowPos(0, rect, 0) + def OnNavigate(self, url): + title = "Web Browser - %s" % (url,) + self.SetWindowText(title) + +def Demo(url=None): + if url is None and len(sys.argv)>1: + url = win32api.GetFullPathName(sys.argv[1]) + f = BrowserFrame(url) + f.Create("Web Browser") + +if __name__=='__main__': + Demo() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/openGLDemo.py b/Lib/site-packages/pythonwin/pywin/Demos/openGLDemo.py new file mode 100644 index 0000000..ae175fe --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/openGLDemo.py @@ -0,0 +1,358 @@ +# Ported from the win32 and MFC OpenGL Samples. + +from pywin.mfc import docview +import sys +try: + from OpenGL.GL import * + from OpenGL.GLU import * +except ImportError: + print("The OpenGL extensions do not appear to be installed.") + print("This Pythonwin demo can not run") + sys.exit(1) + +import win32con +import win32ui +import win32api +import timer + +PFD_TYPE_RGBA = 0 +PFD_TYPE_COLORINDEX = 1 +PFD_MAIN_PLANE = 0 +PFD_OVERLAY_PLANE = 1 +PFD_UNDERLAY_PLANE = (-1) +PFD_DOUBLEBUFFER = 0x00000001 +PFD_STEREO = 0x00000002 +PFD_DRAW_TO_WINDOW = 0x00000004 +PFD_DRAW_TO_BITMAP = 0x00000008 +PFD_SUPPORT_GDI = 0x00000010 +PFD_SUPPORT_OPENGL = 0x00000020 +PFD_GENERIC_FORMAT = 0x00000040 +PFD_NEED_PALETTE = 0x00000080 +PFD_NEED_SYSTEM_PALETTE = 0x00000100 +PFD_SWAP_EXCHANGE = 0x00000200 +PFD_SWAP_COPY = 0x00000400 +PFD_SWAP_LAYER_BUFFERS = 0x00000800 +PFD_GENERIC_ACCELERATED = 0x00001000 +PFD_DEPTH_DONTCARE = 0x20000000 +PFD_DOUBLEBUFFER_DONTCARE = 0x40000000 +PFD_STEREO_DONTCARE = 0x80000000 + + +#threeto8 = [0, 0o111>>1, 0o222>>1, 0o333>>1, 0o444>>1, 0o555>>1, 0o666>>1, 0o377] +threeto8 = [0, 73>>1, 146>>1, 219>>1, 292>>1, 365>>1, 438>>1, 255] +twoto8 = [0, 0x55, 0xaa, 0xff] +oneto8 = [0, 255] + +def ComponentFromIndex(i, nbits, shift): + # val = (unsigned char) (i >> shift); + val = (i >> shift) & 0xF; + if nbits==1: + val = val & 0x1 + return oneto8[val] + elif nbits==2: + val = val & 0x3 + return twoto8[val] + elif nbits==3: + val = val & 0x7 + return threeto8[val] + else: + return 0; + +OpenGLViewParent=docview.ScrollView +class OpenGLView(OpenGLViewParent): + def PreCreateWindow(self, cc): + self.HookMessage (self.OnSize, win32con.WM_SIZE) + # An OpenGL window must be created with the following flags and must not + # include CS_PARENTDC for the class style. Refer to SetPixelFormat + # documentation in the "Comments" section for further information. + style = cc[5] + style = style | win32con.WS_CLIPSIBLINGS | win32con.WS_CLIPCHILDREN + cc = cc[0], cc[1], cc[2], cc[3], cc[4], style, cc[6], cc[7], cc[8] + cc = self._obj_.PreCreateWindow(cc) + return cc + + def OnSize (self, params): + lParam = params[3] + cx = win32api.LOWORD(lParam) + cy = win32api.HIWORD(lParam) + glViewport(0, 0, cx, cy) + + if self.oldrect[2] > cx or self.oldrect[3] > cy: + self.RedrawWindow() + + self.OnSizeChange(cx, cy) + + self.oldrect = self.oldrect[0], self.oldrect[1], cx, cy + + def OnInitialUpdate(self): + self.SetScaleToFitSize((100,100)) # or SetScrollSizes() - A Pythonwin requirement + return self._obj_.OnInitialUpdate() +# return rc + + def OnCreate(self, cs): + self.oldrect = self.GetClientRect() + self._InitContexts() + self.Init() + + def OnDestroy(self, msg): + self.Term() + self._DestroyContexts() + return OpenGLViewParent.OnDestroy(self, msg) + + + def OnDraw(self, dc): + self.DrawScene() + + def OnEraseBkgnd(self, dc): + return 1 + + # The OpenGL helpers + def _SetupPixelFormat(self): + dc = self.dc.GetSafeHdc() + pfd = CreatePIXELFORMATDESCRIPTOR() + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER + pfd.iPixelType = PFD_TYPE_RGBA + pfd.cColorBits = 24 + pfd.cDepthBits = 32 + pfd.iLayerType = PFD_MAIN_PLANE + pixelformat = ChoosePixelFormat(dc, pfd) + SetPixelFormat(dc, pixelformat, pfd) + self._CreateRGBPalette() + + def _CreateRGBPalette(self): + dc = self.dc.GetSafeHdc() + n = GetPixelFormat(dc) + pfd = DescribePixelFormat(dc, n) + if pfd.dwFlags & PFD_NEED_PALETTE: + n = 1 << pfd.cColorBits + pal = [] + for i in range(n): + this = ComponentFromIndex(i, pfd.cRedBits, pfd.cRedShift), \ + ComponentFromIndex(i, pfd.cGreenBits, pfd.cGreenShift), \ + ComponentFromIndex(i, pfd.cBlueBits, pfd.cBlueShift), \ + 0 + pal.append(this) + hpal = win32ui.CreatePalette(pal) + self.dc.SelectPalette(hpal, 0) + self.dc.RealizePalette() + + def _InitContexts(self): + self.dc = self.GetDC() + self._SetupPixelFormat() + hrc = wglCreateContext(self.dc.GetSafeHdc()) + wglMakeCurrent(self.dc.GetSafeHdc(), hrc) + + def _DestroyContexts(self): + hrc = wglGetCurrentContext() + wglMakeCurrent(0, 0) + if hrc: wglDeleteContext(hrc) + + # The methods to support OpenGL + def DrawScene(self): + assert 0, "You must override this method" + + def Init(self): + assert 0, "You must override this method" + + def OnSizeChange(self, cx, cy): + pass + + def Term(self): + pass + + +class TestView(OpenGLView): + + def OnSizeChange(self, right, bottom): + glClearColor( 0.0, 0.0, 0.0, 1.0 ); + glClearDepth( 1.0 ); + glEnable(GL_DEPTH_TEST) + + glMatrixMode( GL_PROJECTION ) + if bottom: + aspect = right / bottom + else: + aspect = 0 # When window created! + glLoadIdentity() + gluPerspective( 45.0, aspect, 3.0, 7.0 ) + glMatrixMode( GL_MODELVIEW ) + + near_plane = 3.0; + far_plane = 7.0; + maxObjectSize = 3.0; + self.radius = near_plane + maxObjectSize/2.0; + + + def Init(self): + pass + + def DrawScene(self): + glClearColor(0.0, 0.0, 0.0, 1.0) + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) + + glPushMatrix() + glTranslatef(0.0, 0.0, -self.radius); + + self._DrawCone() + + self._DrawPyramid() + + glPopMatrix() + glFinish() + + SwapBuffers( wglGetCurrentDC() ) + + def _DrawCone(self): + glColor3f(0.0, 1.0, 0.0) + + glPushMatrix() + glTranslatef(-1.0, 0.0, 0.0); + quadObj = gluNewQuadric(); + gluQuadricDrawStyle(quadObj, GLU_FILL); + gluQuadricNormals(quadObj, GLU_SMOOTH); + gluCylinder(quadObj, 1.0, 0.0, 1.0, 20, 10); +# gluDeleteQuadric(quadObj); + glPopMatrix(); + + def _DrawPyramid(self): + glPushMatrix() + glTranslatef(1.0, 0.0, 0.0) + glBegin(GL_TRIANGLE_FAN) + glColor3f(1.0, 0.0, 0.0) + glVertex3f(0.0, 1.0, 0.0) + glColor3f(0.0, 1.0, 0.0) + glVertex3f(-1.0, 0.0, 0.0) + glColor3f(0.0, 0.0, 1.0) + glVertex3f(0.0, 0.0, 1.0) + glColor3f(0.0, 1.0, 0.0) + glVertex3f(1.0, 0.0, 0.0) + glEnd() + glPopMatrix() + +class CubeView(OpenGLView): + def OnSizeChange(self, right, bottom): + glClearColor( 0.0, 0.0, 0.0, 1.0 ); + glClearDepth( 1.0 ); + glEnable(GL_DEPTH_TEST) + + glMatrixMode( GL_PROJECTION ) + if bottom: + aspect = right / bottom + else: + aspect = 0 # When window created! + glLoadIdentity() + gluPerspective( 45.0, aspect, 3.0, 7.0 ) + glMatrixMode( GL_MODELVIEW ) + + near_plane = 3.0; + far_plane = 7.0; + maxObjectSize = 3.0; + self.radius = near_plane + maxObjectSize/2.0; + + def Init(self): + self.busy = 0 + self.wAngleY = 10.0 + self.wAngleX = 1.0 + self.wAngleZ = 5.0 + self.timerid = timer.set_timer (150, self.OnTimer) + + def OnTimer(self, id, timeVal): + self.DrawScene() + + def Term(self): + timer.kill_timer(self.timerid) + + def DrawScene(self): + if self.busy: return + self.busy = 1 + + glClearColor(0.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + + glTranslatef(0.0, 0.0, -self.radius); + glRotatef(self.wAngleX, 1.0, 0.0, 0.0); + glRotatef(self.wAngleY, 0.0, 1.0, 0.0); + glRotatef(self.wAngleZ, 0.0, 0.0, 1.0); + + self.wAngleX = self.wAngleX + 1.0 + self.wAngleY = self.wAngleY + 10.0 + self.wAngleZ = self.wAngleZ + 5.0; + + + glBegin(GL_QUAD_STRIP); + glColor3f(1.0, 0.0, 1.0); + glVertex3f(-0.5, 0.5, 0.5); + + glColor3f(1.0, 0.0, 0.0); + glVertex3f(-0.5, -0.5, 0.5); + + glColor3f(1.0, 1.0, 1.0); + glVertex3f(0.5, 0.5, 0.5); + + glColor3f(1.0, 1.0, 0.0); + glVertex3f(0.5, -0.5, 0.5); + + glColor3f(0.0, 1.0, 1.0); + glVertex3f(0.5, 0.5, -0.5); + + glColor3f(0.0, 1.0, 0.0); + glVertex3f(0.5, -0.5, -0.5); + + glColor3f(0.0, 0.0, 1.0); + glVertex3f(-0.5, 0.5, -0.5); + + glColor3f(0.0, 0.0, 0.0); + glVertex3f(-0.5, -0.5, -0.5); + + glColor3f(1.0, 0.0, 1.0); + glVertex3f(-0.5, 0.5, 0.5); + + glColor3f(1.0, 0.0, 0.0); + glVertex3f(-0.5, -0.5, 0.5); + + glEnd(); + + glBegin(GL_QUADS); + glColor3f(1.0, 0.0, 1.0); + glVertex3f(-0.5, 0.5, 0.5); + + glColor3f(1.0, 1.0, 1.0); + glVertex3f(0.5, 0.5, 0.5); + + glColor3f(0.0, 1.0, 1.0); + glVertex3f(0.5, 0.5, -0.5); + + glColor3f(0.0, 0.0, 1.0); + glVertex3f(-0.5, 0.5, -0.5); + glEnd(); + + glBegin(GL_QUADS); + glColor3f(1.0, 0.0, 0.0); + glVertex3f(-0.5, -0.5, 0.5); + + glColor3f(1.0, 1.0, 0.0); + glVertex3f(0.5, -0.5, 0.5); + + glColor3f(0.0, 1.0, 0.0); + glVertex3f(0.5, -0.5, -0.5); + + glColor3f(0.0, 0.0, 0.0); + glVertex3f(-0.5, -0.5, -0.5); + glEnd(); + + glPopMatrix(); + + glFinish(); + SwapBuffers(wglGetCurrentDC()); + + self.busy = 0 + +def test(): + template = docview.DocTemplate(None, None, None, CubeView ) +# template = docview.DocTemplate(None, None, None, TestView ) + template.OpenDocumentFile(None) + +if __name__=='__main__': + test() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/progressbar.py b/Lib/site-packages/pythonwin/pywin/Demos/progressbar.py new file mode 100644 index 0000000..0b6b4c4 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/progressbar.py @@ -0,0 +1,88 @@ +# +# Progress bar control example +# +# PyCProgressCtrl encapsulates the MFC CProgressCtrl class. To use it, +# you: +# +# - Create the control with win32ui.CreateProgressCtrl() +# - Create the control window with PyCProgressCtrl.CreateWindow() +# - Initialize the range if you want it to be other than (0, 100) using +# PyCProgressCtrl.SetRange() +# - Either: +# - Set the step size with PyCProgressCtrl.SetStep(), and +# - Increment using PyCProgressCtrl.StepIt() +# or: +# - Set the amount completed using PyCProgressCtrl.SetPos() +# +# Example and progress bar code courtesy of KDL Technologies, Ltd., Hong Kong SAR, China. +# + +from pywin.mfc import dialog +import win32ui +import win32con + +def MakeDlgTemplate(): + style = (win32con.DS_MODALFRAME | + win32con.WS_POPUP | + win32con.WS_VISIBLE | + win32con.WS_CAPTION | + win32con.WS_SYSMENU | + win32con.DS_SETFONT) + cs = (win32con.WS_CHILD | + win32con.WS_VISIBLE) + + w = 215 + h = 36 + + dlg = [["Progress bar control example", + (0, 0, w, h), + style, + None, + (8, "MS Sans Serif")], + ] + + s = win32con.WS_TABSTOP | cs + + dlg.append([128, + "Tick", + win32con.IDOK, + (10, h - 18, 50, 14), s | win32con.BS_DEFPUSHBUTTON]) + + dlg.append([128, + "Cancel", + win32con.IDCANCEL, + (w - 60, h - 18, 50, 14), s | win32con.BS_PUSHBUTTON]) + + return dlg + +class TestDialog(dialog.Dialog): + def OnInitDialog(self): + rc = dialog.Dialog.OnInitDialog(self) + self.pbar = win32ui.CreateProgressCtrl() + self.pbar.CreateWindow (win32con.WS_CHILD | + win32con.WS_VISIBLE, + (10, 10, 310, 24), + self, 1001) + # self.pbar.SetStep (5) + self.progress = 0 + self.pincr = 5 + return rc + + def OnOK(self): + # NB: StepIt wraps at the end if you increment past the upper limit! + # self.pbar.StepIt() + self.progress = self.progress + self.pincr + if self.progress > 100: + self.progress = 100 + if self.progress <= 100: + self.pbar.SetPos(self.progress) + +def demo(modal = 0): + d = TestDialog (MakeDlgTemplate()) + if modal: + d.DoModal() + else: + d.CreateWindow () + +if __name__=='__main__': + demo(1) diff --git a/Lib/site-packages/pythonwin/pywin/Demos/sliderdemo.py b/Lib/site-packages/pythonwin/pywin/Demos/sliderdemo.py new file mode 100644 index 0000000..36fb591 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/sliderdemo.py @@ -0,0 +1,54 @@ +# sliderdemo.py +# Demo of the slider control courtesy of Mike Fletcher. + +import win32con, win32ui +from pywin.mfc import dialog + +class MyDialog(dialog.Dialog): + ''' + Example using simple controls + ''' + _dialogstyle = (win32con.WS_MINIMIZEBOX | win32con.WS_DLGFRAME | + win32con.DS_MODALFRAME | win32con.WS_POPUP | win32con.WS_VISIBLE | + win32con.WS_CAPTION | win32con.WS_SYSMENU | win32con.DS_SETFONT ) + _buttonstyle = (win32con.BS_PUSHBUTTON | win32con.WS_TABSTOP | + win32con.WS_CHILD | win32con.WS_VISIBLE) + ### The static template, contains all "normal" dialog items + DIALOGTEMPLATE = [ + # the dialog itself is the first element in the template + ["Example slider", (0, 0, 50, 43), _dialogstyle, None, (8, "MS SansSerif")], + # rest of elements are the controls within the dialog + # standard "Close" button + [128, "Close", win32con.IDCANCEL, (0, 30, 50, 13), _buttonstyle], ] + ### ID of the control to be created during dialog initialisation + IDC_SLIDER = 9500 + def __init__(self ): + dialog.Dialog.__init__(self, self.DIALOGTEMPLATE) + def OnInitDialog(self): + rc = dialog.Dialog.OnInitDialog(self) + # now initialise your controls that you want to create + # programmatically, including those which are OLE controls + # those created directly by win32ui.Create* + # and your "custom controls" which are subclasses/whatever + win32ui.EnableControlContainer() + self.slider = win32ui.CreateSliderCtrl( ) + self.slider.CreateWindow( win32con.WS_TABSTOP | win32con.WS_VISIBLE, + (0,0,100,30), + self._obj_, + self.IDC_SLIDER) + self.HookMessage(self.OnSliderMove, win32con.WM_HSCROLL) + return rc + + def OnSliderMove(self, params): + print("Slider moved") + + def OnCancel(self): + print("The slider control is at position", self.slider.GetPos()) + self._obj_.OnCancel() +### +def demo(): + dia = MyDialog() + dia.DoModal() + +if __name__ == "__main__": + demo() \ No newline at end of file diff --git a/Lib/site-packages/pythonwin/pywin/Demos/splittst.py b/Lib/site-packages/pythonwin/pywin/Demos/splittst.py new file mode 100644 index 0000000..abfd67d --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/splittst.py @@ -0,0 +1,72 @@ +import win32ui +import win32con +import fontdemo +from pywin.mfc import window, docview +import commctrl + +# derive from CMDIChild. This does much work for us. + +class SplitterFrame(window.MDIChildWnd): + def __init__(self): + # call base CreateFrame + self.images = None + window.MDIChildWnd.__init__(self) + + def OnCreateClient(self, cp, context): + splitter = win32ui.CreateSplitter() + doc = context.doc + frame_rect = self.GetWindowRect() + size = ((frame_rect[2] - frame_rect[0]), + (frame_rect[3] - frame_rect[1])//2) + sub_size = (size[0]//2, size[1]) + splitter.CreateStatic (self, 2, 1) + self.v1 = win32ui.CreateEditView(doc) + self.v2 = fontdemo.FontView(doc) + # CListControl view + self.v3 = win32ui.CreateListView(doc) + sub_splitter = win32ui.CreateSplitter() + # pass "splitter" so each view knows how to get to the others + sub_splitter.CreateStatic (splitter, 1, 2) + sub_splitter.CreateView(self.v1, 0, 0, (sub_size)) + sub_splitter.CreateView(self.v2, 0, 1, (0,0)) # size ignored. + splitter.SetRowInfo(0, size[1] ,0) + splitter.CreateView (self.v3, 1, 0, (0,0)) # size ignored. + # Setup items in the imagelist + self.images = win32ui.CreateImageList(32,32,1,5,5) + self.images.Add(win32ui.GetApp().LoadIcon(win32ui.IDR_MAINFRAME)) + self.images.Add(win32ui.GetApp().LoadIcon(win32ui.IDR_PYTHONCONTYPE)) + self.images.Add(win32ui.GetApp().LoadIcon(win32ui.IDR_TEXTTYPE)) + self.v3.SetImageList(self.images, commctrl.LVSIL_NORMAL) + self.v3.InsertItem(0, "Icon 1", 0) + self.v3.InsertItem(0, "Icon 2", 1) + self.v3.InsertItem(0, "Icon 3", 2) +# self.v3.Arrange(commctrl.LVA_DEFAULT) Hmmm - win95 aligns left always??? + return 1 + def OnDestroy(self, msg): + window.MDIChildWnd.OnDestroy(self, msg) + if self.images: + self.images.DeleteImageList() + self.images = None + + def InitialUpdateFrame(self, doc, makeVisible): + self.v1.ReplaceSel("Hello from Edit Window 1") + self.v1.SetModifiedFlag(0) + +class SampleTemplate(docview.DocTemplate): + def __init__(self): + docview.DocTemplate.__init__(self, win32ui.IDR_PYTHONTYPE, None, SplitterFrame, None) + def InitialUpdateFrame(self, frame, doc, makeVisible): +# print "frame is ", frame, frame._obj_ +# print "doc is ", doc, doc._obj_ + self._obj_.InitialUpdateFrame(frame, doc, makeVisible) # call default handler. + frame.InitialUpdateFrame(doc, makeVisible) + +def demo(): + template = SampleTemplate() + doc=template.OpenDocumentFile(None) + doc.SetTitle("Splitter Demo") + +if __name__=='__main__': + import demoutils + if demoutils.NeedGoodGUI(): + demo() \ No newline at end of file diff --git a/Lib/site-packages/pythonwin/pywin/Demos/threadedgui.py b/Lib/site-packages/pythonwin/pywin/Demos/threadedgui.py new file mode 100644 index 0000000..8cd4377 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/threadedgui.py @@ -0,0 +1,174 @@ +# Demo of using just windows, without documents and views. + +# Also demo of a GUI thread, pretty much direct from the MFC C++ sample MTMDI. + +import win32ui +import win32con +import win32api +import timer + +from pywin.mfc import window, docview, thread +from pywin.mfc.thread import WinThread + + +WM_USER_PREPARE_TO_CLOSE = win32con.WM_USER + 32 + +# font is a dictionary in which the following elements matter: +# (the best matching font to supplied parameters is returned) +# name string name of the font as known by Windows +# size point size of font in logical units +# weight weight of font (win32con.FW_NORMAL, win32con.FW_BOLD) +# italic boolean; true if set to anything but None +# underline boolean; true if set to anything but None + +# This window is a child window of a frame. It is not the frame window itself. +class FontWindow(window.Wnd): + def __init__(self, text = 'Python Rules!'): + window.Wnd.__init__(self) + self.text = text + self.index = 0 + self.incr = 1 + self.width = self.height = 0 + self.ChangeAttributes() + # set up message handlers + + def Create(self, title, style, rect, parent): + classStyle = win32con.CS_HREDRAW | win32con.CS_VREDRAW + className = win32ui.RegisterWndClass(classStyle, 0, win32con.COLOR_WINDOW+1, 0) + self._obj_ = win32ui.CreateWnd() + self._obj_.AttachObject(self) + self._obj_.CreateWindow(className, title, style, rect, parent, win32ui.AFX_IDW_PANE_FIRST) + self.HookMessage (self.OnSize, win32con.WM_SIZE) + self.HookMessage (self.OnPrepareToClose, WM_USER_PREPARE_TO_CLOSE) + self.HookMessage (self.OnDestroy, win32con.WM_DESTROY) + self.timerid = timer.set_timer (100, self.OnTimer) + self.InvalidateRect() + + def OnDestroy (self, msg): + timer.kill_timer(self.timerid) + + def OnTimer(self, id, timeVal): + self.index = self.index + self.incr + if self.index > len(self.text): + self.incr = -1 + self.index = len(self.text) + elif self.index < 0: + self.incr = 1 + self.index = 0 + self.InvalidateRect() + + def OnPaint (self): +# print "Paint message from thread", win32api.GetCurrentThreadId() + dc, paintStruct = self.BeginPaint() + self.OnPrepareDC(dc, None) + + if (self.width == 0 and self.height == 0): + left, top, right, bottom = self.GetClientRect() + self.width = right - left + self.height = bottom - top + x, y = self.width // 2, self.height // 2 + dc.TextOut (x, y, self.text[:self.index]) + self.EndPaint(paintStruct) + + def ChangeAttributes(self): + font_spec = {'name':'Arial', 'height':42} + self.font = win32ui.CreateFont (font_spec) + + def OnPrepareToClose(self, params): + self.DestroyWindow() + + def OnSize (self, params): + lParam = params[3] + self.width = win32api.LOWORD(lParam) + self.height = win32api.HIWORD(lParam) + + def OnPrepareDC (self, dc, printinfo): + # Set up the DC for forthcoming OnDraw call + dc.SetTextColor (win32api.RGB(0,0,255)) + dc.SetBkColor (win32api.GetSysColor (win32con.COLOR_WINDOW)) + dc.SelectObject (self.font) + dc.SetTextAlign (win32con.TA_CENTER | win32con.TA_BASELINE) + +class FontFrame(window.MDIChildWnd): + def __init__(self): + pass # Dont call base class doc/view version... + def Create(self, title, rect = None, parent = None): + style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_OVERLAPPEDWINDOW + self._obj_ = win32ui.CreateMDIChild() + self._obj_.AttachObject(self) + + self._obj_.CreateWindow(None, title, style, rect, parent) + rect = self.GetClientRect() + rect = (0,0,rect[2]-rect[0], rect[3]-rect[1]) + self.child = FontWindow("Not threaded") + self.child.Create("FontDemo", win32con.WS_CHILD | win32con.WS_VISIBLE, rect, self) + + +class TestThread(WinThread): + def __init__(self, parentWindow): + self.parentWindow = parentWindow + self.child = None + WinThread.__init__(self) + def InitInstance(self): + rect = self.parentWindow.GetClientRect() + rect = (0,0,rect[2]-rect[0], rect[3]-rect[1]) + + self.child = FontWindow() + self.child.Create("FontDemo", win32con.WS_CHILD | win32con.WS_VISIBLE, rect, self.parentWindow) + self.SetMainFrame(self.child) + return WinThread.InitInstance(self) + + def ExitInstance(self): + return 0 + +class ThreadedFontFrame(window.MDIChildWnd): + def __init__(self): + pass # Dont call base class doc/view version... + self.thread = None + def Create(self, title, rect = None, parent = None): + style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_OVERLAPPEDWINDOW + self._obj_ = win32ui.CreateMDIChild() + self._obj_.CreateWindow(None, title, style, rect, parent) + self._obj_.HookMessage(self.OnDestroy, win32con.WM_DESTROY) + self._obj_.HookMessage (self.OnSize, win32con.WM_SIZE) + + self.thread = TestThread(self) + self.thread.CreateThread() + + def OnSize(self, msg): + pass + + def OnDestroy(self, msg): + win32ui.OutputDebugString("OnDestroy\n") + if self.thread and self.thread.child: + child = self.thread.child + child.SendMessage(WM_USER_PREPARE_TO_CLOSE, 0, 0) + win32ui.OutputDebugString("Destroyed\n") + + +def Demo(): + f = FontFrame() + f.Create("Font Demo") + +def ThreadedDemo(): + rect = win32ui.GetMainFrame().GetMDIClient().GetClientRect() + rect = rect[0], int(rect[3]*3/4), int(rect[2]/4), rect[3] + incr = rect[2] + for i in range(4): + if i==0: + f = FontFrame() + title = "Not threaded" + else: + f = ThreadedFontFrame() + title = "Threaded GUI Demo" + f.Create(title, rect) + rect = rect[0] + incr, rect[1], rect[2]+incr, rect[3] + # Givem a chance to start + win32api.Sleep(100) + win32ui.PumpWaitingMessages() + +if __name__=='__main__': + import demoutils + if demoutils.NeedGoodGUI(): + ThreadedDemo() +# Demo() diff --git a/Lib/site-packages/pythonwin/pywin/Demos/toolbar.py b/Lib/site-packages/pythonwin/pywin/Demos/toolbar.py new file mode 100644 index 0000000..0bc6496 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/Demos/toolbar.py @@ -0,0 +1,93 @@ +# Demo of ToolBars + +# Shows the toolbar control. +# Demos how to make custom tooltips, etc. + +import win32ui +import win32con +import win32api +from pywin.mfc import docview, window, afxres +import commctrl + +class GenericFrame(window.MDIChildWnd): + def OnCreateClient(self, cp, context): + # handlers for toolbar buttons + self.HookCommand (self.OnPrevious, 401) + self.HookCommand (self.OnNext, 402) + # Its not necessary for us to hook both of these - the + # common controls should fall-back all by themselves. + # Indeed, given we hook TTN_NEEDTEXTW, commctrl.TTN_NEEDTEXTA + # will not be called. + self.HookNotify(self.GetTTText, commctrl.TTN_NEEDTEXT) + self.HookNotify(self.GetTTText, commctrl.TTN_NEEDTEXTW) + +# parent = win32ui.GetMainFrame() + parent = self + style = win32con.WS_CHILD | win32con.WS_VISIBLE | \ + afxres.CBRS_SIZE_DYNAMIC | afxres.CBRS_TOP | afxres.CBRS_TOOLTIPS | afxres.CBRS_FLYBY + + buttons = (win32ui.ID_APP_ABOUT,win32ui.ID_VIEW_INTERACTIVE) + bitmap = win32ui.IDB_BROWSER_HIER + tbid = 0xE840 + self.toolbar = tb = win32ui.CreateToolBar (parent, style, tbid) + tb.LoadBitmap(bitmap) + tb.SetButtons(buttons) + + tb.EnableDocking(afxres.CBRS_ALIGN_ANY) + tb.SetWindowText("Test") + parent.EnableDocking(afxres.CBRS_ALIGN_ANY) + parent.DockControlBar(tb) + parent.LoadBarState("ToolbarTest") + window.MDIChildWnd.OnCreateClient(self, cp, context) + return 1 + + def OnDestroy(self, msg): + self.SaveBarState("ToolbarTest") + + def GetTTText(self, std, extra): + (hwndFrom, idFrom, code) = std + text, hinst, flags = extra + if flags & commctrl.TTF_IDISHWND: + return # Not handled + if (idFrom==win32ui.ID_APP_ABOUT): + # our 'extra' return value needs to be the following + # entries from a NMTTDISPINFO[W] struct: + # (szText, hinst, uFlags). None means 'don't change + # the value' + return 0, ("It works!", None, None) + return None # not handled. + + def GetMessageString(self, id): + if id==win32ui.ID_APP_ABOUT: + return "Dialog Test\nTest" + else: + return self._obj_.GetMessageString(id) + + def OnSize (self, params): + print('OnSize called with ', params) + + def OnNext (self, id, cmd): + print('OnNext called') + + def OnPrevious (self, id, cmd): + print('OnPrevious called') + +msg = """\ +This toolbar was dynamically created.\r +\r +The first item's tooltips is provided by Python code.\r +\r +(Dont close the window with the toolbar in a floating state - it may not re-appear!)\r +""" + +def test(): + template = docview.DocTemplate( win32ui.IDR_PYTHONTYPE, None, GenericFrame, docview.EditView) + doc = template.OpenDocumentFile(None) + doc.SetTitle("Toolbar Test") + view = doc.GetFirstView() + view.SetWindowText(msg) + +if __name__=='__main__': + import demoutils + if demoutils.NeedGoodGUI(): + test() diff --git a/Lib/site-packages/pythonwin/pywin/IDLE.cfg b/Lib/site-packages/pythonwin/pywin/IDLE.cfg new file mode 100644 index 0000000..c724b95 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/IDLE.cfg @@ -0,0 +1,29 @@ +[General] +# We base this configuration on the default config. +# You can list "Based On" as many times as you like +Based On = default + +[Keys] +# Only list keys different to default. +# Note you may wish to rebind some of the default +# Pythonwin keys to "Beep" or "DoNothing" + +Alt+L = LocateSelectedFile +Ctrl+Q = AppExit + +# Other non-default Pythonwin keys +Alt+A = EditSelectAll +Alt+M = LocateModule + +# Movement +Ctrl+D = GotoEndOfFile + +# Tabs and other indent features +Alt+T = <> +Ctrl+[ = <> +Ctrl+] = <> + +[Keys:Interactive] +Alt+P = <> +Alt+N = <> + diff --git a/Lib/site-packages/pythonwin/pywin/__init__.py b/Lib/site-packages/pythonwin/pywin/__init__.py new file mode 100644 index 0000000..b4e0ebb --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/__init__.py @@ -0,0 +1,10 @@ +# is_platform_unicode is an old variable that was never correctly used and +# is no longer referenced in pywin32. It is staying for a few releases incase +# others are looking at it, but it will go away soon! +is_platform_unicode = 0 + +# Ditto default_platform_encoding - not referenced and will die. +default_platform_encoding = "mbcs" + +# This one *is* real and used - but in practice can't be changed. +default_scintilla_encoding = "utf-8" # Scintilla _only_ supports this ATM diff --git a/Lib/site-packages/pythonwin/pywin/debugger/__init__.py b/Lib/site-packages/pythonwin/pywin/debugger/__init__.py new file mode 100644 index 0000000..733268c --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/debugger/__init__.py @@ -0,0 +1,113 @@ +import sys + +# Some cruft to deal with the Pythonwin GUI booting up from a non GUI app. +def _MakeDebuggerGUI(): + app.InitInstance() + +isInprocApp = -1 +def _CheckNeedGUI(): + global isInprocApp + if isInprocApp==-1: + import win32ui + isInprocApp = win32ui.GetApp().IsInproc() + if isInprocApp: + # MAY Need it - may already have one + need = "pywin.debugger.dbgpyapp" not in sys.modules + else: + need = 0 + if need: + import pywin.framework.app + from . import dbgpyapp + pywin.framework.app.CreateDefaultGUI(dbgpyapp.DebuggerPythonApp) + + else: + # Check we have the appropriate editor + # No longer necessary! + pass + return need + +# Inject some methods in the top level name-space. +currentDebugger = None # Wipe out any old one on reload. + +def _GetCurrentDebugger(): + global currentDebugger + if currentDebugger is None: + _CheckNeedGUI() + from . import debugger + currentDebugger = debugger.Debugger() + return currentDebugger + +def GetDebugger(): + # An error here is not nice - as we are probably trying to + # break into the debugger on a Python error, any + # error raised by this is usually silent, and causes + # big problems later! + try: + rc = _GetCurrentDebugger() + rc.GUICheckInit() + return rc + except: + print("Could not create the debugger!") + import traceback + traceback.print_exc() + return None + +def close(): + if currentDebugger is not None: + currentDebugger.close() + +def run(cmd,globals=None, locals=None, start_stepping = 1): + _GetCurrentDebugger().run(cmd, globals,locals, start_stepping) + +def runeval(expression, globals=None, locals=None): + return _GetCurrentDebugger().runeval(expression, globals, locals) + +def runcall(*args): + return _GetCurrentDebugger().runcall(*args) + +def set_trace(): + import sys + d = _GetCurrentDebugger() + + if d.frameShutdown: return # App closing + + if d.stopframe != d.botframe: + # If im not "running" + return + + sys.settrace(None) # May be hooked + d.reset() + d.set_trace() + +# "brk" is an alias for "set_trace" ("break" is a reserved word :-( +brk = set_trace + +# Post-Mortem interface + +def post_mortem(t=None): + if t is None: + t = sys.exc_info()[2] # Will be valid if we are called from an except handler. + if t is None: + try: + t = sys.last_traceback + except AttributeError: + print("No traceback can be found from which to perform post-mortem debugging!") + print("No debugging can continue") + return + p = _GetCurrentDebugger() + if p.frameShutdown: return # App closing + # No idea why I need to settrace to None - it should have been reset by now? + sys.settrace(None) + p.reset() + while t.tb_next != None: t = t.tb_next + p.bAtPostMortem = 1 + p.prep_run(None) + try: + p.interaction(t.tb_frame, t) + finally: + t = None + p.bAtPostMortem = 0 + p.done_run() + +def pm(t=None): + post_mortem(t) diff --git a/Lib/site-packages/pythonwin/pywin/debugger/configui.py b/Lib/site-packages/pythonwin/pywin/debugger/configui.py new file mode 100644 index 0000000..178765c --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/debugger/configui.py @@ -0,0 +1,31 @@ +from . import dbgcon +from pywin.mfc import dialog +import win32ui + +class DebuggerOptionsPropPage(dialog.PropertyPage): + def __init__(self): + dialog.PropertyPage.__init__(self, win32ui.IDD_PP_DEBUGGER) + + def OnInitDialog(self): + options = self.options = dbgcon.LoadDebuggerOptions() + self.AddDDX(win32ui.IDC_CHECK1, dbgcon.OPT_HIDE) + self[dbgcon.OPT_STOP_EXCEPTIONS] = options[dbgcon.OPT_STOP_EXCEPTIONS] + self.AddDDX(win32ui.IDC_CHECK2, dbgcon.OPT_STOP_EXCEPTIONS) + self[dbgcon.OPT_HIDE] = options[dbgcon.OPT_HIDE] + return dialog.PropertyPage.OnInitDialog(self) + + def OnOK(self): + self.UpdateData() + dirty = 0 + for key, val in list(self.items()): + if key in self.options: + if self.options[key] != val: + self.options[key] = val + dirty = 1 + if dirty: + dbgcon.SaveDebuggerOptions(self.options) + # If there is a debugger open, then set its options. + import pywin.debugger + if pywin.debugger.currentDebugger is not None: + pywin.debugger.currentDebugger.options = self.options + return 1 diff --git a/Lib/site-packages/pythonwin/pywin/debugger/dbgcon.py b/Lib/site-packages/pythonwin/pywin/debugger/dbgcon.py new file mode 100644 index 0000000..beb2996 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/debugger/dbgcon.py @@ -0,0 +1,28 @@ +# General constants for the debugger + +DBGSTATE_NOT_DEBUGGING = 0 +DBGSTATE_RUNNING = 1 +DBGSTATE_BREAK = 2 +DBGSTATE_QUITTING = 3 # Attempting to back out of the debug session. + +LINESTATE_CURRENT = 0x1 # This line is where we are stopped +LINESTATE_BREAKPOINT = 0x2 # This line is a breakpoint +LINESTATE_CALLSTACK = 0x4 # This line is in the callstack. + +OPT_HIDE = 'hide' +OPT_STOP_EXCEPTIONS = 'stopatexceptions' + +import win32api, win32ui + +def DoGetOption(optsDict, optName, default): + optsDict[optName] = win32ui.GetProfileVal("Debugger Options", optName, default) + +def LoadDebuggerOptions(): + opts = {} + DoGetOption(opts, OPT_HIDE, 0) + DoGetOption(opts, OPT_STOP_EXCEPTIONS, 1) + return opts + +def SaveDebuggerOptions(opts): + for key, val in opts.items(): + win32ui.WriteProfileVal("Debugger Options", key, val) diff --git a/Lib/site-packages/pythonwin/pywin/debugger/dbgpyapp.py b/Lib/site-packages/pythonwin/pywin/debugger/dbgpyapp.py new file mode 100644 index 0000000..190fac6 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/debugger/dbgpyapp.py @@ -0,0 +1,47 @@ +# dbgpyapp.py - Debugger Python application class +# +import win32con +import win32ui +import sys +import string +import os +from pywin.framework import intpyapp + +version = '0.3.0' + +class DebuggerPythonApp(intpyapp.InteractivePythonApp): + def LoadMainFrame(self): + " Create the main applications frame " + self.frame = self.CreateMainFrame() + self.SetMainFrame(self.frame) + self.frame.LoadFrame(win32ui.IDR_DEBUGGER, win32con.WS_OVERLAPPEDWINDOW) + self.frame.DragAcceptFiles() # we can accept these. + self.frame.ShowWindow(win32con.SW_HIDE); + self.frame.UpdateWindow(); + + # but we do rehook, hooking the new code objects. + self.HookCommands() + + def InitInstance(self): + # Use a registry path of "Python\Pythonwin Debugger + win32ui.SetAppName(win32ui.LoadString(win32ui.IDR_DEBUGGER)) + win32ui.SetRegistryKey("Python %s" % (sys.winver,)) + # We _need_ the Scintilla color editor. + # (and we _always_ get it now :-) + + numMRU = win32ui.GetProfileVal("Settings","Recent File List Size", 10) + win32ui.LoadStdProfileSettings(numMRU) + + self.LoadMainFrame() + + # Display the interactive window if the user wants it. + from pywin.framework import interact + interact.CreateInteractiveWindowUserPreference() + + # Load the modules we use internally. + self.LoadSystemModules() + # Load additional module the user may want. + self.LoadUserModules() + +# win32ui.CreateDebuggerThread() + win32ui.EnableControlContainer() diff --git a/Lib/site-packages/pythonwin/pywin/debugger/debugger.py b/Lib/site-packages/pythonwin/pywin/debugger/debugger.py new file mode 100644 index 0000000..6867e4b --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/debugger/debugger.py @@ -0,0 +1,985 @@ +# debugger.py + +# A debugger for Pythonwin. Built from pdb. + +# Mark Hammond (MHammond@skippinet.com.au) - Dec 94. + +# usage: +# >>> import pywin.debugger +# >>> pywin.debugger.GetDebugger().run("command") + +import pdb +import bdb +import sys +import string +import os +import types + +import win32ui +import win32api +import win32con +import pywin.docking.DockingBar +from pywin.mfc import dialog, object, afxres, window +from pywin.framework import app, interact, editor, scriptutils +from pywin.framework.editor.color.coloreditor import MARKER_CURRENT, MARKER_BREAKPOINT +from pywin.tools import browser, hierlist +import commctrl +import traceback + +#import win32traceutil +if win32ui.UNICODE: + LVN_ENDLABELEDIT = commctrl.LVN_ENDLABELEDITW +else: + LVN_ENDLABELEDIT = commctrl.LVN_ENDLABELEDITA + +from .dbgcon import * + +error = "pywin.debugger.error" + +def SetInteractiveContext(globs, locs): + if interact.edit is not None and interact.edit.currentView is not None: + interact.edit.currentView.SetContext(globs, locs) + +def _LineStateToMarker(ls): + if ls==LINESTATE_CURRENT: + return MARKER_CURRENT +# elif ls == LINESTATE_CALLSTACK: +# return MARKER_CALLSTACK + return MARKER_BREAKPOINT + +class HierListItem(browser.HLIPythonObject): + pass + +class HierFrameItem(HierListItem): + def __init__(self, frame, debugger): + HierListItem.__init__(self, frame, repr(frame)) + self.debugger = debugger + def GetText(self): + name = self.myobject.f_code.co_name + if not name or name == '?' : + # See if locals has a '__name__' (ie, a module) + if '__name__' in self.myobject.f_locals: + name = str(self.myobject.f_locals['__name__']) + " module" + else: + name = '' + + return "%s (%s:%d)" % (name, os.path.split(self.myobject.f_code.co_filename)[1], self.myobject.f_lineno) + def GetBitmapColumn(self): + if self.debugger.curframe is self.myobject: + return 7 + else: + return 8 + def GetSubList(self): + ret = [] + ret.append(HierFrameDict(self.myobject.f_locals, "Locals", 2)) + ret.append(HierFrameDict(self.myobject.f_globals, "Globals", 1)) + return ret + def IsExpandable(self): + return 1 + def TakeDefaultAction(self): + # Set the default frame to be this frame. + self.debugger.set_cur_frame(self.myobject) + return 1 + +class HierFrameDict(browser.HLIDict): + def __init__(self, dict, name, bitmapColumn): + self.bitmapColumn=bitmapColumn + browser.HLIDict.__init__(self, dict, name) + def GetBitmapColumn(self): + return self.bitmapColumn + +class NoStackAvailableItem(HierListItem): + def __init__(self, why): + HierListItem.__init__(self, None, why) + def IsExpandable(self): + return 0 + def GetText(self): + return self.name + def GetBitmapColumn(self): + return 8 + +class HierStackRoot(HierListItem): + def __init__( self, debugger ): + HierListItem.__init__(self, debugger, None) + self.last_stack = [] +## def __del__(self): +## print "HierStackRoot dieing" + def GetSubList(self): + debugger = self.myobject +# print self.debugger.stack, self.debugger.curframe + ret = [] + if debugger.debuggerState==DBGSTATE_BREAK: + stackUse=debugger.stack[:] + stackUse.reverse() + self.last_stack = [] + for frame, lineno in stackUse: + self.last_stack.append( (frame, lineno) ) + if frame is debugger.userbotframe: # Dont bother showing frames below our bottom frame. + break + for frame, lineno in self.last_stack: + ret.append( HierFrameItem( frame, debugger ) ) +## elif debugger.debuggerState==DBGSTATE_NOT_DEBUGGING: +## ret.append(NoStackAvailableItem('')) +## else: +## ret.append(NoStackAvailableItem('')) + return ret + def GetText(self): + return 'root item' + def IsExpandable(self): + return 1 + +class HierListDebugger(hierlist.HierListWithItems): + """ Hier List of stack frames, breakpoints, whatever """ + def __init__(self): + hierlist.HierListWithItems.__init__(self, None, win32ui.IDB_DEBUGGER_HIER, None, win32api.RGB(255,0,0)) + def Setup(self, debugger): + root = HierStackRoot(debugger) + self.AcceptRoot(root) +# def Refresh(self): +# self.Setup() + +class DebuggerWindow(window.Wnd): + def __init__(self, ob): + window.Wnd.__init__(self, ob) + self.debugger = None + + def Init(self, debugger): + self.debugger = debugger + + def GetDefRect(self): + defRect = app.LoadWindowSize("Debugger Windows\\" + self.title) + if defRect[2]-defRect[0]==0: + defRect = 0, 0, 150, 150 + return defRect + + def OnDestroy(self, msg): + newSize = self.GetWindowPlacement()[4] + pywin.framework.app.SaveWindowSize("Debugger Windows\\" + self.title, newSize) + return window.Wnd.OnDestroy(self, msg) + + def OnKeyDown(self, msg): + key = msg[2] + if key in [13, 27, 32]: return 1 + if key in [46,8]: # delete/BS key + self.DeleteSelected() + return 0 + view = scriptutils.GetActiveView() + try: + firer = view.bindings.fire_key_event + except AttributeError: + firer = None + if firer is not None: + return firer(msg) + else: + return 1 + + def DeleteSelected(self): + win32api.MessageBeep() + + def EditSelected(self): + win32api.MessageBeep() + +class DebuggerStackWindow(DebuggerWindow): + title = "Stack" + def __init__(self): + DebuggerWindow.__init__(self, win32ui.CreateTreeCtrl()) + self.list = HierListDebugger() + self.listOK = 0 + def SaveState(self): + self.list.DeleteAllItems() + self.listOK = 0 + win32ui.WriteProfileVal("Debugger Windows\\" + self.title, "Visible", self.IsWindowVisible()) + def CreateWindow(self, parent): + style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_BORDER | commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS + self._obj_.CreateWindow(style, self.GetDefRect(), parent, win32ui.IDC_LIST1) + self.HookMessage(self.OnKeyDown, win32con.WM_KEYDOWN) + self.HookMessage(self.OnKeyDown, win32con.WM_SYSKEYDOWN) + self.list.HierInit (parent, self) + self.listOK = 0 # delayed setup + #self.list.Setup() + + def RespondDebuggerState(self, state): + assert self.debugger is not None, "Init not called" + if not self.listOK: + self.listOK = 1 + self.list.Setup(self.debugger) + else: + self.list.Refresh() + + def RespondDebuggerData(self): + try: + handle = self.GetChildItem(0) + except win32ui.error: + return # No items + while 1: + item = self.list.ItemFromHandle(handle) + col = self.list.GetBitmapColumn(item) + selCol = self.list.GetSelectedBitmapColumn(item) + if selCol is None: selCol = col + if self.list.GetItemImage(handle)!= (col, selCol): + self.list.SetItemImage(handle, col, selCol) + try: + handle = self.GetNextSiblingItem(handle) + except win32ui.error: + break + +class DebuggerListViewWindow(DebuggerWindow): + def __init__(self): + DebuggerWindow.__init__(self, win32ui.CreateListCtrl()) + def CreateWindow(self, parent): + list = self + style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_BORDER | commctrl.LVS_EDITLABELS | commctrl.LVS_REPORT + self._obj_.CreateWindow(style, self.GetDefRect(), parent, win32ui.IDC_LIST1) + self.HookMessage(self.OnKeyDown, win32con.WM_KEYDOWN) + self.HookMessage(self.OnKeyDown, win32con.WM_SYSKEYDOWN) + list = self + title, width = self.columns[0] + itemDetails = (commctrl.LVCFMT_LEFT, width, title, 0) + list.InsertColumn(0, itemDetails) + col = 1 + for title, width in self.columns[1:]: + col = col + 1 + itemDetails = (commctrl.LVCFMT_LEFT, width, title, 0) + list.InsertColumn(col, itemDetails) + parent.HookNotify(self.OnListEndLabelEdit, LVN_ENDLABELEDIT) + parent.HookNotify(self.OnItemRightClick, commctrl.NM_RCLICK) + parent.HookNotify(self.OnItemDoubleClick, commctrl.NM_DBLCLK) + + def RespondDebuggerData(self): + pass + + def RespondDebuggerState(self, state): + pass + + def EditSelected(self): + try: + sel = self.GetNextItem(-1, commctrl.LVNI_SELECTED) + except win32ui.error: + return + self.EditLabel(sel) + + def OnKeyDown(self, msg): + key = msg[2] + # If someone starts typing, they probably are trying to edit the text! + if chr(key) in string.ascii_uppercase: + self.EditSelected() + return 0 + return DebuggerWindow.OnKeyDown(self, msg) + + def OnItemDoubleClick(self, notify_data, extra): + self.EditSelected() + + def OnItemRightClick(self, notify_data, extra): + # First select the item we right-clicked on. + pt = self.ScreenToClient(win32api.GetCursorPos()) + flags, hItem, subitem = self.HitTest(pt) + if hItem==-1 or commctrl.TVHT_ONITEM & flags==0: + return None + self.SetItemState(hItem, commctrl.LVIS_SELECTED, commctrl.LVIS_SELECTED) + + menu = win32ui.CreatePopupMenu() + menu.AppendMenu(win32con.MF_STRING|win32con.MF_ENABLED,1000, "Edit item") + menu.AppendMenu(win32con.MF_STRING|win32con.MF_ENABLED,1001, "Delete item") + dockbar = self.GetParent() + if dockbar.IsFloating(): + hook_parent = win32ui.GetMainFrame() + else: + hook_parent = self.GetParentFrame() + hook_parent.HookCommand(self.OnEditItem, 1000) + hook_parent.HookCommand(self.OnDeleteItem, 1001) + menu.TrackPopupMenu(win32api.GetCursorPos()) # track at mouse position. + return None + + def OnDeleteItem(self,command, code): + self.DeleteSelected() + def OnEditItem(self, command, code): + self.EditSelected() + +class DebuggerBreakpointsWindow(DebuggerListViewWindow): + title = "Breakpoints" + columns = [ ("Condition", 70), ("Location", 1024)] + + def SaveState(self): + items = [] + for i in range(self.GetItemCount()): + items.append(self.GetItemText(i,0)) + items.append(self.GetItemText(i,1)) + win32ui.WriteProfileVal("Debugger Windows\\" + self.title, "BreakpointList", "\t".join(items)) + win32ui.WriteProfileVal("Debugger Windows\\" + self.title, "Visible", self.IsWindowVisible()) + return 1 + + def OnListEndLabelEdit(self, std, extra): + item = extra[0] + text = item[4] + if text is None: return + + item_id = self.GetItem(item[0])[6] + + from bdb import Breakpoint + for bplist in Breakpoint.bplist.values(): + for bp in bplist: + if id(bp)==item_id: + if text.strip().lower()=="none": + text = None + bp.cond = text + break + self.RespondDebuggerData() + + def DeleteSelected(self): + try: + num = self.GetNextItem(-1, commctrl.LVNI_SELECTED) + item_id = self.GetItem(num)[6] + from bdb import Breakpoint + for bplist in list(Breakpoint.bplist.values()): + for bp in bplist: + if id(bp)==item_id: + self.debugger.clear_break(bp.file, bp.line) + break + except win32ui.error: + win32api.MessageBeep() + self.RespondDebuggerData() + + def RespondDebuggerData(self): + l = self + l.DeleteAllItems() + index = -1 + from bdb import Breakpoint + for bplist in Breakpoint.bplist.values(): + for bp in bplist: + baseName = os.path.split(bp.file)[1] + cond = bp.cond + item = index+1, 0, 0, 0, str(cond), 0, id(bp) + index = l.InsertItem(item) + l.SetItemText(index, 1, "%s: %s" % (baseName, bp.line)) + +class DebuggerWatchWindow(DebuggerListViewWindow): + title = "Watch" + columns = [ ("Expression", 70), ("Value", 1024)] + + def CreateWindow(self, parent): + DebuggerListViewWindow.CreateWindow(self, parent) + items = win32ui.GetProfileVal("Debugger Windows\\" + self.title, "Items", "").split("\t") + index = -1 + for item in items: + if item: + index = self.InsertItem(index+1, item) + self.InsertItem(index+1, "") + + def SaveState(self): + items = [] + for i in range(self.GetItemCount()-1): + items.append(self.GetItemText(i,0)) + win32ui.WriteProfileVal("Debugger Windows\\" + self.title, "Items", "\t".join(items)) + win32ui.WriteProfileVal("Debugger Windows\\" + self.title, "Visible", self.IsWindowVisible()) + return 1 + + def OnListEndLabelEdit(self, std, extra): + item = extra[0] + itemno = item[0] + text = item[4] + if text is None: return + self.SetItemText(itemno, 0, text) + if itemno == self.GetItemCount()-1: + self.InsertItem(itemno+1, "") + self.RespondDebuggerState(self.debugger.debuggerState) + + def DeleteSelected(self): + try: + num = self.GetNextItem(-1, commctrl.LVNI_SELECTED) + if num < self.GetItemCount()-1: # We cant delete the last + self.DeleteItem(num) + except win32ui.error: + win32api.MessageBeep() + + def RespondDebuggerState(self, state): + globs = locs = None + if state==DBGSTATE_BREAK: + if self.debugger.curframe: + globs = self.debugger.curframe.f_globals + locs = self.debugger.curframe.f_locals + elif state==DBGSTATE_NOT_DEBUGGING: + import __main__ + globs = locs = __main__.__dict__ + for i in range(self.GetItemCount()-1): + text = self.GetItemText(i, 0) + if globs is None: + val = "" + else: + try: + val = repr( eval( text, globs, locs) ) + except SyntaxError: + val = "Syntax Error" + except: + t, v, tb = sys.exc_info() + val = traceback.format_exception_only(t, v)[0].strip() + tb = None # prevent a cycle. + self.SetItemText(i, 1, val) + +def CreateDebuggerDialog(parent, klass): + control = klass() + control.CreateWindow(parent) + return control + +DebuggerDialogInfos = ( + (0xe810, DebuggerStackWindow, None), + (0xe811, DebuggerBreakpointsWindow, (10, 10)), + (0xe812, DebuggerWatchWindow, None), + ) + +# Prepare all the "control bars" for this package. +# If control bars are not all loaded when the toolbar-state functions are +# called, things go horribly wrong. +def PrepareControlBars(frame): + style = win32con.WS_CHILD | afxres.CBRS_SIZE_DYNAMIC | afxres.CBRS_TOP | afxres.CBRS_TOOLTIPS | afxres.CBRS_FLYBY + tbd = win32ui.CreateToolBar (frame, style, win32ui.ID_VIEW_TOOLBAR_DBG) + tbd.ModifyStyle(0, commctrl.TBSTYLE_FLAT) + tbd.LoadToolBar(win32ui.IDR_DEBUGGER) + tbd.EnableDocking(afxres.CBRS_ALIGN_ANY) + tbd.SetWindowText("Debugger") + frame.DockControlBar(tbd) + + # and the other windows. + for id, klass, float in DebuggerDialogInfos: + try: + frame.GetControlBar(id) + exists=1 + except win32ui.error: + exists=0 + if exists: continue + bar = pywin.docking.DockingBar.DockingBar() + style=win32con.WS_CHILD | afxres.CBRS_LEFT # don't create visible. + bar.CreateWindow(frame, CreateDebuggerDialog, klass.title, id, style, childCreatorArgs=(klass,)) + bar.SetBarStyle( bar.GetBarStyle()|afxres.CBRS_TOOLTIPS|afxres.CBRS_FLYBY|afxres.CBRS_SIZE_DYNAMIC) + bar.EnableDocking(afxres.CBRS_ALIGN_ANY) + if float is None: + frame.DockControlBar(bar) + else: + frame.FloatControlBar(bar, float, afxres.CBRS_ALIGN_ANY) + + ## frame.ShowControlBar(bar, 0, 1) + + +SKIP_NONE=0 +SKIP_STEP=1 +SKIP_RUN=2 + +debugger_parent=pdb.Pdb +class Debugger(debugger_parent): + def __init__(self): + self.inited = 0 + self.skipBotFrame = SKIP_NONE + self.userbotframe = None + self.frameShutdown = 0 + self.pumping = 0 + self.debuggerState = DBGSTATE_NOT_DEBUGGING # Assume so, anyway. + self.shownLineCurrent = None # The last filename I highlighted. + self.shownLineCallstack = None # The last filename I highlighted. + self.last_cmd_debugged = "" + self.abortClosed = 0 + self.isInitialBreakpoint = 0 + debugger_parent.__init__(self) + + # See if any break-points have been set in the editor + for doc in editor.editorTemplate.GetDocumentList(): + lineNo = -1 + while 1: + lineNo = doc.MarkerGetNext(lineNo+1, MARKER_BREAKPOINT) + if lineNo <= 0: break + self.set_break(doc.GetPathName(), lineNo) + + self.reset() + self.inForcedGUI = win32ui.GetApp().IsInproc() + self.options = LoadDebuggerOptions() + self.bAtException = self.bAtPostMortem = 0 + + def __del__(self): + self.close() + def close(self, frameShutdown = 0): + # abortClose indicates if we have total shutdown + # (ie, main window is dieing) + if self.pumping: + # Can stop pump here, as it only posts a message, and + # returns immediately. + if not self.StopDebuggerPump(): # User cancelled close. + return 0 + # NOTE - from this point on the close can not be + # stopped - the WM_QUIT message is already in the queue. + self.frameShutdown = frameShutdown + if not self.inited: return 1 + self.inited = 0 + + SetInteractiveContext(None, None) + + frame = win32ui.GetMainFrame() + # Hide the debuger toolbars (as they wont normally form part of the main toolbar state. + for id, klass, float in DebuggerDialogInfos: + try: + tb = frame.GetControlBar(id) + if tb.dialog is not None: # We may never have actually been shown. + tb.dialog.SaveState() + frame.ShowControlBar(tb, 0, 1) + except win32ui.error: + pass + + self._UnshowCurrentLine() + self.set_quit() + return 1 + + def StopDebuggerPump(self): + assert self.pumping, "Can't stop the debugger pump if Im not pumping!" + # After stopping a pump, I may never return. + if self.GUIAboutToFinishInteract(): + self.pumping = 0 + win32ui.StopDebuggerPump() # Posts a message, so we do return. + return 1 + return 0 + + def get_option(self, option): + """Public interface into debugger options + """ + try: + return self.options[option] + except KeyError: + raise error("Option %s is not a valid option" % option) + + def prep_run(self, cmd): + pass + def done_run(self, cmd=None): + self.RespondDebuggerState(DBGSTATE_NOT_DEBUGGING) + self.close() + def canonic(self, fname): + return os.path.abspath(fname).lower() + def reset(self): + debugger_parent.reset(self) + self.userbotframe = None + self.UpdateAllLineStates() + self._UnshowCurrentLine() + + + def setup(self, f, t): + debugger_parent.setup(self, f, t) + self.bAtException = t is not None + + def set_break(self, filename, lineno, temporary=0, cond = None): + filename = self.canonic(filename) + self.SetLineState(filename, lineno, LINESTATE_BREAKPOINT) + return debugger_parent.set_break(self, filename, lineno, temporary, cond) + + def clear_break(self, filename, lineno): + filename = self.canonic(filename) + self.ResetLineState(filename, lineno, LINESTATE_BREAKPOINT) + return debugger_parent.clear_break(self, filename, lineno) + + def cmdloop(self): + if self.frameShutdown: return # App in the process of closing - never break in! + self.GUIAboutToBreak() + + def print_stack_entry(self, frame): + # We dont want a stack printed - our GUI is better :-) + pass + + def user_return(self, frame, return_value): + # Same as parent, just no "print" + # This function is called when a return trap is set here + frame.f_locals['__return__'] = return_value + self.interaction(frame, None) + + def user_call(self, frame, args): + # base class has an annoying 'print' that adds no value to us... + if self.stop_here(frame): + self.interaction(frame, None) + + def user_exception(self, frame, exc_info): + # This function is called if an exception occurs, + # but only if we are to stop at or just below this level + (exc_type, exc_value, exc_traceback) = exc_info + if self.get_option(OPT_STOP_EXCEPTIONS): + frame.f_locals['__exception__'] = exc_type, exc_value + print("Unhandled exception while debugging...") + # on both py2k and py3k, we may be called with exc_value + # being the args to the exception, or it may already be + # instantiated (IOW, PyErr_Normalize() hasn't been + # called on the args). In py2k this is fine, but in + # py3k, traceback.print_exception fails. So on py3k + # we instantiate an exception instance to print. + if sys.version_info > (3,) and not isinstance(exc_value, BaseException): + # they are args - may be a single item or already a tuple + if not isinstance(exc_value, tuple): + exc_value = (exc_value,) + exc_value = exc_type(*exc_value) + + traceback.print_exception(exc_type, exc_value, exc_traceback) + self.interaction(frame, exc_traceback) + + def user_line(self, frame): + if frame.f_lineno==0: return + debugger_parent.user_line(self, frame) + + def stop_here(self, frame): + if self.isInitialBreakpoint: + self.isInitialBreakpoint = 0 + self.set_continue() + return 0 + if frame is self.botframe and self.skipBotFrame == SKIP_RUN: + self.set_continue() + return 0 + if frame is self.botframe and self.skipBotFrame == SKIP_STEP: + self.set_step() + return 0 + return debugger_parent.stop_here(self, frame) + + def run(self, cmd,globals=None, locals=None, start_stepping = 1): + if not isinstance(cmd, (str, types.CodeType)): + raise TypeError("Only strings can be run") + self.last_cmd_debugged = cmd + if start_stepping: + self.isInitialBreakpoint = 0 + else: + self.isInitialBreakpoint = 1 + try: + if globals is None: + import __main__ + globals = __main__.__dict__ + if locals is None: + locals = globals + self.reset() + self.prep_run(cmd) + sys.settrace(self.trace_dispatch) + if type(cmd) != types.CodeType: + cmd = cmd+'\n' + try: + try: + if start_stepping: self.skipBotFrame = SKIP_STEP + else: self.skipBotFrame = SKIP_RUN + exec(cmd, globals, locals) + except bdb.BdbQuit: + pass + finally: + self.skipBotFrame = SKIP_NONE + self.quitting = 1 + sys.settrace(None) + + finally: + self.done_run(cmd) + + def runeval(self, expr, globals=None, locals=None): + self.prep_run(expr) + try: + debugger_parent.runeval(self, expr, globals, locals) + finally: + self.done_run(expr) + + def runexec(self, what, globs=None, locs=None): + self.reset() + sys.settrace(self.trace_dispatch) + try: + try: + exec(what, globs, locs) + except bdb.BdbQuit: + pass + finally: + self.quitting = 1 + sys.settrace(None) + + def do_set_step(self): + if self.GUIAboutToRun(): + self.set_step() + + def do_set_next(self): + if self.GUIAboutToRun(): + self.set_next(self.curframe) + + def do_set_return(self): + if self.GUIAboutToRun(): + self.set_return(self.curframe) + + def do_set_continue(self): + if self.GUIAboutToRun(): + self.set_continue() + + def set_quit(self): + ok = 1 + if self.pumping: + ok = self.StopDebuggerPump() + if ok: + debugger_parent.set_quit(self) + + def _dump_frame_(self, frame,name=None): + if name is None: name = "" + if frame: + if frame.f_code and frame.f_code.co_filename: + fname = os.path.split(frame.f_code.co_filename)[1] + else: + fname = "??" + print(repr(name), fname, frame.f_lineno, frame) + else: + print(repr(name), "None") + + def set_trace(self): + # Start debugging from _2_ levels up! + try: + 1 + '' + except: + frame = sys.exc_info()[2].tb_frame.f_back.f_back + self.reset() + self.userbotframe = None + while frame: + # scriptutils.py creates a local variable with name + # '_debugger_stop_frame_', and we dont go past it + # (everything above this is Pythonwin framework code) + if "_debugger_stop_frame_" in frame.f_locals: + self.userbotframe = frame + break + + frame.f_trace = self.trace_dispatch + self.botframe = frame + frame = frame.f_back + self.set_step() + sys.settrace(self.trace_dispatch) + + def set_cur_frame(self, frame): + # Sets the "current" frame - ie, the frame with focus. This is the + # frame on which "step out" etc actions are taken. + # This may or may not be the top of the stack. + assert frame is not None, "You must pass a valid frame" + self.curframe = frame + for f, index in self.stack: + if f is frame: + self.curindex = index + break + else: + assert 0, "Can't find the frame in the stack." + SetInteractiveContext(frame.f_globals, frame.f_locals) + self.GUIRespondDebuggerData() + self.ShowCurrentLine() + + def IsBreak(self): + return self.debuggerState == DBGSTATE_BREAK + + def IsDebugging(self): + return self.debuggerState != DBGSTATE_NOT_DEBUGGING + + def RespondDebuggerState(self, state): + if state == self.debuggerState: return + if state==DBGSTATE_NOT_DEBUGGING: # Debugger exists, but not doing anything + title = "" + elif state==DBGSTATE_RUNNING: # Code is running under the debugger. + title = " - running" + elif state==DBGSTATE_BREAK: # We are at a breakpoint or stepping or whatever. + if self.bAtException: + if self.bAtPostMortem: + title = " - post mortem exception" + else: + title = " - exception" + else: + title = " - break" + else: + raise error("Invalid debugger state passed!") + win32ui.GetMainFrame().SetWindowText(win32ui.LoadString(win32ui.IDR_MAINFRAME) + title) + if self.debuggerState == DBGSTATE_QUITTING and state != DBGSTATE_NOT_DEBUGGING: + print("Ignoring state change cos Im trying to stop!", state) + return + self.debuggerState = state + try: + frame = win32ui.GetMainFrame() + except win32ui.error: + frame = None + if frame is not None: + for id, klass, float in DebuggerDialogInfos: + cb = win32ui.GetMainFrame().GetControlBar(id).dialog + cb.RespondDebuggerState(state) + # Tell each open editor window about the state transition + for doc in editor.editorTemplate.GetDocumentList(): + doc.OnDebuggerStateChange(state) + self.ShowCurrentLine() + + # + # GUI debugger interface. + # + def GUICheckInit(self): + if self.inited: return + self.inited = 1 + frame = win32ui.GetMainFrame() + + # Ensure the debugger windows are attached to the debugger. + for id, klass, float in DebuggerDialogInfos: + w = frame.GetControlBar(id) + w.dialog.Init(self) + # Show toolbar if it was visible during last debug session + # This would be better done using a CDockState, but that class is not wrapped yet + if win32ui.GetProfileVal("Debugger Windows\\" + w.dialog.title, "Visible", 0): + frame.ShowControlBar(w, 1, 1) + + # ALWAYS show debugging toolbar, regardless of saved state + tb = frame.GetControlBar(win32ui.ID_VIEW_TOOLBAR_DBG) + frame.ShowControlBar(tb, 1, 1) + self.GUIRespondDebuggerData() + +# frame.RecalcLayout() + + def GetDebuggerBar(self, barName): + frame = win32ui.GetMainFrame() + for id, klass, float in DebuggerDialogInfos: + if klass.title == barName: + return frame.GetControlBar(id) + assert 0, "Can't find a bar of that name!" + + def GUIRespondDebuggerData(self): + if not self.inited: # GUI not inited - no toolbars etc. + return + + for id, klass, float in DebuggerDialogInfos: + cb = win32ui.GetMainFrame().GetControlBar(id).dialog + cb.RespondDebuggerData() + + def GUIAboutToRun(self): + if not self.StopDebuggerPump(): + return 0 + self._UnshowCurrentLine() + self.RespondDebuggerState(DBGSTATE_RUNNING) + SetInteractiveContext(None, None) + return 1 + + def GUIAboutToBreak(self): + "Called as the GUI debugger is about to get context, and take control of the running program." + self.GUICheckInit() + self.RespondDebuggerState(DBGSTATE_BREAK) + self.GUIAboutToInteract() + if self.pumping: + print("!!! Already pumping - outa here") + return + self.pumping = 1 + win32ui.StartDebuggerPump() # NOTE - This will NOT return until the user is finished interacting + assert not self.pumping, "Should not be pumping once the pump has finished" + if self.frameShutdown: # User shut down app while debugging + win32ui.GetMainFrame().PostMessage(win32con.WM_CLOSE) + + def GUIAboutToInteract(self): + "Called as the GUI is about to perform any interaction with the user" + frame = win32ui.GetMainFrame() + # Remember the enabled state of our main frame + # may be disabled primarily if a modal dialog is displayed. + # Only get at enabled via GetWindowLong. + self.bFrameEnabled = frame.IsWindowEnabled() + self.oldForeground = None + fw = win32ui.GetForegroundWindow() + if fw is not frame: + self.oldForeground = fw +# fw.EnableWindow(0) Leave enabled for now? + self.oldFrameEnableState = frame.IsWindowEnabled() + frame.EnableWindow(1) + if self.inForcedGUI and not frame.IsWindowVisible(): + frame.ShowWindow(win32con.SW_SHOW) + frame.UpdateWindow() + if self.curframe: + SetInteractiveContext(self.curframe.f_globals, self.curframe.f_locals) + else: + SetInteractiveContext(None, None) + self.GUIRespondDebuggerData() + + def GUIAboutToFinishInteract(self): + """Called as the GUI is about to finish any interaction with the user + Returns non zero if we are allowed to stop interacting""" + if self.oldForeground is not None: + try: + win32ui.GetMainFrame().EnableWindow(self.oldFrameEnableState) + self.oldForeground.EnableWindow(1) + except win32ui.error: + # old window may be dead. + pass +# self.oldForeground.SetForegroundWindow() - fails?? + if not self.inForcedGUI: + return 1 # Never a problem, and nothing else to do. + # If we are running a forced GUI, we may never get an opportunity + # to interact again. Therefore we perform a "SaveAll", to makesure that + # any documents are saved before leaving. + for template in win32ui.GetApp().GetDocTemplateList(): + for doc in template.GetDocumentList(): + if not doc.SaveModified(): + return 0 + # All documents saved - now hide the app and debugger. + if self.get_option(OPT_HIDE): + frame = win32ui.GetMainFrame() + frame.ShowWindow(win32con.SW_HIDE) + return 1 + + # + # Pythonwin interface - all stuff to do with showing source files, + # changing line states etc. + # + def ShowLineState(self, fileName, lineNo, lineState): + # Set the state of a line, open if not already + self.ShowLineNo(fileName, lineNo) + self.SetLineState(fileName, lineNo, lineState) + + def SetLineState(self, fileName, lineNo, lineState): + # Set the state of a line if the document is open. + doc = editor.editorTemplate.FindOpenDocument(fileName) + if doc is not None: + marker = _LineStateToMarker(lineState) + if not doc.MarkerCheck(lineNo, marker): + doc.MarkerAdd(lineNo, marker) + + def ResetLineState(self, fileName, lineNo, lineState): + # Set the state of a line if the document is open. + doc = editor.editorTemplate.FindOpenDocument(fileName) + if doc is not None: + marker = _LineStateToMarker(lineState) + doc.MarkerDelete(lineNo, marker) + + def UpdateDocumentLineStates(self, doc): + # Show all lines in their special status color. If the doc is open + # all line states are reset. + doc.MarkerDeleteAll( MARKER_BREAKPOINT ) + doc.MarkerDeleteAll( MARKER_CURRENT ) + fname = self.canonic(doc.GetPathName()) + # Now loop over all break-points + for line in self.breaks.get(fname, []): + doc.MarkerAdd(line, MARKER_BREAKPOINT) + # And the current line if in this document. + if self.shownLineCurrent and fname == self.shownLineCurrent[0]: + lineNo = self.shownLineCurrent[1] + if not doc.MarkerCheck(lineNo, MARKER_CURRENT): + doc.MarkerAdd(lineNo, MARKER_CURRENT) +# if self.shownLineCallstack and fname == self.shownLineCallstack[0]: +# doc.MarkerAdd(self.shownLineCallstack[1], MARKER_CURRENT) + + def UpdateAllLineStates(self): + for doc in editor.editorTemplate.GetDocumentList(): + self.UpdateDocumentLineStates(doc) + + def ShowCurrentLine(self): + # Show the current line. Only ever 1 current line - undoes last current + # The "Current Line" is self.curframe. + # The "Callstack Line" is the top of the stack. + # If current == callstack, only show as current. + self._UnshowCurrentLine() # un-highlight the old one. + if self.curframe: + fileName = self.canonic(self.curframe.f_code.co_filename) + lineNo = self.curframe.f_lineno + self.shownLineCurrent = fileName, lineNo + self.ShowLineState(fileName, lineNo, LINESTATE_CURRENT) + + def _UnshowCurrentLine(self): + "Unshow the current line, and forget it" + if self.shownLineCurrent is not None: + fname, lineno = self.shownLineCurrent + self.ResetLineState(fname, lineno, LINESTATE_CURRENT) + self.shownLineCurrent = None + + def ShowLineNo( self, filename, lineno ): + wasOpen = editor.editorTemplate.FindOpenDocument(filename) is not None + if os.path.isfile(filename) and scriptutils.JumpToDocument(filename, lineno): + if not wasOpen: + doc = editor.editorTemplate.FindOpenDocument(filename) + if doc is not None: + self.UpdateDocumentLineStates(doc) + return 1 + return 0 + return 1 + else: + # Can't find the source file - linecache may have it? + import linecache + line = linecache.getline(filename, lineno) + print("%s(%d): %s" % (os.path.basename(filename), lineno, line[:-1].expandtabs(4))) + return 0 diff --git a/Lib/site-packages/pythonwin/pywin/debugger/fail.py b/Lib/site-packages/pythonwin/pywin/debugger/fail.py new file mode 100644 index 0000000..90c743a --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/debugger/fail.py @@ -0,0 +1,48 @@ +# NOTE NOTE - This module is designed to fail! +# +# The ONLY purpose for this script is testing/demoing the +# Pythonwin debugger package. + +# It does nothing useful, and it even doesnt do that! + +import pywin.debugger, sys, time +import traceback + +def a(): + a=1 + try: + b() + except: + # Break into the debugger with the exception information. + pywin.debugger.post_mortem(sys.exc_info()[2]) + a=1 + a=2 + a=3 + a=4 + pass + +def b(): + b=1 + pywin.debugger.set_trace() + # After importing or running this module, you are likely to be + # sitting at the next line. This is because we explicitely + # broke into the debugger using the "set_trace() function + # "pywin.debugger.brk()" is a shorter alias for this. + c() + pass + +def c(): + c=1 + d() + +def d(): + d=1 + e(d) + raise ValueError("Hi") + +def e(arg): + e=1 + time.sleep(1) + return e + +a() diff --git a/Lib/site-packages/pythonwin/pywin/default.cfg b/Lib/site-packages/pythonwin/pywin/default.cfg new file mode 100644 index 0000000..8da047e --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/default.cfg @@ -0,0 +1,215 @@ +# The default keyboard etc configuration file for Pythonwin. +# +# The format of this file is very similar to a Windows INI file. +# Sections are identified with [Section] lines, but comments +# use the standatd Python # character. Depending on the section, +# lines may not be in the standard "key=value" format. + +# NOTE: You should not need to modify this file. +# Simply create a new .CFG file, and add an entry: +# [General] +# BasedOn = Default +# +# and add your customisations. Then select your new configuration +# from the Pythonwin View/Options/Editor dialog. +# This way you get to add your own customisations, +# but still take advantage of changes to the default +# configuration in new releases. + +# See IDLE.cfg for an example extension configuration. +# +########################################################################## + +[IDLE Extensions] + +# The list of IDLE extensions to load. The extensions +# AutoIndent, AutoFormat and possibly others are +# "built-in", so do not need specifying. + +FormatParagraph +CallTips + + +[Keys] + +# The list of _default_ key definitions. +# See [Keys:Interactive] and [Keys:Editor] below for further defs. + +#Events of the format <> +# are events defined in IDLE extensions. + +Alt+Q = <> + +Ctrl+W = ViewWhitespace +Ctrl+Shift+8 = ViewWhitespace # The MSVC default key def. + +Ctrl+Shift+F = ViewFixedFont + +# Auto-complete, call-tips, etc. +Alt+/ = <> +Ctrl+Space = <> +( = <> +) = <> +Up = <> +Down = <> +Left = <> +Right = <> +. = KeyDot + +# Debugger - These are the MSVC default keys, for want of a better choice. +F9 = DbgBreakpointToggle +F5 = DbgGo +Shift+F5 = DbgClose +F11 = DbgStep +F10 = DbgStepOver +Shift+F11 = DbgStepOut + +Ctrl+F3 = AutoFindNext + + +[Keys:Editor] +# Key bindings specific to the editor +F2 = GotoNextBookmark +Ctrl+F2 = ToggleBookmark +Ctrl+G = GotoLine + +Alt+I = ShowInteractiveWindow +Alt-B = AddBanner # A sample Event defined in this file. + +# Block operations +Alt+3 = <> +Shift+Alt+3 = <> +Alt+4 = <> # IDLE default. +Alt+5 = <> +Alt+6 = <> + +# Tabs and other indent features +Back = <> +Ctrl+T = <> +Alt+U = <> +Enter = EnterKey +Tab = TabKey +Shift-Tab = <> + +# Folding +Add = FoldExpand +Alt+Add = FoldExpandAll +Shift+Add = FoldExpandSecondLevel +Subtract = FoldCollapse +Alt+Subtract = FoldCollapseAll +Shift+Subtract = FoldCollapseSecondLevel +Multiply = FoldTopLevel + +[Keys:Interactive] +# Key bindings specific to the interactive window. +# History for the interactive window +Ctrl+Up = <> +Ctrl+Down = <> +Enter = ProcessEnter +Ctrl+Enter = ProcessEnter +Shift+Enter = ProcessEnter +Esc = ProcessEsc +Alt+I = WindowBack # Toggle back to previous window. +Home = InteractiveHome # A sample Event defined in this file. +Shift+Home = InteractiveHomeExtend # A sample Event defined in this file. + +# When docked, the Ctrl+Tab and Shift+Ctrl+Tab keys dont work as expected. +Ctrl+Tab = MDINext +Ctrl+Shift+Tab = MDIPrev + +[Extensions] +# Python event handlers specific to this config file. +# All functions not starting with an "_" are assumed +# to be events, and take 2 params: +# * editor_window is the same object passed to IDLE +# extensions. editor_window.text is a text widget +# that conforms to the Tk text widget interface. +# * event is the event being fired. Will always be None +# in the current implementation. + +# Simply by defining these functions, they are available as +# events. +# Note that we bind keystrokes to these events in the various +# [Keys] sections. + +# Add a simple file/class/function simple banner +def AddBanner(editor_window, event): + + text = editor_window.text + big_line = "#" * 70 + banner = "%s\n## \n## \n## \n%s\n" % (big_line, big_line) + + # Insert at the start of the current line. + pos = text.index("insert linestart") + + text.undo_block_start() # Allow action to be undone as a single unit. + text.insert(pos, banner) + text.undo_block_stop() + + # Now set the insert point to the middle of the banner. + line, col = [int(s) for s in pos.split(".")] + text.mark_set("insert", "%d.1 lineend" % (line+2, ) ) + + +# Here is a sample event bound to the "Home" key in the +# interactive window +def InteractiveHome(editor_window, event): + return _DoInteractiveHome(editor_window.text, 0) + +def InteractiveHomeExtend(editor_window, event): + return _DoInteractiveHome(editor_window.text, 1) + +def _DoInteractiveHome(text, extend): + import sys + # If Scintilla has an autocomplete window open, then let Scintilla handle it. + if text.edit.SCIAutoCActive(): + return 1 + of_interest = "insert linestart + %d c" % len(sys.ps1) + if not text.compare("insert", "==", of_interest) and \ + text.get("insert linestart", of_interest) in [sys.ps1, sys.ps2]: # Not sys.ps? line + end = of_interest + else: + end = "insert linestart" + + if extend: start = "insert" + else: start = end + text.tag_add("sel", start, end) + +# From Niki Spahie +def AutoFindNext(editor_window, event): + "find selected text or word under cursor" + + from pywin.scintilla import find + from pywin.scintilla import scintillacon + + try: + sci = editor_window.edit + word = sci.GetSelText() + if word: + find.lastSearch.findText = word + find.lastSearch.sel = sci.GetSel() + else: + pos = sci.SendScintilla( scintillacon.SCI_GETCURRENTPOS ) + start = sci.SendScintilla( scintillacon.SCI_WORDSTARTPOSITION, pos, 1 ) + end = sci.SendScintilla( scintillacon.SCI_WORDENDPOSITION, pos, 1 ) + word = sci.GetTextRange( start, end ) + if word: + find.lastSearch.findText = word + find.lastSearch.sel = (start,end) + except Exception: + import traceback + traceback.print_exc() + find.FindNext() + + +# A couple of generic events. +def Beep(editor_window, event): + editor_window.text.beep() + +def DoNothing(editor_window, event): + pass + +def ContinueEvent(editor_window, event): + # Almost an "unbind" - allows Pythonwin/MFC to handle the keystroke + return 1 + diff --git a/Lib/site-packages/pythonwin/pywin/dialogs/__init__.py b/Lib/site-packages/pythonwin/pywin/dialogs/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Lib/site-packages/pythonwin/pywin/dialogs/ideoptions.py b/Lib/site-packages/pythonwin/pywin/dialogs/ideoptions.py new file mode 100644 index 0000000..aaf10d4 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/dialogs/ideoptions.py @@ -0,0 +1,116 @@ +# The property page to define generic IDE options for Pythonwin + +from pywin.mfc import dialog +from pywin.framework import interact +import win32ui +import win32con + +buttonControlMap = { + win32ui.IDC_BUTTON1: win32ui.IDC_EDIT1, + win32ui.IDC_BUTTON2: win32ui.IDC_EDIT2, + win32ui.IDC_BUTTON3: win32ui.IDC_EDIT3, +} + +class OptionsPropPage(dialog.PropertyPage): + def __init__(self): + dialog.PropertyPage.__init__(self, win32ui.IDD_PP_IDE) + self.AddDDX(win32ui.IDC_CHECK1, "bShowAtStartup") + self.AddDDX(win32ui.IDC_CHECK2, "bDocking") + self.AddDDX(win32ui.IDC_EDIT4, 'MRUSize', "i") + + def OnInitDialog(self): + + edit = self.GetDlgItem(win32ui.IDC_EDIT1) + format = eval(win32ui.GetProfileVal(interact.sectionProfile, interact.STYLE_INTERACTIVE_PROMPT, str(interact.formatInput))) + edit.SetDefaultCharFormat(format) + edit.SetWindowText("Input Text") + + edit = self.GetDlgItem(win32ui.IDC_EDIT2) + format = eval(win32ui.GetProfileVal(interact.sectionProfile, interact.STYLE_INTERACTIVE_OUTPUT, str(interact.formatOutput))) + edit.SetDefaultCharFormat(format) + edit.SetWindowText("Output Text") + + edit = self.GetDlgItem(win32ui.IDC_EDIT3) + format = eval(win32ui.GetProfileVal(interact.sectionProfile, interact.STYLE_INTERACTIVE_ERROR, str(interact.formatOutputError))) + edit.SetDefaultCharFormat(format) + edit.SetWindowText("Error Text") + + self['bShowAtStartup'] = interact.LoadPreference("Show at startup", 1) + self['bDocking'] = interact.LoadPreference("Docking", 0) + self['MRUSize'] = win32ui.GetProfileVal("Settings","Recent File List Size", 10) + + # Hook the button clicks. + self.HookCommand(self.HandleCharFormatChange, win32ui.IDC_BUTTON1) + self.HookCommand(self.HandleCharFormatChange, win32ui.IDC_BUTTON2) + self.HookCommand(self.HandleCharFormatChange, win32ui.IDC_BUTTON3) + + # Ensure the spin control remains in range. + spinner = self.GetDlgItem(win32ui.IDC_SPIN1) + spinner.SetRange(1, 16) + + return dialog.PropertyPage.OnInitDialog(self) + + # Called to save away the new format tuple for the specified item. + def HandleCharFormatChange(self, id, code): + if code == win32con.BN_CLICKED: + editId = buttonControlMap.get(id) + assert editId is not None, "Format button has no associated edit control" + editControl = self.GetDlgItem(editId) + existingFormat = editControl.GetDefaultCharFormat() + flags = win32con.CF_SCREENFONTS + d=win32ui.CreateFontDialog(existingFormat, flags, None, self) + if d.DoModal()==win32con.IDOK: + cf = d.GetCharFormat() + editControl.SetDefaultCharFormat(cf) + self.SetModified(1) + return 0 # We handled this fully! + + def OnOK(self): + # Handle the edit controls - get all the fonts, put them back into interact, then + # get interact to save its stuff! + controlAttrs = [ + (win32ui.IDC_EDIT1, interact.STYLE_INTERACTIVE_PROMPT), + (win32ui.IDC_EDIT2, interact.STYLE_INTERACTIVE_OUTPUT), + (win32ui.IDC_EDIT3, interact.STYLE_INTERACTIVE_ERROR)] + for id, key in controlAttrs: + control = self.GetDlgItem(id) + fmt = control.GetDefaultCharFormat() + win32ui.WriteProfileVal(interact.sectionProfile, key, str(fmt)) + + # Save the other interactive window options. + interact.SavePreference("Show at startup", self['bShowAtStartup']) + interact.SavePreference("Docking", self['bDocking']) + + # And the other options. + win32ui.WriteProfileVal("Settings","Recent File List Size", self['MRUSize']) + + return 1 + def ChangeFormat(self, fmtAttribute, fmt): + dlg = win32ui.CreateFontDialog(fmt) + if dlg.DoModal() != win32con.IDOK: return None + return dlg.GetCharFormat() + + def OnFormatTitle(self, command, code): + fmt = self.GetFormat(interact.formatTitle) + if fmt: + formatTitle = fmt + SaveFontPreferences() + + def OnFormatInput(self, command, code): + global formatInput + fmt = self.GetFormat(formatInput) + if fmt: + formatInput = fmt + SaveFontPreferences() + def OnFormatOutput(self, command, code): + global formatOutput + fmt = self.GetFormat(formatOutput) + if fmt: + formatOutput = fmt + SaveFontPreferences() + def OnFormatError(self, command, code): + global formatOutputError + fmt = self.GetFormat(formatOutputError) + if fmt: + formatOutputError = fmt + SaveFontPreferences() diff --git a/Lib/site-packages/pythonwin/pywin/dialogs/list.py b/Lib/site-packages/pythonwin/pywin/dialogs/list.py new file mode 100644 index 0000000..62d0c4c --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/dialogs/list.py @@ -0,0 +1,122 @@ +from pywin.mfc import dialog +import win32ui, win32con, commctrl, win32api + +class ListDialog (dialog.Dialog): + + def __init__ (self, title, list): + dialog.Dialog.__init__ (self, self._maketemplate(title)) + self.HookMessage (self.on_size, win32con.WM_SIZE) + self.HookNotify(self.OnListItemChange, commctrl.LVN_ITEMCHANGED) + self.HookCommand(self.OnListClick, win32ui.IDC_LIST1) + self.items = list + + def _maketemplate(self, title): + style = win32con.WS_DLGFRAME | win32con.WS_SYSMENU | win32con.WS_VISIBLE + ls = ( + win32con.WS_CHILD | + win32con.WS_VISIBLE | + commctrl.LVS_ALIGNLEFT | + commctrl.LVS_REPORT + ) + bs = ( + win32con.WS_CHILD | + win32con.WS_VISIBLE + ) + return [ [title, (0, 0, 200, 200), style, None, (8, "MS Sans Serif")], + ["SysListView32", None, win32ui.IDC_LIST1, (0, 0, 200, 200), ls], + [128, "OK", win32con.IDOK, (10, 0, 50, 14), bs | win32con.BS_DEFPUSHBUTTON], + [128, "Cancel",win32con.IDCANCEL,(0, 0, 50, 14), bs], + ] + + def FillList(self): + size = self.GetWindowRect() + width = size[2] - size[0] - (10) + itemDetails = (commctrl.LVCFMT_LEFT, width, "Item", 0) + self.itemsControl.InsertColumn(0, itemDetails) + index = 0 + for item in self.items: + index = self.itemsControl.InsertItem(index+1, str(item), 0) + + def OnListClick(self, id, code): + if code==commctrl.NM_DBLCLK: + self.EndDialog(win32con.IDOK) + return 1 + + def OnListItemChange(self,std, extra): + (hwndFrom, idFrom, code), (itemNotify, sub, newState, oldState, change, point, lparam) = std, extra + oldSel = (oldState & commctrl.LVIS_SELECTED)!=0 + newSel = (newState & commctrl.LVIS_SELECTED)!=0 + if oldSel != newSel: + try: + self.selecteditem = itemNotify + self.butOK.EnableWindow(1) + except win32ui.error: + self.selecteditem = None + + + def OnInitDialog (self): + rc = dialog.Dialog.OnInitDialog (self) + self.itemsControl = self.GetDlgItem(win32ui.IDC_LIST1) + self.butOK = self.GetDlgItem(win32con.IDOK) + self.butCancel = self.GetDlgItem(win32con.IDCANCEL) + + self.FillList() + + size = self.GetWindowRect() + self.LayoutControls(size[2]-size[0], size[3]-size[1]) + self.butOK.EnableWindow(0) # wait for first selection + return rc + + def LayoutControls(self, w, h): + self.itemsControl.MoveWindow((0,0,w,h-30)) + self.butCancel.MoveWindow((10, h-24, 60, h-4)) + self.butOK.MoveWindow((w-60, h-24, w-10, h-4)) + + def on_size (self, params): + lparam = params[3] + w = win32api.LOWORD(lparam) + h = win32api.HIWORD(lparam) + self.LayoutControls(w, h) + +class ListsDialog(ListDialog): + def __init__(self, title, list, colHeadings = ['Item']): + ListDialog.__init__(self, title, list) + self.colHeadings = colHeadings + + def FillList(self): + index = 0 + size = self.GetWindowRect() + width = size[2] - size[0] - (10) - win32api.GetSystemMetrics(win32con.SM_CXVSCROLL) + numCols = len(self.colHeadings) + + for col in self.colHeadings: + itemDetails = (commctrl.LVCFMT_LEFT, width/numCols, col, 0) + self.itemsControl.InsertColumn(index, itemDetails) + index = index + 1 + index = 0 + for items in self.items: + index = self.itemsControl.InsertItem(index+1, str(items[0]), 0) + for itemno in range(1,numCols): + item = items[itemno] + self.itemsControl.SetItemText(index, itemno, str(item)) + +def SelectFromList (title, lst): + dlg = ListDialog(title, lst) + if dlg.DoModal()==win32con.IDOK: + return dlg.selecteditem + else: + return None + +def SelectFromLists (title, lists, headings): + dlg = ListsDialog(title, lists, headings) + if dlg.DoModal()==win32con.IDOK: + return dlg.selecteditem + else: + return None + +def test(): +# print SelectFromList('Single list', [1,2,3]) + print(SelectFromLists('Multi-List', [ ('1',1, 'a'), ('2',2, 'b'), ('3',3, 'c' )], ['Col 1', 'Col 2'])) + +if __name__=='__main__': + test() diff --git a/Lib/site-packages/pythonwin/pywin/dialogs/login.py b/Lib/site-packages/pythonwin/pywin/dialogs/login.py new file mode 100644 index 0000000..a6f06f1 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/dialogs/login.py @@ -0,0 +1,121 @@ +'''login -- PythonWin user ID and password dialog box + +(Adapted from originally distributed with Mark Hammond's PythonWin - +this now replaces it!) + +login.GetLogin() displays a modal "OK/Cancel" dialog box with input +fields for a user ID and password. The password field input is masked +with *'s. GetLogin takes two optional parameters, a window title, and a +default user ID. If these parameters are omitted, the title defaults to +"Login", and the user ID is left blank. GetLogin returns a (userid, password) +tuple. GetLogin can be called from scripts running on the console - i.e. you +don't need to write a full-blown GUI app to use it. + +login.GetPassword() is similar, except there is no username field. + +Example: +import pywin.dialogs.login +title = "FTP Login" +def_user = "fred" +userid, password = pywin.dialogs.login.GetLogin(title, def_user) + +Jim Eggleston, 28 August 1996 +Merged with dlgpass and moved to pywin.dialogs by Mark Hammond Jan 1998. +''' + +import win32ui +import win32api +import win32con +from pywin.mfc import dialog + +def MakeLoginDlgTemplate(title): + style = win32con.DS_MODALFRAME | win32con.WS_POPUP | win32con.WS_VISIBLE | win32con.WS_CAPTION | win32con.WS_SYSMENU | win32con.DS_SETFONT + cs = win32con.WS_CHILD | win32con.WS_VISIBLE + + # Window frame and title + dlg = [ [title, (0, 0, 184, 40), style, None, (8, "MS Sans Serif")], ] + + # ID label and text box + dlg.append([130, "User ID:", -1, (7, 9, 69, 9), cs | win32con.SS_LEFT]) + s = cs | win32con.WS_TABSTOP | win32con.WS_BORDER + dlg.append(['EDIT', None, win32ui.IDC_EDIT1, (50, 7, 60, 12), s]) + + # Password label and text box + dlg.append([130, "Password:", -1, (7, 22, 69, 9), cs | win32con.SS_LEFT]) + s = cs | win32con.WS_TABSTOP | win32con.WS_BORDER + dlg.append(['EDIT', None, win32ui.IDC_EDIT2, (50, 20, 60, 12), s | win32con.ES_PASSWORD]) + + # OK/Cancel Buttons + s = cs | win32con.WS_TABSTOP + dlg.append([128, "OK", win32con.IDOK, (124, 5, 50, 14), s | win32con.BS_DEFPUSHBUTTON]) + s = win32con.BS_PUSHBUTTON | s + dlg.append([128, "Cancel", win32con.IDCANCEL, (124, 20, 50, 14), s]) + return dlg + +def MakePasswordDlgTemplate(title): + style = win32con.DS_MODALFRAME | win32con.WS_POPUP | win32con.WS_VISIBLE | win32con.WS_CAPTION | win32con.WS_SYSMENU | win32con.DS_SETFONT + cs = win32con.WS_CHILD | win32con.WS_VISIBLE + # Window frame and title + dlg = [ [title, (0, 0, 177, 45), style, None, (8, "MS Sans Serif")], ] + + # Password label and text box + dlg.append([130, "Password:", -1, (7, 7, 69, 9), cs | win32con.SS_LEFT]) + s = cs | win32con.WS_TABSTOP | win32con.WS_BORDER + dlg.append(['EDIT', None, win32ui.IDC_EDIT1, (50, 7, 60, 12), s | win32con.ES_PASSWORD]) + + # OK/Cancel Buttons + s = cs | win32con.WS_TABSTOP | win32con.BS_PUSHBUTTON + dlg.append([128, "OK", win32con.IDOK, (124, 5, 50, 14), s | win32con.BS_DEFPUSHBUTTON]) + dlg.append([128, "Cancel", win32con.IDCANCEL, (124, 22, 50, 14), s]) + return dlg + +class LoginDlg(dialog.Dialog): + Cancel = 0 + def __init__(self, title): + dialog.Dialog.__init__(self, MakeLoginDlgTemplate(title) ) + self.AddDDX(win32ui.IDC_EDIT1,'userid') + self.AddDDX(win32ui.IDC_EDIT2,'password') + +def GetLogin(title='Login', userid='', password=''): + d = LoginDlg(title) + d['userid'] = userid + d['password'] = password + if d.DoModal() != win32con.IDOK: + return (None, None) + else: + return (d['userid'], d['password']) + +class PasswordDlg(dialog.Dialog): + def __init__(self, title): + dialog.Dialog.__init__(self, MakePasswordDlgTemplate(title) ) + self.AddDDX(win32ui.IDC_EDIT1,'password') + +def GetPassword(title='Password', password=''): + d = PasswordDlg(title) + d['password'] = password + if d.DoModal()!=win32con.IDOK: + return None + return d['password'] + +if __name__ == "__main__": + import sys + title = 'Login' + def_user = '' + if len(sys.argv) > 1: + title = sys.argv[1] + if len(sys.argv) > 2: + def_userid = sys.argv[2] + userid, password = GetLogin(title, def_user) + if userid == password == None: + print("User pressed Cancel") + else: + print("User ID: ", userid) + print("Password:", password) + newpassword = GetPassword("Reenter just for fun", password) + if newpassword is None: + print("User cancelled") + else: + what = "" + if newpassword != password: + what = "not " + print("The passwords did %smatch" % (what)) diff --git a/Lib/site-packages/pythonwin/pywin/dialogs/status.py b/Lib/site-packages/pythonwin/pywin/dialogs/status.py new file mode 100644 index 0000000..8237b91 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/dialogs/status.py @@ -0,0 +1,227 @@ +# No cancel button. + +from pywin.mfc import dialog +from pywin.mfc.thread import WinThread +import threading +import win32ui +import win32con +import win32api +import time + +def MakeProgressDlgTemplate(caption, staticText = ""): + style = (win32con.DS_MODALFRAME | + win32con.WS_POPUP | + win32con.WS_VISIBLE | + win32con.WS_CAPTION | + win32con.WS_SYSMENU | + win32con.DS_SETFONT) + cs = (win32con.WS_CHILD | + win32con.WS_VISIBLE) + + w = 215 + h = 36 # With button + h = 40 + + dlg = [[caption, + (0, 0, w, h), + style, + None, + (8, "MS Sans Serif")], + ] + + s = win32con.WS_TABSTOP | cs + + dlg.append([130, staticText, 1000, (7, 7, w-7, h-32), cs | win32con.SS_LEFT]) + +# dlg.append([128, +# "Cancel", +# win32con.IDCANCEL, +# (w - 60, h - 18, 50, 14), s | win32con.BS_PUSHBUTTON]) + + return dlg + +class CStatusProgressDialog(dialog.Dialog): + def __init__(self, title, msg = "", maxticks = 100, tickincr = 1): + self.initMsg = msg + templ = MakeProgressDlgTemplate(title, msg) + dialog.Dialog.__init__(self, templ) + self.maxticks = maxticks + self.tickincr = tickincr + self.pbar = None + + def OnInitDialog(self): + rc = dialog.Dialog.OnInitDialog(self) + self.static = self.GetDlgItem(1000) + self.pbar = win32ui.CreateProgressCtrl() + self.pbar.CreateWindow (win32con.WS_CHILD | + win32con.WS_VISIBLE, + (10, 30, 310, 44), + self, 1001) + self.pbar.SetRange(0, self.maxticks) + self.pbar.SetStep(self.tickincr) + self.progress = 0 + self.pincr = 5 + return rc + + def Close(self): + self.EndDialog(0) + + def SetMaxTicks(self, maxticks): + if self.pbar is not None: + self.pbar.SetRange(0, maxticks) + + def Tick(self): + if self.pbar is not None: + self.pbar.StepIt() + + def SetTitle(self, text): + self.SetWindowText(text) + + def SetText(self, text): + self.SetDlgItemText(1000, text) + + def Set(self, pos, max = None): + if self.pbar is not None: + self.pbar.SetPos(pos) + if max is not None: + self.pbar.SetRange(0, max) + +# a progress dialog created in a new thread - especially suitable for +# console apps with no message loop. +MYWM_SETTITLE = win32con.WM_USER+10 +MYWM_SETMSG = win32con.WM_USER+11 +MYWM_TICK = win32con.WM_USER+12 +MYWM_SETMAXTICKS = win32con.WM_USER+13 +MYWM_SET = win32con.WM_USER+14 + +class CThreadedStatusProcessDialog(CStatusProgressDialog): + def __init__(self, title, msg = "", maxticks = 100, tickincr = 1): + self.title = title + self.msg = msg + self.threadid = win32api.GetCurrentThreadId() + CStatusProgressDialog.__init__(self, title, msg, maxticks, tickincr) + + def OnInitDialog(self): + rc = CStatusProgressDialog.OnInitDialog(self) + self.HookMessage(self.OnTitle, MYWM_SETTITLE) + self.HookMessage(self.OnMsg, MYWM_SETMSG) + self.HookMessage(self.OnTick, MYWM_TICK) + self.HookMessage(self.OnMaxTicks, MYWM_SETMAXTICKS) + self.HookMessage(self.OnSet, MYWM_SET) + return rc + + def _Send(self, msg): + try: + self.PostMessage(msg) + except win32ui.error: + # the user closed the window - but this does not cancel the + # process - so just ignore it. + pass + + def OnTitle(self, msg): + CStatusProgressDialog.SetTitle(self, self.title) + + def OnMsg(self, msg): + CStatusProgressDialog.SetText(self, self.msg) + + def OnTick(self, msg): + CStatusProgressDialog.Tick(self) + + def OnMaxTicks(self, msg): + CStatusProgressDialog.SetMaxTicks(self, self.maxticks) + + def OnSet(self, msg): + CStatusProgressDialog.Set(self, self.pos, self.max) + + def Close(self): + assert self.threadid, "No thread!" + win32api.PostThreadMessage(self.threadid, win32con.WM_QUIT, 0, 0) + + def SetMaxTicks(self, maxticks): + self.maxticks = maxticks + self._Send(MYWM_SETMAXTICKS) + def SetTitle(self, title): + self.title = title + self._Send(MYWM_SETTITLE) + def SetText(self, text): + self.msg = text + self._Send(MYWM_SETMSG) + def Tick(self): + self._Send(MYWM_TICK) + def Set(self, pos, max = None): + self.pos = pos + self.max = max + self._Send(MYWM_SET) + +class ProgressThread(WinThread): + def __init__(self, title, msg = "", maxticks = 100, tickincr = 1): + self.title = title + self.msg = msg + self.maxticks = maxticks + self.tickincr = tickincr + self.dialog = None + WinThread.__init__(self) + self.createdEvent = threading.Event() + + def InitInstance(self): + self.dialog = CThreadedStatusProcessDialog( self.title, self.msg, self.maxticks, self.tickincr) + self.dialog.CreateWindow() + try: + self.dialog.SetForegroundWindow() + except win32ui.error: + pass + self.createdEvent.set() + return WinThread.InitInstance(self) + + def ExitInstance(self): + return 0 + + +def StatusProgressDialog(title, msg = "", maxticks = 100, parent = None): + d = CStatusProgressDialog (title, msg, maxticks) + d.CreateWindow (parent) + return d + +def ThreadedStatusProgressDialog(title, msg = "", maxticks = 100): + t = ProgressThread(title, msg, maxticks) + t.CreateThread() + # Need to run a basic "PumpWaitingMessages" loop just incase we are + # running inside Pythonwin. + # Basic timeout incase things go terribly wrong. Ideally we should use + # win32event.MsgWaitForMultipleObjects(), but we use a threading module + # event - so use a dumb strategy + end_time = time.time() + 10 + while time.time() < end_time: + if t.createdEvent.isSet(): + break + win32ui.PumpWaitingMessages() + time.sleep(0.1) + return t.dialog + +def demo(): + d = StatusProgressDialog("A Demo", "Doing something...") + import win32api + for i in range(100): + if i == 50: + d.SetText("Getting there...") + if i==90: + d.SetText("Nearly done...") + win32api.Sleep(20) + d.Tick() + d.Close() + +def thread_demo(): + d = ThreadedStatusProgressDialog("A threaded demo", "Doing something") + import win32api + for i in range(100): + if i == 50: + d.SetText("Getting there...") + if i==90: + d.SetText("Nearly done...") + win32api.Sleep(20) + d.Tick() + d.Close() + +if __name__=='__main__': + thread_demo() + #demo() diff --git a/Lib/site-packages/pythonwin/pywin/docking/DockingBar.py b/Lib/site-packages/pythonwin/pywin/docking/DockingBar.py new file mode 100644 index 0000000..5a3492c --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/docking/DockingBar.py @@ -0,0 +1,541 @@ +# DockingBar.py + +# Ported directly (comments and all) from the samples at www.codeguru.com + +# WARNING: Use at your own risk, as this interface is highly likely to change. +# Currently we support only one child per DockingBar. Later we need to add +# support for multiple children. + +import win32api, win32con, win32ui +from pywin.mfc import afxres, window +import struct + +clrBtnHilight = win32api.GetSysColor(win32con.COLOR_BTNHILIGHT) +clrBtnShadow = win32api.GetSysColor(win32con.COLOR_BTNSHADOW) + +def CenterPoint(rect): + width = rect[2]-rect[0] + height = rect[3]-rect[1] + return rect[0] + width//2, rect[1] + height//2 + +def OffsetRect(rect, point): + (x, y) = point + return rect[0]+x, rect[1]+y, rect[2]+x, rect[3]+y + +def DeflateRect(rect, point): + (x, y) = point + return rect[0]+x, rect[1]+y, rect[2]-x, rect[3]-y + +def PtInRect(rect, pt): + return rect[0] <= pt[0] < rect[2] and rect[1] <= pt[1] < rect[3] + +class DockingBar(window.Wnd): + def __init__(self, obj=None): + if obj is None: + obj = win32ui.CreateControlBar() + window.Wnd.__init__(self, obj) + self.dialog = None + self.nDockBarID = 0 + self.sizeMin = 32, 32 + self.sizeHorz = 200, 200 + self.sizeVert = 200, 200 + self.sizeFloat = 200, 200 + self.bTracking = 0 + self.bInRecalcNC = 0 + self.cxEdge = 6 + self.cxBorder = 3 + self.cxGripper = 20 + self.brushBkgd = win32ui.CreateBrush() + self.brushBkgd.CreateSolidBrush(win32api.GetSysColor(win32con.COLOR_BTNFACE)) + + # Support for diagonal resizing + self.cyBorder = 3 + self.cCaptionSize = win32api.GetSystemMetrics(win32con.SM_CYSMCAPTION) + self.cMinWidth = win32api.GetSystemMetrics(win32con.SM_CXMIN) + self.cMinHeight = win32api.GetSystemMetrics(win32con.SM_CYMIN) + self.rectUndock = (0,0,0,0) + + def OnUpdateCmdUI(self, target, bDisableIfNoHndler): + return self.UpdateDialogControls(target, bDisableIfNoHndler) + + def CreateWindow(self, parent, childCreator, title, id, style=win32con.WS_CHILD | win32con.WS_VISIBLE | afxres.CBRS_LEFT, childCreatorArgs=()): + assert not ((style & afxres.CBRS_SIZE_FIXED) and (style & afxres.CBRS_SIZE_DYNAMIC)), "Invalid style" + self.rectClose = self.rectBorder = self.rectGripper = self.rectTracker = 0,0,0,0 + + # save the style + self._obj_.dwStyle = style & afxres.CBRS_ALL + + cursor = win32api.LoadCursor(0, win32con.IDC_ARROW) + wndClass = win32ui.RegisterWndClass(win32con.CS_DBLCLKS, cursor, self.brushBkgd.GetSafeHandle(), 0) + + self._obj_.CreateWindow(wndClass, title, style, (0,0,0,0), parent, id) + + # Create the child dialog + self.dialog = childCreator(*(self,) + childCreatorArgs) + + # use the dialog dimensions as default base dimensions + assert self.dialog.IsWindow(), "The childCreator function %s did not create a window!" % childCreator + rect = self.dialog.GetWindowRect() + self.sizeHorz = self.sizeVert = self.sizeFloat = rect[2]-rect[0], rect[3]-rect[1] + + self.sizeHorz = self.sizeHorz[0], self.sizeHorz[1] + self.cxEdge + self.cxBorder + self.sizeVert = self.sizeVert[0] + self.cxEdge + self.cxBorder, self.sizeVert[1] + self.HookMessages() + + def CalcFixedLayout(self, bStretch, bHorz): + rectTop = self.dockSite.GetControlBar(afxres.AFX_IDW_DOCKBAR_TOP).GetWindowRect() + rectLeft = self.dockSite.GetControlBar(afxres.AFX_IDW_DOCKBAR_LEFT).GetWindowRect() + if bStretch: + nHorzDockBarWidth = 32767 + nVertDockBarHeight = 32767 + else: + nHorzDockBarWidth = rectTop[2]-rectTop[0] + 4 + nVertDockBarHeight = rectLeft[3]-rectLeft[1] + 4 + + if self.IsFloating(): + return self.sizeFloat + if bHorz: + return nHorzDockBarWidth, self.sizeHorz[1] + return self.sizeVert[0], nVertDockBarHeight + + def CalcDynamicLayout(self, length, mode): + # Support for diagonal sizing. + if self.IsFloating(): + self.GetParent().GetParent().ModifyStyle(win32ui.MFS_4THICKFRAME, 0) + if mode & (win32ui.LM_HORZDOCK | win32ui.LM_VERTDOCK): + flags = win32con.SWP_NOSIZE | win32con.SWP_NOMOVE | win32con.SWP_NOZORDER |\ + win32con.SWP_NOACTIVATE | win32con.SWP_FRAMECHANGED + self.SetWindowPos(0, (0, 0, 0, 0,), flags) + self.dockSite.RecalcLayout() + return self._obj_.CalcDynamicLayout(length, mode) + + if mode & win32ui.LM_MRUWIDTH: + return self.sizeFloat + if mode & win32ui.LM_COMMIT: + self.sizeFloat = length, self.sizeFloat[1] + return self.sizeFloat + # More diagonal sizing. + if self.IsFloating(): + dc = self.dockContext + pt = win32api.GetCursorPos() + windowRect = self.GetParent().GetParent().GetWindowRect() + + hittest = dc.nHitTest + if hittest==win32con.HTTOPLEFT: + cx = max(windowRect[2] - pt[0], self.cMinWidth) - self.cxBorder + cy = max(windowRect[3] - self.cCaptionSize - pt[1],self.cMinHeight) - 1 + self.sizeFloat = cx, cy + + top = min(pt[1], windowRect[3] - self.cCaptionSize - self.cMinHeight) - self.cyBorder + left = min(pt[0], windowRect[2] - self.cMinWidth) - 1 + dc.rectFrameDragHorz = left, top, dc.rectFrameDragHorz[2], dc.rectFrameDragHorz[3] + return self.sizeFloat + if hittest==win32con.HTTOPRIGHT: + cx = max(pt[0] - windowRect[0], self.cMinWidth) + cy = max(windowRect[3] - self.cCaptionSize - pt[1], self.cMinHeight) - 1 + self.sizeFloat = cx, cy + + top = min(pt[1], windowRect[3] - self.cCaptionSize - self.cMinHeight) - self.cyBorder + dc.rectFrameDragHorz = dc.rectFrameDragHorz[0], top, dc.rectFrameDragHorz[2], dc.rectFrameDragHorz[3] + return self.sizeFloat + + if hittest==win32con.HTBOTTOMLEFT: + cx = max(windowRect[2] - pt[0], self.cMinWidth) - self.cxBorder + cy = max(pt[1] - windowRect[1] - self.cCaptionSize, self.cMinHeight) + self.sizeFloat = cx, cy + + left = min(pt[0], windowRect[2] -self.cMinWidth) - 1 + dc.rectFrameDragHorz = left, dc.rectFrameDragHorz[1], dc.rectFrameDragHorz[2], dc.rectFrameDragHorz[3] + return self.sizeFloat + + if hittest==win32con.HTBOTTOMRIGHT: + cx = max(pt[0] - windowRect[0], self.cMinWidth) + cy = max(pt[1] - windowRect[1] - self.cCaptionSize, self.cMinHeight) + self.sizeFloat = cx, cy + return self.sizeFloat + + if mode & win32ui.LM_LENGTHY: + self.sizeFloat = self.sizeFloat[0], max(self.sizeMin[1], length) + return self.sizeFloat + else: + return max(self.sizeMin[0], length), self.sizeFloat[1] + + def OnWindowPosChanged(self, msg): + if self.GetSafeHwnd()==0 or self.dialog is None: + return 0 + lparam = msg[3] + """ LPARAM used with WM_WINDOWPOSCHANGED: + typedef struct { + HWND hwnd; + HWND hwndInsertAfter; + int x; + int y; + int cx; + int cy; + UINT flags;} WINDOWPOS; + """ + format = "PPiiiii" + bytes = win32ui.GetBytes( lparam, struct.calcsize(format) ) + hwnd, hwndAfter, x, y, cx, cy, flags = struct.unpack(format, bytes) + + if self.bInRecalcNC: + rc = self.GetClientRect() + self.dialog.MoveWindow(rc) + return 0 + # Find on which side are we docked + nDockBarID = self.GetParent().GetDlgCtrlID() + # Return if dropped at same location + # no docking side change and no size change + if (nDockBarID == self.nDockBarID) and \ + (flags & win32con.SWP_NOSIZE) and \ + ((self._obj_.dwStyle & afxres.CBRS_BORDER_ANY) != afxres.CBRS_BORDER_ANY): + return + self.nDockBarID = nDockBarID + + # Force recalc the non-client area + self.bInRecalcNC = 1 + try: + swpflags = win32con.SWP_NOSIZE | win32con.SWP_NOMOVE | win32con.SWP_NOZORDER | win32con.SWP_FRAMECHANGED + self.SetWindowPos(0, (0,0,0,0), swpflags) + finally: + self.bInRecalcNC = 0 + return 0 + + # This is a virtual and not a message hook. + def OnSetCursor(self, window, nHitTest, wMouseMsg): + if nHitTest != win32con.HTSIZE or self.bTracking: + return self._obj_.OnSetCursor(window, nHitTest, wMouseMsg) + + if self.IsHorz(): + win32api.SetCursor(win32api.LoadCursor(0, win32con.IDC_SIZENS)) + else: + win32api.SetCursor(win32api.LoadCursor(0, win32con.IDC_SIZEWE)) + return 1 + + # Mouse Handling + def OnLButtonUp(self, msg): + if not self.bTracking: + return 1 # pass it on. + self.StopTracking(1) + return 0 # Dont pass on + + def OnLButtonDown(self, msg): + # UINT nFlags, CPoint point) + # only start dragging if clicked in "void" space + if self.dockBar is not None: + # start the drag + pt = msg[5] + pt = self.ClientToScreen(pt) + self.dockContext.StartDrag(pt) + return 0 + return 1 + + def OnNcLButtonDown(self, msg): + if self.bTracking: return 0 + nHitTest = wparam = msg[2] + pt = msg[5] + + if nHitTest==win32con.HTSYSMENU and not self.IsFloating(): + self.GetDockingFrame().ShowControlBar(self, 0, 0) + elif nHitTest == win32con.HTMINBUTTON and not self.IsFloating(): + self.dockContext.ToggleDocking() + elif nHitTest == win32con.HTCAPTION and not self.IsFloating() and self.dockBar is not None: + self.dockContext.StartDrag(pt) + elif nHitTest == win32con.HTSIZE and not self.IsFloating(): + self.StartTracking() + else: + return 1 + return 0 + + def OnLButtonDblClk(self, msg): + # only toggle docking if clicked in "void" space + if self.dockBar is not None: + # toggle docking + self.dockContext.ToggleDocking() + return 0 + return 1 + + def OnNcLButtonDblClk(self, msg): + nHitTest = wparam = msg[2] + # UINT nHitTest, CPoint point) + if self.dockBar is not None and nHitTest == win32con.HTCAPTION: + # toggle docking + self.dockContext.ToggleDocking() + return 0 + return 1 + + def OnMouseMove(self, msg): + flags = wparam = msg[2] + lparam = msg[3] + if self.IsFloating() or not self.bTracking: + return 1 + + # Convert unsigned 16 bit to signed 32 bit. + x=win32api.LOWORD(lparam) + if x & 32768: x = x | -65536 + y = win32api.HIWORD(lparam) + if y & 32768: y = y | -65536 + pt = x, y + cpt = CenterPoint(self.rectTracker) + pt = self.ClientToWnd(pt) + if self.IsHorz(): + if cpt[1] != pt[1]: + self.OnInvertTracker(self.rectTracker) + self.rectTracker = OffsetRect(self.rectTracker, (0, pt[1] - cpt[1])) + self.OnInvertTracker(self.rectTracker) + else: + if cpt[0] != pt[0]: + self.OnInvertTracker(self.rectTracker) + self.rectTracker = OffsetRect(self.rectTracker, (pt[0]-cpt[0], 0)) + self.OnInvertTracker(self.rectTracker) + + return 0 # Dont pass it on. + +# def OnBarStyleChange(self, old, new): + + def OnNcCalcSize(self, bCalcValid, size_info): + (rc0, rc1, rc2, pos) = size_info + self.rectBorder = self.GetWindowRect() + self.rectBorder = OffsetRect( self.rectBorder, (-self.rectBorder[0], -self.rectBorder[1]) ) + + dwBorderStyle = self._obj_.dwStyle | afxres.CBRS_BORDER_ANY + + if self.nDockBarID==afxres.AFX_IDW_DOCKBAR_TOP: + dwBorderStyle = dwBorderStyle & ~afxres.CBRS_BORDER_BOTTOM; + rc0.left = rc0.left + self.cxGripper + rc0.bottom = rc0.bottom-self.cxEdge + rc0.top = rc0.top + self.cxBorder + rc0.right = rc0.right - self.cxBorder + self.rectBorder = self.rectBorder[0], self.rectBorder[3]-self.cxEdge, self.rectBorder[2], self.rectBorder[3] + elif self.nDockBarID==afxres.AFX_IDW_DOCKBAR_BOTTOM: + dwBorderStyle = dwBorderStyle & ~afxres.CBRS_BORDER_TOP + rc0.left = rc0.left + self.cxGripper + rc0.top = rc0.top + self.cxEdge + rc0.bottom = rc0.bottom - self.cxBorder + rc0.right = rc0.right - self.cxBorder + self.rectBorder = self.rectBorder[0], self.rectBorder[1], self.rectBorder[2], self.rectBorder[1]+self.cxEdge + elif self.nDockBarID==afxres.AFX_IDW_DOCKBAR_LEFT: + dwBorderStyle = dwBorderStyle & ~afxres.CBRS_BORDER_RIGHT + rc0.right = rc0.right - self.cxEdge + rc0.left = rc0.left + self.cxBorder + rc0.bottom = rc0.bottom - self.cxBorder + rc0.top = rc0.top + self.cxGripper + self.rectBorder = self.rectBorder[2] - self.cxEdge, self.rectBorder[1], self.rectBorder[2], self.rectBorder[3] + elif self.nDockBarID==afxres.AFX_IDW_DOCKBAR_RIGHT: + dwBorderStyle = dwBorderStyle & ~afxres.CBRS_BORDER_LEFT + rc0.left = rc0.left + self.cxEdge + rc0.right = rc0.right - self.cxBorder + rc0.bottom = rc0.bottom - self.cxBorder + rc0.top = rc0.top + self.cxGripper + self.rectBorder = self.rectBorder[0], self.rectBorder[1], self.rectBorder[0]+self.cxEdge, self.rectBorder[3] + else: + self.rectBorder = 0,0,0,0 + + self.SetBarStyle(dwBorderStyle) + return 0 + + def OnNcPaint(self, msg): + self.EraseNonClient() + dc = self.GetWindowDC() + ctl = win32api.GetSysColor(win32con.COLOR_BTNHIGHLIGHT) + cbr = win32api.GetSysColor(win32con.COLOR_BTNSHADOW) + dc.Draw3dRect(self.rectBorder, ctl, cbr) + + self.DrawGripper(dc) + + rect = self.GetClientRect() + self.InvalidateRect( rect, 1) + return 0 + + def OnNcHitTest(self, pt): # A virtual, not a hooked message. + if self.IsFloating(): + return 1 + + ptOrig = pt + rect = self.GetWindowRect() + pt = pt[0] - rect[0], pt[1] - rect[1] + + if PtInRect(self.rectClose, pt): + return win32con.HTSYSMENU + elif PtInRect(self.rectUndock, pt): + return win32con.HTMINBUTTON + elif PtInRect(self.rectGripper, pt): + return win32con.HTCAPTION + elif PtInRect(self.rectBorder, pt): + return win32con.HTSIZE + else: + return self._obj_.OnNcHitTest(ptOrig) + + def StartTracking(self): + self.SetCapture() + + # make sure no updates are pending + self.RedrawWindow(None, None, win32con.RDW_ALLCHILDREN | win32con.RDW_UPDATENOW) + self.dockSite.LockWindowUpdate() + + self.ptOld = CenterPoint(self.rectBorder) + self.bTracking = 1 + + self.rectTracker = self.rectBorder; + if not self.IsHorz(): + l, t, r, b = self.rectTracker + b = b - 4 + self.rectTracker = l, t, r, b + + self.OnInvertTracker(self.rectTracker); + + def OnCaptureChanged(self, msg): + hwnd = lparam = msg[3] + if self.bTracking and hwnd != self.GetSafeHwnd(): + self.StopTracking(0) # cancel tracking + return 1 + + def StopTracking(self, bAccept): + self.OnInvertTracker(self.rectTracker) + self.dockSite.UnlockWindowUpdate() + self.bTracking = 0 + self.ReleaseCapture() + if not bAccept: return + + rcc = self.dockSite.GetWindowRect() + if self.IsHorz(): + newsize = self.sizeHorz[1] + maxsize = newsize + (rcc[3]-rcc[1]) + minsize = self.sizeMin[1] + else: + newsize = self.sizeVert[0] + maxsize = newsize + (rcc[2]-rcc[0]) + minsize = self.sizeMin[0] + + pt = CenterPoint(self.rectTracker) + if self.nDockBarID== afxres.AFX_IDW_DOCKBAR_TOP: + newsize = newsize + (pt[1] - self.ptOld[1]) + elif self.nDockBarID== afxres.AFX_IDW_DOCKBAR_BOTTOM: + newsize = newsize + (- pt[1] + self.ptOld[1]) + elif self.nDockBarID== afxres.AFX_IDW_DOCKBAR_LEFT: + newsize = newsize + (pt[0] - self.ptOld[0]) + elif self.nDockBarID== afxres.AFX_IDW_DOCKBAR_RIGHT: + newsize = newsize + (- pt[0] + self.ptOld[0]) + newsize = max(minsize, min(maxsize, newsize)) + if self.IsHorz(): + self.sizeHorz = self.sizeHorz[0], newsize + else: + self.sizeVert = newsize, self.sizeVert[1] + self.dockSite.RecalcLayout() + return 0 + + def OnInvertTracker(self, rect): + assert rect[2]-rect[0]>0 and rect[3]-rect[1]>0, "rect is empty" + assert self.bTracking + rcc = self.GetWindowRect() + rcf = self.dockSite.GetWindowRect() + + rect = OffsetRect(rect, (rcc[0] - rcf[0], rcc[1] - rcf[1])) + rect = DeflateRect(rect, (1, 1)); + + flags = win32con.DCX_WINDOW|win32con.DCX_CACHE|win32con.DCX_LOCKWINDOWUPDATE + dc = self.dockSite.GetDCEx(None, flags) + try: + brush = win32ui.GetHalftoneBrush() + oldBrush = dc.SelectObject(brush) + + dc.PatBlt((rect[0], rect[1]), (rect[2]-rect[0], rect[3]-rect[1]), win32con.PATINVERT) + dc.SelectObject(oldBrush) + finally: + self.dockSite.ReleaseDC(dc) + + def IsHorz(self): + return self.nDockBarID == afxres.AFX_IDW_DOCKBAR_TOP or \ + self.nDockBarID == afxres.AFX_IDW_DOCKBAR_BOTTOM + + def ClientToWnd(self, pt): + x, y=pt + if self.nDockBarID == afxres.AFX_IDW_DOCKBAR_BOTTOM: + y = y + self.cxEdge + elif self.nDockBarID == afxres.AFX_IDW_DOCKBAR_RIGHT: + x = x + self.cxEdge + return x,y + + def DrawGripper(self, dc): + # no gripper if floating + if self._obj_.dwStyle & afxres.CBRS_FLOATING: + return + + # -==HACK==- + # in order to calculate the client area properly after docking, + # the client area must be recalculated twice (I have no idea why) + self.dockSite.RecalcLayout() + # -==END HACK==- + + gripper = self.GetWindowRect() + gripper = self.ScreenToClient( gripper ) + gripper = OffsetRect( gripper, (-gripper[0], -gripper[1]) ) + gl, gt, gr, gb = gripper + + if self._obj_.dwStyle & afxres.CBRS_ORIENT_HORZ: + # gripper at left + self.rectGripper = gl, gt + 40, gl+20, gb + # draw close box + self.rectClose = gl+7, gt + 10, gl+19, gt+22 + dc.DrawFrameControl(self.rectClose, win32con.DFC_CAPTION, win32con.DFCS_CAPTIONCLOSE) + # draw docking toggle box + self.rectUndock = OffsetRect(self.rectClose, (0,13)) + dc.DrawFrameControl(self.rectUndock, win32con.DFC_CAPTION, win32con.DFCS_CAPTIONMAX); + + gt = gt + 38 + gb = gb - 10 + gl = gl + 10 + gr = gl + 3 + gripper = gl, gt, gr, gb + dc.Draw3dRect( gripper, clrBtnHilight, clrBtnShadow ) + dc.Draw3dRect( OffsetRect(gripper, (4,0)), clrBtnHilight, clrBtnShadow ) + else: + # gripper at top + self.rectGripper = gl, gt, gr-40, gt+20 + # draw close box + self.rectClose = gr-21, gt+7, gr-10, gt+18 + dc.DrawFrameControl(self.rectClose, win32con.DFC_CAPTION, win32con.DFCS_CAPTIONCLOSE) + # draw docking toggle box + self.rectUndock = OffsetRect( self.rectClose, (-13,0) ) + dc.DrawFrameControl(self.rectUndock, win32con.DFC_CAPTION, win32con.DFCS_CAPTIONMAX) + gr = gr - 38; + gl = gl + 10 + gt = gt + 10 + gb = gt + 3 + + gripper = gl, gt, gr, gb + dc.Draw3dRect( gripper, clrBtnHilight, clrBtnShadow ) + dc.Draw3dRect( OffsetRect(gripper, (0,4) ), clrBtnHilight, clrBtnShadow ) + + def HookMessages(self): + self.HookMessage(self.OnLButtonUp, win32con.WM_LBUTTONUP) + self.HookMessage(self.OnLButtonDown, win32con.WM_LBUTTONDOWN) + self.HookMessage(self.OnLButtonDblClk, win32con.WM_LBUTTONDBLCLK) + self.HookMessage(self.OnNcLButtonDown, win32con.WM_NCLBUTTONDOWN) + self.HookMessage(self.OnNcLButtonDblClk, win32con.WM_NCLBUTTONDBLCLK) + self.HookMessage(self.OnMouseMove, win32con.WM_MOUSEMOVE) + self.HookMessage(self.OnNcPaint, win32con.WM_NCPAINT) + self.HookMessage(self.OnCaptureChanged, win32con.WM_CAPTURECHANGED) + self.HookMessage(self.OnWindowPosChanged, win32con.WM_WINDOWPOSCHANGED) +# self.HookMessage(self.OnSize, win32con.WM_SIZE) + +def EditCreator(parent): + d = win32ui.CreateEdit() + es = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_BORDER | win32con.ES_MULTILINE | win32con.ES_WANTRETURN + d.CreateWindow( es, (0,0,150,150), parent, 1000) + return d + +def test(): + import pywin.mfc.dialog + global bar + bar = DockingBar() + creator = EditCreator + bar.CreateWindow(win32ui.GetMainFrame(), creator, "Coolbar Demo",0xfffff) +# win32ui.GetMainFrame().ShowControlBar(bar, 1, 0) + bar.SetBarStyle( bar.GetBarStyle()|afxres.CBRS_TOOLTIPS|afxres.CBRS_FLYBY|afxres.CBRS_SIZE_DYNAMIC) + bar.EnableDocking(afxres.CBRS_ALIGN_ANY) + win32ui.GetMainFrame().DockControlBar(bar, afxres.AFX_IDW_DOCKBAR_BOTTOM) + + +if __name__=='__main__': + test() diff --git a/Lib/site-packages/pythonwin/pywin/docking/__init__.py b/Lib/site-packages/pythonwin/pywin/docking/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Lib/site-packages/pythonwin/pywin/framework/__init__.py b/Lib/site-packages/pythonwin/pywin/framework/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Lib/site-packages/pythonwin/pywin/framework/app.py b/Lib/site-packages/pythonwin/pywin/framework/app.py new file mode 100644 index 0000000..8bc02fd --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/app.py @@ -0,0 +1,408 @@ +# App.py +# Application stuff. +# The application is responsible for managing the main frame window. +# +# We also grab the FileOpen command, to invoke our Python editor +" The PythonWin application code. Manages most aspects of MDI, etc " +import win32con +import win32api +import win32ui +import sys +import string +import os +from pywin.mfc import window, dialog, afxres +from pywin.mfc.thread import WinApp +import traceback +import regutil + +from . import scriptutils + +## NOTE: App and AppBuild should NOT be used - instead, you should contruct your +## APP class manually whenever you like (just ensure you leave these 2 params None!) +## Whoever wants the generic "Application" should get it via win32iu.GetApp() + +# These are "legacy" +AppBuilder = None +App = None # default - if used, must end up a CApp derived class. + +# Helpers that should one day be removed! +def AddIdleHandler(handler): + print("app.AddIdleHandler is deprecated - please use win32ui.GetApp().AddIdleHandler() instead.") + return win32ui.GetApp().AddIdleHandler(handler) +def DeleteIdleHandler(handler): + print("app.DeleteIdleHandler is deprecated - please use win32ui.GetApp().DeleteIdleHandler() instead.") + return win32ui.GetApp().DeleteIdleHandler(handler) + +# Helper for writing a Window position by name, and later loading it. +def SaveWindowSize(section,rect,state=""): + """ Writes a rectangle to an INI file + Args: section = section name in the applications INI file + rect = a rectangle in a (cy, cx, y, x) tuple + (same format as CREATESTRUCT position tuples).""" + left, top, right, bottom = rect + if state: state = state + " " + win32ui.WriteProfileVal(section,state+"left",left) + win32ui.WriteProfileVal(section,state+"top",top) + win32ui.WriteProfileVal(section,state+"right",right) + win32ui.WriteProfileVal(section,state+"bottom",bottom) + +def LoadWindowSize(section, state=""): + """ Loads a section from an INI file, and returns a rect in a tuple (see SaveWindowSize)""" + if state: state = state + " " + left = win32ui.GetProfileVal(section,state+"left",0) + top = win32ui.GetProfileVal(section,state+"top",0) + right = win32ui.GetProfileVal(section,state+"right",0) + bottom = win32ui.GetProfileVal(section,state+"bottom",0) + return (left, top, right, bottom) + +def RectToCreateStructRect(rect): + return (rect[3]-rect[1], rect[2]-rect[0], rect[1], rect[0] ) + + +# Define FrameWindow and Application objects +# +# The Main Frame of the application. +class MainFrame(window.MDIFrameWnd): + sectionPos = "Main Window" + statusBarIndicators = ( afxres.ID_SEPARATOR, #// status line indicator + afxres.ID_INDICATOR_CAPS, + afxres.ID_INDICATOR_NUM, + afxres.ID_INDICATOR_SCRL, + win32ui.ID_INDICATOR_LINENUM, + win32ui.ID_INDICATOR_COLNUM ) + + def OnCreate(self, cs): + self._CreateStatusBar() + return 0 + + def _CreateStatusBar(self): + self.statusBar = win32ui.CreateStatusBar(self) + self.statusBar.SetIndicators(self.statusBarIndicators) + self.HookCommandUpdate(self.OnUpdatePosIndicator, win32ui.ID_INDICATOR_LINENUM) + self.HookCommandUpdate(self.OnUpdatePosIndicator, win32ui.ID_INDICATOR_COLNUM) + + def OnUpdatePosIndicator(self, cmdui): + editControl = scriptutils.GetActiveEditControl() + value = " " * 5 + if editControl is not None: + try: + startChar, endChar = editControl.GetSel() + lineNo = editControl.LineFromChar(startChar) + colNo = endChar - editControl.LineIndex(lineNo) + + if cmdui.m_nID==win32ui.ID_INDICATOR_LINENUM: + value = "%0*d" % (5, lineNo + 1) + else: + value = "%0*d" % (3, colNo + 1) + except win32ui.error: + pass + cmdui.SetText(value) + cmdui.Enable() + + def PreCreateWindow(self, cc): + cc = self._obj_.PreCreateWindow(cc) + pos = LoadWindowSize(self.sectionPos) + self.startRect = pos + if pos[2] - pos[0]: + rect = RectToCreateStructRect(pos) + cc = cc[0], cc[1], cc[2], cc[3], rect, cc[5], cc[6], cc[7], cc[8] + return cc + + def OnDestroy(self, msg): + # use GetWindowPlacement(), as it works even when min'd or max'd + rectNow = self.GetWindowPlacement()[4] + if rectNow != self.startRect: + SaveWindowSize(self.sectionPos, rectNow) + return 0 + +class CApp(WinApp): + " A class for the application " + def __init__(self): + self.oldCallbackCaller = None + WinApp.__init__(self, win32ui.GetApp() ) + self.idleHandlers = [] + + def InitInstance(self): + " Called to crank up the app " + HookInput() + numMRU = win32ui.GetProfileVal("Settings","Recent File List Size", 10) + win32ui.LoadStdProfileSettings(numMRU) +# self._obj_.InitMDIInstance() + if win32api.GetVersionEx()[0]<4: + win32ui.SetDialogBkColor() + win32ui.Enable3dControls() + + # install a "callback caller" - a manager for the callbacks +# self.oldCallbackCaller = win32ui.InstallCallbackCaller(self.CallbackManager) + self.LoadMainFrame() + self.SetApplicationPaths() + + def ExitInstance(self): + " Called as the app dies - too late to prevent it here! " + win32ui.OutputDebug("Application shutdown\n") + # Restore the callback manager, if any. + try: + win32ui.InstallCallbackCaller(self.oldCallbackCaller) + except AttributeError: + pass + if self.oldCallbackCaller: + del self.oldCallbackCaller + self.frame=None # clean Python references to the now destroyed window object. + self.idleHandlers = [] + # Attempt cleanup if not already done! + if self._obj_: self._obj_.AttachObject(None) + self._obj_ = None + global App + global AppBuilder + App = None + AppBuilder = None + return 0 + + def HaveIdleHandler(self, handler): + return handler in self.idleHandlers + def AddIdleHandler(self, handler): + self.idleHandlers.append(handler) + def DeleteIdleHandler(self, handler): + self.idleHandlers.remove(handler) + def OnIdle(self, count): + try: + ret = 0 + handlers = self.idleHandlers[:] # copy list, as may be modified during loop + for handler in handlers: + try: + thisRet = handler(handler, count) + except: + print("Idle handler %s failed" % (repr(handler))) + traceback.print_exc() + print("Idle handler removed from list") + try: + self.DeleteIdleHandler(handler) + except ValueError: # Item not in list. + pass + thisRet = 0 + ret = ret or thisRet + return ret + except KeyboardInterrupt: + pass + def CreateMainFrame(self): + return MainFrame() + + def LoadMainFrame(self): + " Create the main applications frame " + self.frame = self.CreateMainFrame() + self.SetMainFrame(self.frame) + self.frame.LoadFrame(win32ui.IDR_MAINFRAME, win32con.WS_OVERLAPPEDWINDOW) + self.frame.DragAcceptFiles() # we can accept these. + self.frame.ShowWindow(win32ui.GetInitialStateRequest()) + self.frame.UpdateWindow() + self.HookCommands() + + def OnHelp(self,id, code): + try: + if id==win32ui.ID_HELP_GUI_REF: + helpFile = regutil.GetRegisteredHelpFile("Pythonwin Reference") + helpCmd = win32con.HELP_CONTENTS + else: + helpFile = regutil.GetRegisteredHelpFile("Main Python Documentation") + helpCmd = win32con.HELP_FINDER + if helpFile is None: + win32ui.MessageBox("The help file is not registered!") + else: + from . import help + help.OpenHelpFile(helpFile, helpCmd) + except: + t, v, tb = sys.exc_info() + win32ui.MessageBox("Internal error in help file processing\r\n%s: %s" % (t,v)) + tb = None # Prevent a cycle + + def DoLoadModules(self, modules): + # XXX - this should go, but the debugger uses it :-( + # dont do much checking! + for module in modules: + __import__(module) + + def HookCommands(self): + self.frame.HookMessage(self.OnDropFiles,win32con.WM_DROPFILES) + self.HookCommand(self.HandleOnFileOpen,win32ui.ID_FILE_OPEN) + self.HookCommand(self.HandleOnFileNew,win32ui.ID_FILE_NEW) + self.HookCommand(self.OnFileMRU,win32ui.ID_FILE_MRU_FILE1) + self.HookCommand(self.OnHelpAbout,win32ui.ID_APP_ABOUT) + self.HookCommand(self.OnHelp, win32ui.ID_HELP_PYTHON) + self.HookCommand(self.OnHelp, win32ui.ID_HELP_GUI_REF) + # Hook for the right-click menu. + self.frame.GetWindow(win32con.GW_CHILD).HookMessage(self.OnRClick,win32con.WM_RBUTTONDOWN) + + def SetApplicationPaths(self): + # Load the users/application paths + new_path = [] + apppath=win32ui.GetProfileVal('Python','Application Path','').split(';') + for path in apppath: + if len(path)>0: + new_path.append(win32ui.FullPath(path)) + for extra_num in range(1,11): + apppath=win32ui.GetProfileVal('Python','Application Path %d'%extra_num,'').split(';') + if len(apppath) == 0: + break + for path in apppath: + if len(path)>0: + new_path.append(win32ui.FullPath(path)) + sys.path = new_path + sys.path + + def OnRClick(self,params): + " Handle right click message " + # put up the entire FILE menu! + menu = win32ui.LoadMenu(win32ui.IDR_TEXTTYPE).GetSubMenu(0) + menu.TrackPopupMenu(params[5]) # track at mouse position. + return 0 + + def OnDropFiles(self,msg): + " Handle a file being dropped from file manager " + hDropInfo = msg[2] + self.frame.SetActiveWindow() # active us + nFiles = win32api.DragQueryFile(hDropInfo) + try: + for iFile in range(0,nFiles): + fileName = win32api.DragQueryFile(hDropInfo, iFile) + win32ui.GetApp().OpenDocumentFile( fileName ) + finally: + win32api.DragFinish(hDropInfo); + + return 0 + +# No longer used by Pythonwin, as the C++ code has this same basic functionality +# but handles errors slightly better. +# It all still works, tho, so if you need similar functionality, you can use it. +# Therefore I havent deleted this code completely! +# def CallbackManager( self, ob, args = () ): +# """Manage win32 callbacks. Trap exceptions, report on them, then return 'All OK' +# to the frame-work. """ +# import traceback +# try: +# ret = apply(ob, args) +# return ret +# except: +# # take copies of the exception values, else other (handled) exceptions may get +# # copied over by the other fns called. +# win32ui.SetStatusText('An exception occured in a windows command handler.') +# t, v, tb = sys.exc_info() +# traceback.print_exception(t, v, tb.tb_next) +# try: +# sys.stdout.flush() +# except (NameError, AttributeError): +# pass + + # Command handlers. + def OnFileMRU( self, id, code ): + " Called when a File 1-n message is recieved " + fileName = win32ui.GetRecentFileList()[id - win32ui.ID_FILE_MRU_FILE1] + win32ui.GetApp().OpenDocumentFile(fileName) + + def HandleOnFileOpen( self, id, code ): + " Called when FileOpen message is received " + win32ui.GetApp().OnFileOpen() + + def HandleOnFileNew( self, id, code ): + " Called when FileNew message is received " + win32ui.GetApp().OnFileNew() + + def OnHelpAbout( self, id, code ): + " Called when HelpAbout message is received. Displays the About dialog. " + win32ui.InitRichEdit() + dlg=AboutBox() + dlg.DoModal() + +def _GetRegistryValue(key, val, default = None): + # val is registry value - None for default val. + try: + hkey = win32api.RegOpenKey(win32con.HKEY_CURRENT_USER, key) + return win32api.RegQueryValueEx(hkey, val)[0] + except win32api.error: + try: + hkey = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, key) + return win32api.RegQueryValueEx(hkey, val)[0] + except win32api.error: + return default + +scintilla = "Scintilla is Copyright 1998-2008 Neil Hodgson (http://www.scintilla.org)" +idle = "This program uses IDLE extensions by Guido van Rossum, Tim Peters and others." +contributors = "Thanks to the following people for making significant contributions: Roger Upole, Sidnei da Silva, Sam Rushing, Curt Hagenlocher, Dave Brennan, Roger Burnham, Gordon McMillan, Neil Hodgson, Laramie Leavitt. (let me know if I have forgotten you!)" +# The About Box +class AboutBox(dialog.Dialog): + def __init__(self, idd=win32ui.IDD_ABOUTBOX): + dialog.Dialog.__init__(self, idd) + def OnInitDialog(self): + text = "Pythonwin - Python IDE and GUI Framework for Windows.\n\n%s\n\nPython is %s\n\n%s\n\n%s\n\n%s" % (win32ui.copyright, sys.copyright, scintilla, idle, contributors) + self.SetDlgItemText(win32ui.IDC_EDIT1, text) + # Get the build number - written by installers. + # For distutils build, read pywin32.version.txt + import distutils.sysconfig + site_packages = distutils.sysconfig.get_python_lib(plat_specific=1) + try: + build_no = open(os.path.join(site_packages, "pywin32.version.txt")).read().strip() + ver = "pywin32 build %s" % build_no + except EnvironmentError: + ver = None + if ver is None: + # See if we are Part of Active Python + ver = _GetRegistryValue("SOFTWARE\\ActiveState\\ActivePython", "CurrentVersion") + if ver is not None: + ver = "ActivePython build %s" % (ver,) + if ver is None: + ver = "" + self.SetDlgItemText(win32ui.IDC_ABOUT_VERSION, ver) + self.HookCommand(self.OnButHomePage, win32ui.IDC_BUTTON1) + + def OnButHomePage(self, id, code): + if code == win32con.BN_CLICKED: + win32api.ShellExecute(0, "open", "http://starship.python.net/crew/mhammond/win32", None, "", 1) + +def Win32RawInput(prompt=None): + "Provide raw_input() for gui apps" + # flush stderr/out first. + try: + sys.stdout.flush() + sys.stderr.flush() + except: + pass + if prompt is None: prompt = "" + ret=dialog.GetSimpleInput(prompt) + if ret==None: + raise KeyboardInterrupt("operation cancelled") + return ret + +def Win32Input(prompt=None): + "Provide input() for gui apps" + return eval(input(prompt)) + +def HookInput(): + try: + raw_input + # must be py2x... + sys.modules['__builtin__'].raw_input=Win32RawInput + sys.modules['__builtin__'].input=Win32Input + except NameError: + # must be py3k + import code + sys.modules['builtins'].input=Win32RawInput + +def HaveGoodGUI(): + """Returns true if we currently have a good gui available. + """ + return "pywin.framework.startup" in sys.modules + +def CreateDefaultGUI( appClass = None): + """Creates a default GUI environment + """ + if appClass is None: + from . import intpyapp # Bring in the default app - could be param'd later. + appClass = intpyapp.InteractivePythonApp + # Create and init the app. + appClass().InitInstance() + +def CheckCreateDefaultGUI(): + """Checks and creates if necessary a default GUI environment. + """ + rc = HaveGoodGUI() + if not rc: + CreateDefaultGUI() + return rc diff --git a/Lib/site-packages/pythonwin/pywin/framework/bitmap.py b/Lib/site-packages/pythonwin/pywin/framework/bitmap.py new file mode 100644 index 0000000..6adba7e --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/bitmap.py @@ -0,0 +1,143 @@ +import win32ui +import win32con +import win32api +import string +import os +from . import app +import sys + +from pywin.mfc import docview, window + +bStretch = 1 + +class BitmapDocument(docview.Document): + "A bitmap document. Holds the bitmap data itself." + def __init__(self, template): + docview.Document.__init__(self, template) + self.bitmap=None + def OnNewDocument(self): + # I can not create new bitmaps. + win32ui.MessageBox("Bitmaps can not be created.") + def OnOpenDocument(self, filename): + self.bitmap=win32ui.CreateBitmap() + # init data members + f = open(filename, 'rb') + try: + try: + self.bitmap.LoadBitmapFile(f) + except IOError: + win32ui.MessageBox("Could not load the bitmap from %s" % filename) + return 0 + finally: + f.close() + self.size = self.bitmap.GetSize() + return 1 + def DeleteContents(self): + self.bitmap=None + +class BitmapView(docview.ScrollView): + "A view of a bitmap. Obtains data from document." + def __init__(self, doc): + docview.ScrollView.__init__(self, doc) + self.width = self.height = 0 + # set up message handlers + self.HookMessage (self.OnSize, win32con.WM_SIZE) + + def OnInitialUpdate(self): + doc = self.GetDocument() + if doc.bitmap: + bitmapSize = doc.bitmap.GetSize() + self.SetScrollSizes(win32con.MM_TEXT, bitmapSize) + + def OnSize (self, params): + lParam = params[3] + self.width = win32api.LOWORD(lParam) + self.height = win32api.HIWORD(lParam) + + def OnDraw (self, dc): + # set sizes used for "non stretch" mode. + doc = self.GetDocument() + if doc.bitmap is None: return + bitmapSize = doc.bitmap.GetSize() + if bStretch: + # stretch BMP. + viewRect = (0,0,self.width, self.height) + bitmapRect = (0,0,bitmapSize[0], bitmapSize[1]) + doc.bitmap.Paint(dc, viewRect, bitmapRect) + else: + # non stretch. + doc.bitmap.Paint(dc) + +class BitmapFrame(window.MDIChildWnd): + def OnCreateClient( self, createparams, context ): + borderX = win32api.GetSystemMetrics(win32con.SM_CXFRAME) + borderY = win32api.GetSystemMetrics(win32con.SM_CYFRAME) + titleY = win32api.GetSystemMetrics(win32con.SM_CYCAPTION) # includes border + # try and maintain default window pos, else adjust if cant fit + # get the main client window dimensions. + mdiClient = win32ui.GetMainFrame().GetWindow(win32con.GW_CHILD) + clientWindowRect=mdiClient.ScreenToClient(mdiClient.GetWindowRect()) + clientWindowSize=(clientWindowRect[2]-clientWindowRect[0],clientWindowRect[3]-clientWindowRect[1]) + left, top, right, bottom=mdiClient.ScreenToClient(self.GetWindowRect()) +# width, height=context.doc.size[0], context.doc.size[1] +# width = width+borderX*2 +# height= height+titleY+borderY*2-1 +# if (left+width)>clientWindowSize[0]: +# left = clientWindowSize[0] - width +# if left<0: +# left = 0 +# width = clientWindowSize[0] +# if (top+height)>clientWindowSize[1]: +# top = clientWindowSize[1] - height +# if top<0: +# top = 0 +# height = clientWindowSize[1] +# self.frame.MoveWindow((left, top, left+width, top+height),0) + window.MDIChildWnd.OnCreateClient(self, createparams, context) + return 1 + + +class BitmapTemplate(docview.DocTemplate): + def __init__(self): + docview.DocTemplate.__init__(self, win32ui.IDR_PYTHONTYPE, BitmapDocument, BitmapFrame, BitmapView) + def MatchDocType(self, fileName, fileType): + doc = self.FindOpenDocument(fileName) + if doc: return doc + ext = os.path.splitext(fileName)[1].lower() + if ext =='.bmp': # removed due to PIL! or ext=='.ppm': + return win32ui.CDocTemplate_Confidence_yesAttemptNative + return win32ui.CDocTemplate_Confidence_maybeAttemptForeign +# return win32ui.CDocTemplate_Confidence_noAttempt + +# For debugging purposes, when this module may be reloaded many times. +try: + win32ui.GetApp().RemoveDocTemplate(bitmapTemplate) +except NameError: + pass + +bitmapTemplate = BitmapTemplate() +bitmapTemplate.SetDocStrings('\nBitmap\nBitmap\nBitmap (*.bmp)\n.bmp\nPythonBitmapFileType\nPython Bitmap File') +win32ui.GetApp().AddDocTemplate(bitmapTemplate) + +# This works, but just didnt make it through the code reorg. +#class PPMBitmap(Bitmap): +# def LoadBitmapFile(self, file ): +# magic=file.readline() +# if magic <> "P6\n": +# raise TypeError, "The file is not a PPM format file" +# rowcollist=string.split(file.readline()) +# cols=string.atoi(rowcollist[0]) +# rows=string.atoi(rowcollist[1]) +# file.readline() # whats this one? +# self.bitmap.LoadPPMFile(file,(cols,rows)) + + +def t(): + bitmapTemplate.OpenDocumentFile('d:\\winnt\\arcade.bmp') + #OpenBMPFile( 'd:\\winnt\\arcade.bmp') + +def demo(): + import glob + winDir=win32api.GetWindowsDirectory() + for fileName in glob.glob1(winDir, '*.bmp')[:2]: + bitmapTemplate.OpenDocumentFile(os.path.join(winDir, fileName)) diff --git a/Lib/site-packages/pythonwin/pywin/framework/cmdline.py b/Lib/site-packages/pythonwin/pywin/framework/cmdline.py new file mode 100644 index 0000000..cca6a41 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/cmdline.py @@ -0,0 +1,49 @@ +# cmdline - command line utilities. +import sys +import win32ui +import string + +def ParseArgs( str ): + import string + ret=[] + pos = 0 + length=len(str) + while pos=length: + break + if str[pos]=='"': + pos=pos+1 + try: + endPos = str.index('"', pos)-1 + nextPos = endPos+2 + except ValueError: + endPos=length + nextPos=endPos+1 + else: + endPos = pos + while endPos> 1 + top = (bottom - win32api.GetSystemMetrics(win32con.SM_CYICON)) >> 1 + hIcon = win32ui.GetApp().LoadIcon(self.iconId) + self.GetDC().DrawIcon((left, top), hIcon) + + # Only needed to provide a minimized icon (and this seems + # less important under win95/NT4 + def OnEraseBkgnd(self, dc): + if self.IsIconic(): + return 1 + else: + return self._obj_.OnEraseBkgnd(dc) + def OnQueryDragIcon(self): + return win32ui.GetApp().LoadIcon(self.iconId) + + def PreDoModal(self): + pass + + +class DialogApp(app.CApp): + "An application class, for an app with main dialog box" + def InitInstance(self): +# win32ui.SetProfileFileName('dlgapp.ini') + win32ui.LoadStdProfileSettings() + win32ui.EnableControlContainer() + win32ui.Enable3dControls() + self.dlg = self.frame = self.CreateDialog() + + if self.frame is None: + raise error("No dialog was created by CreateDialog()") + return + + self._obj_.InitDlgInstance(self.dlg) + self.PreDoModal() + self.dlg.PreDoModal() + self.dlg.DoModal() + + def CreateDialog(self): + pass + def PreDoModal(self): + pass + diff --git a/Lib/site-packages/pythonwin/pywin/framework/editor/ModuleBrowser.py b/Lib/site-packages/pythonwin/pywin/framework/editor/ModuleBrowser.py new file mode 100644 index 0000000..c486ebb --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/editor/ModuleBrowser.py @@ -0,0 +1,200 @@ +# ModuleBrowser.py - A view that provides a module browser for an editor document. +import pywin.mfc.docview +import win32ui +import win32con +import commctrl +import win32api +from pywin.tools import hierlist, browser +import pywin.framework.scriptutils +import afxres + +import pyclbr + +class HierListCLBRModule(hierlist.HierListItem): + def __init__(self, modName, clbrdata): + self.modName = modName + self.clbrdata = clbrdata + def GetText(self): + return self.modName + def GetSubList(self): + ret = [] + for item in self.clbrdata.values(): + if item.__class__ != pyclbr.Class: # ie, it is a pyclbr Function instance (only introduced post 1.5.2) + ret.append(HierListCLBRFunction( item ) ) + else: + ret.append(HierListCLBRClass( item) ) + ret.sort() + return ret + def IsExpandable(self): + return 1 + +class HierListCLBRItem(hierlist.HierListItem): + def __init__(self, name, file, lineno, suffix = ""): + self.name = str(name) + self.file = file + self.lineno = lineno + self.suffix = suffix + def __lt__(self, other): + return self.name < other.name + def __eq__(self, other): + return self.name == other.name + def GetText(self): + return self.name + self.suffix + def TakeDefaultAction(self): + if self.file: + pywin.framework.scriptutils.JumpToDocument(self.file, self.lineno, bScrollToTop = 1) + else: + win32ui.SetStatusText("Can not locate the source code for this object.") + def PerformItemSelected(self): + if self.file is None: + msg = "%s - source can not be located." % (self.name, ) + else: + msg = "%s defined at line %d of %s" % (self.name, self.lineno, self.file) + win32ui.SetStatusText(msg) + +class HierListCLBRClass(HierListCLBRItem): + def __init__(self, clbrclass, suffix = ""): + try: + name = clbrclass.name + file = clbrclass.file + lineno = clbrclass.lineno + self.super = clbrclass.super + self.methods = clbrclass.methods + except AttributeError: + name = clbrclass + file = lineno = None + self.super = []; self.methods = {} + HierListCLBRItem.__init__(self, name, file, lineno, suffix) + def GetSubList(self): + r1 = [] + for c in self.super: + r1.append(HierListCLBRClass(c, " (Parent class)")) + r1.sort() + r2=[] + for meth, lineno in self.methods.items(): + r2.append(HierListCLBRMethod(meth, self.file, lineno)) + r2.sort() + return r1+r2 + def IsExpandable(self): + return len(self.methods) + len(self.super) + def GetBitmapColumn(self): + return 21 + +class HierListCLBRFunction(HierListCLBRItem): + def __init__(self, clbrfunc, suffix = ""): + name = clbrfunc.name + file = clbrfunc.file + lineno = clbrfunc.lineno + HierListCLBRItem.__init__(self, name, file, lineno, suffix) + def GetBitmapColumn(self): + return 22 + +class HierListCLBRMethod(HierListCLBRItem): + def GetBitmapColumn(self): + return 22 + +class HierListCLBRErrorItem(hierlist.HierListItem): + def __init__(self, text): + self.text = text + def GetText(self): + return self.text + def GetSubList(self): + return [HierListCLBRErrorItem(self.text)] + def IsExpandable(self): + return 0 + +class HierListCLBRErrorRoot(HierListCLBRErrorItem): + def IsExpandable(self): + return 1 + +class BrowserView(pywin.mfc.docview.TreeView): + def OnInitialUpdate(self): + self.list = None + rc = self._obj_.OnInitialUpdate() + self.HookMessage(self.OnSize, win32con.WM_SIZE) + self.bDirty = 0 + self.destroying = 0 + return rc + + def DestroyBrowser(self): + self.DestroyList() + + def OnActivateView(self, activate, av, dv): +# print "AV", self.bDirty, activate + if activate: + self.CheckRefreshList() + return self._obj_.OnActivateView(activate, av, dv) + + def _MakeRoot(self): + path = self.GetDocument().GetPathName() + if not path: + return HierListCLBRErrorRoot("Error: Can not browse a file until it is saved") + else: + mod, path = pywin.framework.scriptutils.GetPackageModuleName(path) + if self.bDirty: + what = "Refreshing" + # Hack for pyclbr being too smart + try: + del pyclbr._modules[mod] + except (KeyError, AttributeError): + pass + else: + what = "Building" + win32ui.SetStatusText("%s class list - please wait..." % (what,), 1) + win32ui.DoWaitCursor(1) + try: + reader = pyclbr.readmodule_ex # new version post 1.5.2 + except AttributeError: + reader = pyclbr.readmodule + try: + data = reader(mod, [path]) + if data: + return HierListCLBRModule(mod, data) + else: + return HierListCLBRErrorRoot("No Python classes in module.") + + finally: + win32ui.DoWaitCursor(0) + win32ui.SetStatusText(win32ui.LoadString(afxres.AFX_IDS_IDLEMESSAGE)) + + def DestroyList(self): + self.destroying = 1 + list = getattr(self, "list", None) # If the document was not successfully opened, we may not have a list. + self.list = None + if list is not None: + list.HierTerm() + self.destroying = 0 + + def CheckMadeList(self): + if self.list is not None or self.destroying: return + self.rootitem = root = self._MakeRoot() + self.list = list = hierlist.HierListWithItems( root, win32ui.IDB_BROWSER_HIER) + list.HierInit(self.GetParentFrame(), self) + list.SetStyle(commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS) + + def CheckRefreshList(self): + if self.bDirty: + if self.list is None: + self.CheckMadeList() + else: + new_root = self._MakeRoot() + if self.rootitem.__class__==new_root.__class__==HierListCLBRModule: + self.rootitem.modName = new_root.modName + self.rootitem.clbrdata = new_root.clbrdata + self.list.Refresh() + else: + self.list.AcceptRoot(self._MakeRoot()) + self.bDirty = 0 + + def OnSize(self, params): + lparam = params[3] + w = win32api.LOWORD(lparam) + h = win32api.HIWORD(lparam) + if w != 0: + self.CheckMadeList() + elif w == 0: + self.DestroyList() + return 1 + + def _UpdateUIForState(self): + self.bDirty = 1 diff --git a/Lib/site-packages/pythonwin/pywin/framework/editor/__init__.py b/Lib/site-packages/pythonwin/pywin/framework/editor/__init__.py new file mode 100644 index 0000000..bdcb6ec --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/editor/__init__.py @@ -0,0 +1,90 @@ +# __init__ for the Pythonwin editor package. +# +# We used to support optional editors - eg, color or non-color. +# +# This really isnt necessary with Scintilla, and scintilla +# is getting so deeply embedded that it was too much work. + +import win32ui, sys, win32con + +defaultCharacterFormat = (-402653169, 0, 200, 0, 0, 0, 49, 'Courier New') + +##def GetDefaultEditorModuleName(): +## import pywin +## # If someone has set pywin.editormodulename, then this is what we use +## try: +## prefModule = pywin.editormodulename +## except AttributeError: +## prefModule = win32ui.GetProfileVal("Editor","Module", "") +## return prefModule +## +##def WriteDefaultEditorModule(module): +## try: +## module = module.__name__ +## except: +## pass +## win32ui.WriteProfileVal("Editor", "Module", module) + +def LoadDefaultEditor(): + pass +## prefModule = GetDefaultEditorModuleName() +## restorePrefModule = None +## mod = None +## if prefModule: +## try: +## mod = __import__(prefModule) +## except 'xx': +## msg = "Importing your preferred editor ('%s') failed.\n\nError %s: %s\n\nAn attempt will be made to load the default editor.\n\nWould you like this editor disabled in the future?" % (prefModule, sys.exc_info()[0], sys.exc_info()[1]) +## rc = win32ui.MessageBox(msg, "Error importing editor", win32con.MB_YESNO) +## if rc == win32con.IDNO: +## restorePrefModule = prefModule +## WriteDefaultEditorModule("") +## del rc +## +## try: +## # Try and load the default one - dont catch errors here. +## if mod is None: +## prefModule = "pywin.framework.editor.color.coloreditor" +## mod = __import__(prefModule) +## +## # Get at the real module. +## mod = sys.modules[prefModule] +## +## # Do a "from mod import *" +## globals().update(mod.__dict__) +## +## finally: +## # Restore the users default editor if it failed and they requested not to disable it. +## if restorePrefModule: +## WriteDefaultEditorModule(restorePrefModule) + +def GetEditorOption(option, defaultValue, min=None, max = None): + rc = win32ui.GetProfileVal("Editor", option, defaultValue) + if min is not None and rc < min: rc = defaultValue + if max is not None and rc > max: rc = defaultValue + return rc + +def SetEditorOption(option, newValue): + win32ui.WriteProfileVal("Editor", option, newValue) + +def DeleteEditorOption(option): + try: + win32ui.WriteProfileVal("Editor", option, None) + except win32ui.error: + pass + +# Load and save font tuples +def GetEditorFontOption(option, default = None): + if default is None: default = defaultCharacterFormat + fmt = GetEditorOption( option, "" ) + if fmt == "": return default + try: + return eval(fmt) + except: + print("WARNING: Invalid font setting in registry - setting ignored") + return default + +def SetEditorFontOption(option, newValue): + SetEditorOption(option, str(newValue)) + +from pywin.framework.editor.color.coloreditor import editorTemplate diff --git a/Lib/site-packages/pythonwin/pywin/framework/editor/color/__init__.py b/Lib/site-packages/pythonwin/pywin/framework/editor/color/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Lib/site-packages/pythonwin/pywin/framework/editor/color/coloreditor.py b/Lib/site-packages/pythonwin/pywin/framework/editor/color/coloreditor.py new file mode 100644 index 0000000..4cad4dc --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/editor/color/coloreditor.py @@ -0,0 +1,525 @@ +# Color Editor originally by Neil Hodgson, but restructured by mh to integrate +# even tighter into Pythonwin. +import win32ui +import win32con +import win32api +import sys + +import pywin.scintilla.keycodes +from pywin.scintilla import bindings + +from pywin.framework.editor import GetEditorOption, SetEditorOption, GetEditorFontOption, SetEditorFontOption, defaultCharacterFormat +#from pywin.framework.editor import EditorPropertyPage + +MSG_CHECK_EXTERNAL_FILE = win32con.WM_USER+1999 ## WARNING: Duplicated in document.py and editor.py + +# Define a few common markers +MARKER_BOOKMARK = 0 +MARKER_BREAKPOINT = 1 +MARKER_CURRENT = 2 + +from pywin.debugger import dbgcon +from pywin.scintilla.document import CScintillaDocument +from pywin.framework.editor.document import EditorDocumentBase +from pywin.scintilla import scintillacon # For the marker definitions +import pywin.scintilla.view + +class SyntEditDocument(EditorDocumentBase): + "A SyntEdit document. " + def OnDebuggerStateChange(self, state): + self._ApplyOptionalToViews("OnDebuggerStateChange", state) + def HookViewNotifications(self, view): + EditorDocumentBase.HookViewNotifications(self, view) + view.SCISetUndoCollection(1) + def FinalizeViewCreation(self, view): + EditorDocumentBase.FinalizeViewCreation(self, view) + if view==self.GetFirstView(): + self.GetDocTemplate().CheckIDLEMenus(view.idle) + +SyntEditViewParent=pywin.scintilla.view.CScintillaView +class SyntEditView(SyntEditViewParent): + "A view of a SyntEdit. Obtains data from document." + def __init__(self, doc): + SyntEditViewParent.__init__(self, doc) + self.bCheckingFile = 0 + + def OnInitialUpdate(self): + SyntEditViewParent.OnInitialUpdate(self) + + self.HookMessage(self.OnRClick,win32con.WM_RBUTTONDOWN) + + for id in [win32ui.ID_VIEW_FOLD_COLLAPSE, win32ui.ID_VIEW_FOLD_COLLAPSE_ALL, + win32ui.ID_VIEW_FOLD_EXPAND, win32ui.ID_VIEW_FOLD_EXPAND_ALL]: + + self.HookCommand(self.OnCmdViewFold, id) + self.HookCommandUpdate(self.OnUpdateViewFold, id) + self.HookCommand(self.OnCmdViewFoldTopLevel, win32ui.ID_VIEW_FOLD_TOPLEVEL) + + # Define the markers +# self.SCIMarkerDeleteAll() + self.SCIMarkerDefineAll(MARKER_BOOKMARK, scintillacon.SC_MARK_ROUNDRECT, win32api.RGB(0x0, 0x0, 0x0), win32api.RGB(0, 0xff, 0xff)) + + self.SCIMarkerDefine(MARKER_CURRENT, scintillacon.SC_MARK_ARROW) + self.SCIMarkerSetBack(MARKER_CURRENT, win32api.RGB(0xff, 0xff, 0x00)) + + # Define the folding markers + if 1: #traditional markers + self.SCIMarkerDefineAll(scintillacon.SC_MARKNUM_FOLDEROPEN, scintillacon.SC_MARK_MINUS, win32api.RGB(0xff, 0xff, 0xff), win32api.RGB(0, 0, 0)) + self.SCIMarkerDefineAll(scintillacon.SC_MARKNUM_FOLDER, scintillacon.SC_MARK_PLUS, win32api.RGB(0xff, 0xff, 0xff), win32api.RGB(0, 0, 0)) + self.SCIMarkerDefineAll(scintillacon.SC_MARKNUM_FOLDERSUB, scintillacon.SC_MARK_EMPTY, win32api.RGB(0xff, 0xff, 0xff), win32api.RGB(0, 0, 0)) + self.SCIMarkerDefineAll(scintillacon.SC_MARKNUM_FOLDERTAIL, scintillacon.SC_MARK_EMPTY, win32api.RGB(0xff, 0xff, 0xff), win32api.RGB(0, 0, 0)) + self.SCIMarkerDefineAll(scintillacon.SC_MARKNUM_FOLDEREND, scintillacon.SC_MARK_EMPTY, win32api.RGB(0xff, 0xff, 0xff), win32api.RGB(0, 0, 0)) + self.SCIMarkerDefineAll(scintillacon.SC_MARKNUM_FOLDEROPENMID, scintillacon.SC_MARK_EMPTY, win32api.RGB(0xff, 0xff, 0xff), win32api.RGB(0, 0, 0)) + self.SCIMarkerDefineAll(scintillacon.SC_MARKNUM_FOLDERMIDTAIL, scintillacon.SC_MARK_EMPTY, win32api.RGB(0xff, 0xff, 0xff), win32api.RGB(0, 0, 0)) + else: # curved markers + self.SCIMarkerDefineAll(scintillacon.SC_MARKNUM_FOLDEROPEN, scintillacon.SC_MARK_CIRCLEMINUS, win32api.RGB(0xff, 0xff, 0xff), win32api.RGB(0, 0, 0)) + self.SCIMarkerDefineAll(scintillacon.SC_MARKNUM_FOLDER, scintillacon.SC_MARK_CIRCLEPLUS, win32api.RGB(0xff, 0xff, 0xff), win32api.RGB(0, 0, 0)) + self.SCIMarkerDefineAll(scintillacon.SC_MARKNUM_FOLDERSUB, scintillacon.SC_MARK_VLINE, win32api.RGB(0xff, 0xff, 0xff), win32api.RGB(0, 0, 0)) + self.SCIMarkerDefineAll(scintillacon.SC_MARKNUM_FOLDERTAIL, scintillacon.SC_MARK_LCORNERCURVE, win32api.RGB(0xff, 0xff, 0xff), win32api.RGB(0, 0, 0)) + self.SCIMarkerDefineAll(scintillacon.SC_MARKNUM_FOLDEREND, scintillacon.SC_MARK_CIRCLEPLUSCONNECTED, win32api.RGB(0xff, 0xff, 0xff), win32api.RGB(0, 0, 0)) + self.SCIMarkerDefineAll(scintillacon.SC_MARKNUM_FOLDEROPENMID, scintillacon.SC_MARK_CIRCLEMINUSCONNECTED, win32api.RGB(0xff, 0xff, 0xff), win32api.RGB(0, 0, 0)) + self.SCIMarkerDefineAll(scintillacon.SC_MARKNUM_FOLDERMIDTAIL, scintillacon.SC_MARK_TCORNERCURVE, win32api.RGB(0xff, 0xff, 0xff), win32api.RGB(0, 0, 0)) + + self.SCIMarkerDefine(MARKER_BREAKPOINT, scintillacon.SC_MARK_CIRCLE) + # Marker background depends on debugger state + self.SCIMarkerSetFore(MARKER_BREAKPOINT, win32api.RGB(0x0, 0, 0)) + # Get the current debugger state. + try: + import pywin.debugger + if pywin.debugger.currentDebugger is None: + state = dbgcon.DBGSTATE_NOT_DEBUGGING + else: + state = pywin.debugger.currentDebugger.debuggerState + except ImportError: + state = dbgcon.DBGSTATE_NOT_DEBUGGING + self.OnDebuggerStateChange(state) + + def _GetSubConfigNames(self): + return ["editor"] # Allow [Keys:Editor] sections to be specific to us + + def DoConfigChange(self): + SyntEditViewParent.DoConfigChange(self) + tabSize = GetEditorOption("Tab Size", 4, 2) + indentSize = GetEditorOption("Indent Size", 4, 2) + bUseTabs = GetEditorOption("Use Tabs", 0) + bSmartTabs = GetEditorOption("Smart Tabs", 1) + ext = self.idle.IDLEExtension("AutoIndent") # Required extension. + + self.SCISetViewWS( GetEditorOption("View Whitespace", 0) ) + self.SCISetViewEOL( GetEditorOption("View EOL", 0) ) + self.SCISetIndentationGuides( GetEditorOption("View Indentation Guides", 0) ) + + if GetEditorOption("Right Edge Enabled", 0): + mode = scintillacon.EDGE_BACKGROUND + else: + mode = scintillacon.EDGE_NONE + self.SCISetEdgeMode(mode) + self.SCISetEdgeColumn( GetEditorOption("Right Edge Column", 75) ) + self.SCISetEdgeColor( GetEditorOption("Right Edge Color", win32api.RGB(0xef, 0xef, 0xef))) + + width = GetEditorOption("Marker Margin Width", 16) + self.SCISetMarginWidthN(1, width) + width = GetEditorOption("Fold Margin Width", 12) + self.SCISetMarginWidthN(2, width) + width = GetEditorOption("Line Number Margin Width", 0) + self.SCISetMarginWidthN(0, width) + self.bFolding = GetEditorOption("Enable Folding", 1) + fold_flags = 0 + self.SendScintilla(scintillacon.SCI_SETMODEVENTMASK, scintillacon.SC_MOD_CHANGEFOLD); + if self.bFolding: + if GetEditorOption("Fold Lines", 1): + fold_flags = 16 + + self.SCISetProperty("fold", self.bFolding) + self.SCISetFoldFlags(fold_flags) + + tt_color = GetEditorOption("Tab Timmy Color", win32api.RGB(0xff, 0, 0)) + self.SendScintilla(scintillacon.SCI_INDICSETFORE, 1, tt_color) + + tt_use = GetEditorOption("Use Tab Timmy", 1) + if tt_use: + self.SCISetProperty("tab.timmy.whinge.level", "1") + + # Auto-indent has very complicated behaviour. In a nutshell, the only + # way to get sensible behaviour from it is to ensure tabwidth != indentsize. + # Further, usetabs will only ever go from 1->0, never 0->1. + # This is _not_ the behaviour Pythonwin wants: + # * Tab width is arbitary, so should have no impact on smarts. + # * bUseTabs setting should reflect how new files are created, and + # if Smart Tabs disabled, existing files are edited + # * If "Smart Tabs" is enabled, bUseTabs should have no bearing + # for existing files (unless of course no context can be determined) + # + # So for smart tabs we configure the widget with completely dummy + # values (ensuring tabwidth != indentwidth), ask it to guess, then + # look at the values it has guessed, and re-configure + if bSmartTabs: + ext.config(usetabs=1, tabwidth=5, indentwidth=4) + ext.set_indentation_params(1) + if ext.indentwidth==5: + # Either 5 literal spaces, or a single tab character. Assume a tab + usetabs = 1 + indentwidth = tabSize + else: + # Either Indented with spaces, and indent size has been guessed or + # an empty file (or no context found - tough!) + if self.GetTextLength()==0: # emtpy + usetabs = bUseTabs + indentwidth = indentSize + else: # guessed. + indentwidth = ext.indentwidth + usetabs = 0 + # Tab size can never be guessed - set at user preference. + ext.config(usetabs=usetabs, indentwidth=indentwidth, tabwidth=tabSize) + else: + # Dont want smart-tabs - just set the options! + ext.config(usetabs=bUseTabs, tabwidth=tabSize, indentwidth=indentSize) + self.SCISetIndent(indentSize) + self.SCISetTabWidth(tabSize) + + def OnDebuggerStateChange(self, state): + if state == dbgcon.DBGSTATE_NOT_DEBUGGING: + # Indicate breakpoints arent really usable. + # Not quite white - useful when no marker margin, so set as background color. + self.SCIMarkerSetBack(MARKER_BREAKPOINT, win32api.RGB(0xef, 0xef, 0xef)) + else: + # A light-red, so still readable when no marker margin. + self.SCIMarkerSetBack(MARKER_BREAKPOINT, win32api.RGB(0xff, 0x80, 0x80)) + + def HookDocumentHandlers(self): + SyntEditViewParent.HookDocumentHandlers(self) + self.HookMessage(self.OnCheckExternalDocumentUpdated,MSG_CHECK_EXTERNAL_FILE) + + def HookHandlers(self): + SyntEditViewParent.HookHandlers(self) + self.HookMessage(self.OnSetFocus, win32con.WM_SETFOCUS) + + def _PrepareUserStateChange(self): + return self.GetSel(), self.GetFirstVisibleLine() + def _EndUserStateChange(self, info): + scrollOff = info[1] - self.GetFirstVisibleLine() + if scrollOff: + self.LineScroll(scrollOff) + # Make sure we dont reset the cursor beyond the buffer. + max = self.GetTextLength() + newPos = min(info[0][0], max), min(info[0][1], max) + self.SetSel(newPos) + + ####################################### + # The Windows Message or Notify handlers. + ####################################### + def OnMarginClick(self, std, extra): + notify = self.SCIUnpackNotifyMessage(extra) + if notify.margin==2: # Our fold margin + line_click = self.LineFromChar(notify.position) +# max_line = self.GetLineCount() + if self.SCIGetFoldLevel(line_click) & scintillacon.SC_FOLDLEVELHEADERFLAG: + # If a fold point. + self.SCIToggleFold(line_click) + return 1 + + def OnSetFocus(self,msg): + # Even though we use file change notifications, we should be very sure about it here. + self.OnCheckExternalDocumentUpdated(msg) + return 1 + + def OnCheckExternalDocumentUpdated(self, msg): + if self.bCheckingFile: return + self.bCheckingFile = 1 + self.GetDocument().CheckExternalDocumentUpdated() + self.bCheckingFile = 0 + + def OnRClick(self,params): + menu = win32ui.CreatePopupMenu() + self.AppendMenu(menu, "&Locate module", "LocateModule") + self.AppendMenu(menu, flags=win32con.MF_SEPARATOR) + self.AppendMenu(menu, "&Undo", "EditUndo") + self.AppendMenu(menu, '&Redo', 'EditRedo') + self.AppendMenu(menu, flags=win32con.MF_SEPARATOR) + self.AppendMenu(menu, 'Cu&t', 'EditCut') + self.AppendMenu(menu, '&Copy', 'EditCopy') + self.AppendMenu(menu, '&Paste', 'EditPaste') + self.AppendMenu(menu, flags=win32con.MF_SEPARATOR) + self.AppendMenu(menu, '&Select all', 'EditSelectAll') + self.AppendMenu(menu, 'View &Whitespace', 'ViewWhitespace', checked=self.SCIGetViewWS()) + self.AppendMenu(menu, "&Fixed Font", "ViewFixedFont", checked = self._GetColorizer().bUseFixed) + self.AppendMenu(menu, flags=win32con.MF_SEPARATOR) + self.AppendMenu(menu, "&Goto line...", "GotoLine") + + submenu = win32ui.CreatePopupMenu() + newitems = self.idle.GetMenuItems("edit") + for text, event in newitems: + self.AppendMenu(submenu, text, event) + + flags=win32con.MF_STRING|win32con.MF_ENABLED|win32con.MF_POPUP + menu.AppendMenu(flags, submenu.GetHandle(), "&Source code") + + flags = win32con.TPM_LEFTALIGN|win32con.TPM_LEFTBUTTON|win32con.TPM_RIGHTBUTTON + menu.TrackPopupMenu(params[5], flags, self) + return 0 + def OnCmdViewFold(self, cid, code): # Handle the menu command + if cid == win32ui.ID_VIEW_FOLD_EXPAND_ALL: + self.FoldExpandAllEvent(None) + elif cid == win32ui.ID_VIEW_FOLD_EXPAND: + self.FoldExpandEvent(None) + elif cid == win32ui.ID_VIEW_FOLD_COLLAPSE_ALL: + self.FoldCollapseAllEvent(None) + elif cid == win32ui.ID_VIEW_FOLD_COLLAPSE: + self.FoldCollapseEvent(None) + else: + print("Unknown collapse/expand ID") + def OnUpdateViewFold(self, cmdui): # Update the tick on the UI. + if not self.bFolding: + cmdui.Enable(0) + return + id = cmdui.m_nID + if id in [win32ui.ID_VIEW_FOLD_EXPAND_ALL, win32ui.ID_VIEW_FOLD_COLLAPSE_ALL]: + cmdui.Enable() + else: + enable = 0 + lineno = self.LineFromChar(self.GetSel()[0]) + foldable = self.SCIGetFoldLevel(lineno) & scintillacon.SC_FOLDLEVELHEADERFLAG + is_expanded = self.SCIGetFoldExpanded(lineno) + if id == win32ui.ID_VIEW_FOLD_EXPAND: + if foldable and not is_expanded: + enable = 1 + elif id == win32ui.ID_VIEW_FOLD_COLLAPSE: + if foldable and is_expanded: + enable = 1 + cmdui.Enable(enable) + + def OnCmdViewFoldTopLevel(self, cid, code): # Handle the menu command + self.FoldTopLevelEvent(None) + + ####################################### + # The Events + ####################################### + def ToggleBookmarkEvent(self, event, pos = -1): + """Toggle a bookmark at the specified or current position + """ + if pos==-1: + pos, end = self.GetSel() + startLine = self.LineFromChar(pos) + self.GetDocument().MarkerToggle(startLine+1, MARKER_BOOKMARK) + return 0 + + def GotoNextBookmarkEvent(self, event, fromPos=-1): + """ Move to the next bookmark + """ + if fromPos==-1: + fromPos, end = self.GetSel() + startLine = self.LineFromChar(fromPos)+1 # Zero based line to start + nextLine = self.GetDocument().MarkerGetNext(startLine+1, MARKER_BOOKMARK)-1 + if nextLine<0: + nextLine = self.GetDocument().MarkerGetNext(0, MARKER_BOOKMARK)-1 + if nextLine <0 or nextLine == startLine-1: + win32api.MessageBeep() + else: + self.SCIEnsureVisible(nextLine) + self.SCIGotoLine(nextLine) + return 0 + + def TabKeyEvent(self, event): + """Insert an indent. If no selection, a single indent, otherwise a block indent + """ + # Handle auto-complete first. + if self.SCIAutoCActive(): + self.SCIAutoCComplete() + return 0 + # Call the IDLE event. + return self.bindings.fire("<>", event) + + def EnterKeyEvent(self, event): + """Handle the enter key with special handling for auto-complete + """ + # Handle auto-complete first. + if self.SCIAutoCActive(): + self.SCIAutoCComplete() + self.SCIAutoCCancel() + # Call the IDLE event. + return self.bindings.fire("<>", event) + + def ShowInteractiveWindowEvent(self, event): + import pywin.framework.interact + pywin.framework.interact.ShowInteractiveWindow() + + def FoldTopLevelEvent(self, event = None): + if not self.bFolding: + return 1 + + win32ui.DoWaitCursor(1) + try: + self.Colorize() + maxLine = self.GetLineCount() + # Find the first line, and check out its state. + for lineSeek in range(maxLine): + if self.SCIGetFoldLevel(lineSeek) & scintillacon.SC_FOLDLEVELHEADERFLAG: + expanding = not self.SCIGetFoldExpanded(lineSeek) + break + else: + # no folds here! + return + for lineSeek in range(lineSeek, maxLine): + level = self.SCIGetFoldLevel(lineSeek) + level_no = level & scintillacon.SC_FOLDLEVELNUMBERMASK - scintillacon.SC_FOLDLEVELBASE + is_header = level & scintillacon.SC_FOLDLEVELHEADERFLAG + # print lineSeek, level_no, is_header + if level_no == 0 and is_header: + if (expanding and not self.SCIGetFoldExpanded(lineSeek)) or \ + (not expanding and self.SCIGetFoldExpanded(lineSeek)): + self.SCIToggleFold(lineSeek) + finally: + win32ui.DoWaitCursor(-1) + + def FoldExpandSecondLevelEvent(self, event): + if not self.bFolding: + return 1 + win32ui.DoWaitCursor(1) + ## I think this is needed since Scintilla may not have + ## already formatted parts of file outside visible window. + self.Colorize() + levels=[scintillacon.SC_FOLDLEVELBASE] + ## Scintilla's level number is based on amount of whitespace indentation + for lineno in range(self.GetLineCount()): + level = self.SCIGetFoldLevel(lineno) + if not level & scintillacon.SC_FOLDLEVELHEADERFLAG: + continue + curr_level = level & scintillacon.SC_FOLDLEVELNUMBERMASK + if curr_level > levels[-1]: + levels.append(curr_level) + try: + level_ind=levels.index(curr_level) + except ValueError: + ## probably syntax error in source file, bail + break + levels=levels[:level_ind+1] + if level_ind == 1 and not self.SCIGetFoldExpanded(lineno): + self.SCIToggleFold(lineno) + win32ui.DoWaitCursor(-1) + + def FoldCollapseSecondLevelEvent(self, event): + if not self.bFolding: + return 1 + win32ui.DoWaitCursor(1) + ## I think this is needed since Scintilla may not have + ## already formatted parts of file outside visible window. + self.Colorize() + levels=[scintillacon.SC_FOLDLEVELBASE] + ## Scintilla's level number is based on amount of whitespace indentation + for lineno in range(self.GetLineCount()): + level = self.SCIGetFoldLevel(lineno) + if not level & scintillacon.SC_FOLDLEVELHEADERFLAG: + continue + curr_level = level & scintillacon.SC_FOLDLEVELNUMBERMASK + if curr_level > levels[-1]: + levels.append(curr_level) + try: + level_ind=levels.index(curr_level) + except ValueError: + ## probably syntax error in source file, bail + break + levels=levels[:level_ind+1] + if level_ind == 1 and self.SCIGetFoldExpanded(lineno): + self.SCIToggleFold(lineno) + win32ui.DoWaitCursor(-1) + + def FoldExpandEvent(self, event): + if not self.bFolding: + return 1 + win32ui.DoWaitCursor(1) + lineno = self.LineFromChar(self.GetSel()[0]) + if self.SCIGetFoldLevel(lineno) & scintillacon.SC_FOLDLEVELHEADERFLAG and \ + not self.SCIGetFoldExpanded(lineno): + self.SCIToggleFold(lineno) + win32ui.DoWaitCursor(-1) + + def FoldExpandAllEvent(self, event): + if not self.bFolding: + return 1 + win32ui.DoWaitCursor(1) + for lineno in range(0, self.GetLineCount()): + if self.SCIGetFoldLevel(lineno) & scintillacon.SC_FOLDLEVELHEADERFLAG and \ + not self.SCIGetFoldExpanded(lineno): + self.SCIToggleFold(lineno) + win32ui.DoWaitCursor(-1) + + def FoldCollapseEvent(self, event): + if not self.bFolding: + return 1 + win32ui.DoWaitCursor(1) + lineno = self.LineFromChar(self.GetSel()[0]) + if self.SCIGetFoldLevel(lineno) & scintillacon.SC_FOLDLEVELHEADERFLAG and \ + self.SCIGetFoldExpanded(lineno): + self.SCIToggleFold(lineno) + win32ui.DoWaitCursor(-1) + + def FoldCollapseAllEvent(self, event): + if not self.bFolding: + return 1 + win32ui.DoWaitCursor(1) + self.Colorize() + for lineno in range(0, self.GetLineCount()): + if self.SCIGetFoldLevel(lineno) & scintillacon.SC_FOLDLEVELHEADERFLAG and \ + self.SCIGetFoldExpanded(lineno): + self.SCIToggleFold(lineno) + win32ui.DoWaitCursor(-1) + + +from pywin.framework.editor.frame import EditorFrame +class SplitterFrame(EditorFrame): + def OnCreate(self, cs): + self.HookCommand(self.OnWindowSplit, win32ui.ID_WINDOW_SPLIT) + return 1 + def OnWindowSplit(self, id, code): + self.GetDlgItem(win32ui.AFX_IDW_PANE_FIRST).DoKeyboardSplit() + return 1 + +from pywin.framework.editor.template import EditorTemplateBase +class SyntEditTemplate(EditorTemplateBase): + def __init__(self, res=win32ui.IDR_TEXTTYPE, makeDoc=None, makeFrame=None, makeView=None): + if makeDoc is None: makeDoc = SyntEditDocument + if makeView is None: makeView = SyntEditView + if makeFrame is None: makeFrame = SplitterFrame + self.bSetMenus = 0 + EditorTemplateBase.__init__(self, res, makeDoc, makeFrame, makeView) + + def CheckIDLEMenus(self, idle): + if self.bSetMenus: return + self.bSetMenus = 1 + + submenu = win32ui.CreatePopupMenu() + newitems = idle.GetMenuItems("edit") + flags=win32con.MF_STRING|win32con.MF_ENABLED + for text, event in newitems: + id = bindings.event_to_commands.get(event) + if id is not None: + keyname = pywin.scintilla.view.configManager.get_key_binding( event, ["editor"] ) + if keyname is not None: + text = text + "\t" + keyname + submenu.AppendMenu(flags, id, text) + + mainMenu = self.GetSharedMenu() + editMenu = mainMenu.GetSubMenu(1) + editMenu.AppendMenu(win32con.MF_SEPARATOR, 0, "") + editMenu.AppendMenu(win32con.MF_STRING | win32con.MF_POPUP | win32con.MF_ENABLED, submenu.GetHandle(), "&Source Code") + + def _CreateDocTemplate(self, resourceId): + return win32ui.CreateDocTemplate(resourceId) + + def CreateWin32uiDocument(self): + return self.DoCreateDoc() + + def GetPythonPropertyPages(self): + """Returns a list of property pages + """ + from pywin.scintilla import configui + return EditorTemplateBase.GetPythonPropertyPages(self) + [configui.ScintillaFormatPropertyPage()] + +# For debugging purposes, when this module may be reloaded many times. +try: + win32ui.GetApp().RemoveDocTemplate(editorTemplate) +except NameError: + pass + +editorTemplate = SyntEditTemplate() +win32ui.GetApp().AddDocTemplate(editorTemplate) diff --git a/Lib/site-packages/pythonwin/pywin/framework/editor/configui.py b/Lib/site-packages/pythonwin/pywin/framework/editor/configui.py new file mode 100644 index 0000000..cff8f8a --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/editor/configui.py @@ -0,0 +1,257 @@ +from pywin.mfc import dialog +from . import document +import win32ui +import win32con +import win32api + +from pywin.framework.editor import GetEditorOption, SetEditorOption, DeleteEditorOption, GetEditorFontOption, SetEditorFontOption, defaultCharacterFormat, editorTemplate +import pywin.scintilla.config + +# The standard 16 color VGA palette should always be possible +paletteVGA = ( ("Black",0,0,0), ("Navy",0,0,128), ("Green",0,128,0), ("Cyan",0,128,128), + ("Maroon",128,0,0), ("Purple",128,0,128), ("Olive",128,128,0), ("Gray",128,128,128), + ("Silver",192,192,192), ("Blue",0,0,255), ("Lime",0,255,0), ("Aqua",0,255,255), + ("Red",255,0,0), ("Fuchsia",255,0,255), ("Yellow",255,255,0), ("White",255,255,255) ) + +###################################################### +# +# Property Page for editor options +# +class EditorPropertyPage(dialog.PropertyPage): + def __init__(self): + dialog.PropertyPage.__init__(self, win32ui.IDD_PP_EDITOR) + self.autooptions = [] + self._AddEditorOption(win32ui.IDC_AUTO_RELOAD, "i", "Auto Reload", 1) + self._AddEditorOption(win32ui.IDC_COMBO1, "i", "Backup Type", document.BAK_DOT_BAK_BAK_DIR) + self._AddEditorOption(win32ui.IDC_AUTOCOMPLETE, "i", "Autocomplete Attributes", 1) + self._AddEditorOption(win32ui.IDC_CALLTIPS, "i", "Show Call Tips", 1) + self._AddEditorOption(win32ui.IDC_MARGIN_LINENUMBER, "i", "Line Number Margin Width", 0) + self._AddEditorOption(win32ui.IDC_RADIO1, "i", "MarkersInMargin", None) + self._AddEditorOption(win32ui.IDC_MARGIN_MARKER, "i", "Marker Margin Width", None) + self["Marker Margin Width"] = GetEditorOption("Marker Margin Width", 16) + + # Folding + self._AddEditorOption(win32ui.IDC_MARGIN_FOLD, "i", "Fold Margin Width", 12) + self._AddEditorOption(win32ui.IDC_FOLD_ENABLE, "i", "Enable Folding", 1) + self._AddEditorOption(win32ui.IDC_FOLD_ON_OPEN, "i", "Fold On Open", 0) + self._AddEditorOption(win32ui.IDC_FOLD_SHOW_LINES, "i", "Fold Lines", 1) + + # Right edge. + self._AddEditorOption(win32ui.IDC_RIGHTEDGE_ENABLE, "i", "Right Edge Enabled", 0) + self._AddEditorOption(win32ui.IDC_RIGHTEDGE_COLUMN, "i", "Right Edge Column", 75) + + # Source control, etc + self.AddDDX(win32ui.IDC_VSS_INTEGRATE, "bVSS") + self.AddDDX(win32ui.IDC_KEYBOARD_CONFIG, "Configs", "l") + self["Configs"] = pywin.scintilla.config.find_config_files() + + + + def _AddEditorOption(self, idd, typ, optionName, defaultVal): + self.AddDDX(idd, optionName, typ) + # some options are "derived" - ie, can be implied from others + # (eg, "view markers in background" is implied from "markerMarginWidth==0" + # So we don't actually store these values, but they do still get DDX support. + if defaultVal is not None: + self[optionName] = GetEditorOption(optionName, defaultVal) + self.autooptions.append((optionName, defaultVal)) + + def OnInitDialog(self): + for name, val in self.autooptions: + self[name] = GetEditorOption(name, val) + + # Note that these MUST be in the same order as the BAK constants. + cbo = self.GetDlgItem(win32ui.IDC_COMBO1) + cbo.AddString("None") + cbo.AddString(".BAK File") + cbo.AddString("TEMP dir") + cbo.AddString("Own dir") + + # Source Safe + bVSS = GetEditorOption("Source Control Module", "") == "pywin.framework.editor.vss" + self['bVSS'] = bVSS + + edit = self.GetDlgItem(win32ui.IDC_RIGHTEDGE_SAMPLE) + edit.SetWindowText("Sample Color") + + rc = dialog.PropertyPage.OnInitDialog(self) + + try: + self.GetDlgItem(win32ui.IDC_KEYBOARD_CONFIG).SelectString(-1, GetEditorOption("Keyboard Config", "default")) + except win32ui.error: + import traceback + traceback.print_exc() + pass + + self.HookCommand(self.OnButSimple, win32ui.IDC_FOLD_ENABLE) + self.HookCommand(self.OnButSimple, win32ui.IDC_RADIO1) + self.HookCommand(self.OnButSimple, win32ui.IDC_RADIO2) + self.HookCommand(self.OnButSimple, win32ui.IDC_RIGHTEDGE_ENABLE) + self.HookCommand(self.OnButEdgeColor, win32ui.IDC_RIGHTEDGE_DEFINE) + + butMarginEnabled = self['Marker Margin Width'] > 0 + self.GetDlgItem(win32ui.IDC_RADIO1).SetCheck(butMarginEnabled) + self.GetDlgItem(win32ui.IDC_RADIO2).SetCheck(not butMarginEnabled) + + self.edgeColor = self.initialEdgeColor = GetEditorOption("Right Edge Color", win32api.RGB(0xef, 0xef, 0xef)) + for spinner_id in (win32ui.IDC_SPIN1, win32ui.IDC_SPIN2, win32ui.IDC_SPIN3): + spinner=self.GetDlgItem(spinner_id) + spinner.SetRange(0,100) + self.UpdateUIForState() + + return rc + + def OnButSimple(self, id, code): + if code == win32con.BN_CLICKED: + self.UpdateUIForState() + + def OnButEdgeColor(self, id, code): + if code == win32con.BN_CLICKED: + d = win32ui.CreateColorDialog(self.edgeColor, 0, self) + # Ensure the current color is a custom color (as it may not be in the swatch) + # plus some other nice gray scales. + ccs = [self.edgeColor] + for c in range(0xef, 0x4f, -0x10): + ccs.append(win32api.RGB(c,c,c)) + d.SetCustomColors( ccs ) + if d.DoModal() == win32con.IDOK: + self.edgeColor = d.GetColor() + self.UpdateUIForState() + + def UpdateUIForState(self): + folding = self.GetDlgItem(win32ui.IDC_FOLD_ENABLE).GetCheck() + self.GetDlgItem(win32ui.IDC_FOLD_ON_OPEN).EnableWindow(folding) + self.GetDlgItem(win32ui.IDC_FOLD_SHOW_LINES).EnableWindow(folding) + + widthEnabled = self.GetDlgItem(win32ui.IDC_RADIO1).GetCheck() + self.GetDlgItem(win32ui.IDC_MARGIN_MARKER).EnableWindow(widthEnabled) + self.UpdateData() # Ensure self[] is up to date with the control data. + if widthEnabled and self["Marker Margin Width"] == 0: + self["Marker Margin Width"] = 16 + self.UpdateData(0) # Ensure control up to date with self[] + + # Right edge + edgeEnabled = self.GetDlgItem(win32ui.IDC_RIGHTEDGE_ENABLE).GetCheck() + self.GetDlgItem(win32ui.IDC_RIGHTEDGE_COLUMN).EnableWindow(edgeEnabled) + self.GetDlgItem(win32ui.IDC_RIGHTEDGE_SAMPLE).EnableWindow(edgeEnabled) + self.GetDlgItem(win32ui.IDC_RIGHTEDGE_DEFINE).EnableWindow(edgeEnabled) + + edit = self.GetDlgItem(win32ui.IDC_RIGHTEDGE_SAMPLE) + edit.SetBackgroundColor(0, self.edgeColor) + + def OnOK(self): + for name, defVal in self.autooptions: + SetEditorOption(name, self[name]) + # Margin width gets handled differently. + if self['MarkersInMargin'] == 0: + SetEditorOption("Marker Margin Width", self["Marker Margin Width"]) + else: + SetEditorOption("Marker Margin Width", 0) + if self.edgeColor != self.initialEdgeColor: + SetEditorOption("Right Edge Color", self.edgeColor) + if self['bVSS']: + SetEditorOption("Source Control Module", "pywin.framework.editor.vss") + else: + if GetEditorOption("Source Control Module", "")=='pywin.framework.editor.vss': + SetEditorOption("Source Control Module", "") + # Keyboard config + configname = self.GetDlgItem(win32ui.IDC_KEYBOARD_CONFIG).GetWindowText() + if configname: + if configname == "default": + DeleteEditorOption("Keyboard Config") + else: + SetEditorOption("Keyboard Config", configname) + + import pywin.scintilla.view + pywin.scintilla.view.LoadConfiguration() + + # Now tell all views we have changed. +## for doc in editorTemplate.GetDocumentList(): +## for view in doc.GetAllViews(): +## try: +## fn = view.OnConfigChange +## except AttributeError: +## continue +## fn() + return 1 + +class EditorWhitespacePropertyPage(dialog.PropertyPage): + def __init__(self): + dialog.PropertyPage.__init__(self, win32ui.IDD_PP_TABS) + self.autooptions = [] + self._AddEditorOption(win32ui.IDC_TAB_SIZE, "i", "Tab Size", 4) + self._AddEditorOption(win32ui.IDC_INDENT_SIZE, "i", "Indent Size", 4) + self._AddEditorOption(win32ui.IDC_USE_SMART_TABS, "i", "Smart Tabs", 1) + self._AddEditorOption(win32ui.IDC_VIEW_WHITESPACE, "i", "View Whitespace", 0) + self._AddEditorOption(win32ui.IDC_VIEW_EOL, "i", "View EOL", 0) + self._AddEditorOption(win32ui.IDC_VIEW_INDENTATIONGUIDES, "i", "View Indentation Guides", 0) + + def _AddEditorOption(self, idd, typ, optionName, defaultVal): + self.AddDDX(idd, optionName, typ) + self[optionName] = GetEditorOption(optionName, defaultVal) + self.autooptions.append((optionName, defaultVal)) + + def OnInitDialog(self): + for name, val in self.autooptions: + self[name] = GetEditorOption(name, val) + + rc = dialog.PropertyPage.OnInitDialog(self) + + idc = win32ui.IDC_TABTIMMY_NONE + if GetEditorOption("Use Tab Timmy", 1): + idc = win32ui.IDC_TABTIMMY_IND + self.GetDlgItem(idc).SetCheck(1) + + idc = win32ui.IDC_RADIO1 + if GetEditorOption("Use Tabs", 0): + idc = win32ui.IDC_USE_TABS + self.GetDlgItem(idc).SetCheck(1) + + tt_color = GetEditorOption("Tab Timmy Color", win32api.RGB(0xff, 0, 0)) + self.cbo = self.GetDlgItem(win32ui.IDC_COMBO1) + for c in paletteVGA: + self.cbo.AddString(c[0]) + sel = 0 + for c in paletteVGA: + if tt_color == win32api.RGB(c[1], c[2], c[3]): + break + sel = sel + 1 + else: + sel = -1 + self.cbo.SetCurSel(sel) + self.HookCommand(self.OnButSimple, win32ui.IDC_TABTIMMY_NONE) + self.HookCommand(self.OnButSimple, win32ui.IDC_TABTIMMY_IND) + self.HookCommand(self.OnButSimple, win32ui.IDC_TABTIMMY_BG) + # Set ranges for the spinners. + for spinner_id in [win32ui.IDC_SPIN1, win32ui.IDC_SPIN2]: + spinner = self.GetDlgItem(spinner_id) + spinner.SetRange(1, 16) + return rc + + def OnButSimple(self, id, code): + if code == win32con.BN_CLICKED: + self.UpdateUIForState() + + def UpdateUIForState(self): + timmy = self.GetDlgItem(win32ui.IDC_TABTIMMY_NONE).GetCheck() + self.GetDlgItem(win32ui.IDC_COMBO1).EnableWindow(not timmy) + + def OnOK(self): + for name, defVal in self.autooptions: + SetEditorOption(name, self[name]) + + SetEditorOption("Use Tabs", self.GetDlgItem(win32ui.IDC_USE_TABS).GetCheck()) + + SetEditorOption("Use Tab Timmy", self.GetDlgItem(win32ui.IDC_TABTIMMY_IND).GetCheck()) + c = paletteVGA[self.cbo.GetCurSel()] + SetEditorOption("Tab Timmy Color", win32api.RGB(c[1], c[2], c[3])) + + return 1 + +def testpp(): + ps = dialog.PropertySheet("Editor Options") + ps.AddPage(EditorWhitespacePropertyPage()) + ps.DoModal() + +if __name__=='__main__': + testpp() \ No newline at end of file diff --git a/Lib/site-packages/pythonwin/pywin/framework/editor/document.py b/Lib/site-packages/pythonwin/pywin/framework/editor/document.py new file mode 100644 index 0000000..bccb63f --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/editor/document.py @@ -0,0 +1,332 @@ +# We no longer support the old, non-colour editor! + +from pywin.mfc import docview, object +from pywin.framework.editor import GetEditorOption +import win32ui +import os +import win32con +import string +import traceback +import win32api +import shutil + +BAK_NONE=0 +BAK_DOT_BAK=1 +BAK_DOT_BAK_TEMP_DIR=2 +BAK_DOT_BAK_BAK_DIR=3 + +MSG_CHECK_EXTERNAL_FILE = win32con.WM_USER+1999 ## WARNING: Duplicated in editor.py and coloreditor.py + +import pywin.scintilla.document +ParentEditorDocument=pywin.scintilla.document.CScintillaDocument +class EditorDocumentBase(ParentEditorDocument): + def __init__(self, template): + self.bAutoReload = GetEditorOption("Auto Reload", 1) + self.bDeclinedReload = 0 # Has the user declined to reload. + self.fileStat = None + self.bReportedFileNotFound = 0 + + # what sort of bak file should I create. + # default to write to %temp%/bak/filename.ext + self.bakFileType=GetEditorOption("Backup Type", BAK_DOT_BAK_BAK_DIR) + + self.watcherThread = FileWatchingThread(self) + self.watcherThread.CreateThread() + # Should I try and use VSS integration? + self.scModuleName=GetEditorOption("Source Control Module", "") + self.scModule = None # Loaded when first used. + ParentEditorDocument.__init__(self, template, template.CreateWin32uiDocument()) + + def OnCloseDocument(self ): + self.watcherThread.SignalStop() + return self._obj_.OnCloseDocument() + +# def OnOpenDocument(self, name): +# rc = ParentEditorDocument.OnOpenDocument(self, name) +# self.GetFirstView()._SetLoadedText(self.text) +# self._DocumentStateChanged() +# return rc + + def OnSaveDocument( self, fileName ): + win32ui.SetStatusText("Saving file...",1) + # rename to bak if required. + dir, basename = os.path.split(fileName) + if self.bakFileType==BAK_DOT_BAK: + bakFileName=dir+'\\'+os.path.splitext(basename)[0]+'.bak' + elif self.bakFileType==BAK_DOT_BAK_TEMP_DIR: + bakFileName=win32api.GetTempPath()+'\\'+os.path.splitext(basename)[0]+'.bak' + elif self.bakFileType==BAK_DOT_BAK_BAK_DIR: + tempPath=os.path.join(win32api.GetTempPath(),'bak') + try: + os.mkdir(tempPath,0) + except os.error: + pass + bakFileName=os.path.join(tempPath,basename) + try: + os.unlink(bakFileName) # raise NameError if no bakups wanted. + except (os.error, NameError): + pass + try: + # Do a copy as it might be on different volumes, + # and the file may be a hard-link, causing the link + # to follow the backup. + shutil.copy2(fileName, bakFileName) + except (os.error, NameError, IOError): + pass + try: + self.SaveFile(fileName) + except IOError as details: + win32ui.MessageBox("Error - could not save file\r\n\r\n%s"%details) + return 0 + except (UnicodeEncodeError, LookupError) as details: + rc = win32ui.MessageBox("Encoding failed: \r\n%s"%details + + '\r\nPlease add desired source encoding as first line of file, eg \r\n' + + '# -*- coding: mbcs -*-\r\n\r\n' + + 'If you continue, the file will be saved as binary and will\r\n' + + 'not be valid in the declared encoding.\r\n\r\n' + + 'Save the file as binary with an invalid encoding?', + "File save failed", + win32con.MB_YESNO | win32con.MB_DEFBUTTON2) + if rc==win32con.IDYES: + try: + self.SaveFile(fileName, encoding="latin-1") + except IOError as details: + win32ui.MessageBox("Error - could not save file\r\n\r\n%s"%details) + return 0 + else: + return 0 + self.SetModifiedFlag(0) # No longer dirty + self.bDeclinedReload = 0 # They probably want to know if it changes again! + win32ui.AddToRecentFileList(fileName) + self.SetPathName(fileName) + win32ui.SetStatusText("Ready") + self._DocumentStateChanged() + return 1 + + def FinalizeViewCreation(self, view): + ParentEditorDocument.FinalizeViewCreation(self, view) + if view == self.GetFirstView(): + self._DocumentStateChanged() + if view.bFolding and GetEditorOption("Fold On Open", 0): + view.FoldTopLevelEvent() + + def HookViewNotifications(self, view): + ParentEditorDocument.HookViewNotifications(self, view) + + # Support for reloading the document from disk - presumably after some + # external application has modified it (or possibly source control has + # checked it out. + def ReloadDocument(self): + """Reloads the document from disk. Assumes the file has + been saved and user has been asked if necessary - it just does it! + """ + win32ui.SetStatusText("Reloading document. Please wait...", 1) + self.SetModifiedFlag(0) + # Loop over all views, saving their state, then reload the document + views = self.GetAllViews() + states = [] + for view in views: + try: + info = view._PrepareUserStateChange() + except AttributeError: # Not our editor view? + info = None + states.append(info) + self.OnOpenDocument(self.GetPathName()) + for view, info in zip(views, states): + if info is not None: + view._EndUserStateChange(info) + self._DocumentStateChanged() + win32ui.SetStatusText("Document reloaded.") + + # Reloading the file + def CheckExternalDocumentUpdated(self): + if self.bDeclinedReload or not self.GetPathName(): + return + try: + newstat = os.stat(self.GetPathName()) + except os.error as exc: + if not self.bReportedFileNotFound: + print("The file '%s' is open for editing, but\nchecking it for changes caused the error: %s" % (self.GetPathName(), exc.strerror)) + self.bReportedFileNotFound = 1 + return + if self.bReportedFileNotFound: + print("The file '%s' has re-appeared - continuing to watch for changes..." % (self.GetPathName(),)) + self.bReportedFileNotFound = 0 # Once found again we want to start complaining. + changed = (self.fileStat is None) or \ + self.fileStat[0] != newstat[0] or \ + self.fileStat[6] != newstat[6] or \ + self.fileStat[8] != newstat[8] or \ + self.fileStat[9] != newstat[9] + if changed: + question = None + if self.IsModified(): + question = "%s\r\n\r\nThis file has been modified outside of the source editor.\r\nDo you want to reload it and LOSE THE CHANGES in the source editor?" % self.GetPathName() + mbStyle = win32con.MB_YESNO | win32con.MB_DEFBUTTON2 # Default to "No" + else: + if not self.bAutoReload: + question = "%s\r\n\r\nThis file has been modified outside of the source editor.\r\nDo you want to reload it?" % self.GetPathName() + mbStyle = win32con.MB_YESNO # Default to "Yes" + if question: + rc = win32ui.MessageBox(question, None, mbStyle) + if rc!=win32con.IDYES: + self.bDeclinedReload = 1 + return + self.ReloadDocument() + + def _DocumentStateChanged(self): + """Called whenever the documents state (on disk etc) has been changed + by the editor (eg, as the result of a save operation) + """ + if self.GetPathName(): + try: + self.fileStat = os.stat(self.GetPathName()) + except os.error: + self.fileStat = None + else: + self.fileStat = None + self.watcherThread._DocumentStateChanged() + self._UpdateUIForState() + self._ApplyOptionalToViews("_UpdateUIForState") + self._ApplyOptionalToViews("SetReadOnly", self._IsReadOnly()) + self._ApplyOptionalToViews("SCISetSavePoint") + # Allow the debugger to reset us too. + import pywin.debugger + if pywin.debugger.currentDebugger is not None: + pywin.debugger.currentDebugger.UpdateDocumentLineStates(self) + + # Read-only document support - make it obvious to the user + # that the file is read-only. + def _IsReadOnly(self): + return self.fileStat is not None and (self.fileStat[0] & 128)==0 + + def _UpdateUIForState(self): + """Change the title to reflect the state of the document - + eg ReadOnly, Dirty, etc + """ + filename = self.GetPathName() + if not filename: return # New file - nothing to do + try: + # This seems necessary so the internal state of the window becomes + # "visible". without it, it is still shown, but certain functions + # (such as updating the title) dont immediately work? + self.GetFirstView().ShowWindow(win32con.SW_SHOW) + title = win32ui.GetFileTitle(filename) + except win32ui.error: + title = filename + if self._IsReadOnly(): + title = title + " (read-only)" + self.SetTitle(title) + + def MakeDocumentWritable(self): + pretend_ss = 0 # Set to 1 to test this without source safe :-) + if not self.scModuleName and not pretend_ss: # No Source Control support. + win32ui.SetStatusText("Document is read-only, and no source-control system is configured") + win32api.MessageBeep() + return 0 + + # We have source control support - check if the user wants to use it. + msg = "Would you like to check this file out?" + defButton = win32con.MB_YESNO + if self.IsModified(): + msg = msg + "\r\n\r\nALL CHANGES IN THE EDITOR WILL BE LOST" + defButton = win32con.MB_YESNO + if win32ui.MessageBox(msg, None, defButton)!=win32con.IDYES: + return 0 + + if pretend_ss: + print("We are only pretending to check it out!") + win32api.SetFileAttributes(self.GetPathName(), win32con.FILE_ATTRIBUTE_NORMAL) + self.ReloadDocument() + return 1 + + # Now call on the module to do it. + if self.scModule is None: + try: + self.scModule = __import__(self.scModuleName) + for part in self.scModuleName.split('.')[1:]: + self.scModule = getattr(self.scModule, part) + except: + traceback.print_exc() + print("Error loading source control module.") + return 0 + + if self.scModule.CheckoutFile(self.GetPathName()): + self.ReloadDocument() + return 1 + return 0 + + def CheckMakeDocumentWritable(self): + if self._IsReadOnly(): + return self.MakeDocumentWritable() + return 1 + + def SaveModified(self): + # Called as the document is closed. If we are about + # to prompt for a save, bring the document to the foreground. + if self.IsModified(): + frame = self.GetFirstView().GetParentFrame() + try: + frame.MDIActivate() + frame.AutoRestore() + except: + print("Could not bring document to foreground") + return self._obj_.SaveModified() + +# NOTE - I DONT use the standard threading module, +# as this waits for all threads to terminate at shutdown. +# When using the debugger, it is possible shutdown will +# occur without Pythonwin getting a complete shutdown, +# so we deadlock at the end - threading is waiting for +import pywin.mfc.thread +import win32event +class FileWatchingThread(pywin.mfc.thread.WinThread): + def __init__(self, doc): + self.doc = doc + self.adminEvent = win32event.CreateEvent(None, 0, 0, None) + self.stopEvent = win32event.CreateEvent(None, 0, 0, None) + self.watchEvent = None + pywin.mfc.thread.WinThread.__init__(self) + + def _DocumentStateChanged(self): + win32event.SetEvent(self.adminEvent) + + def RefreshEvent(self): + self.hwnd = self.doc.GetFirstView().GetSafeHwnd() + if self.watchEvent is not None: + win32api.FindCloseChangeNotification(self.watchEvent) + self.watchEvent = None + path = self.doc.GetPathName() + if path: path = os.path.dirname(path) + if path: + filter = win32con.FILE_NOTIFY_CHANGE_FILE_NAME | \ + win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES | \ + win32con.FILE_NOTIFY_CHANGE_LAST_WRITE + try: + self.watchEvent = win32api.FindFirstChangeNotification(path, 0, filter) + except win32api.error as exc: + print("Can not watch file", path, "for changes -", exc.strerror) + def SignalStop(self): + win32event.SetEvent(self.stopEvent) + def Run(self): + while 1: + handles = [self.stopEvent, self.adminEvent] + if self.watchEvent is not None: + handles.append(self.watchEvent) + rc = win32event.WaitForMultipleObjects(handles, 0, win32event.INFINITE) + if rc == win32event.WAIT_OBJECT_0: + break + elif rc == win32event.WAIT_OBJECT_0+1: + self.RefreshEvent() + else: + win32api.PostMessage(self.hwnd, MSG_CHECK_EXTERNAL_FILE, 0, 0) + try: + # If the directory has been removed underneath us, we get this error. + win32api.FindNextChangeNotification(self.watchEvent) + except win32api.error as exc: + print("Can not watch file", self.doc.GetPathName(), "for changes -", exc.strerror) + break + + # close a circular reference + self.doc = None + if self.watchEvent: + win32api.FindCloseChangeNotification(self.watchEvent) diff --git a/Lib/site-packages/pythonwin/pywin/framework/editor/editor.py b/Lib/site-packages/pythonwin/pywin/framework/editor/editor.py new file mode 100644 index 0000000..818771c --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/editor/editor.py @@ -0,0 +1,465 @@ +##################################################################### +# +# editor.py +# +# A general purpose text editor, built on top of the win32ui edit +# type, which is built on an MFC CEditView +# +# +# We now support reloading of externally modified documented +# (eg, presumably by some other process, such as source control or +# another editor. +# We also suport auto-loading of externally modified files. +# - if the current document has not been modified in this +# editor, but has been modified on disk, then the file +# can be automatically reloaded. +# +# Note that it will _always_ prompt you if the file in the editor has been modified. + + +import win32ui +import win32api +import win32con +import regex +import re +import string +import sys, os +import traceback +from pywin.mfc import docview, dialog, afxres + +from pywin.framework.editor import GetEditorOption, SetEditorOption, GetEditorFontOption, SetEditorFontOption, defaultCharacterFormat + +patImport=regex.symcomp('import \(.*\)') +patIndent=regex.compile('^\\([ \t]*[~ \t]\\)') + +ID_LOCATE_FILE = 0xe200 +ID_GOTO_LINE = 0xe2001 +MSG_CHECK_EXTERNAL_FILE = win32con.WM_USER+1999 ## WARNING: Duplicated in document.py and coloreditor.py + +# Key Codes that modify the bufffer when Ctrl or Alt are NOT pressed. +MODIFYING_VK_KEYS = [win32con.VK_BACK, win32con.VK_TAB, win32con.VK_RETURN, win32con.VK_SPACE, win32con.VK_DELETE] +for k in range(48, 91): + MODIFYING_VK_KEYS.append(k) + +# Key Codes that modify the bufffer when Ctrl is pressed. +MODIFYING_VK_KEYS_CTRL = [win32con.VK_BACK, win32con.VK_RETURN, win32con.VK_SPACE, win32con.VK_DELETE] + +# Key Codes that modify the bufffer when Alt is pressed. +MODIFYING_VK_KEYS_ALT = [win32con.VK_BACK, win32con.VK_RETURN, win32con.VK_SPACE, win32con.VK_DELETE] + + +# The editor itself starts here. +# Using the MFC Document/View model, we have an EditorDocument, which is responsible for +# managing the contents of the file, and a view which is responsible for rendering it. +# +# Due to a limitation in the Windows edit controls, we are limited to one view +# per document, although nothing in this code assumes this (I hope!) + +isRichText=1 # We are using the Rich Text control. This has not been tested with value "0" for quite some time! + +#ParentEditorDocument=docview.Document +from .document import EditorDocumentBase +ParentEditorDocument=EditorDocumentBase +class EditorDocument(ParentEditorDocument): + # + # File loading and saving operations + # + def OnOpenDocument(self, filename): + # + # handle Unix and PC text file format. + # + + # Get the "long name" of the file name, as it may have been translated + # to short names by the shell. + self.SetPathName(filename) # Must set this early! + # Now do the work! + self.BeginWaitCursor() + win32ui.SetStatusText("Loading file...",1) + try: + f = open(filename,"rb") + except IOError: + win32ui.MessageBox(filename + '\nCan not find this file\nPlease verify that the correct path and file name are given') + self.EndWaitCursor() + return 0 + raw=f.read() + f.close() + contents = self.TranslateLoadedData(raw) + rc = 0 + if win32ui.IsWin32s() and len(contents)>62000: # give or take a few bytes + win32ui.MessageBox("This file is too big for Python on Windows 3.1\r\nPlease use another editor to view this file.") + else: + try: + self.GetFirstView().SetWindowText(contents) + rc = 1 + except TypeError: # Null byte in file. + win32ui.MessageBox("This file contains NULL bytes, and can not be edited") + rc = 0 + + self.EndWaitCursor() + self.SetModifiedFlag(0) # No longer dirty + self._DocumentStateChanged() + return rc + + def TranslateLoadedData(self, data): + """Given raw data read from a file, massage it suitable for the edit window""" + # if a CR in the first 250 chars, then perform the expensive translate + if data[:250].find('\r')==-1: + win32ui.SetStatusText("Translating from Unix file format - please wait...",1) + return re.sub('\r*\n','\r\n',data) + else: + return data + + def SaveFile(self, fileName, encoding=None): + if isRichText: + view = self.GetFirstView() + view.SaveTextFile(fileName, encoding=encoding) + else: # Old style edit view window. + self.GetFirstView().SaveFile(fileName) + try: + # Make sure line cache has updated info about me! + import linecache + linecache.checkcache() + except: + pass + + # + # Color state stuff + # + def SetAllLineColors(self, color = None): + for view in self.GetAllViews(): + view.SetAllLineColors(color) + + def SetLineColor(self, lineNo, color): + "Color a line of all views" + for view in self.GetAllViews(): + view.SetLineColor(lineNo, color) + + +# def StreamTextOut(self, data): ### This seems unreliable??? +# self.saveFileHandle.write(data) +# return 1 # keep em coming! + +#ParentEditorView=docview.EditView +ParentEditorView=docview.RichEditView +class EditorView(ParentEditorView): + def __init__(self, doc): + ParentEditorView.__init__(self, doc) + if isRichText: + self.SetWordWrap(win32ui.CRichEditView_WrapNone) + + self.addToMRU = 1 + self.HookHandlers() + self.bCheckingFile = 0 + + self.defCharFormat = GetEditorFontOption("Default Font", defaultCharacterFormat) + + # Smart tabs override everything else if context can be worked out. + self.bSmartTabs = GetEditorOption("Smart Tabs", 1) + + self.tabSize = GetEditorOption("Tab Size", 8) + self.indentSize = GetEditorOption("Indent Size", 8) + # If next indent is at a tab position, and useTabs is set, a tab will be inserted. + self.bUseTabs = GetEditorOption("Use Tabs", 1) + + def OnInitialUpdate(self): + rc = self._obj_.OnInitialUpdate() + self.SetDefaultCharFormat(self.defCharFormat) + return rc + + def CutCurLine(self): + curLine = self._obj_.LineFromChar() + nextLine = curLine+1 + start = self._obj_.LineIndex(curLine) + end = self._obj_.LineIndex(nextLine) + if end==0: # must be last line. + end = start + self.end.GetLineLength(curLine) + self._obj_.SetSel(start,end) + self._obj_.Cut() + def _PrepareUserStateChange(self): + "Return selection, lineindex, etc info, so it can be restored" + self.SetRedraw(0) + return self.GetModify(), self.GetSel(), self.GetFirstVisibleLine() + def _EndUserStateChange(self, info): + scrollOff = info[2] - self.GetFirstVisibleLine() + if scrollOff: + self.LineScroll(scrollOff) + self.SetSel(info[1]) + self.SetModify(info[0]) + self.SetRedraw(1) + self.InvalidateRect() + self.UpdateWindow() + + def _UpdateUIForState(self): + self.SetReadOnly(self.GetDocument()._IsReadOnly()) + + def SetAllLineColors(self, color = None): + if isRichText: + info = self._PrepareUserStateChange() + try: + if color is None: color = self.defCharFormat[4] + self.SetSel(0,-1) + self.SetSelectionCharFormat((win32con.CFM_COLOR, 0,0,0,color)) + finally: + self._EndUserStateChange(info) + + def SetLineColor(self, lineNo, color): + "lineNo is the 1 based line number to set. If color is None, default color is used." + if isRichText: + info = self._PrepareUserStateChange() + try: + if color is None: color = self.defCharFormat[4] + lineNo = lineNo-1 + startIndex = self.LineIndex(lineNo) + if startIndex!=-1: + self.SetSel(startIndex, self.LineIndex(lineNo+1)) + self.SetSelectionCharFormat((win32con.CFM_COLOR, 0,0,0,color)) + finally: + self._EndUserStateChange(info) + + def Indent(self): + """Insert an indent to move the cursor to the next tab position. + + Honors the tab size and 'use tabs' settings. Assumes the cursor is already at the + position to be indented, and the selection is a single character (ie, not a block) + """ + start, end = self._obj_.GetSel() + startLine = self._obj_.LineFromChar(start) + line = self._obj_.GetLine(startLine) + realCol = start - self._obj_.LineIndex(startLine) + # Calulate the next tab stop. + # Expand existing tabs. + curCol = 0 + for ch in line[:realCol]: + if ch=='\t': + curCol = ((curCol / self.tabSize) + 1) * self.tabSize + else: + curCol = curCol + 1 + nextColumn = ((curCol / self.indentSize) + 1) * self.indentSize +# print "curCol is", curCol, "nextColumn is", nextColumn + ins = None + if self.bSmartTabs: + # Look for some context. + if realCol==0: # Start of the line - see if the line above can tell us + lookLine = startLine-1 + while lookLine >= 0: + check = self._obj_.GetLine(lookLine)[0:1] + if check in ['\t', ' ']: + ins = check + break + lookLine = lookLine - 1 + else: # See if the previous char can tell us + check = line[realCol-1] + if check in ['\t', ' ']: + ins = check + + # Either smart tabs off, or not smart enough! + # Use the "old style" settings. + if ins is None: + if self.bUseTabs and nextColumn % self.tabSize==0: + ins = '\t' + else: + ins = ' ' + + if ins == ' ': + # Calc the number of spaces to take us to the next stop + ins = ins * (nextColumn - curCol) + + self._obj_.ReplaceSel(ins) + + + def BlockDent(self, isIndent, startLine, endLine): + " Indent/Undent all lines specified " + if not self.GetDocument().CheckMakeDocumentWritable(): return 0 + tabSize=self.tabSize # hard-code for now! + info = self._PrepareUserStateChange() + try: + for lineNo in range(startLine, endLine): + pos=self._obj_.LineIndex(lineNo) + self._obj_.SetSel(pos, pos) + if isIndent: + self.Indent() + else: + line = self._obj_.GetLine(lineNo) + try: + noToDel = 0 + if line[0]=='\t': + noToDel = 1 + elif line[0]==' ': + for noToDel in range(0,tabSize): + if line[noToDel]!=' ': + break + else: + noToDel=tabSize + if noToDel: + self._obj_.SetSel(pos, pos+noToDel) + self._obj_.Clear() + except IndexError: + pass + finally: + self._EndUserStateChange(info) + self.GetDocument().SetModifiedFlag(1) # Now dirty + self._obj_.SetSel(self.LineIndex(startLine), self.LineIndex(endLine)) + + def GotoLine(self, lineNo = None): + try: + if lineNo is None: + lineNo = int(input("Enter Line Number")) + except (ValueError, KeyboardInterrupt): + return 0 + self.GetLineCount() # Seems to be needed when file first opened??? + charNo = self.LineIndex(lineNo-1) + self.SetSel(charNo) + + def HookHandlers(self): # children can override, but should still call me! +# self.HookAllKeyStrokes(self.OnKey) + self.HookMessage(self.OnCheckExternalDocumentUpdated,MSG_CHECK_EXTERNAL_FILE) + self.HookMessage(self.OnRClick,win32con.WM_RBUTTONDOWN) + self.HookMessage(self.OnSetFocus, win32con.WM_SETFOCUS) + self.HookMessage(self.OnKeyDown, win32con.WM_KEYDOWN) + self.HookKeyStroke(self.OnKeyCtrlY, 25) # ^Y + self.HookKeyStroke(self.OnKeyCtrlG, 7) # ^G + self.HookKeyStroke(self.OnKeyTab, 9) # TAB + self.HookKeyStroke(self.OnKeyEnter, 13) # Enter + self.HookCommand(self.OnCmdLocateFile, ID_LOCATE_FILE) + self.HookCommand(self.OnCmdGotoLine, ID_GOTO_LINE) + self.HookCommand(self.OnEditPaste, afxres.ID_EDIT_PASTE) + self.HookCommand(self.OnEditCut, afxres.ID_EDIT_CUT) + + # Hook Handlers + def OnSetFocus(self,msg): + # Even though we use file change notifications, we should be very sure about it here. + self.OnCheckExternalDocumentUpdated(msg) + + def OnRClick(self,params): + menu = win32ui.CreatePopupMenu() + + # look for a module name + line=self._obj_.GetLine().strip() + flags=win32con.MF_STRING|win32con.MF_ENABLED + if patImport.match(line)==len(line): + menu.AppendMenu(flags, ID_LOCATE_FILE, "&Locate %s.py"%patImport.group('name')) + menu.AppendMenu(win32con.MF_SEPARATOR); + menu.AppendMenu(flags, win32ui.ID_EDIT_UNDO, '&Undo') + menu.AppendMenu(win32con.MF_SEPARATOR); + menu.AppendMenu(flags, win32ui.ID_EDIT_CUT, 'Cu&t') + menu.AppendMenu(flags, win32ui.ID_EDIT_COPY, '&Copy') + menu.AppendMenu(flags, win32ui.ID_EDIT_PASTE, '&Paste') + menu.AppendMenu(flags, win32con.MF_SEPARATOR); + menu.AppendMenu(flags, win32ui.ID_EDIT_SELECT_ALL, '&Select all') + menu.AppendMenu(flags, win32con.MF_SEPARATOR); + menu.AppendMenu(flags, ID_GOTO_LINE, '&Goto line...') + menu.TrackPopupMenu(params[5]) + return 0 + + def OnCmdGotoLine(self, cmd, code): + self.GotoLine() + return 0 + + def OnCmdLocateFile(self, cmd, code): + modName = patImport.group('name') + if not modName: + return 0 + import pywin.framework.scriptutils + fileName = pywin.framework.scriptutils.LocatePythonFile(modName) + if fileName is None: + win32ui.SetStatusText("Can't locate module %s" % modName) + else: + win32ui.GetApp().OpenDocumentFile(fileName) + return 0 + + # Key handlers + def OnKeyEnter(self, key): + if not self.GetDocument().CheckMakeDocumentWritable(): return 0 + curLine = self._obj_.GetLine() + self._obj_.ReplaceSel('\r\n') # insert the newline + # If the current line indicates the next should be indented, + # then copy the current indentation to this line. + res = patIndent.match(curLine,0) + if res>0 and curLine.strip(): + curIndent = patIndent.group(1) + self._obj_.ReplaceSel(curIndent) + return 0 # dont pass on + + def OnKeyCtrlY(self, key): + if not self.GetDocument().CheckMakeDocumentWritable(): return 0 + self.CutCurLine() + return 0 # dont let him have it! + def OnKeyCtrlG(self, key): + self.GotoLine() + return 0 # dont let him have it! + def OnKeyTab(self, key): + if not self.GetDocument().CheckMakeDocumentWritable(): return 0 + start, end = self._obj_.GetSel() + if start==end: # normal TAB key + self.Indent() + return 0 # we handled this. + + # Otherwise it is a block indent/dedent. + if start>end: + start, end = end, start # swap them. + startLine = self._obj_.LineFromChar(start) + endLine = self._obj_.LineFromChar(end) + + self.BlockDent(win32api.GetKeyState(win32con.VK_SHIFT)>=0, startLine, endLine) + return 0 + + + def OnEditPaste(self, id, code): + # Return 1 if we can make the file editable.(or it already is!) + return self.GetDocument().CheckMakeDocumentWritable() + + def OnEditCut(self, id, code): + # Return 1 if we can make the file editable.(or it already is!) + return self.GetDocument().CheckMakeDocumentWritable() + + def OnKeyDown(self, msg): + key = msg[2] + if win32api.GetKeyState(win32con.VK_CONTROL) & 0x8000: + modList = MODIFYING_VK_KEYS_CTRL + elif win32api.GetKeyState(win32con.VK_MENU) & 0x8000: + modList = MODIFYING_VK_KEYS_ALT + else: + modList = MODIFYING_VK_KEYS + + if key in modList: + # Return 1 if we can make the file editable.(or it already is!) + return self.GetDocument().CheckMakeDocumentWritable() + return 1 # Pass it on OK + +# def OnKey(self, key): +# return self.GetDocument().CheckMakeDocumentWritable() + + def OnCheckExternalDocumentUpdated(self, msg): + if self._obj_ is None or self.bCheckingFile: return + self.bCheckingFile = 1 + self.GetDocument().CheckExternalDocumentUpdated() + self.bCheckingFile = 0 + +from .template import EditorTemplateBase +class EditorTemplate(EditorTemplateBase): + def __init__(self, res=win32ui.IDR_TEXTTYPE, makeDoc=None, makeFrame=None, makeView=None): + if makeDoc is None: makeDoc = EditorDocument + if makeView is None: makeView = EditorView + EditorTemplateBase.__init__(self, res, makeDoc, makeFrame, makeView) + + def _CreateDocTemplate(self, resourceId): + return win32ui.CreateRichEditDocTemplate(resourceId) + + def CreateWin32uiDocument(self): + return self.DoCreateRichEditDoc() + +def Create(fileName = None, title=None, template = None): + return editorTemplate.OpenDocumentFile(fileName) + +from pywin.framework.editor import GetDefaultEditorModuleName +prefModule = GetDefaultEditorModuleName() +# Initialize only if this is the "default" editor. +if __name__==prefModule: + # For debugging purposes, when this module may be reloaded many times. + try: + win32ui.GetApp().RemoveDocTemplate(editorTemplate) + except (NameError, win32ui.error): + pass + + editorTemplate = EditorTemplate() + win32ui.GetApp().AddDocTemplate(editorTemplate) diff --git a/Lib/site-packages/pythonwin/pywin/framework/editor/frame.py b/Lib/site-packages/pythonwin/pywin/framework/editor/frame.py new file mode 100644 index 0000000..b7bfaff --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/editor/frame.py @@ -0,0 +1,76 @@ +# frame.py - The MDI frame window for an editor. +import pywin.framework.window +import win32ui +import win32con +import afxres + +from . import ModuleBrowser + +class EditorFrame(pywin.framework.window.MDIChildWnd): + def OnCreateClient(self, cp, context): + + # Create the default view as specified by the template (ie, the editor view) + view = context.template.MakeView(context.doc) + # Create the browser view. + browserView = ModuleBrowser.BrowserView(context.doc) + view2 = context.template.MakeView(context.doc) + + splitter = win32ui.CreateSplitter() + style = win32con.WS_CHILD | win32con.WS_VISIBLE + splitter.CreateStatic (self, 1, 2, style, win32ui.AFX_IDW_PANE_FIRST) + sub_splitter = self.sub_splitter = win32ui.CreateSplitter() + sub_splitter.CreateStatic (splitter, 2, 1, style, win32ui.AFX_IDW_PANE_FIRST+1) + + # Note we must add the default view first, so that doc.GetFirstView() returns the editor view. + sub_splitter.CreateView(view, 1, 0, (0,0)) + splitter.CreateView (browserView, 0, 0, (0,0)) + sub_splitter.CreateView(view2,0, 0, (0,0)) + +## print "First view is", context.doc.GetFirstView() +## print "Views are", view, view2, browserView +## print "Parents are", view.GetParent(), view2.GetParent(), browserView.GetParent() +## print "Splitter is", splitter +## print "sub splitter is", sub_splitter + ## Old +## splitter.CreateStatic (self, 1, 2) +## splitter.CreateView(view, 0, 1, (0,0)) # size ignored. +## splitter.CreateView (browserView, 0, 0, (0, 0)) + + # Restrict the size of the browser splitter (and we can avoid filling + # it until it is shown) + splitter.SetColumnInfo(0, 10, 20) + # And the active view is our default view (so it gets initial focus) + self.SetActiveView(view) + + def GetEditorView(self): + # In a multi-view (eg, splitter) environment, get + # an editor (ie, scintilla) view + # Look for the splitter opened the most! + if self.sub_splitter is None: + return self.GetDlgItem(win32ui.AFX_IDW_PANE_FIRST) + v1 = self.sub_splitter.GetPane(0,0) + v2 = self.sub_splitter.GetPane(1,0) + r1 = v1.GetWindowRect() + r2 = v2.GetWindowRect() + if r1[3]-r1[1] > r2[3]-r2[1]: + return v1 + return v2 + + def GetBrowserView(self): + # XXX - should fix this :-) + return self.GetActiveDocument().GetAllViews()[1] + + def OnClose(self): + doc=self.GetActiveDocument() + if not doc.SaveModified(): + ## Cancel button selected from Save dialog, do not actually close + ## print 'close cancelled' + return 0 + ## So the 'Save' dialog doesn't come up twice + doc._obj_.SetModifiedFlag(False) + + # Must force the module browser to close itself here (OnDestroy for the view itself is too late!) + self.sub_splitter = None # ensure no circles! + self.GetBrowserView().DestroyBrowser() + return self._obj_.OnClose() + \ No newline at end of file diff --git a/Lib/site-packages/pythonwin/pywin/framework/editor/template.py b/Lib/site-packages/pythonwin/pywin/framework/editor/template.py new file mode 100644 index 0000000..c7e400b --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/editor/template.py @@ -0,0 +1,50 @@ +import string +import win32ui +import win32api +from pywin.mfc import docview +import pywin.framework.window +import os +from . import frame + +ParentEditorTemplate=docview.DocTemplate +class EditorTemplateBase(ParentEditorTemplate): + def __init__(self, res=win32ui.IDR_TEXTTYPE, makeDoc=None, makeFrame=None, makeView=None): + if makeFrame is None: makeFrame = frame.EditorFrame + ParentEditorTemplate.__init__(self, res, makeDoc, makeFrame, makeView) + + def _CreateDocTemplate(self, resourceId): + assert 0, "You must override this" + def CreateWin32uiDocument(self): + assert 0, "You must override this" + def GetFileExtensions(self): + return ".txt", ".py" + def MatchDocType(self, fileName, fileType): + doc = self.FindOpenDocument(fileName) + if doc: return doc + ext = os.path.splitext(fileName)[1].lower() + if ext in self.GetFileExtensions(): + return win32ui.CDocTemplate_Confidence_yesAttemptNative + return win32ui.CDocTemplate_Confidence_maybeAttemptForeign + + def InitialUpdateFrame(self, frame, doc, makeVisible=1): + self._obj_.InitialUpdateFrame(frame, doc, makeVisible) # call default handler. + doc._UpdateUIForState() + + def GetPythonPropertyPages(self): + """Returns a list of property pages + """ + from . import configui + return [configui.EditorPropertyPage(), configui.EditorWhitespacePropertyPage()] + + def OpenDocumentFile(self, filename, bMakeVisible = 1): + if filename is not None: + try: + path = os.path.split(filename)[0] +# print "The editor is translating", `filename`,"to", + filename = win32api.FindFiles(filename)[0][8] + filename = os.path.join(path, filename) +# print `filename` + except (win32api.error, IndexError) as details: + pass +# print "Couldnt get the full filename!", details + return self._obj_.OpenDocumentFile(filename, bMakeVisible) diff --git a/Lib/site-packages/pythonwin/pywin/framework/editor/vss.py b/Lib/site-packages/pythonwin/pywin/framework/editor/vss.py new file mode 100644 index 0000000..178924a --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/editor/vss.py @@ -0,0 +1,93 @@ +# vss.py -- Source Control using Microsoft VSS. + +# Provides routines for checking files out of VSS. +# +# Uses an INI file very similar to how VB integrates with VSS - even +# as far as using the same name. + +# The file must be named "Mssccprj.scc", and be in the format of +# an INI file. This file may be in a parent directory, in which +# case the project name will be built from what is specified in the +# ini file, plus the path from the INI file to the file itself. +# +# The INI file should have a [Python] section, and a +# Project=Project Name +# and optionally +# Database=?? + + +import win32ui, win32api, win32con, os, string, sys + +import traceback + +g_iniName = "Mssccprj.scc" # Use the same INI name as VB! + +g_sourceSafe = None + +def FindVssProjectInfo(fullfname): + """Looks up the file system for an INI file describing the project. + + Looking up the tree is for ni style packages. + + Returns (projectName, pathToFileName) where pathToFileName contains + the path from the ini file to the actual file. + """ + path, fnameonly = os.path.split(fullfname) + origPath = path + project = "" + retPaths = [fnameonly] + while not project: + iniName = os.path.join(path, g_iniName) + database = win32api.GetProfileVal("Python","Database", "", iniName) + project = win32api.GetProfileVal("Python","Project", "", iniName) + if project: + break; + # No valid INI file in this directory - look up a level. + path, addpath = os.path.split(path) + if not addpath: # Root? + break + retPaths.insert(0, addpath) + if not project: + win32ui.MessageBox("%s\r\n\r\nThis directory is not configured for Python/VSS" % origPath) + return + return project, "/".join(retPaths), database + + +def CheckoutFile(fileName): + global g_sourceSafe + import pythoncom + ok = 0 + # Assumes the fileName has a complete path, + # and that the INI file can be found in that path + # (or a parent path if a ni style package) + try: + import win32com.client, win32com.client.gencache + mod = win32com.client.gencache.EnsureModule('{783CD4E0-9D54-11CF-B8EE-00608CC9A71F}', 0, 5, 0) + if mod is None: + win32ui.MessageBox("VSS does not appear to be installed. The TypeInfo can not be created") + return ok + + rc = FindVssProjectInfo(fileName) + if rc is None: + return + project, vssFname, database = rc + if g_sourceSafe is None: + g_sourceSafe=win32com.client.Dispatch("SourceSafe") + # SS seems a bit wierd. It defaults the arguments as empty strings, but + # then complains when they are used - so we pass "Missing" + if not database: + database = pythoncom.Missing + g_sourceSafe.Open(database, pythoncom.Missing, pythoncom.Missing) + item = g_sourceSafe.VSSItem("$/%s/%s" % (project, vssFname)) + item.Checkout(None, fileName) + ok = 1 + except pythoncom.com_error as exc: + win32ui.MessageBox(exc.strerror, "Error checking out file") + except: + typ, val, tb = sys.exc_info() + traceback.print_exc() + win32ui.MessageBox("%s - %s" % (str(typ), str(val)),"Error checking out file") + tb = None # Cleanup a cycle + return ok + + diff --git a/Lib/site-packages/pythonwin/pywin/framework/help.py b/Lib/site-packages/pythonwin/pywin/framework/help.py new file mode 100644 index 0000000..db47ce4 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/help.py @@ -0,0 +1,151 @@ + # help.py - help utilities for PythonWin. +import win32api +import win32con +import win32ui +import string +import sys +import regutil +import string, os + +htmlhelp_handle = None + +html_help_command_translators = { + win32con.HELP_CONTENTS : 1, # HH_DISPLAY_TOC + win32con.HELP_CONTEXT : 15, # HH_HELP_CONTEXT + win32con.HELP_FINDER : 1, # HH_DISPLAY_TOC +} + +def FinalizeHelp(): + global htmlhelp_handle + if htmlhelp_handle is not None: + import win32help + try: + #frame = win32ui.GetMainFrame().GetSafeHwnd() + frame = 0 + win32help.HtmlHelp(frame, None, win32help.HH_UNINITIALIZE, htmlhelp_handle) + except win32help.error: + print("Failed to finalize htmlhelp!") + htmlhelp_handle = None + +def OpenHelpFile(fileName, helpCmd = None, helpArg = None): + "Open a help file, given a full path" + # default help arg. + win32ui.DoWaitCursor(1) + try: + if helpCmd is None: helpCmd = win32con.HELP_CONTENTS + ext = os.path.splitext(fileName)[1].lower() + if ext == ".hlp": + win32api.WinHelp( win32ui.GetMainFrame().GetSafeHwnd(), fileName, helpCmd, helpArg) + # XXX - using the htmlhelp API wreaks havoc with keyboard shortcuts + # so we disable it, forcing ShellExecute, which works fine (but + # doesn't close the help file when Pythonwin is closed. + # Tom Heller also points out http://www.microsoft.com/mind/0499/faq/faq0499.asp, + # which may or may not be related. + elif 0 and ext == ".chm": + import win32help + global htmlhelp_handle + helpCmd = html_help_command_translators.get(helpCmd, helpCmd) + #frame = win32ui.GetMainFrame().GetSafeHwnd() + frame = 0 # Dont want it overlapping ours! + if htmlhelp_handle is None: + htmlhelp_hwnd, htmlhelp_handle = win32help.HtmlHelp(frame, None, win32help.HH_INITIALIZE) + win32help.HtmlHelp(frame, fileName, helpCmd, helpArg) + else: + # Hope that the extension is registered, and we know what to do! + win32api.ShellExecute(0, "open", fileName, None, "", win32con.SW_SHOW) + return fileName + finally: + win32ui.DoWaitCursor(-1) + +def ListAllHelpFiles(): + ret = [] + ret = _ListAllHelpFilesInRoot(win32con.HKEY_LOCAL_MACHINE) + # Ensure we don't get dups. + for item in _ListAllHelpFilesInRoot(win32con.HKEY_CURRENT_USER): + if item not in ret: + ret.append(item) + return ret + +def _ListAllHelpFilesInRoot(root): + """Returns a list of (helpDesc, helpFname) for all registered help files + """ + import regutil + retList = [] + try: + key = win32api.RegOpenKey(root, regutil.BuildDefaultPythonKey() + "\\Help", 0, win32con.KEY_READ) + except win32api.error as exc: + import winerror + if exc.winerror!=winerror.ERROR_FILE_NOT_FOUND: + raise + return retList + try: + keyNo = 0 + while 1: + try: + helpDesc = win32api.RegEnumKey(key, keyNo) + helpFile = win32api.RegQueryValue(key, helpDesc) + retList.append((helpDesc, helpFile)) + keyNo = keyNo + 1 + except win32api.error as exc: + import winerror + if exc.winerror!=winerror.ERROR_NO_MORE_ITEMS: + raise + break + finally: + win32api.RegCloseKey(key) + return retList + +def SelectAndRunHelpFile(): + from pywin.dialogs import list + helpFiles = ListAllHelpFiles() + if len(helpFiles)==1: + # only 1 help file registered - probably ours - no point asking + index = 0 + else: + index = list.SelectFromLists("Select Help file", helpFiles, ["Title"]) + if index is not None: + OpenHelpFile(helpFiles[index][1]) + + +helpIDMap = None + +def SetHelpMenuOtherHelp(mainMenu): + """Modifies the main Help Menu to handle all registered help files. + mainMenu -- The main menu to modify - usually from docTemplate.GetSharedMenu() + """ + + # Load all help files from the registry. + global helpIDMap + if helpIDMap is None: + helpIDMap = {} + cmdID = win32ui.ID_HELP_OTHER + excludeList = ['Main Python Documentation', 'Pythonwin Reference'] + firstList = ListAllHelpFiles() + # We actually want to not only exclude these entries, but + # their help file names (as many entries may share the same name) + excludeFnames = [] + for desc, fname in firstList: + if desc in excludeList: + excludeFnames.append(fname) + + helpDescs = [] + for desc, fname in firstList: + if fname not in excludeFnames: + helpIDMap[cmdID] = (desc, fname) + win32ui.GetMainFrame().HookCommand(HandleHelpOtherCommand, cmdID) + cmdID = cmdID + 1 + + helpMenu = mainMenu.GetSubMenu(mainMenu.GetMenuItemCount()-1) # Help menu always last. + otherHelpMenuPos = 2 # cant search for ID, as sub-menu has no ID. + otherMenu = helpMenu.GetSubMenu(otherHelpMenuPos) + while otherMenu.GetMenuItemCount(): + otherMenu.DeleteMenu(0, win32con.MF_BYPOSITION) + + if helpIDMap: + for id, (desc, fname) in helpIDMap.items(): + otherMenu.AppendMenu(win32con.MF_ENABLED|win32con.MF_STRING,id, desc) + else: + helpMenu.EnableMenuItem(otherHelpMenuPos, win32con.MF_BYPOSITION | win32con.MF_GRAYED) + +def HandleHelpOtherCommand(cmd, code): + OpenHelpFile(helpIDMap[cmd][1]) diff --git a/Lib/site-packages/pythonwin/pywin/framework/interact.py b/Lib/site-packages/pythonwin/pywin/framework/interact.py new file mode 100644 index 0000000..d80bdcb --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/interact.py @@ -0,0 +1,870 @@ + +################################################################## +## +## Interactive Shell Window +## + +import sys, os +import code +import string + +import win32ui +import win32api +import win32clipboard +import win32con +import traceback +import afxres +import array +import __main__ + +import pywin.scintilla.formatter +import pywin.scintilla.control +import pywin.scintilla.IDLEenvironment +import pywin.framework.app + +## sequential after ID_GOTO_LINE defined in editor.py +ID_EDIT_COPY_CODE = 0xe2002 +ID_EDIT_EXEC_CLIPBOARD = 0x2003 + +trace=pywin.scintilla.formatter.trace + +from . import winout + +import re +# from IDLE. +_is_block_opener = re.compile(r":\s*(#.*)?$").search +_is_block_closer = re.compile(r""" + \s* + ( return + | break + | continue + | raise + | pass + ) + \b +""", re.VERBOSE).match + +tracebackHeader = "Traceback (".encode("ascii") + +sectionProfile = "Interactive Window" +valueFormatTitle = "FormatTitle" +valueFormatInput = "FormatInput" +valueFormatOutput = "FormatOutput" +valueFormatOutputError = "FormatOutputError" + +# These are defaults only. Values are read from the registry. +formatTitle = (-536870897, 0, 220, 0, 16711680, 184, 34, 'Arial') +formatInput = (-402653169, 0, 200, 0, 0, 0, 49, 'Courier New') +formatOutput = (-402653169, 0, 200, 0, 8421376, 0, 49, 'Courier New') +formatOutputError = (-402653169, 0, 200, 0, 255, 0, 49, 'Courier New') + +try: + sys.ps1 +except AttributeError: + sys.ps1 = '>>> ' + sys.ps2 = '... ' + +def LoadPreference(preference, default = ""): + return win32ui.GetProfileVal(sectionProfile, preference, default) + +def SavePreference( prefName, prefValue ): + win32ui.WriteProfileVal( sectionProfile, prefName, prefValue ) + +def GetPromptPrefix(line): + ps1=sys.ps1 + if line[:len(ps1)]==ps1: return ps1 + ps2=sys.ps2 + if line[:len(ps2)]==ps2: return ps2 + +############################################################# +# +# Colorizer related code. +# +############################################################# +STYLE_INTERACTIVE_EOL = "Interactive EOL" +STYLE_INTERACTIVE_OUTPUT = "Interactive Output" +STYLE_INTERACTIVE_PROMPT = "Interactive Prompt" +STYLE_INTERACTIVE_BANNER = "Interactive Banner" +STYLE_INTERACTIVE_ERROR = "Interactive Error" +STYLE_INTERACTIVE_ERROR_FINALLINE = "Interactive Error (final line)" + +INTERACTIVE_STYLES = [STYLE_INTERACTIVE_EOL, STYLE_INTERACTIVE_OUTPUT, STYLE_INTERACTIVE_PROMPT, STYLE_INTERACTIVE_BANNER, STYLE_INTERACTIVE_ERROR, STYLE_INTERACTIVE_ERROR_FINALLINE] + +FormatterParent = pywin.scintilla.formatter.PythonSourceFormatter +class InteractiveFormatter(FormatterParent): + def __init__(self, scintilla): + FormatterParent.__init__(self, scintilla) + self.bannerDisplayed = False + + def SetStyles(self): + FormatterParent.SetStyles(self) + Style = pywin.scintilla.formatter.Style + self.RegisterStyle( Style(STYLE_INTERACTIVE_EOL, STYLE_INTERACTIVE_PROMPT ) ) + self.RegisterStyle( Style(STYLE_INTERACTIVE_PROMPT, formatInput ) ) + self.RegisterStyle( Style(STYLE_INTERACTIVE_OUTPUT, formatOutput) ) + self.RegisterStyle( Style(STYLE_INTERACTIVE_BANNER, formatTitle ) ) + self.RegisterStyle( Style(STYLE_INTERACTIVE_ERROR, formatOutputError ) ) + self.RegisterStyle( Style(STYLE_INTERACTIVE_ERROR_FINALLINE, STYLE_INTERACTIVE_ERROR ) ) + + def LoadPreference(self, name, default): + rc = win32ui.GetProfileVal("Format", name, default) + if rc==default: + rc = win32ui.GetProfileVal(sectionProfile, name, default) + return rc + + def ColorizeInteractiveCode(self, cdoc, styleStart, stylePyStart): + lengthDoc = len(cdoc) + if lengthDoc == 0: return + state = styleStart + # As per comments in Colorize(), we work with the raw utf8 + # bytes. To avoid too muych py3k pain, we treat each utf8 byte + # as a latin-1 unicode character - we only use it to compare + # against ascii chars anyway... + chNext = cdoc[0:1].decode('latin-1') + startSeg = 0 + i = 0 + lastState=state # debug only + while i < lengthDoc: + ch = chNext + chNext = cdoc[i+1:i+2].decode('latin-1') + +# trace("ch=%r, i=%d, next=%r, state=%s" % (ch, i, chNext, state)) + if state == STYLE_INTERACTIVE_EOL: + if ch not in '\r\n': + self.ColorSeg(startSeg, i-1, state) + startSeg = i + if ch in [sys.ps1[0], sys.ps2[0]]: + state = STYLE_INTERACTIVE_PROMPT + elif cdoc[i:i+len(tracebackHeader)]==tracebackHeader: + state = STYLE_INTERACTIVE_ERROR + else: + state = STYLE_INTERACTIVE_OUTPUT + elif state == STYLE_INTERACTIVE_PROMPT: + if ch not in sys.ps1 + sys.ps2 + " ": + self.ColorSeg(startSeg, i-1, state) + startSeg = i + if ch in '\r\n': + state = STYLE_INTERACTIVE_EOL + else: + state = stylePyStart # Start coloring Python code. + elif state in [STYLE_INTERACTIVE_OUTPUT]: + if ch in '\r\n': + self.ColorSeg(startSeg, i-1, state) + startSeg = i + state = STYLE_INTERACTIVE_EOL + elif state == STYLE_INTERACTIVE_ERROR: + if ch in '\r\n' and chNext and chNext not in string.whitespace: + # Everything including me + self.ColorSeg(startSeg, i, state) + startSeg = i+1 + state = STYLE_INTERACTIVE_ERROR_FINALLINE + elif i == 0 and ch not in string.whitespace: + # If we are coloring from the start of a line, + # we need this better check for the last line + # Color up to not including me + self.ColorSeg(startSeg, i-1, state) + startSeg = i + state = STYLE_INTERACTIVE_ERROR_FINALLINE + elif state == STYLE_INTERACTIVE_ERROR_FINALLINE: + if ch in '\r\n': + self.ColorSeg(startSeg, i-1, state) + startSeg = i + state = STYLE_INTERACTIVE_EOL + elif state == STYLE_INTERACTIVE_BANNER: + if ch in '\r\n' and (chNext=='' or chNext in ">["): + # Everything including me + self.ColorSeg(startSeg, i-1, state) + startSeg = i + state = STYLE_INTERACTIVE_EOL + else: + # It is a PythonColorizer state - seek past the end of the line + # and ask the Python colorizer to color that. + end = startSeg + while end < lengthDoc and cdoc[end] not in '\r\n'.encode('ascii'): + end = end + 1 + self.ColorizePythonCode( cdoc[:end], startSeg, state) + stylePyStart = self.GetStringStyle(end-1) + if stylePyStart is None: + stylePyStart = pywin.scintilla.formatter.STYLE_DEFAULT + else: + stylePyStart = stylePyStart.name + startSeg =end + i = end - 1 # ready for increment. + chNext = cdoc[end:end+1].decode('latin-1') + state = STYLE_INTERACTIVE_EOL + if lastState != state: + lastState = state + i = i + 1 + # and the rest + if startSeg 1: + # Likely we are being asked to color from the start of the line. + # We find the last formatted character on the previous line. + # If TQString, we continue it. Otherwise, we reset. + look = start -1 + while look and self.scintilla.SCIGetCharAt(look) in '\n\r': + look = look - 1 + if look and look < start-1: # Did we find a char before the \n\r sets? + strstyle = self.GetStringStyle(look) + quote_char = None + if strstyle is not None: + if strstyle.name == pywin.scintilla.formatter.STYLE_TQSSTRING: + quote_char = "'" + elif strstyle.name == pywin.scintilla.formatter.STYLE_TQDSTRING: + quote_char = '"' + if quote_char is not None: + # It is a TQS. If the TQS is not terminated, we + # carry the style through. + if look > 2: + look_str = self.scintilla.SCIGetCharAt(look-2) + self.scintilla.SCIGetCharAt(look-1) + self.scintilla.SCIGetCharAt(look) + if look_str != quote_char * 3: + stylePyStart = strstyle.name + if stylePyStart is None: stylePyStart = pywin.scintilla.formatter.STYLE_DEFAULT + + if start > 0: + stylenum = self.scintilla.SCIGetStyleAt(start - 1) + styleStart = self.GetStyleByNum(stylenum).name + elif self.bannerDisplayed: + styleStart = STYLE_INTERACTIVE_EOL + else: + styleStart = STYLE_INTERACTIVE_BANNER + self.bannerDisplayed = True + self.scintilla.SCIStartStyling(start, 31) + self.style_buffer = array.array("b", (0,)*len(stringVal)) + self.ColorizeInteractiveCode(stringVal, styleStart, stylePyStart) + self.scintilla.SCISetStylingEx(self.style_buffer) + self.style_buffer = None + +############################################################### +# +# This class handles the Python interactive interpreter. +# +# It uses a basic EditWindow, and does all the magic. +# This is triggered by the enter key hander attached by the +# start-up code. It determines if a command is to be executed +# or continued (ie, emit "... ") by snooping around the current +# line, looking for the prompts +# +class PythonwinInteractiveInterpreter(code.InteractiveInterpreter): + def __init__(self, locals = None, globals = None): + if locals is None: locals = __main__.__dict__ + if globals is None: globals = locals + self.globals = globals + code.InteractiveInterpreter.__init__(self, locals) + def showsyntaxerror(self, filename=None): + sys.stderr.write(tracebackHeader.decode('ascii')) # So the color syntaxer recognises it. + code.InteractiveInterpreter.showsyntaxerror(self, filename) + def runcode(self, code): + try: + exec(code, self.globals, self.locals) + except SystemExit: + raise + except: + self.showtraceback() + +class InteractiveCore: + def __init__(self, banner = None): + self.banner = banner +# LoadFontPreferences() + def Init(self): + self.oldStdOut = self.oldStdErr = None + +# self.SetWordWrap(win32ui.CRichEditView_WrapNone) + self.interp = PythonwinInteractiveInterpreter() + + self.OutputGrab() # Release at cleanup. + + if self.GetTextLength()==0: + if self.banner is None: + suffix = "" + if win32ui.debug: suffix = ", debug build" + sys.stderr.write("PythonWin %s on %s%s.\n" % (sys.version, sys.platform, suffix) ) + sys.stderr.write("Portions %s - see 'Help/About PythonWin' for further copyright information.\n" % (win32ui.copyright,) ) + else: + sys.stderr.write(banner) + rcfile = os.environ.get('PYTHONSTARTUP') + if rcfile: + import __main__ + try: + execfile(rcfile, __main__.__dict__, __main__.__dict__) + except: + sys.stderr.write(">>> \nError executing PYTHONSTARTUP script %r\n" % (rcfile)) + traceback.print_exc(file=sys.stderr) + self.AppendToPrompt([]) + + def SetContext(self, globals, locals, name = "Dbg"): + oldPrompt = sys.ps1 + if globals is None: + # Reset + sys.ps1 = ">>> " + sys.ps2 = "... " + locals = globals = __main__.__dict__ + else: + sys.ps1 = "[%s]>>> " % name + sys.ps2 = "[%s]... " % name + self.interp.locals = locals + self.interp.globals = globals + self.AppendToPrompt([], oldPrompt) + + def GetContext(self): + return self.interp.globals, self.interp.locals + + def DoGetLine(self, line=-1): + if line==-1: line = self.LineFromChar() + line = self.GetLine(line) + while line and line[-1] in ['\r', '\n']: + line = line[:-1] + return line + def AppendToPrompt(self,bufLines, oldPrompt = None): + " Take a command and stick it at the end of the buffer (with python prompts inserted if required)." + self.flush() + lastLineNo = self.GetLineCount()-1 + line = self.DoGetLine(lastLineNo) + if oldPrompt and line==oldPrompt: + self.SetSel(self.GetTextLength()-len(oldPrompt), self.GetTextLength()) + self.ReplaceSel(sys.ps1) + elif (line!=str(sys.ps1)): + if len(line)!=0: self.write('\n') + self.write(sys.ps1) + self.flush() + self.idle.text.mark_set("iomark", "end-1c") + if not bufLines: + return + terms = (["\n" + sys.ps2] * (len(bufLines)-1)) + [''] + for bufLine, term in zip(bufLines, terms): + if bufLine.strip(): + self.write( bufLine + term ) + self.flush() + + def EnsureNoPrompt(self): + # Get ready to write some text NOT at a Python prompt. + self.flush() + lastLineNo = self.GetLineCount()-1 + line = self.DoGetLine(lastLineNo) + if not line or line in [sys.ps1, sys.ps2]: + self.SetSel(self.GetTextLength()-len(line), self.GetTextLength()) + self.ReplaceSel('') + else: + # Just add a new line. + self.write('\n') + + def _GetSubConfigNames(self): + return ["interactive"] # Allow [Keys:Interactive] sections to be specific + + def HookHandlers(self): + # Hook menu command (executed when a menu item with that ID is selected from a menu/toolbar + self.HookCommand(self.OnSelectBlock, win32ui.ID_EDIT_SELECT_BLOCK) + self.HookCommand(self.OnEditCopyCode, ID_EDIT_COPY_CODE) + self.HookCommand(self.OnEditExecClipboard, ID_EDIT_EXEC_CLIPBOARD) + mod = pywin.scintilla.IDLEenvironment.GetIDLEModule("IdleHistory") + if mod is not None: + self.history = mod.History(self.idle.text, "\n" + sys.ps2) + else: + self.history = None + # hack for now for event handling. + + # GetBlockBoundary takes a line number, and will return the + # start and and line numbers of the block, and a flag indicating if the + # block is a Python code block. + # If the line specified has a Python prompt, then the lines are parsed + # backwards and forwards, and the flag is true. + # If the line does not start with a prompt, the block is searched forward + # and backward until a prompt _is_ found, and all lines in between without + # prompts are returned, and the flag is false. + def GetBlockBoundary( self, lineNo ): + line = self.DoGetLine(lineNo) + maxLineNo = self.GetLineCount()-1 + prefix = GetPromptPrefix(line) + if prefix is None: # Non code block + flag = 0 + startLineNo = lineNo + while startLineNo>0: + if GetPromptPrefix(self.DoGetLine(startLineNo-1)) is not None: + break # there _is_ a prompt + startLineNo = startLineNo-1 + endLineNo = lineNo + while endLineNo0 and prefix!=str(sys.ps1): + prefix = GetPromptPrefix(self.DoGetLine(startLineNo-1)) + if prefix is None: + break; # there is no prompt. + startLineNo = startLineNo - 1 + endLineNo = lineNo + while endLineNo= start: + thisLine = self.DoGetLine(end) + promptLen = len(GetPromptPrefix(thisLine)) + retList = [thisLine[promptLen:]] + retList + end = end-1 + return retList + + def OutputGrab(self): +# import win32traceutil; return + self.oldStdOut = sys.stdout + self.oldStdErr = sys.stderr + sys.stdout=self + sys.stderr=self + self.flush() + + def OutputRelease(self): + # a command may have overwritten these - only restore if not. + if self.oldStdOut is not None: + if sys.stdout == self: + sys.stdout=self.oldStdOut + if self.oldStdErr is not None: + if sys.stderr == self: + sys.stderr=self.oldStdErr + self.oldStdOut = None + self.oldStdErr = None + self.flush() + + ################################### + # + # Message/Command/Key Hooks. + # + # Enter key handler + # + def ProcessEnterEvent(self, event ): + #If autocompletion has been triggered, complete and do not process event + if self.SCIAutoCActive(): + self.SCIAutoCComplete() + self.SCICancel() + return + + self.SCICancel() + # First, check for an error message + haveGrabbedOutput = 0 + if self.HandleSpecialLine(): return 0 + + lineNo = self.LineFromChar() + start, end, isCode = self.GetBlockBoundary(lineNo) + # If we are not in a code block just go to the prompt (or create a new one) + if not isCode: + self.AppendToPrompt([]) + win32ui.SetStatusText(win32ui.LoadString(afxres.AFX_IDS_IDLEMESSAGE)) + return + + lines = self.ExtractCommand((start,end)) + + # If we are in a code-block, but it isnt at the end of the buffer + # then copy it to the end ready for editing and subsequent execution + if end!=self.GetLineCount()-1: + win32ui.SetStatusText('Press ENTER to execute command') + self.AppendToPrompt(lines) + self.SetSel(-2) + return + + # If SHIFT held down, we want new code here and now! + bNeedIndent = win32api.GetKeyState(win32con.VK_SHIFT)<0 or win32api.GetKeyState(win32con.VK_CONTROL)<0 + if bNeedIndent: + self.ReplaceSel("\n") + else: + self.SetSel(-2) + self.ReplaceSel("\n") + source = '\n'.join(lines) + while source and source[-1] in '\t ': + source = source[:-1] + self.OutputGrab() # grab the output for the command exec. + try: + if self.interp.runsource(source, ""): # Need more input! + bNeedIndent = 1 + else: + # If the last line isnt empty, append a newline + if self.history is not None: + self.history.history_store(source) + self.AppendToPrompt([]) + win32ui.SetStatusText(win32ui.LoadString(afxres.AFX_IDS_IDLEMESSAGE)) +# win32ui.SetStatusText('Successfully executed statement') + finally: + self.OutputRelease() + if bNeedIndent: + win32ui.SetStatusText('Ready to continue the command') + # Now attempt correct indentation (should use IDLE?) + curLine = self.DoGetLine(lineNo)[len(sys.ps2):] + pos = 0 + indent='' + while len(curLine)>pos and curLine[pos] in string.whitespace: + indent = indent + curLine[pos] + pos = pos + 1 + if _is_block_opener(curLine): + indent = indent + '\t' + elif _is_block_closer(curLine): + indent = indent[:-1] + # use ReplaceSel to ensure it goes at the cursor rather than end of buffer. + self.ReplaceSel(sys.ps2+indent) + return 0 + + # ESC key handler + def ProcessEscEvent(self, event): + # Implement a cancel. + if self.SCIAutoCActive() or self.SCICallTipActive(): + self.SCICancel() + else: + win32ui.SetStatusText('Cancelled.') + self.AppendToPrompt(('',)) + return 0 + + def OnSelectBlock(self,command, code): + lineNo = self.LineFromChar() + start, end, isCode = self.GetBlockBoundary(lineNo) + startIndex = self.LineIndex(start) + endIndex = self.LineIndex(end+1)-2 # skip \r + \n + if endIndex<0: # must be beyond end of buffer + endIndex = -2 # self.Length() + self.SetSel(startIndex,endIndex) + + def OnEditCopyCode(self, command, code): + """ Sanitizes code from interactive window, removing prompts and output, + and inserts it in the clipboard.""" + code=self.GetSelText() + lines=code.splitlines() + out_lines=[] + for line in lines: + if line.startswith(sys.ps1): + line=line[len(sys.ps1):] + out_lines.append(line) + elif line.startswith(sys.ps2): + line=line[len(sys.ps2):] + out_lines.append(line) + out_code=os.linesep.join(out_lines) + win32clipboard.OpenClipboard() + try: + win32clipboard.SetClipboardData(win32clipboard.CF_UNICODETEXT, str(out_code)) + finally: + win32clipboard.CloseClipboard() + + def OnEditExecClipboard(self, command, code): + """ Executes python code directly from the clipboard.""" + win32clipboard.OpenClipboard() + try: + code=win32clipboard.GetClipboardData(win32clipboard.CF_UNICODETEXT) + finally: + win32clipboard.CloseClipboard() + + code=code.replace('\r\n','\n')+'\n' + try: + o=compile(code, '', 'exec') + exec(o, __main__.__dict__) + except: + traceback.print_exc() + + def GetRightMenuItems(self): + # Just override parents + ret = [] + flags = 0 + ret.append((flags, win32ui.ID_EDIT_UNDO, '&Undo')) + ret.append(win32con.MF_SEPARATOR) + ret.append((flags, win32ui.ID_EDIT_CUT, 'Cu&t')) + ret.append((flags, win32ui.ID_EDIT_COPY, '&Copy')) + + start, end=self.GetSel() + if start!=end: + ret.append((flags, ID_EDIT_COPY_CODE, 'Copy code without prompts')) + if win32clipboard.IsClipboardFormatAvailable(win32clipboard.CF_UNICODETEXT): + ret.append((flags, ID_EDIT_EXEC_CLIPBOARD, 'Execute python code from clipboard')) + + ret.append((flags, win32ui.ID_EDIT_PASTE, '&Paste')) + ret.append(win32con.MF_SEPARATOR) + ret.append((flags, win32ui.ID_EDIT_SELECT_ALL, '&Select all')) + ret.append((flags, win32ui.ID_EDIT_SELECT_BLOCK, 'Select &block')) + ret.append((flags, win32ui.ID_VIEW_WHITESPACE, "View &Whitespace")) + return ret + + def MDINextEvent(self, event): + win32ui.GetMainFrame().MDINext(0) + def MDIPrevEvent(self, event): + win32ui.GetMainFrame().MDINext(0) + + def WindowBackEvent(self, event): + parent = self.GetParentFrame() + if parent == win32ui.GetMainFrame(): + # It is docked. + try: + wnd, isactive = parent.MDIGetActive() + wnd.SetFocus() + except win32ui.error: + # No MDI window active! + pass + else: + # Normal Window + try: + lastActive = self.GetParentFrame().lastActive + # If the window is invalid, reset it. + if lastActive is not None and (lastActive._obj_ is None or lastActive.GetSafeHwnd()==0): + lastActive = self.GetParentFrame().lastActive = None + win32ui.SetStatusText("The last active Window has been closed.") + except AttributeError: + print("Can't find the last active window!") + lastActive = None + if lastActive is not None: + lastActive.MDIActivate() + +class InteractiveView(InteractiveCore, winout.WindowOutputView): + def __init__(self, doc): + InteractiveCore.__init__(self) + winout.WindowOutputView.__init__(self, doc) + self.encoding = pywin.default_scintilla_encoding + + def _MakeColorizer(self): + return InteractiveFormatter(self) + def OnInitialUpdate(self): + winout.WindowOutputView.OnInitialUpdate(self) + self.SetWordWrap() + self.Init() + def HookHandlers(self): + winout.WindowOutputView.HookHandlers(self) + InteractiveCore.HookHandlers(self) + +class CInteractivePython(winout.WindowOutput): + def __init__(self, makeDoc = None, makeFrame = None): + self.IsFinalDestroy = 0 + winout.WindowOutput.__init__(self, sectionProfile, sectionProfile, \ + winout.flags.WQ_LINE, 1, None, makeDoc, makeFrame, InteractiveView ) + self.Create() + + def OnViewDestroy(self, view): + if self.IsFinalDestroy: + view.OutputRelease() + winout.WindowOutput.OnViewDestroy(self, view) + + def Close(self): + self.IsFinalDestroy = 1 + winout.WindowOutput.Close(self) + +class InteractiveFrame(winout.WindowOutputFrame): + def __init__(self): + self.lastActive = None + winout.WindowOutputFrame.__init__(self) + + def OnMDIActivate(self, bActive, wndActive, wndDeactive): + if bActive: + self.lastActive = wndDeactive + +###################################################################### +## +## Dockable Window Support +## +###################################################################### +ID_DOCKED_INTERACTIVE_CONTROLBAR = 0xe802 + +DockedInteractiveViewParent = InteractiveView +class DockedInteractiveView(DockedInteractiveViewParent): + def HookHandlers(self): + DockedInteractiveViewParent.HookHandlers(self) + self.HookMessage(self.OnSetFocus, win32con.WM_SETFOCUS) + self.HookMessage(self.OnKillFocus, win32con.WM_KILLFOCUS) + def OnSetFocus(self, msg): + self.GetParentFrame().SetActiveView(self) + return 1 + def OnKillFocus(self, msg): + # If we are losing focus to another in this app, reset the main frame's active view. + hwnd = wparam = msg[2] + try: + wnd = win32ui.CreateWindowFromHandle(hwnd) + reset = wnd.GetTopLevelFrame()==self.GetTopLevelFrame() + except win32ui.error: + reset = 0 # Not my window + if reset: self.GetParentFrame().SetActiveView(None) + return 1 + def OnDestroy(self, msg): + newSize = self.GetWindowPlacement()[4] + pywin.framework.app.SaveWindowSize("Interactive Window", newSize, "docked") + try: + if self.GetParentFrame().GetActiveView==self: + self.GetParentFrame().SetActiveView(None) + except win32ui.error: + pass + try: + if win32ui.GetMainFrame().GetActiveView()==self: + win32ui.GetMainFrame().SetActiveView(None) + except win32ui.error: + pass + return DockedInteractiveViewParent.OnDestroy(self, msg) + +class CDockedInteractivePython(CInteractivePython): + def __init__(self, dockbar): + self.bFirstCreated = 0 + self.dockbar = dockbar + CInteractivePython.__init__(self) + def NeedRecreateWindow(self): + if self.bCreating: + return 0 + try: + frame = win32ui.GetMainFrame() + if frame.closing: + return 0 # Dieing! + except (win32ui.error, AttributeError): + return 0 # The app is dieing! + try: + cb = frame.GetControlBar(ID_DOCKED_INTERACTIVE_CONTROLBAR) + return not cb.IsWindowVisible() + except win32ui.error: + return 1 # Control bar does not exist! + def RecreateWindow(self): + try: + dockbar = win32ui.GetMainFrame().GetControlBar(ID_DOCKED_INTERACTIVE_CONTROLBAR) + win32ui.GetMainFrame().ShowControlBar(dockbar, 1, 1) + except win32ui.error: + CreateDockedInteractiveWindow() + + def Create(self): + self.bCreating = 1 + doc = InteractiveDocument(None, self.DoCreateDoc()) + view = DockedInteractiveView(doc) + defRect = pywin.framework.app.LoadWindowSize("Interactive Window", "docked") + if defRect[2]-defRect[0]==0: + defRect = 0, 0, 500, 200 + style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_BORDER + id = 1050 # win32ui.AFX_IDW_PANE_FIRST + view.CreateWindow(self.dockbar, id, style, defRect) + view.OnInitialUpdate() + self.bFirstCreated = 1 + + self.currentView = doc.GetFirstView() + self.bCreating = 0 + if self.title: doc.SetTitle(self.title) + +# The factory we pass to the dockable window support. +def InteractiveViewCreator(parent): + global edit + edit = CDockedInteractivePython(parent) + return edit.currentView + +def CreateDockedInteractiveWindow(): + # Later, the DockingBar should be capable of hosting multiple + # children. + from pywin.docking.DockingBar import DockingBar + bar = DockingBar() + creator = InteractiveViewCreator + bar.CreateWindow(win32ui.GetMainFrame(), creator, "Interactive Window", ID_DOCKED_INTERACTIVE_CONTROLBAR) + bar.SetBarStyle( bar.GetBarStyle()|afxres.CBRS_TOOLTIPS|afxres.CBRS_FLYBY|afxres.CBRS_SIZE_DYNAMIC) + bar.EnableDocking(afxres.CBRS_ALIGN_ANY) + win32ui.GetMainFrame().DockControlBar(bar, afxres.AFX_IDW_DOCKBAR_BOTTOM) + +###################################################################### +# +# The public interface to this module. +# +###################################################################### +# No extra functionality now, but maybe later, so +# publicize these names. +InteractiveDocument = winout.WindowOutputDocument + +# We remember our one and only interactive window in the "edit" variable. +edit = None + +def CreateInteractiveWindowUserPreference(makeDoc = None, makeFrame = None): + """Create some sort of interactive window if the user's preference say we should. + """ + bCreate = LoadPreference("Show at startup", 1) + if bCreate: + CreateInteractiveWindow(makeDoc, makeFrame) + +def CreateInteractiveWindow(makeDoc = None, makeFrame = None): + """Create a standard or docked interactive window unconditionally + """ + assert edit is None, "Creating second interactive window!" + bDocking = LoadPreference("Docking", 0) + if bDocking: + CreateDockedInteractiveWindow() + else: + CreateMDIInteractiveWindow(makeDoc, makeFrame) + assert edit is not None, "Created interactive window, but did not set the global!" + edit.currentView.SetFocus() + +def CreateMDIInteractiveWindow(makeDoc = None, makeFrame = None): + """Create a standard (non-docked) interactive window unconditionally + """ + global edit + if makeDoc is None: makeDoc = InteractiveDocument + if makeFrame is None: makeFrame = InteractiveFrame + edit = CInteractivePython(makeDoc=makeDoc,makeFrame=makeFrame) + +def DestroyInteractiveWindow(): + """ Destroy the interactive window. + This is different to Closing the window, + which may automatically re-appear. Once destroyed, it can never be recreated, + and a complete new instance must be created (which the various other helper + functions will then do after making this call + """ + global edit + if edit is not None and edit.currentView is not None: + if edit.currentView.GetParentFrame() == win32ui.GetMainFrame(): + # It is docked - do nothing now (this is only called at shutdown!) + pass + else: + # It is a standard window - call Close on the container. + edit.Close() + edit = None + +def CloseInteractiveWindow(): + """Close the interactive window, allowing it to be re-created on demand. + """ + global edit + if edit is not None and edit.currentView is not None: + if edit.currentView.GetParentFrame() == win32ui.GetMainFrame(): + # It is docked, just hide the dock bar. + frame = win32ui.GetMainFrame() + cb = frame.GetControlBar(ID_DOCKED_INTERACTIVE_CONTROLBAR) + frame.ShowControlBar(cb, 0, 1) + else: + # It is a standard window - destroy the frame/view, allowing the object itself to remain. + edit.currentView.GetParentFrame().DestroyWindow() + +def ToggleInteractiveWindow(): + """If the interactive window is visible, hide it, otherwise show it. + """ + if edit is None: + CreateInteractiveWindow() + else: + if edit.NeedRecreateWindow(): + edit.RecreateWindow() + else: + # Close it, allowing a reopen. + CloseInteractiveWindow() + +def ShowInteractiveWindow(): + """Shows (or creates if necessary) an interactive window""" + if edit is None: + CreateInteractiveWindow() + else: + if edit.NeedRecreateWindow(): + edit.RecreateWindow() + else: + parent = edit.currentView.GetParentFrame() + if parent == win32ui.GetMainFrame(): # It is docked. + edit.currentView.SetFocus() + else: # It is a "normal" window + edit.currentView.GetParentFrame().AutoRestore() + win32ui.GetMainFrame().MDIActivate(edit.currentView.GetParentFrame()) + +def IsInteractiveWindowVisible(): + return edit is not None and not edit.NeedRecreateWindow() diff --git a/Lib/site-packages/pythonwin/pywin/framework/intpyapp.py b/Lib/site-packages/pythonwin/pywin/framework/intpyapp.py new file mode 100644 index 0000000..0bcf36e --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/intpyapp.py @@ -0,0 +1,447 @@ +# intpyapp.py - Interactive Python application class +# +import win32con +import win32api +import win32ui +import __main__ +import sys +import string +from . import app +import traceback +from pywin.mfc import window, afxres, dialog +import commctrl +from . import dbgcommands + +lastLocateFileName = ".py" # used in the "File/Locate" dialog... + +# todo - _SetupSharedMenu should be moved to a framework class. +def _SetupSharedMenu_(self): + sharedMenu = self.GetSharedMenu() + from pywin.framework import toolmenu + toolmenu.SetToolsMenu(sharedMenu) + from pywin.framework import help + help.SetHelpMenuOtherHelp(sharedMenu) +from pywin.mfc import docview +docview.DocTemplate._SetupSharedMenu_=_SetupSharedMenu_ + +class MainFrame(app.MainFrame): + def OnCreate(self, createStruct): + self.closing = 0 + if app.MainFrame.OnCreate(self, createStruct)==-1: + return -1 + style = win32con.WS_CHILD | afxres.CBRS_SIZE_DYNAMIC | afxres.CBRS_TOP | afxres.CBRS_TOOLTIPS | afxres.CBRS_FLYBY + + self.EnableDocking(afxres.CBRS_ALIGN_ANY) + + tb = win32ui.CreateToolBar (self, style | win32con.WS_VISIBLE) + tb.ModifyStyle(0, commctrl.TBSTYLE_FLAT) + tb.LoadToolBar(win32ui.IDR_MAINFRAME) + tb.EnableDocking(afxres.CBRS_ALIGN_ANY) + tb.SetWindowText("Standard") + self.DockControlBar(tb) + # Any other packages which use toolbars + from pywin.debugger.debugger import PrepareControlBars + PrepareControlBars(self) + # Note "interact" also uses dockable windows, but they already happen + + # And a "Tools" menu on the main frame. + menu = self.GetMenu() + from . import toolmenu + toolmenu.SetToolsMenu(menu, 2) + # And fix the "Help" menu on the main frame + from pywin.framework import help + help.SetHelpMenuOtherHelp(menu) + + def OnClose(self): + try: + import pywin.debugger + if pywin.debugger.currentDebugger is not None and pywin.debugger.currentDebugger.pumping: + try: + pywin.debugger.currentDebugger.close(1) + except: + traceback.print_exc() + return + except win32ui.error: + pass + self.closing = 1 + self.SaveBarState("ToolbarDefault") + self.SetActiveView(None) # Otherwise MFC's OnClose may _not_ prompt for save. + + from pywin.framework import help + help.FinalizeHelp() + + self.DestroyControlBar(afxres.AFX_IDW_TOOLBAR) + self.DestroyControlBar(win32ui.ID_VIEW_TOOLBAR_DBG) + + return self._obj_.OnClose() + + def DestroyControlBar(self, id): + try: + bar = self.GetControlBar(id) + except win32ui.error: + return + bar.DestroyWindow() + + def OnCommand(self, wparam, lparam): + # By default, the current MDI child frame will process WM_COMMAND + # messages before any docked control bars - even if the control bar + # has focus. This is a problem for the interactive window when docked. + # Therefore, we detect the situation of a view having the main frame + # as its parent, and assume it must be a docked view (which it will in an MDI app) + try: + v = self.GetActiveView() # Raise an exception if none - good - then we want default handling + # Main frame _does_ have a current view (ie, a docking view) - see if it wants it. + if v.OnCommand(wparam, lparam): + return 1 + except (win32ui.error, AttributeError): + pass + return self._obj_.OnCommand(wparam, lparam) + +class InteractivePythonApp(app.CApp): + # This works if necessary - just we dont need to override the Run method. +# def Run(self): +# return self._obj_.Run() + + def HookCommands(self): + app.CApp.HookCommands(self) + dbgcommands.DebuggerCommandHandler().HookCommands() + self.HookCommand(self.OnViewBrowse,win32ui.ID_VIEW_BROWSE) + self.HookCommand(self.OnFileImport,win32ui.ID_FILE_IMPORT) + self.HookCommand(self.OnFileCheck,win32ui.ID_FILE_CHECK) + self.HookCommandUpdate(self.OnUpdateFileCheck, win32ui.ID_FILE_CHECK) + self.HookCommand(self.OnFileRun,win32ui.ID_FILE_RUN) + self.HookCommand(self.OnFileLocate,win32ui.ID_FILE_LOCATE) + self.HookCommand(self.OnInteractiveWindow, win32ui.ID_VIEW_INTERACTIVE) + self.HookCommandUpdate(self.OnUpdateInteractiveWindow, win32ui.ID_VIEW_INTERACTIVE) + self.HookCommand(self.OnViewOptions, win32ui.ID_VIEW_OPTIONS) + self.HookCommand(self.OnHelpIndex, afxres.ID_HELP_INDEX) + self.HookCommand(self.OnFileSaveAll, win32ui.ID_FILE_SAVE_ALL) + self.HookCommand(self.OnViewToolbarDbg, win32ui.ID_VIEW_TOOLBAR_DBG) + self.HookCommandUpdate(self.OnUpdateViewToolbarDbg, win32ui.ID_VIEW_TOOLBAR_DBG) + + def CreateMainFrame(self): + return MainFrame() + + def MakeExistingDDEConnection(self): + # Use DDE to connect to an existing instance + # Return None if no existing instance + try: + from . import intpydde + except ImportError: + # No dde support! + return None + conv = intpydde.CreateConversation(self.ddeServer) + try: + conv.ConnectTo("Pythonwin", "System") + return conv + except intpydde.error: + return None + + def InitDDE(self): + # Do all the magic DDE handling. + # Returns TRUE if we have pumped the arguments to our + # remote DDE app, and we should terminate. + try: + from . import intpydde + except ImportError: + self.ddeServer = None + intpydde = None + if intpydde is not None: + self.ddeServer = intpydde.DDEServer(self) + self.ddeServer.Create("Pythonwin", intpydde.CBF_FAIL_SELFCONNECTIONS ) + try: + # If there is an existing instance, pump the arguments to it. + connection = self.MakeExistingDDEConnection() + if connection is not None: + if self.ProcessArgs(sys.argv, connection) is None: + return 1 + except: + # It is too early to 'print' an exception - we + # don't have stdout setup yet! + win32ui.DisplayTraceback(sys.exc_info(), " - error in DDE conversation with Pythonwin") + + def InitInstance(self): + # Allow "/nodde" and "/new" to optimize this! + if "/nodde" not in sys.argv and "/new" not in sys.argv: + if self.InitDDE(): + return 1 # A remote DDE client is doing it for us! + else: + self.ddeServer = None + + win32ui.SetRegistryKey("Python %s" % (sys.winver,)) # MFC automatically puts the main frame caption on! + app.CApp.InitInstance(self) + + # Create the taskbar icon + win32ui.CreateDebuggerThread() + + # Allow Pythonwin to host OCX controls. + win32ui.EnableControlContainer() + + # Display the interactive window if the user wants it. + from . import interact + interact.CreateInteractiveWindowUserPreference() + + # Load the modules we use internally. + self.LoadSystemModules() + + # Load additional module the user may want. + self.LoadUserModules() + + # Load the ToolBar state near the end of the init process, as + # there may be Toolbar IDs created by the user or other modules. + # By now all these modules should be loaded, so all the toolbar IDs loaded. + try: + self.frame.LoadBarState("ToolbarDefault") + except win32ui.error: + # MFC sucks. It does essentially "GetDlgItem(x)->Something", so if the + # toolbar with ID x does not exist, MFC crashes! Pythonwin has a trap for this + # but I need to investigate more how to prevent it (AFAIK, ensuring all the + # toolbars are created by now _should_ stop it!) + pass + + # Finally process the command line arguments. + self.ProcessArgs(sys.argv) + + def ExitInstance(self): + win32ui.DestroyDebuggerThread() + try: + from . import interact + interact.DestroyInteractiveWindow() + except: + pass + if self.ddeServer is not None: + self.ddeServer.Shutdown() + self.ddeServer = None + return app.CApp.ExitInstance(self) + + def Activate(self): + # Bring to the foreground. Mainly used when another app starts up, it asks + # this one to activate itself, then it terminates. + frame = win32ui.GetMainFrame() + frame.SetForegroundWindow() + if frame.GetWindowPlacement()[1]==win32con.SW_SHOWMINIMIZED: + frame.ShowWindow(win32con.SW_RESTORE) + + def ProcessArgs(self, args, dde = None): + # If we are going to talk to a remote app via DDE, then + # activate it! + if dde is not None: dde.Exec("self.Activate()") + if len(args) and args[0] in ['/nodde','/new']: del args[0] # already handled. + if len(args)<1 or not args[0]: # argv[0]=='' when started without args, just like Python.exe! + return + try: + if args[0] and args[0][0]!='/': + argStart = 0 + argType = win32ui.GetProfileVal("Python","Default Arg Type","/edit").lower() + else: + argStart = 1 + argType = args[0] + if argStart >= len(args): + raise TypeError("The command line requires an additional arg.") + if argType=="/edit": + # Load up the default application. + if dde: + fname = win32api.GetFullPathName(args[argStart]) + dde.Exec("win32ui.GetApp().OpenDocumentFile(%s)" % (repr(fname))) + else: + win32ui.GetApp().OpenDocumentFile(args[argStart]) + elif argType=="/rundlg": + if dde: + dde.Exec("from pywin.framework import scriptutils;scriptutils.RunScript('%s', '%s', 1)" % (args[argStart], ' '.join(args[argStart+1:]))) + else: + from . import scriptutils + scriptutils.RunScript(args[argStart], ' '.join(args[argStart+1:])) + elif argType=="/run": + if dde: + dde.Exec("from pywin.framework import scriptutils;scriptutils.RunScript('%s', '%s', 0)" % (args[argStart], ' '.join(args[argStart+1:]))) + else: + from . import scriptutils + scriptutils.RunScript(args[argStart], ' '.join(args[argStart+1:]), 0) + elif argType=="/app": + raise RuntimeError("/app only supported for new instances of Pythonwin.exe") + elif argType=='/dde': # Send arbitary command + if dde is not None: + dde.Exec(args[argStart]) + else: + win32ui.MessageBox("The /dde command can only be used\r\nwhen Pythonwin is already running") + else: + raise TypeError("Command line arguments not recognised") + except: + # too early for print anything. + win32ui.DisplayTraceback(sys.exc_info(), " - error processing command line args") + + + def LoadSystemModules(self): + self.DoLoadModules("pywin.framework.editor,pywin.framework.stdin") + + def LoadUserModules(self, moduleNames = None): + # Load the users modules. + if moduleNames is None: + default = "pywin.framework.sgrepmdi,pywin.framework.mdi_pychecker" + moduleNames=win32ui.GetProfileVal('Python','Startup Modules',default) + self.DoLoadModules(moduleNames) + + def DoLoadModules(self, moduleNames): # ", sep string of module names. + if not moduleNames: return + modules = moduleNames.split(",") + for module in modules: + try: + __import__(module) + except: # Catch em all, else the app itself dies! 'ImportError: + traceback.print_exc() + msg = 'Startup import of user module "%s" failed' % module + print(msg) + win32ui.MessageBox(msg) + + # + # DDE Callback + # + def OnDDECommand(self, command): + try: + exec(command + "\n") + except: + print("ERROR executing DDE command: ", command) + traceback.print_exc() + raise + + # + # General handlers + # + def OnViewBrowse( self, id, code ): + " Called when ViewBrowse message is received " + from pywin.mfc import dialog + from pywin.tools import browser + obName = dialog.GetSimpleInput('Object', '__builtins__', 'Browse Python Object') + if obName is None: + return + try: + browser.Browse(eval(obName, __main__.__dict__, __main__.__dict__)) + except NameError: + win32ui.MessageBox('This is no object with this name') + except AttributeError: + win32ui.MessageBox('The object has no attribute of that name') + except: + traceback.print_exc() + win32ui.MessageBox('This object can not be browsed') + + def OnFileImport( self, id, code ): + " Called when a FileImport message is received. Import the current or specified file" + from . import scriptutils + scriptutils.ImportFile() + + def OnFileCheck( self, id, code ): + " Called when a FileCheck message is received. Check the current file." + from . import scriptutils + scriptutils.CheckFile() + + def OnUpdateFileCheck(self, cmdui): + from . import scriptutils + cmdui.Enable( scriptutils.GetActiveFileName(0) is not None ) + + def OnFileRun( self, id, code ): + " Called when a FileRun message is received. " + from . import scriptutils + showDlg = win32api.GetKeyState(win32con.VK_SHIFT) >= 0 + scriptutils.RunScript(None, None, showDlg) + + def OnFileLocate( self, id, code ): + from pywin.mfc import dialog + from . import scriptutils + import os + global lastLocateFileName # save the new version away for next time... + + name = dialog.GetSimpleInput('File name', lastLocateFileName, 'Locate Python File') + if name is None: # Cancelled. + return + lastLocateFileName = name + # if ".py" supplied, rip it off! + # should also check for .pys and .pyw + if lastLocateFileName[-3:].lower()=='.py': + lastLocateFileName = lastLocateFileName[:-3] + lastLocateFileName = lastLocateFileName.replace(".","\\") + newName = scriptutils.LocatePythonFile(lastLocateFileName) + if newName is None: + win32ui.MessageBox("The file '%s' can not be located" % lastLocateFileName) + else: + win32ui.GetApp().OpenDocumentFile(newName) + + # Display all the "options" proprety pages we can find + def OnViewOptions(self, id, code): + win32ui.InitRichEdit() + sheet = dialog.PropertySheet("Pythonwin Options") + # Add property pages we know about that need manual work. + from pywin.dialogs import ideoptions + sheet.AddPage( ideoptions.OptionsPropPage() ) + + from . import toolmenu + sheet.AddPage( toolmenu.ToolMenuPropPage() ) + + # Get other dynamic pages from templates. + pages = [] + for template in self.GetDocTemplateList(): + try: + # Dont actually call the function with the exception handler. + getter = template.GetPythonPropertyPages + except AttributeError: + # Template does not provide property pages! + continue + pages = pages + getter() + + # Debugger template goes at the end + try: + from pywin.debugger import configui + except ImportError: + configui = None + if configui is not None: pages.append(configui.DebuggerOptionsPropPage()) + # Now simply add the pages, and display the dialog. + for page in pages: + sheet.AddPage(page) + + if sheet.DoModal()==win32con.IDOK: + win32ui.SetStatusText("Applying configuration changes...", 1) + win32ui.DoWaitCursor(1) + # Tell every Window in our app that win.ini has changed! + win32ui.GetMainFrame().SendMessageToDescendants(win32con.WM_WININICHANGE, 0, 0) + win32ui.DoWaitCursor(0) + + def OnInteractiveWindow(self, id, code): + # toggle the existing state. + from . import interact + interact.ToggleInteractiveWindow() + + def OnUpdateInteractiveWindow(self, cmdui): + try: + interact=sys.modules['pywin.framework.interact'] + state = interact.IsInteractiveWindowVisible() + except KeyError: # Interactive module hasnt ever been imported. + state = 0 + cmdui.Enable() + cmdui.SetCheck(state) + + def OnFileSaveAll(self, id, code): + # Only attempt to save editor documents. + from pywin.framework.editor import editorTemplate + num = 0 + for doc in editorTemplate.GetDocumentList(): + if doc.IsModified() and doc.GetPathName(): + num = num = 1 + doc.OnSaveDocument(doc.GetPathName()) + win32ui.SetStatusText("%d documents saved" % num, 1) + + def OnViewToolbarDbg(self, id, code): + if code==0: + return not win32ui.GetMainFrame().OnBarCheck(id) + + def OnUpdateViewToolbarDbg(self, cmdui): + win32ui.GetMainFrame().OnUpdateControlBarMenu(cmdui) + cmdui.Enable(1) + + def OnHelpIndex( self, id, code ): + from . import help + help.SelectAndRunHelpFile() + +# As per the comments in app.py, this use is depreciated. +# app.AppBuilder = InteractivePythonApp + +# Now all we do is create the application +thisApp = InteractivePythonApp() diff --git a/Lib/site-packages/pythonwin/pywin/framework/intpydde.py b/Lib/site-packages/pythonwin/pywin/framework/intpydde.py new file mode 100644 index 0000000..4939f9f --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/intpydde.py @@ -0,0 +1,56 @@ +# DDE support for Pythonwin +# +# Seems to work fine (in the context that IE4 seems to have broken +# DDE on _all_ NT4 machines I have tried, but only when a "Command Prompt" window +# is open. Strange, but true. If you have problems with this, close all Command Prompts! + + +import win32ui +import win32api, win32con +from pywin.mfc import object +from dde import * +import sys, traceback + +class DDESystemTopic(object.Object): + def __init__(self, app): + self.app = app + object.Object.__init__(self, CreateServerSystemTopic()) + def Exec(self, data): + try: +# print "Executing", cmd + self.app.OnDDECommand(data) + except: + t,v,tb = sys.exc_info() + # The DDE Execution failed. + print("Error executing DDE command.") + traceback.print_exception(t,v,tb) + return 0 + +class DDEServer(object.Object): + def __init__(self, app): + self.app = app + object.Object.__init__(self, CreateServer()) + self.topic = self.item = None + + def CreateSystemTopic(self): + return DDESystemTopic(self.app) + + def Shutdown(self): + self._obj_.Shutdown() + self._obj_.Destroy() + if self.topic is not None: + self.topic.Destroy() + self.topic = None + if self.item is not None: + self.item.Destroy() + self.item = None + + def OnCreate(self): + return 1 + + def Status(self, msg): + try: + win32ui.SetStatusText(msg) + except win32ui.error: + pass + diff --git a/Lib/site-packages/pythonwin/pywin/framework/mdi_pychecker.py b/Lib/site-packages/pythonwin/pywin/framework/mdi_pychecker.py new file mode 100644 index 0000000..b3dc8d5 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/mdi_pychecker.py @@ -0,0 +1,629 @@ +###################################################################### +## +## The Pychecker MDI Plug-In UserModule for Pythonwin +## +## contributed by Robert Kiendl +## +## Style is similar to (and inherited) from the SGrepMDI UserModule +## +## Usage: +## +## Start Pychecker on current file: Menu/File/New../Pychecker. +## Use it: Jump to Pychecker warning source lines by double-click. +## Auto-add "#$pycheck_no" / "#$pycheck_no=specific-re-pattern" tags +## to source lines by context/right-mouse-click on warning lines. +## +## It requires pychecker installed and the pychecker.bat to be on +## the PATH. Example pychecker.bat: +## +## REM pychecker.bat +## C:\bin\python.exe C:\PYTHON23\Lib\site-packages\pychecker\checker.py %1 %2 %3 %4 %5 %6 %7 %8 %9 +## +## Adding it as default module in PythonWin: +## +## +++ ./intpyapp.py 2006-10-02 17:59:32.974161600 +0200 +## @@ -272,7 +282,7 @@ +## def LoadUserModules(self, moduleNames = None): +## # Load the users modules. +## if moduleNames is None: +## - default = "sgrepmdi" +## + default = "sgrepmdi,mdi_pychecker" +## moduleNames=win32ui.GetProfileVal('Python','Startup Modules',default) +## self.DoLoadModules(moduleNames) +## +###################################################################### + +import win32ui +import win32api +from pywin.mfc import docview, dialog, window +import win32con +import sys, string, re, glob, os, stat, time +from . import scriptutils + +def getsubdirs(d): + dlist = [] + flist = glob.glob(d+'\\*') + for f in flist: + if os.path.isdir(f): + dlist.append(f) + dlist = dlist + getsubdirs(f) + return dlist + +class dirpath: + def __init__(self, str, recurse=0): + dp = str.split(';') + dirs = {} + for d in dp: + if os.path.isdir(d): + d = d.lower() + if d not in dirs: + dirs[d] = None + if recurse: + subdirs = getsubdirs(d) + for sd in subdirs: + sd = sd.lower() + if sd not in dirs: + dirs[sd] = None + elif os.path.isfile(d): + pass + else: + x = None + if d in os.environ: + x = dirpath(os.environ[d]) + elif d[:5] == 'HKEY_': + keystr = d.split('\\') + try: + root = eval('win32con.'+keystr[0]) + except: + win32ui.MessageBox("Can't interpret registry key name '%s'" % keystr[0]) + try: + subkey = '\\'.join(keystr[1:]) + val = win32api.RegQueryValue(root, subkey) + if val: + x = dirpath(val) + else: + win32ui.MessageBox("Registry path '%s' did not return a path entry" % d) + except: + win32ui.MessageBox("Can't interpret registry key value: %s" % keystr[1:]) + else: + win32ui.MessageBox("Directory '%s' not found" % d) + if x: + for xd in x: + if xd not in dirs: + dirs[xd] = None + if recurse: + subdirs = getsubdirs(xd) + for sd in subdirs: + sd = sd.lower() + if sd not in dirs: + dirs[sd] = None + self.dirs = [] + for d in dirs.keys(): + self.dirs.append(d) + + def __getitem__(self, key): + return self.dirs[key] + def __len__(self): + return len(self.dirs) + def __setitem__(self, key, value): + self.dirs[key] = value + def __delitem__(self, key): + del self.dirs[key] + def __getslice__(self, lo, hi): + return self.dirs[lo:hi] + def __setslice__(self, lo, hi, seq): + self.dirs[lo:hi] = seq + def __delslice__(self, lo, hi): + del self.dirs[lo:hi] + def __add__(self, other): + if type(other) == type(self) or type(other) == type([]): + return self.dirs + other.dirs + def __radd__(self, other): + if type(other) == type(self) or type(other) == type([]): + return other.dirs + self.dirs + +# Group(1) is the filename, group(2) is the lineno. +#regexGrepResult=regex.compile("^\\([a-zA-Z]:.*\\)(\\([0-9]+\\))") +#regexGrep=re.compile(r"^([a-zA-Z]:[^(]*)\((\d+)\)") +regexGrep=re.compile(r"^(..[^\(:]+)?[\(:](\d+)[\):]:?\s*(.*)") + +#these are the atom numbers defined by Windows for basic dialog controls + +BUTTON = 0x80 +EDIT = 0x81 +STATIC = 0x82 +LISTBOX = 0x83 +SCROLLBAR = 0x84 +COMBOBOX = 0x85 + +class TheTemplate(docview.RichEditDocTemplate): + def __init__(self): + docview.RichEditDocTemplate.__init__(self, win32ui.IDR_TEXTTYPE, TheDocument, TheFrame, TheView) + self.SetDocStrings("\nPychecker\nPychecker\nPychecker params (*.pychecker)\n.pychecker\n\n\n") + win32ui.GetApp().AddDocTemplate(self) + self.docparams = None + + def MatchDocType(self, fileName, fileType): + doc = self.FindOpenDocument(fileName) + if doc: return doc + ext = os.path.splitext(fileName)[1].lower() + if ext =='.pychecker': + return win32ui.CDocTemplate_Confidence_yesAttemptNative + return win32ui.CDocTemplate_Confidence_noAttempt + + def setParams(self, params): + self.docparams = params + + def readParams(self): + tmp = self.docparams + self.docparams = None + return tmp + +class TheFrame(window.MDIChildWnd): + # The template and doc params will one day be removed. + def __init__(self, wnd = None): + window.MDIChildWnd.__init__(self, wnd) + +class TheDocument(docview.RichEditDoc): + def __init__(self, template): + docview.RichEditDoc.__init__(self, template) + self.dirpattern = '' + self.filpattern = '' + self.greppattern = '' + self.casesensitive = 1 + self.recurse = 1 + self.verbose = 0 + + def OnOpenDocument(self, fnm): + #this bizarre stuff with params is so right clicking in a result window + #and starting a new grep can communicate the default parameters to the + #new grep. + try: + params = open(fnm,'r').read() + except: + params = None + self.setInitParams(params) + return self.OnNewDocument() + + def OnCloseDocument(self): + try: + win32ui.GetApp().DeleteIdleHandler(self.idleHandler) + except: + pass + return self._obj_.OnCloseDocument() + + def saveInitParams(self): + # Only save the flags, not the text boxes. + paramstr = "\t\t\t%d\t%d" % (self.casesensitive, self.recurse) + win32ui.WriteProfileVal("Pychecker", "Params", paramstr) + + def setInitParams(self, paramstr): + if paramstr is None: + paramstr = win32ui.GetProfileVal("Pychecker", "Params", '\t\t\t1\t0\t0') + params = paramstr.split('\t') + if len(params) < 3: + params = params + ['']*(3-len(params)) + if len(params) < 6: + params = params + [0]*(6-len(params)) + self.dirpattern = params[0] + self.filpattern = params[1] + self.greppattern = params[2] or '-#1000 --only' + self.casesensitive = int(params[3]) + self.recurse = int(params[4]) + self.verbose = int(params[5]) + # setup some reasonable defaults. + if not self.dirpattern: + try: + editor=win32ui.GetMainFrame().MDIGetActive()[0].GetEditorView() + self.dirpattern=os.path.abspath(os.path.dirname(editor.GetDocument().GetPathName())) + except (AttributeError,win32ui.error): + self.dirpattern = os.getcwd() + if not self.filpattern: + try: + editor=win32ui.GetMainFrame().MDIGetActive()[0].GetEditorView() + self.filpattern=editor.GetDocument().GetPathName() + except AttributeError: + self.filpattern = "*.py" + + def OnNewDocument(self): + if self.dirpattern == '': + self.setInitParams(greptemplate.readParams()) + d = TheDialog(self.dirpattern, self.filpattern, self.greppattern, self.casesensitive, self.recurse, self.verbose) + if d.DoModal() == win32con.IDOK: + self.dirpattern = d['dirpattern'] + self.filpattern = d['filpattern'] + self.greppattern = d['greppattern'] + #self.casesensitive = d['casesensitive'] + #self.recurse = d['recursive'] + #self.verbose = d['verbose'] + self.doSearch() + self.saveInitParams() + return 1 + return 0 # cancelled - return zero to stop frame creation. + + def doSearch(self): + self.dp = dirpath(self.dirpattern, self.recurse) + self.SetTitle("Pychecker Run '%s' (options: %s)" % (self.filpattern, self.greppattern)) + #self.text = [] + self.GetFirstView().Append('#Pychecker Run in '+self.dirpattern+' %s\n'%time.asctime()) + if self.verbose: + self.GetFirstView().Append('# ='+repr(self.dp.dirs)+'\n') + self.GetFirstView().Append('# Files '+self.filpattern+'\n') + self.GetFirstView().Append('# Options '+self.greppattern+'\n') + self.fplist = self.filpattern.split(';') + self.GetFirstView().Append('# Running... ( double click on result lines in order to jump to the source code ) \n') + win32ui.SetStatusText("Pychecker running. Please wait...", 0) + self.dpndx = self.fpndx = 0 + self.fndx = -1 + if not self.dp: + self.GetFirstView().Append("# ERROR: '%s' does not resolve to any search locations" % self.dirpattern) + self.SetModifiedFlag(0) + else: + ##self.flist = glob.glob(self.dp[0]+'\\'+self.fplist[0]) + import operator + self.flist = reduce(operator.add, list(map(glob.glob,self.fplist)) ) + #import pywin.debugger;pywin.debugger.set_trace() + self.startPycheckerRun() + def idleHandler(self,handler,count): + import time + time.sleep(0.001) + if self.result!=None: + win32ui.GetApp().DeleteIdleHandler(self.idleHandler) + return 0 + return 1 #more + def startPycheckerRun(self): + self.result=None + old=win32api.SetCursor(win32api.LoadCursor(0, win32con.IDC_APPSTARTING)) + win32ui.GetApp().AddIdleHandler(self.idleHandler) + import _thread + _thread.start_new(self.threadPycheckerRun,()) + ##win32api.SetCursor(old) + def threadPycheckerRun(self): + result='' + rc=-1 + try: + options = self.greppattern + files= ' '.join(self.flist) + # Recently MarkH has failed to run pychecker without it having + # been explicitly installed - so we assume it is and locate it + # from its default location. + # Step1 - get python.exe + py = os.path.join(sys.prefix, 'python.exe') + if not os.path.isfile(py): + if "64 bit" in sys.version: + py = os.path.join(sys.prefix, 'PCBuild', 'amd64', 'python.exe') + else: + py = os.path.join(sys.prefix, 'PCBuild', 'python.exe') + try: + py = win32api.GetShortPathName(py) + except win32api.error: + py = "" + # Find checker.py + from distutils.sysconfig import get_python_lib + pychecker = os.path.join(get_python_lib(), 'pychecker', 'checker.py') + if not os.path.isfile(py): + result = "Can't find python.exe!\n" + elif not os.path.isfile(pychecker): + result = "Can't find checker.py - please install pychecker " \ + "(or run 'setup.py install' if you have the source version)\n" + else: + cmd='%s "%s" %s %s 2>&1' % (py, pychecker, options,files) + ##fin,fout,ferr=os.popen3(cmd) + ##result=ferr.read()+fout.read() + result=os.popen(cmd).read() + ##rc=f.close() + self.GetFirstView().Append(result) + finally: + self.result=result + print('== Pychecker run finished ==') + self.GetFirstView().Append('\n'+'== Pychecker run finished ==') + self.SetModifiedFlag(0) + def _inactive_idleHandler(self, handler, count): + self.fndx = self.fndx + 1 + if self.fndx < len(self.flist): + f = self.flist[self.fndx] + if self.verbose: + self.GetFirstView().Append('# ..'+f+'\n') + win32ui.SetStatusText("Searching "+f, 0) + lines = open(f, 'r').readlines() + for i in range(len(lines)): + line = lines[i] + if self.pat.search(line) != None: + self.GetFirstView().Append(f+'('+repr(i+1) + ') '+line) + else: + self.fndx = -1 + self.fpndx = self.fpndx + 1 + if self.fpndx < len(self.fplist): + self.flist = glob.glob(self.dp[self.dpndx] + '\\' + self.fplist[self.fpndx]) + else: + self.fpndx = 0 + self.dpndx = self.dpndx + 1 + if self.dpndx < len(self.dp): + self.flist = glob.glob(self.dp[self.dpndx] + '\\' + self.fplist[self.fpndx]) + else: + win32ui.SetStatusText("Search complete.", 0) + self.SetModifiedFlag(0) # default to not modified. + try: + win32ui.GetApp().DeleteIdleHandler(self.idleHandler) + except: + pass + return 0 + return 1 + + def GetParams(self): + return self.dirpattern+'\t'+self.filpattern+'\t'+self.greppattern+'\t'+repr(self.casesensitive)+'\t'+repr(self.recurse)+'\t'+repr(self.verbose) + + def OnSaveDocument(self, filename): +# print 'OnSaveDocument() filename=',filename + savefile = open(filename,"wb") + txt = self.GetParams()+'\n' +# print 'writing',txt + savefile.write(txt) + savefile.close() + self.SetModifiedFlag(0) + return 1 + +ID_OPEN_FILE = 0xe500 +ID_PYCHECKER = 0xe501 +ID_SAVERESULTS = 0x502 +ID_TRYAGAIN = 0x503 +ID_ADDCOMMENT = 0x504 +ID_ADDPYCHECKNO2 = 0x505 + +class TheView(docview.RichEditView): + def __init__(self, doc): + docview.RichEditView.__init__(self, doc) + self.SetWordWrap(win32ui.CRichEditView_WrapNone) + self.HookHandlers() + + def OnInitialUpdate(self): + rc = self._obj_.OnInitialUpdate() + format = (-402653169, 0, 200, 0, 0, 0, 49, 'Courier New') + self.SetDefaultCharFormat(format) + return rc + + def HookHandlers(self): + self.HookMessage(self.OnRClick, win32con.WM_RBUTTONDOWN) + self.HookCommand(self.OnCmdOpenFile, ID_OPEN_FILE) + self.HookCommand(self.OnCmdThe, ID_PYCHECKER) + self.HookCommand(self.OnCmdSave, ID_SAVERESULTS) + self.HookCommand(self.OnTryAgain, ID_TRYAGAIN) + self.HookCommand(self.OnAddComment, ID_ADDCOMMENT) + self.HookCommand(self.OnAddComment, ID_ADDPYCHECKNO2) + self.HookMessage(self.OnLDblClick,win32con.WM_LBUTTONDBLCLK) + + def OnLDblClick(self,params): + line = self.GetLine() + regexGrepResult = regexGrep.match(line) + if regexGrepResult: + fname = regexGrepResult.group(1) + line = int(regexGrepResult.group(2)) + scriptutils.JumpToDocument(fname, line) + return 0 # dont pass on + return 1 # pass it on by default. + + def OnRClick(self, params): + menu = win32ui.CreatePopupMenu() + flags=win32con.MF_STRING|win32con.MF_ENABLED + lineno = self._obj_.LineFromChar(-1) #selection or current line + line = self._obj_.GetLine(lineno) + regexGrepResult = regexGrep.match(line) + charstart, charend = self._obj_.GetSel() + if regexGrepResult: + self.fnm = regexGrepResult.group(1) + self.lnnum = int(regexGrepResult.group(2)) + menu.AppendMenu(flags, ID_OPEN_FILE, "&Open "+self.fnm) + menu.AppendMenu(flags, ID_ADDCOMMENT, "&Add to source: Comment Tag/#$pycheck_no ..") + menu.AppendMenu(flags, ID_ADDPYCHECKNO2, "&Add to source: Specific #$pycheck_no=%(errtext)s ..") + menu.AppendMenu(win32con.MF_SEPARATOR) + menu.AppendMenu(flags, ID_TRYAGAIN, "&Try Again") + menu.AppendMenu(flags, win32ui.ID_EDIT_CUT, 'Cu&t') + menu.AppendMenu(flags, win32ui.ID_EDIT_COPY, '&Copy') + menu.AppendMenu(flags, win32ui.ID_EDIT_PASTE, '&Paste') + menu.AppendMenu(flags, win32con.MF_SEPARATOR); + menu.AppendMenu(flags, win32ui.ID_EDIT_SELECT_ALL, '&Select all') + menu.AppendMenu(flags, win32con.MF_SEPARATOR); + menu.AppendMenu(flags, ID_SAVERESULTS, 'Sa&ve results') + menu.TrackPopupMenu(params[5]) + return 0 + + def OnAddComment(self, cmd, code): + addspecific= cmd==ID_ADDPYCHECKNO2 + _=list(self.GetSel()) + _.sort() + start,end=_ + line_start, line_end = self.LineFromChar(start), self.LineFromChar(end) + first=1 + for i in range(line_start,line_end+1): + line = self.GetLine(i) + m = regexGrep.match(line) + if m: + if first: + first=0 + cmnt=dialog.GetSimpleInput( "Add to %s lines" % (line_end-line_start+1), + addspecific and " #$pycheck_no=%(errtext)s" or " #$pycheck_no" ) + if not cmnt: + return 0 + ##import pywin.debugger;pywin.debugger.set_trace() + fname = m.group(1) + line = int(m.group(2)) + view = scriptutils.JumpToDocument(fname,line) + pos=view.LineIndex(line)-1 + if view.GetTextRange(pos-1,pos) in ('\r','\n'): + pos -= 1 + view.SetSel(pos, pos) + errtext=m.group(3) + if start!=end and line_start==line_end: + errtext=self.GetSelText() + errtext=repr(re.escape(errtext).replace('\ ',' ')) + view.ReplaceSel( addspecific and cmnt % locals() + or cmnt ) + return 0 + + + def OnCmdOpenFile(self, cmd, code): + doc = win32ui.GetApp().OpenDocumentFile(self.fnm) + if doc: + vw = doc.GetFirstView() + #hope you have an editor that implements GotoLine()! + try: + vw.GotoLine(int(self.lnnum)) + except: + pass + return 0 + + def OnCmdThe(self, cmd, code): + curparamsstr = self.GetDocument().GetParams() + params = curparamsstr.split('\t') + params[2] = self.sel + greptemplate.setParams('\t'.join(params)) + greptemplate.OpenDocumentFile() + return 0 + + def OnTryAgain(self, cmd, code): + greptemplate.setParams(self.GetDocument().GetParams()) + greptemplate.OpenDocumentFile() + return 0 + + def OnCmdSave(self, cmd, code): + flags = win32con.OFN_OVERWRITEPROMPT + dlg = win32ui.CreateFileDialog(0, None, None, flags, "Text Files (*.txt)|*.txt||", self) + dlg.SetOFNTitle("Save Results As") + if dlg.DoModal() == win32con.IDOK: + pn = dlg.GetPathName() + self._obj_.SaveFile(pn) + return 0 + + def Append(self, strng): + numlines = self.GetLineCount() + endpos = self.LineIndex(numlines-1) + len(self.GetLine(numlines-1)) + self.SetSel(endpos, endpos) + self.ReplaceSel(strng) + + +class TheDialog(dialog.Dialog): + def __init__(self, dp, fp, gp, cs, r, v): + style = win32con.DS_MODALFRAME | win32con.WS_POPUP | win32con.WS_VISIBLE | win32con.WS_CAPTION | win32con.WS_SYSMENU | win32con.DS_SETFONT + CS = win32con.WS_CHILD | win32con.WS_VISIBLE + tmp = [ ["Pychecker Run", (0, 0, 210, 90), style, None, (8, "MS Sans Serif")], ] + tmp.append([STATIC, "Files:", -1, (7, 7, 50, 9), CS ]) + tmp.append([EDIT, gp, 103, (52, 7, 144, 11), CS | win32con.WS_TABSTOP | win32con.ES_AUTOHSCROLL | win32con.WS_BORDER]) + tmp.append([STATIC, "Directories:", -1, (7, 20, 50, 9), CS ]) + tmp.append([EDIT, dp, 102, (52, 20, 128, 11), CS | win32con.WS_TABSTOP | win32con.ES_AUTOHSCROLL | win32con.WS_BORDER]) + tmp.append([BUTTON, '...', 110, (182,20, 16, 11), CS | win32con.BS_PUSHBUTTON | win32con.WS_TABSTOP]) + tmp.append([STATIC, "Options:", -1, (7, 33, 50, 9), CS ]) + tmp.append([EDIT, fp, 101, (52, 33, 128, 11), CS | win32con.WS_TABSTOP | win32con.ES_AUTOHSCROLL | win32con.WS_BORDER ]) + tmp.append([BUTTON, '...', 111, (182,33, 16, 11), CS | win32con.BS_PUSHBUTTON | win32con.WS_TABSTOP]) + #tmp.append([BUTTON,'Case sensitive', 104, (7, 45, 72, 9), CS | win32con.BS_AUTOCHECKBOX | win32con.BS_LEFTTEXT| win32con.WS_TABSTOP]) + #tmp.append([BUTTON,'Subdirectories', 105, (7, 56, 72, 9), CS | win32con.BS_AUTOCHECKBOX | win32con.BS_LEFTTEXT| win32con.WS_TABSTOP]) + #tmp.append([BUTTON,'Verbose', 106, (7, 67, 72, 9), CS | win32con.BS_AUTOCHECKBOX | win32con.BS_LEFTTEXT| win32con.WS_TABSTOP]) + tmp.append([BUTTON,'OK', win32con.IDOK, (166,53, 32, 12), CS | win32con.BS_DEFPUSHBUTTON| win32con.WS_TABSTOP]) + tmp.append([BUTTON,'Cancel', win32con.IDCANCEL, (166,67, 32, 12), CS | win32con.BS_PUSHBUTTON| win32con.WS_TABSTOP]) + dialog.Dialog.__init__(self, tmp) + self.AddDDX(101,'greppattern') + self.AddDDX(102,'dirpattern') + self.AddDDX(103,'filpattern') + #self.AddDDX(104,'casesensitive') + #self.AddDDX(105,'recursive') + #self.AddDDX(106,'verbose') + self._obj_.data['greppattern'] = gp + self._obj_.data['dirpattern'] = dp + self._obj_.data['filpattern'] = fp + #self._obj_.data['casesensitive'] = cs + #self._obj_.data['recursive'] = r + #self._obj_.data['verbose'] = v + self.HookCommand(self.OnMoreDirectories, 110) + self.HookCommand(self.OnMoreFiles, 111) + + def OnMoreDirectories(self, cmd, code): + self.getMore('Pychecker\\Directories', 'dirpattern') + + def OnMoreFiles(self, cmd, code): + self.getMore('Pychecker\\File Types', 'filpattern') + + def getMore(self, section, key): + self.UpdateData(1) + #get the items out of the ini file + ini = win32ui.GetProfileFileName() + secitems = win32api.GetProfileSection(section, ini) + items = [] + for secitem in secitems: + items.append(secitem.split('=')[1]) + dlg = TheParamsDialog(items) + if dlg.DoModal() == win32con.IDOK: + itemstr = ';'.join(dlg.getItems()) + self._obj_.data[key] = itemstr + #update the ini file with dlg.getNew() + i = 0 + newitems = dlg.getNew() + if newitems: + items = items + newitems + for item in items: + win32api.WriteProfileVal(section, repr(i), item, ini) + i = i + 1 + self.UpdateData(0) + + def OnOK(self): + self.UpdateData(1) + for id, name in [(101,'greppattern'), (102,'dirpattern'), (103,'filpattern')]: + if not self[name]: + self.GetDlgItem(id).SetFocus() + win32api.MessageBeep() + win32ui.SetStatusText("Please enter a value") + return + self._obj_.OnOK() + +class TheParamsDialog(dialog.Dialog): + def __init__(self, items): + self.items = items + self.newitems = [] + style = win32con.DS_MODALFRAME | win32con.WS_POPUP | win32con.WS_VISIBLE | win32con.WS_CAPTION | win32con.WS_SYSMENU | win32con.DS_SETFONT + CS = win32con.WS_CHILD | win32con.WS_VISIBLE + tmp = [ ["Pychecker Parameters", (0, 0, 205, 100), style, None, (8, "MS Sans Serif")], ] + tmp.append([LISTBOX, '', 107, (7, 7, 150, 72), CS | win32con.LBS_MULTIPLESEL| win32con.LBS_STANDARD | win32con.LBS_HASSTRINGS | win32con.WS_TABSTOP | win32con.LBS_NOTIFY]) + tmp.append([BUTTON,'OK', win32con.IDOK, (167, 7, 32, 12), CS | win32con.BS_DEFPUSHBUTTON| win32con.WS_TABSTOP]) + tmp.append([BUTTON,'Cancel', win32con.IDCANCEL, (167,23, 32, 12), CS | win32con.BS_PUSHBUTTON| win32con.WS_TABSTOP]) + tmp.append([STATIC,'New:', -1, (2, 83, 15, 12), CS]) + tmp.append([EDIT, '', 108, (18, 83, 139, 12), CS | win32con.WS_TABSTOP | win32con.ES_AUTOHSCROLL | win32con.WS_BORDER]) + tmp.append([BUTTON,'Add', 109, (167,83, 32, 12), CS | win32con.BS_PUSHBUTTON| win32con.WS_TABSTOP]) + dialog.Dialog.__init__(self, tmp) + self.HookCommand(self.OnAddItem, 109) + self.HookCommand(self.OnListDoubleClick, 107) + + def OnInitDialog(self): + lb = self.GetDlgItem(107) + for item in self.items: + lb.AddString(item) + return self._obj_.OnInitDialog() + + def OnAddItem(self, cmd, code): + eb = self.GetDlgItem(108) + item = eb.GetLine(0) + self.newitems.append(item) + lb = self.GetDlgItem(107) + i = lb.AddString(item) + lb.SetSel(i, 1) + return 1 + + def OnListDoubleClick(self, cmd, code): + if code == win32con.LBN_DBLCLK: + self.OnOK() + return 1 + + def OnOK(self): + lb = self.GetDlgItem(107) + self.selections = lb.GetSelTextItems() + self._obj_.OnOK() + + def getItems(self): + return self.selections + + def getNew(self): + return self.newitems + +try: + win32ui.GetApp().RemoveDocTemplate(greptemplate) +except NameError: + pass + +greptemplate = TheTemplate() diff --git a/Lib/site-packages/pythonwin/pywin/framework/scriptutils.py b/Lib/site-packages/pythonwin/pywin/framework/scriptutils.py new file mode 100644 index 0000000..a0db778 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/scriptutils.py @@ -0,0 +1,623 @@ +""" +Various utilities for running/importing a script +""" +import sys +import win32ui +import win32api +import win32con +import __main__ +from pywin.mfc import dialog +from pywin.mfc.docview import TreeView +import os +import string +import traceback +import linecache +import bdb + +from .cmdline import ParseArgs + +RS_DEBUGGER_NONE=0 # Dont run under the debugger. +RS_DEBUGGER_STEP=1 # Start stepping under the debugger +RS_DEBUGGER_GO=2 # Just run under the debugger, stopping only at break-points. +RS_DEBUGGER_PM=3 # Dont run under debugger, but do post-mortem analysis on exception. + +debugging_options = """No debugging +Step-through in the debugger +Run in the debugger +Post-Mortem of unhandled exceptions""".split("\n") + +byte_cr = "\r".encode("ascii") +byte_lf = "\n".encode("ascii") +byte_crlf = "\r\n".encode("ascii") + +# A dialog box for the "Run Script" command. +class DlgRunScript(dialog.Dialog): + "A class for the 'run script' dialog" + def __init__(self, bHaveDebugger): + dialog.Dialog.__init__(self, win32ui.IDD_RUN_SCRIPT ) + self.AddDDX(win32ui.IDC_EDIT1, "script") + self.AddDDX(win32ui.IDC_EDIT2, "args") + self.AddDDX(win32ui.IDC_COMBO1, "debuggingType", "i") + self.HookCommand(self.OnBrowse, win32ui.IDC_BUTTON2) + self.bHaveDebugger = bHaveDebugger + def OnInitDialog(self): + rc = dialog.Dialog.OnInitDialog(self) + cbo = self.GetDlgItem(win32ui.IDC_COMBO1) + for o in debugging_options: + cbo.AddString(o) + cbo.SetCurSel(self['debuggingType']) + if not self.bHaveDebugger: + cbo.EnableWindow(0) + + def OnBrowse(self, id, cmd): + openFlags = win32con.OFN_OVERWRITEPROMPT|win32con.OFN_FILEMUSTEXIST + dlg = win32ui.CreateFileDialog(1,None,None,openFlags, "Python Scripts (*.py)|*.py||", self) + dlg.SetOFNTitle("Run Script") + if dlg.DoModal()!=win32con.IDOK: + return 0 + self['script'] = dlg.GetPathName() + self.UpdateData(0) + return 0 + +def GetDebugger(): + """Get the default Python debugger. Returns the debugger, or None. + + It is assumed the debugger has a standard "pdb" defined interface. + Currently always returns the 'pywin.debugger' debugger, or None + (pdb is _not_ returned as it is not effective in this GUI environment) + """ + try: + import pywin.debugger + return pywin.debugger + except ImportError: + return None + +def IsOnPythonPath(path): + "Given a path only, see if it is on the Pythonpath. Assumes path is a full path spec." + # must check that the command line arg's path is in sys.path + for syspath in sys.path: + try: + # Python 1.5 and later allows an empty sys.path entry. + if syspath and win32ui.FullPath(syspath)==path: + return 1 + except win32ui.error as details: + print("Warning: The sys.path entry '%s' is invalid\n%s" % (syspath, details)) + return 0 + +def GetPackageModuleName(fileName): + """Given a filename, return (module name, new path). + eg - given "c:\a\b\c\my.py", return ("b.c.my",None) if "c:\a" is on sys.path. + If no package found, will return ("my", "c:\a\b\c") + """ + path, fname = os.path.split(fileName) + path=origPath=win32ui.FullPath(path) + fname = os.path.splitext(fname)[0] + modBits = [] + newPathReturn = None + if not IsOnPythonPath(path): + # Module not directly on the search path - see if under a package. + while len(path)>3: # ie 'C:\' + path, modBit = os.path.split(path) + modBits.append(modBit) + # If on path, _and_ existing package of that name loaded. + if IsOnPythonPath(path) and modBit in sys.modules and \ + (os.path.exists(os.path.join(path, modBit, '__init__.py')) or \ + os.path.exists(os.path.join(path, modBit, '__init__.pyc')) or \ + os.path.exists(os.path.join(path, modBit, '__init__.pyo')) \ + ): + modBits.reverse() + return ".".join(modBits) + "." + fname, newPathReturn + # Not found - look a level higher + else: + newPathReturn = origPath + + return fname, newPathReturn + +def GetActiveView(): + """Gets the edit control (eg, EditView) with the focus, or None + """ + try: + childFrame, bIsMaximised = win32ui.GetMainFrame().MDIGetActive() + return childFrame.GetActiveView() + except win32ui.error: + return None + +def GetActiveEditControl(): + view = GetActiveView() + if view is None: return None + if hasattr(view, "SCIAddText"): # Is it a scintilla control? + return view + try: + return view.GetRichEditCtrl() + except AttributeError: + pass + try: + return view.GetEditCtrl() + except AttributeError: + pass + +def GetActiveEditorDocument(): + """Returns the active editor document and view, or (None,None) if no + active document or its not an editor document. + """ + view = GetActiveView() + if view is None or isinstance(view, TreeView): + return (None, None) + doc = view.GetDocument() + if hasattr(doc, "MarkerAdd"): # Is it an Editor document? + return doc, view + return (None, None) + +def GetActiveFileName(bAutoSave = 1): + """Gets the file name for the active frame, saving it if necessary. + + Returns None if it cant be found, or raises KeyboardInterrupt. + """ + pathName = None + active = GetActiveView() + if active is None: + return None + try: + doc = active.GetDocument() + pathName = doc.GetPathName() + + if bAutoSave and \ + (len(pathName)>0 or \ + doc.GetTitle()[:8]=="Untitled" or \ + doc.GetTitle()[:6]=="Script"): # if not a special purpose window + if doc.IsModified(): + try: + doc.OnSaveDocument(pathName) + pathName = doc.GetPathName() + + # clear the linecache buffer + linecache.clearcache() + + except win32ui.error: + raise KeyboardInterrupt + + except (win32ui.error, AttributeError): + pass + if not pathName: + return None + return pathName + +lastScript = '' +lastArgs = '' +lastDebuggingType = RS_DEBUGGER_NONE + +def RunScript(defName=None, defArgs=None, bShowDialog = 1, debuggingType=None): + global lastScript, lastArgs, lastDebuggingType + _debugger_stop_frame_ = 1 # Magic variable so the debugger will hide me! + + # Get the debugger - may be None! + debugger = GetDebugger() + + if defName is None: + try: + pathName = GetActiveFileName() + except KeyboardInterrupt: + return # User cancelled save. + else: + pathName = defName + if not pathName: + pathName = lastScript + if defArgs is None: + args = '' + if pathName==lastScript: + args = lastArgs + else: + args = defArgs + if debuggingType is None: debuggingType = lastDebuggingType + + if not pathName or bShowDialog: + dlg = DlgRunScript(debugger is not None) + dlg['script'] = pathName + dlg['args'] = args + dlg['debuggingType'] = debuggingType + if dlg.DoModal() != win32con.IDOK: + return + script=dlg['script'] + args=dlg['args'] + debuggingType = dlg['debuggingType'] + if not script: return + if debuggingType == RS_DEBUGGER_GO and debugger is not None: + # This may surprise users - they select "Run under debugger", but + # it appears not to! Only warn when they pick from the dialog! + # First - ensure the debugger is activated to pickup any break-points + # set in the editor. + try: + # Create the debugger, but _dont_ init the debugger GUI. + rd = debugger._GetCurrentDebugger() + except AttributeError: + rd = None + if rd is not None and len(rd.breaks)==0: + msg = "There are no active break-points.\r\n\r\nSelecting this debug option without any\r\nbreak-points is unlikely to have the desired effect\r\nas the debugger is unlikely to be invoked..\r\n\r\nWould you like to step-through in the debugger instead?" + rc = win32ui.MessageBox(msg, win32ui.LoadString(win32ui.IDR_DEBUGGER), win32con.MB_YESNOCANCEL | win32con.MB_ICONINFORMATION) + if rc == win32con.IDCANCEL: + return + if rc == win32con.IDYES: + debuggingType = RS_DEBUGGER_STEP + + lastDebuggingType = debuggingType + lastScript = script + lastArgs = args + else: + script = pathName + + # try and open the script. + if len(os.path.splitext(script)[1])==0: # check if no extension supplied, and give one. + script = script + '.py' + # If no path specified, try and locate the file + path, fnameonly = os.path.split(script) + if len(path)==0: + try: + os.stat(fnameonly) # See if it is OK as is... + script = fnameonly + except os.error: + fullScript = LocatePythonFile(script) + if fullScript is None: + win32ui.MessageBox("The file '%s' can not be located" % script ) + return + script = fullScript + else: + path = win32ui.FullPath(path) + if not IsOnPythonPath(path): sys.path.append(path) + + # py3k fun: If we use text mode to open the file, we get \r\n + # translated so Python allows the syntax (good!), but we get back + # text already decoded from the default encoding (bad!) and Python + # ignores any encoding decls (bad!). If we use binary mode we get + # the raw bytes and Python looks at the encoding (good!) but \r\n + # chars stay in place so Python throws a syntax error (bad!). + # So: so the binary thing and manually normalize \r\n. + try: + f = open(script, 'rb') + except IOError as exc: + win32ui.MessageBox("The file could not be opened - %s (%d)" % (exc.strerror, exc.errno)) + return + + # Get the source-code - as above, normalize \r\n + code = f.read().replace(byte_crlf, byte_lf).replace(byte_cr, byte_lf) + byte_lf + + # Remember and hack sys.argv for the script. + oldArgv = sys.argv + sys.argv = ParseArgs(args) + sys.argv.insert(0, script) + # sys.path[0] is the path of the script + oldPath0 = sys.path[0] + newPath0 = os.path.split(script)[0] + if not oldPath0: # if sys.path[0] is empty + sys.path[0] = newPath0 + insertedPath0 = 0 + else: + sys.path.insert(0, newPath0) + insertedPath0 = 1 + bWorked = 0 + win32ui.DoWaitCursor(1) + base = os.path.split(script)[1] + # Allow windows to repaint before starting. + win32ui.PumpWaitingMessages() + win32ui.SetStatusText('Running script %s...' % base,1 ) + exitCode = 0 + from pywin.framework import interact + # Check the debugger flags + if debugger is None and (debuggingType != RS_DEBUGGER_NONE): + win32ui.MessageBox("No debugger is installed. Debugging options have been ignored!") + debuggingType = RS_DEBUGGER_NONE + + # Get a code object - ignore the debugger for this, as it is probably a syntax error + # at this point + try: + codeObject = compile(code, script, "exec") + except: + # Almost certainly a syntax error! + _HandlePythonFailure("run script", script) + # No code object which to run/debug. + return + __main__.__file__=script + try: + if debuggingType == RS_DEBUGGER_STEP: + debugger.run(codeObject, __main__.__dict__, start_stepping=1) + elif debuggingType == RS_DEBUGGER_GO: + debugger.run(codeObject, __main__.__dict__, start_stepping=0) + else: + # Post mortem or no debugging + exec(codeObject, __main__.__dict__) + bWorked = 1 + except bdb.BdbQuit: + # Dont print tracebacks when the debugger quit, but do print a message. + print("Debugging session cancelled.") + exitCode = 1 + bWorked = 1 + except SystemExit as code: + exitCode = code + bWorked = 1 + except KeyboardInterrupt: + # Consider this successful, as we dont want the debugger. + # (but we do want a traceback!) + if interact.edit and interact.edit.currentView: + interact.edit.currentView.EnsureNoPrompt() + traceback.print_exc() + if interact.edit and interact.edit.currentView: + interact.edit.currentView.AppendToPrompt([]) + bWorked = 1 + except: + if interact.edit and interact.edit.currentView: + interact.edit.currentView.EnsureNoPrompt() + traceback.print_exc() + if interact.edit and interact.edit.currentView: + interact.edit.currentView.AppendToPrompt([]) + if debuggingType == RS_DEBUGGER_PM: + debugger.pm() + del __main__.__file__ + sys.argv = oldArgv + if insertedPath0: + del sys.path[0] + else: + sys.path[0] = oldPath0 + f.close() + if bWorked: + win32ui.SetStatusText("Script '%s' returned exit code %s" %(script, exitCode)) + else: + win32ui.SetStatusText('Exception raised while running script %s' % base) + try: + sys.stdout.flush() + except AttributeError: + pass + + win32ui.DoWaitCursor(0) + +def ImportFile(): + """ This code looks for the current window, and determines if it can be imported. If not, + it will prompt for a file name, and allow it to be imported. """ + try: + pathName = GetActiveFileName() + except KeyboardInterrupt: + pathName = None + + if pathName is not None: + if os.path.splitext(pathName)[1].lower() not in ('.py','.pyw','.pyx'): + pathName = None + + if pathName is None: + openFlags = win32con.OFN_OVERWRITEPROMPT|win32con.OFN_FILEMUSTEXIST + dlg = win32ui.CreateFileDialog(1,None,None,openFlags, "Python Scripts (*.py;*.pyw)|*.py;*.pyw;*.pyx||") + dlg.SetOFNTitle("Import Script") + if dlg.DoModal()!=win32con.IDOK: + return 0 + + pathName = dlg.GetPathName() + + # If already imported, dont look for package + path, modName = os.path.split(pathName) + modName, modExt = os.path.splitext(modName) + newPath = None + # note that some packages (*cough* email *cough*) use "lazy importers" + # meaning sys.modules can change as a side-effect of looking at + # module.__file__ - so we must take a copy (ie, items() in py2k, + # list(items()) in py3k) + for key, mod in list(sys.modules.items()): + if hasattr(mod, '__file__'): + fname = mod.__file__ + base, ext = os.path.splitext(fname) + if ext.lower() in ['.pyo', '.pyc']: + ext = '.py' + fname = base + ext + if win32ui.ComparePath(fname, pathName): + modName = key + break + else: # for not broken + modName, newPath = GetPackageModuleName(pathName) + if newPath: sys.path.append(newPath) + + if modName in sys.modules: + bNeedReload = 1 + what = "reload" + else: + what = "import" + bNeedReload = 0 + + win32ui.SetStatusText(what.capitalize()+'ing module...',1) + win32ui.DoWaitCursor(1) +# win32ui.GetMainFrame().BeginWaitCursor() + + try: + # always do an import, as it is cheap if it's already loaded. This ensures + # it is in our name space. + codeObj = compile('import '+modName,'','exec') + except SyntaxError: + win32ui.SetStatusText('Invalid filename for import: "' +modName+'"') + return + try: + exec(codeObj, __main__.__dict__) + mod = sys.modules.get(modName) + if bNeedReload: + try: + ## The interpreter sees this import as a local assignment, so Python 2.x throws + ## UnboundLocalError: local variable 'reload' referenced before assignment + ## when you try to use reload after this fails + from imp import reload as my_reload # py3k + except ImportError: + my_reload = reload # reload a builtin in py2k + mod = my_reload(sys.modules[modName]) + win32ui.SetStatusText('Successfully ' + what + "ed module '"+modName+"': %s" % getattr(mod,'__file__',"")) + except: + _HandlePythonFailure(what) + win32ui.DoWaitCursor(0) + +def CheckFile(): + """ This code looks for the current window, and gets Python to check it + without actually executing any code (ie, by compiling only) + """ + try: + pathName = GetActiveFileName() + except KeyboardInterrupt: + return + + what = "check" + win32ui.SetStatusText(what.capitalize()+'ing module...',1) + win32ui.DoWaitCursor(1) + try: + f = open(pathName) + except IOError as details: + print("Cant open file '%s' - %s" % (pathName, details)) + return + try: + code = f.read() + "\n" + finally: + f.close() + try: + codeObj = compile(code, pathName,'exec') + if RunTabNanny(pathName): + win32ui.SetStatusText("Python and the TabNanny successfully checked the file '"+os.path.basename(pathName)+"'") + except SyntaxError: + _HandlePythonFailure(what, pathName) + except: + traceback.print_exc() + _HandlePythonFailure(what) + win32ui.DoWaitCursor(0) + +def RunTabNanny(filename): + import io as io + tabnanny = FindTabNanny() + if tabnanny is None: + win32ui.MessageBox("The TabNanny is not around, so the children can run amok!" ) + return + + # Capture the tab-nanny output + newout = io.StringIO() + old_out = sys.stderr, sys.stdout + sys.stderr = sys.stdout = newout + try: + tabnanny.check(filename) + finally: + # Restore output + sys.stderr, sys.stdout = old_out + data = newout.getvalue() + if data: + try: + lineno = data.split()[1] + lineno = int(lineno) + _JumpToPosition(filename, lineno) + try: # Try and display whitespace + GetActiveEditControl().SCISetViewWS(1) + except: + pass + win32ui.SetStatusText("The TabNanny found trouble at line %d" % lineno) + except (IndexError, TypeError, ValueError): + print("The tab nanny complained, but I cant see where!") + print(data) + return 0 + return 1 + +def _JumpToPosition(fileName, lineno, col = 1): + JumpToDocument(fileName, lineno, col) + +def JumpToDocument(fileName, lineno=0, col = 1, nChars = 0, bScrollToTop = 0): + # Jump to the position in a file. + # If lineno is <= 0, dont move the position - just open/restore. + # if nChars > 0, select that many characters. + # if bScrollToTop, the specified line will be moved to the top of the window + # (eg, bScrollToTop should be false when jumping to an error line to retain the + # context, but true when jumping to a method defn, where we want the full body. + # Return the view which is editing the file, or None on error. + doc = win32ui.GetApp().OpenDocumentFile(fileName) + if doc is None: return None + frame = doc.GetFirstView().GetParentFrame() + try: + view = frame.GetEditorView() + if frame.GetActiveView() != view: + frame.SetActiveView(view) + frame.AutoRestore() + except AttributeError: # Not an editor frame?? + view = doc.GetFirstView() + if lineno > 0: + charNo = view.LineIndex(lineno-1) + start = charNo + col - 1 + size = view.GetTextLength() + try: + view.EnsureCharsVisible(charNo) + except AttributeError: + print("Doesnt appear to be one of our views?") + view.SetSel(min(start, size), min(start + nChars, size)) + if bScrollToTop: + curTop = view.GetFirstVisibleLine() + nScroll = (lineno-1) - curTop + view.LineScroll(nScroll, 0) + view.SetFocus() + return view + +def _HandlePythonFailure(what, syntaxErrorPathName = None): + typ, details, tb = sys.exc_info() + if isinstance(details, SyntaxError): + try: + msg, (fileName, line, col, text) = details + if (not fileName or fileName =="") and syntaxErrorPathName: + fileName = syntaxErrorPathName + _JumpToPosition(fileName, line, col) + except (TypeError, ValueError): + msg = str(details) + win32ui.SetStatusText('Failed to ' + what + ' - syntax error - %s' % msg) + else: + traceback.print_exc() + win32ui.SetStatusText('Failed to ' + what + ' - ' + str(details) ) + tb = None # Clean up a cycle. + +# Find the Python TabNanny in either the standard library or the Python Tools/Scripts directory. +def FindTabNanny(): + try: + return __import__("tabnanny") + except ImportError: + pass + # OK - not in the standard library - go looking. + filename = "tabnanny.py" + try: + path = win32api.RegQueryValue(win32con.HKEY_LOCAL_MACHINE, "SOFTWARE\\Python\\PythonCore\\%s\\InstallPath" % (sys.winver)) + except win32api.error: + print("WARNING - The Python registry does not have an 'InstallPath' setting") + print(" The file '%s' can not be located" % (filename)) + return None + fname = os.path.join(path, "Tools\\Scripts\\%s" % filename) + try: + os.stat(fname) + except os.error: + print("WARNING - The file '%s' can not be located in path '%s'" % (filename, path)) + return None + + tabnannyhome, tabnannybase = os.path.split(fname) + tabnannybase = os.path.splitext(tabnannybase)[0] + # Put tab nanny at the top of the path. + sys.path.insert(0, tabnannyhome) + try: + return __import__(tabnannybase) + finally: + # remove the tab-nanny from the path + del sys.path[0] + +def LocatePythonFile( fileName, bBrowseIfDir = 1 ): + " Given a file name, return a fully qualified file name, or None " + # first look for the exact file as specified + if not os.path.isfile(fileName): + # Go looking! + baseName = fileName + for path in sys.path: + fileName = os.path.abspath(os.path.join(path, baseName)) + if os.path.isdir(fileName): + if bBrowseIfDir: + d=win32ui.CreateFileDialog(1, "*.py", None, 0, "Python Files (*.py)|*.py|All files|*.*") + d.SetOFNInitialDir(fileName) + rc=d.DoModal() + if rc==win32con.IDOK: + fileName = d.GetPathName() + break + else: + return None + else: + fileName = fileName + ".py" + if os.path.isfile(fileName): + break # Found it! + + else: # for not broken out of + return None + return win32ui.FullPath(fileName) diff --git a/Lib/site-packages/pythonwin/pywin/framework/sgrepmdi.py b/Lib/site-packages/pythonwin/pywin/framework/sgrepmdi.py new file mode 100644 index 0000000..e66a500 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/sgrepmdi.py @@ -0,0 +1,530 @@ +#SGrepMDI is by Gordon McMillan (gmcm@hypernet.com) +#It does basically what Find In Files does in MSVC with a couple enhancements. +# - It saves any directories in the app's ini file (if you want to get rid +# of them you'll have to edit the file) +# - "Directories" can be directories, +# - semicolon separated lists of "directories", +# - environment variables that evaluate to "directories", +# - registry path names that evaluate to "directories", +# - all of which is recursive, so you can mix them all up. +# - It is MDI, so you can 'nest' greps and return to earlier ones, +# (ie, have multiple results open at the same time) +# - Like FIF, double clicking a line opens an editor and takes you to the line. +# - You can highlight text, right click and start a new grep with the selected +# text as search pattern and same directories etc as before. +# - You can save grep parameters (so you don't lose your hardearned pattern) +# from File|Save +# - You can save grep results by right clicking in the result window. +# Hats off to Mark Hammond for providing an environment where I could cobble +# something like this together in a couple evenings! + +import win32ui +import win32api +from pywin.mfc import docview, dialog, window +import win32con +import string +import re +import glob +import os +import stat +import glob +from . import scriptutils + +def getsubdirs(d): + dlist = [] + flist = glob.glob(d+'\\*') + for f in flist: + if os.path.isdir(f): + dlist.append(f) + dlist = dlist + getsubdirs(f) + return dlist + +class dirpath: + def __init__(self, str, recurse=0): + dp = str.split(';') + dirs = {} + for d in dp: + if os.path.isdir(d): + d = d.lower() + if d not in dirs: + dirs[d] = None + if recurse: + subdirs = getsubdirs(d) + for sd in subdirs: + sd = sd.lower() + if sd not in dirs: + dirs[sd] = None + elif os.path.isfile(d): + pass + else: + x = None + if d in os.environ: + x = dirpath(os.environ[d]) + elif d[:5] == 'HKEY_': + keystr = d.split('\\') + try: + root = eval('win32con.'+keystr[0]) + except: + win32ui.MessageBox("Can't interpret registry key name '%s'" % keystr[0]) + try: + subkey = '\\'.join(keystr[1:]) + val = win32api.RegQueryValue(root, subkey) + if val: + x = dirpath(val) + else: + win32ui.MessageBox("Registry path '%s' did not return a path entry" % d) + except: + win32ui.MessageBox("Can't interpret registry key value: %s" % keystr[1:]) + else: + win32ui.MessageBox("Directory '%s' not found" % d) + if x: + for xd in x: + if xd not in dirs: + dirs[xd] = None + if recurse: + subdirs = getsubdirs(xd) + for sd in subdirs: + sd = sd.lower() + if sd not in dirs: + dirs[sd] = None + self.dirs = [] + for d in list(dirs.keys()): + self.dirs.append(d) + + def __getitem__(self, key): + return self.dirs[key] + def __len__(self): + return len(self.dirs) + def __setitem__(self, key, value): + self.dirs[key] = value + def __delitem__(self, key): + del self.dirs[key] + def __getslice__(self, lo, hi): + return self.dirs[lo:hi] + def __setslice__(self, lo, hi, seq): + self.dirs[lo:hi] = seq + def __delslice__(self, lo, hi): + del self.dirs[lo:hi] + def __add__(self, other): + if type(other) == type(self) or type(other) == type([]): + return self.dirs + other.dirs + def __radd__(self, other): + if type(other) == type(self) or type(other) == type([]): + return other.dirs + self.dirs + +# Group(1) is the filename, group(2) is the lineno. +#regexGrepResult=regex.compile("^\\([a-zA-Z]:.*\\)(\\([0-9]+\\))") + +regexGrep=re.compile(r"^([a-zA-Z]:[^(]*)\(([0-9]+)\)") + +#these are the atom numbers defined by Windows for basic dialog controls + +BUTTON = 0x80 +EDIT = 0x81 +STATIC = 0x82 +LISTBOX = 0x83 +SCROLLBAR = 0x84 +COMBOBOX = 0x85 + +class GrepTemplate(docview.RichEditDocTemplate): + def __init__(self): + docview.RichEditDocTemplate.__init__(self, win32ui.IDR_TEXTTYPE, GrepDocument, GrepFrame, GrepView) + self.SetDocStrings("\nGrep\nGrep\nGrep params (*.grep)\n.grep\n\n\n") + win32ui.GetApp().AddDocTemplate(self) + self.docparams = None + + def MatchDocType(self, fileName, fileType): + doc = self.FindOpenDocument(fileName) + if doc: return doc + ext = os.path.splitext(fileName)[1].lower() + if ext =='.grep': + return win32ui.CDocTemplate_Confidence_yesAttemptNative + return win32ui.CDocTemplate_Confidence_noAttempt + + def setParams(self, params): + self.docparams = params + + def readParams(self): + tmp = self.docparams + self.docparams = None + return tmp + +class GrepFrame(window.MDIChildWnd): + # The template and doc params will one day be removed. + def __init__(self, wnd = None): + window.MDIChildWnd.__init__(self, wnd) + +class GrepDocument(docview.RichEditDoc): + def __init__(self, template): + docview.RichEditDoc.__init__(self, template) + self.dirpattern = '' + self.filpattern = '' + self.greppattern = '' + self.casesensitive = 1 + self.recurse = 1 + self.verbose = 0 + + def OnOpenDocument(self, fnm): + #this bizarre stuff with params is so right clicking in a result window + #and starting a new grep can communicate the default parameters to the + #new grep. + try: + params = open(fnm,'r').read() + except: + params = None + self.setInitParams(params) + return self.OnNewDocument() + + def OnCloseDocument(self): + try: + win32ui.GetApp().DeleteIdleHandler(self.SearchFile) + except: + pass + return self._obj_.OnCloseDocument() + + def saveInitParams(self): + # Only save the flags, not the text boxes. + paramstr = "\t%s\t\t%d\t%d" % (self.filpattern, self.casesensitive, self.recurse) + win32ui.WriteProfileVal("Grep", "Params", paramstr) + + def setInitParams(self, paramstr): + if paramstr is None: + paramstr = win32ui.GetProfileVal("Grep", "Params", '\t\t\t1\t0\t0') + params = paramstr.split('\t') + if len(params) < 3: + params = params + ['']*(3-len(params)) + if len(params) < 6: + params = params + [0]*(6-len(params)) + self.dirpattern = params[0] + self.filpattern = params[1] + self.greppattern = params[2] + self.casesensitive = int(params[3]) + self.recurse = int(params[4]) + self.verbose = int(params[5]) + # setup some reasonable defaults. + if not self.dirpattern: + try: + editor=win32ui.GetMainFrame().MDIGetActive()[0].GetEditorView() + self.dirpattern=os.path.abspath(os.path.dirname(editor.GetDocument().GetPathName())) + except (AttributeError, win32ui.error): + self.dirpattern = os.getcwd() + if not self.filpattern: + self.filpattern = "*.py" + + def OnNewDocument(self): + if self.dirpattern == '': + self.setInitParams(greptemplate.readParams()) + d = GrepDialog(self.dirpattern, self.filpattern, self.greppattern, self.casesensitive, self.recurse, self.verbose) + if d.DoModal() == win32con.IDOK: + self.dirpattern = d['dirpattern'] + self.filpattern = d['filpattern'] + self.greppattern = d['greppattern'] + self.casesensitive = d['casesensitive'] + self.recurse = d['recursive'] + self.verbose = d['verbose'] + self.doSearch() + self.saveInitParams() + return 1 + return 0 # cancelled - return zero to stop frame creation. + + def doSearch(self): + self.dp = dirpath(self.dirpattern, self.recurse) + self.SetTitle("Grep for %s in %s" % (self.greppattern, self.filpattern)) + #self.text = [] + self.GetFirstView().Append('#Search '+self.dirpattern+'\n') + if self.verbose: + self.GetFirstView().Append('# ='+repr(self.dp.dirs)+'\n') + self.GetFirstView().Append('# Files '+self.filpattern+'\n') + self.GetFirstView().Append('# For '+self.greppattern+'\n') + self.fplist = self.filpattern.split(';') + if self.casesensitive: + self.pat = re.compile(self.greppattern) + else: + self.pat = re.compile(self.greppattern, re.IGNORECASE) + win32ui.SetStatusText("Searching. Please wait...", 0) + self.dpndx = self.fpndx = 0 + self.fndx = -1 + if not self.dp: + self.GetFirstView().Append("# ERROR: '%s' does not resolve to any search locations" % self.dirpattern) + self.SetModifiedFlag(0) + else: + self.flist = glob.glob(self.dp[0]+'\\'+self.fplist[0]) + win32ui.GetApp().AddIdleHandler(self.SearchFile) + + def SearchFile(self, handler, count): + self.fndx = self.fndx + 1 + if self.fndx < len(self.flist): + f = self.flist[self.fndx] + if self.verbose: + self.GetFirstView().Append('# ..'+f+'\n') + # Directories may match the file type pattern, and files may be removed + # while grep is running + if os.path.isfile(f): + win32ui.SetStatusText("Searching "+f, 0) + lines = open(f, 'r').readlines() + for i in range(len(lines)): + line = lines[i] + if self.pat.search(line) != None: + self.GetFirstView().Append(f+'('+repr(i+1) + ') '+line) + else: + self.fndx = -1 + self.fpndx = self.fpndx + 1 + if self.fpndx < len(self.fplist): + self.flist = glob.glob(self.dp[self.dpndx] + '\\' + self.fplist[self.fpndx]) + else: + self.fpndx = 0 + self.dpndx = self.dpndx + 1 + if self.dpndx < len(self.dp): + self.flist = glob.glob(self.dp[self.dpndx] + '\\' + self.fplist[self.fpndx]) + else: + win32ui.SetStatusText("Search complete.", 0) + self.SetModifiedFlag(0) # default to not modified. + try: + win32ui.GetApp().DeleteIdleHandler(self.SearchFile) + except: + pass + return 0 + return 1 + + def GetParams(self): + return self.dirpattern+'\t'+self.filpattern+'\t'+self.greppattern+'\t'+repr(self.casesensitive)+'\t'+repr(self.recurse)+'\t'+repr(self.verbose) + + def OnSaveDocument(self, filename): +# print 'OnSaveDocument() filename=',filename + savefile = open(filename,"wb") + txt = self.GetParams()+'\n' +# print 'writing',txt + savefile.write(txt) + savefile.close() + self.SetModifiedFlag(0) + return 1 + +ID_OPEN_FILE = 0xe400 +ID_GREP = 0xe401 +ID_SAVERESULTS = 0x402 +ID_TRYAGAIN = 0x403 + +class GrepView(docview.RichEditView): + def __init__(self, doc): + docview.RichEditView.__init__(self, doc) + self.SetWordWrap(win32ui.CRichEditView_WrapNone) + self.HookHandlers() + + def OnInitialUpdate(self): + rc = self._obj_.OnInitialUpdate() + format = (-402653169, 0, 200, 0, 0, 0, 49, 'Courier New') + self.SetDefaultCharFormat(format) + return rc + + def HookHandlers(self): + self.HookMessage(self.OnRClick, win32con.WM_RBUTTONDOWN) + self.HookCommand(self.OnCmdOpenFile, ID_OPEN_FILE) + self.HookCommand(self.OnCmdGrep, ID_GREP) + self.HookCommand(self.OnCmdSave, ID_SAVERESULTS) + self.HookCommand(self.OnTryAgain, ID_TRYAGAIN) + self.HookMessage(self.OnLDblClick,win32con.WM_LBUTTONDBLCLK) + + def OnLDblClick(self,params): + line = self.GetLine() + regexGrepResult = regexGrep.match(line) + if regexGrepResult: + fname = regexGrepResult.group(1) + line = int(regexGrepResult.group(2)) + scriptutils.JumpToDocument(fname, line) + return 0 # dont pass on + return 1 # pass it on by default. + + def OnRClick(self, params): + menu = win32ui.CreatePopupMenu() + flags=win32con.MF_STRING|win32con.MF_ENABLED + lineno = self._obj_.LineFromChar(-1) #selection or current line + line = self._obj_.GetLine(lineno) + regexGrepResult = regexGrep.match(line) + if regexGrepResult: + self.fnm = regexGrepResult.group(1) + self.lnnum = int(regexGrepResult.group(2)) + menu.AppendMenu(flags, ID_OPEN_FILE, "&Open "+self.fnm) + menu.AppendMenu(win32con.MF_SEPARATOR) + menu.AppendMenu(flags, ID_TRYAGAIN, "&Try Again") + charstart, charend = self._obj_.GetSel() + if charstart != charend: + linestart = self._obj_.LineIndex(lineno) + self.sel = line[charstart-linestart:charend-linestart] + menu.AppendMenu(flags, ID_GREP, "&Grep for "+self.sel) + menu.AppendMenu(win32con.MF_SEPARATOR) + menu.AppendMenu(flags, win32ui.ID_EDIT_CUT, 'Cu&t') + menu.AppendMenu(flags, win32ui.ID_EDIT_COPY, '&Copy') + menu.AppendMenu(flags, win32ui.ID_EDIT_PASTE, '&Paste') + menu.AppendMenu(flags, win32con.MF_SEPARATOR); + menu.AppendMenu(flags, win32ui.ID_EDIT_SELECT_ALL, '&Select all') + menu.AppendMenu(flags, win32con.MF_SEPARATOR); + menu.AppendMenu(flags, ID_SAVERESULTS, 'Sa&ve results') + menu.TrackPopupMenu(params[5]) + return 0 + + def OnCmdOpenFile(self, cmd, code): + doc = win32ui.GetApp().OpenDocumentFile(self.fnm) + if doc: + vw = doc.GetFirstView() + #hope you have an editor that implements GotoLine()! + try: + vw.GotoLine(int(self.lnnum)) + except: + pass + return 0 + + def OnCmdGrep(self, cmd, code): + curparamsstr = self.GetDocument().GetParams() + params = curparamsstr.split('\t') + params[2] = self.sel + greptemplate.setParams('\t'.join(params)) + greptemplate.OpenDocumentFile() + return 0 + + def OnTryAgain(self, cmd, code): + greptemplate.setParams(self.GetDocument().GetParams()) + greptemplate.OpenDocumentFile() + return 0 + + def OnCmdSave(self, cmd, code): + flags = win32con.OFN_OVERWRITEPROMPT + dlg = win32ui.CreateFileDialog(0, None, None, flags, "Text Files (*.txt)|*.txt||", self) + dlg.SetOFNTitle("Save Results As") + if dlg.DoModal() == win32con.IDOK: + pn = dlg.GetPathName() + self._obj_.SaveTextFile(pn) + return 0 + + def Append(self, strng): + numlines = self.GetLineCount() + endpos = self.LineIndex(numlines-1) + len(self.GetLine(numlines-1)) + self.SetSel(endpos, endpos) + self.ReplaceSel(strng) + + +class GrepDialog(dialog.Dialog): + def __init__(self, dp, fp, gp, cs, r, v): + style = win32con.DS_MODALFRAME | win32con.WS_POPUP | win32con.WS_VISIBLE | win32con.WS_CAPTION | win32con.WS_SYSMENU | win32con.DS_SETFONT + CS = win32con.WS_CHILD | win32con.WS_VISIBLE + tmp = [ ["Grep", (0, 0, 210, 90), style, None, (8, "MS Sans Serif")], ] + tmp.append([STATIC, "Grep For:", -1, (7, 7, 50, 9), CS ]) + tmp.append([EDIT, gp, 101, (52, 7, 144, 11), CS | win32con.WS_TABSTOP | win32con.ES_AUTOHSCROLL | win32con.WS_BORDER]) + tmp.append([STATIC, "Directories:", -1, (7, 20, 50, 9), CS ]) + tmp.append([EDIT, dp, 102, (52, 20, 128, 11), CS | win32con.WS_TABSTOP | win32con.ES_AUTOHSCROLL | win32con.WS_BORDER]) + tmp.append([BUTTON, '...', 110, (182,20, 16, 11), CS | win32con.BS_PUSHBUTTON | win32con.WS_TABSTOP]) + tmp.append([STATIC, "File types:", -1, (7, 33, 50, 9), CS ]) + tmp.append([EDIT, fp, 103, (52, 33, 128, 11), CS | win32con.WS_TABSTOP | win32con.ES_AUTOHSCROLL | win32con.WS_BORDER ]) + tmp.append([BUTTON, '...', 111, (182,33, 16, 11), CS | win32con.BS_PUSHBUTTON | win32con.WS_TABSTOP]) + tmp.append([BUTTON,'Case sensitive', 104, (7, 45, 72, 9), CS | win32con.BS_AUTOCHECKBOX | win32con.BS_LEFTTEXT| win32con.WS_TABSTOP]) + tmp.append([BUTTON,'Subdirectories', 105, (7, 56, 72, 9), CS | win32con.BS_AUTOCHECKBOX | win32con.BS_LEFTTEXT| win32con.WS_TABSTOP]) + tmp.append([BUTTON,'Verbose', 106, (7, 67, 72, 9), CS | win32con.BS_AUTOCHECKBOX | win32con.BS_LEFTTEXT| win32con.WS_TABSTOP]) + tmp.append([BUTTON,'OK', win32con.IDOK, (166,53, 32, 12), CS | win32con.BS_DEFPUSHBUTTON| win32con.WS_TABSTOP]) + tmp.append([BUTTON,'Cancel', win32con.IDCANCEL, (166,67, 32, 12), CS | win32con.BS_PUSHBUTTON| win32con.WS_TABSTOP]) + dialog.Dialog.__init__(self, tmp) + self.AddDDX(101,'greppattern') + self.AddDDX(102,'dirpattern') + self.AddDDX(103,'filpattern') + self.AddDDX(104,'casesensitive') + self.AddDDX(105,'recursive') + self.AddDDX(106,'verbose') + self._obj_.data['greppattern'] = gp + self._obj_.data['dirpattern'] = dp + self._obj_.data['filpattern'] = fp + self._obj_.data['casesensitive'] = cs + self._obj_.data['recursive'] = r + self._obj_.data['verbose'] = v + self.HookCommand(self.OnMoreDirectories, 110) + self.HookCommand(self.OnMoreFiles, 111) + + def OnMoreDirectories(self, cmd, code): + self.getMore('Grep\\Directories', 'dirpattern') + + def OnMoreFiles(self, cmd, code): + self.getMore('Grep\\File Types', 'filpattern') + + def getMore(self, section, key): + self.UpdateData(1) + #get the items out of the ini file + ini = win32ui.GetProfileFileName() + secitems = win32api.GetProfileSection(section, ini) + items = [] + for secitem in secitems: + items.append(secitem.split('=')[1]) + dlg = GrepParamsDialog(items) + if dlg.DoModal() == win32con.IDOK: + itemstr = ';'.join(dlg.getItems()) + self._obj_.data[key] = itemstr + #update the ini file with dlg.getNew() + i = 0 + newitems = dlg.getNew() + if newitems: + items = items + newitems + for item in items: + win32api.WriteProfileVal(section, repr(i), item, ini) + i = i + 1 + self.UpdateData(0) + + def OnOK(self): + self.UpdateData(1) + for id, name in [(101,'greppattern'), (102,'dirpattern'), (103,'filpattern')]: + if not self[name]: + self.GetDlgItem(id).SetFocus() + win32api.MessageBeep() + win32ui.SetStatusText("Please enter a value") + return + self._obj_.OnOK() + +class GrepParamsDialog(dialog.Dialog): + def __init__(self, items): + self.items = items + self.newitems = [] + style = win32con.DS_MODALFRAME | win32con.WS_POPUP | win32con.WS_VISIBLE | win32con.WS_CAPTION | win32con.WS_SYSMENU | win32con.DS_SETFONT + CS = win32con.WS_CHILD | win32con.WS_VISIBLE + tmp = [ ["Grep Parameters", (0, 0, 205, 100), style, None, (8, "MS Sans Serif")], ] + tmp.append([LISTBOX, '', 107, (7, 7, 150, 72), CS | win32con.LBS_MULTIPLESEL| win32con.LBS_STANDARD | win32con.LBS_HASSTRINGS | win32con.WS_TABSTOP | win32con.LBS_NOTIFY]) + tmp.append([BUTTON,'OK', win32con.IDOK, (167, 7, 32, 12), CS | win32con.BS_DEFPUSHBUTTON| win32con.WS_TABSTOP]) + tmp.append([BUTTON,'Cancel', win32con.IDCANCEL, (167,23, 32, 12), CS | win32con.BS_PUSHBUTTON| win32con.WS_TABSTOP]) + tmp.append([STATIC,'New:', -1, (2, 83, 15, 12), CS]) + tmp.append([EDIT, '', 108, (18, 83, 139, 12), CS | win32con.WS_TABSTOP | win32con.ES_AUTOHSCROLL | win32con.WS_BORDER]) + tmp.append([BUTTON,'Add', 109, (167,83, 32, 12), CS | win32con.BS_PUSHBUTTON| win32con.WS_TABSTOP]) + dialog.Dialog.__init__(self, tmp) + self.HookCommand(self.OnAddItem, 109) + self.HookCommand(self.OnListDoubleClick, 107) + + def OnInitDialog(self): + lb = self.GetDlgItem(107) + for item in self.items: + lb.AddString(item) + return self._obj_.OnInitDialog() + + def OnAddItem(self, cmd, code): + eb = self.GetDlgItem(108) + item = eb.GetLine(0) + self.newitems.append(item) + lb = self.GetDlgItem(107) + i = lb.AddString(item) + lb.SetSel(i, 1) + return 1 + + def OnListDoubleClick(self, cmd, code): + if code == win32con.LBN_DBLCLK: + self.OnOK() + return 1 + + def OnOK(self): + lb = self.GetDlgItem(107) + self.selections = lb.GetSelTextItems() + self._obj_.OnOK() + + def getItems(self): + return self.selections + + def getNew(self): + return self.newitems + +try: + win32ui.GetApp().RemoveDocTemplate(greptemplate) +except NameError: + pass + +greptemplate = GrepTemplate() diff --git a/Lib/site-packages/pythonwin/pywin/framework/startup.py b/Lib/site-packages/pythonwin/pywin/framework/startup.py new file mode 100644 index 0000000..d8f8908 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/startup.py @@ -0,0 +1,62 @@ +# startup.py +# +"The main application startup code for PythonWin." + +# +# This does the basic command line handling. + +# Keep this as short as possible, cos error output is only redirected if +# this runs OK. Errors in imported modules are much better - the messages go somewhere (not any more :-) + +import sys +import win32ui + +# You may wish to redirect error output somewhere useful if you have startup errors. +# eg, 'import win32traceutil' will do this for you. +# import win32traceutil # Just uncomment this line to see error output! + +# An old class I used to use - generally only useful if Pythonwin is running under MSVC +#class DebugOutput: +# softspace=1 +# def write(self,message): +# win32ui.OutputDebug(message) +#sys.stderr=sys.stdout=DebugOutput() + +# To fix a problem with Pythonwin when started from the Pythonwin directory, +# we update the pywin path to ensure it is absolute. +# If it is indeed relative, it will be relative to our current directory. +# If its already absolute, then this will have no affect. +import pywin, pywin.framework +pywin.__path__[0] = win32ui.FullPath(pywin.__path__[0]) +pywin.framework.__path__[0] = win32ui.FullPath(pywin.framework.__path__[0]) + +# make a few wierd sys values. This is so later we can clobber sys.argv to trick +# scripts when running under a GUI environment. + +moduleName = "pywin.framework.intpyapp" +sys.appargvoffset = 0 +sys.appargv = sys.argv[:] +# Must check for /app param here. +if len(sys.argv)>=2 and sys.argv[0].lower()=='/app': + from . import cmdline + moduleName = cmdline.FixArgFileName(sys.argv[1]) + sys.appargvoffset = 2 + newargv=sys.argv[sys.appargvoffset:] +# newargv.insert(0, sys.argv[0]) + sys.argv = newargv + +# Import the application module. +__import__(moduleName) + +try: + win32ui.GetApp()._obj_ + # This worked - an app already exists - do nothing more +except (AttributeError, win32ui.error): + # This means either no app object exists at all, or the one + # that does exist does not have a Python class (ie, was created + # by the host .EXE). In this case, we do the "old style" init... + from . import app + if app.AppBuilder is None: + raise TypeError("No application object has been registered") + + app.App = app.AppBuilder() diff --git a/Lib/site-packages/pythonwin/pywin/framework/stdin.py b/Lib/site-packages/pythonwin/pywin/framework/stdin.py new file mode 100644 index 0000000..ee54f73 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/stdin.py @@ -0,0 +1,173 @@ +# Copyright (c) 2000 David Abrahams. Permission to copy, use, modify, sell +# and distribute this software is granted provided this copyright +# notice appears in all copies. This software is provided "as is" without +# express or implied warranty, and with no claim as to its suitability for +# any purpose. +"""Provides a class Stdin which can be used to emulate the regular old +sys.stdin for the PythonWin interactive window. Right now it just pops +up a raw_input() dialog. With luck, someone will integrate it into the +actual PythonWin interactive window someday. + +WARNING: Importing this file automatically replaces sys.stdin with an +instance of Stdin (below). This is useful because you can just open +Stdin.py in PythonWin and hit the import button to get it set up right +if you don't feel like changing PythonWin's source. To put things back +the way they were, simply use this magic incantation: + import sys + sys.stdin = sys.stdin.real_file +""" +import sys + +try: + get_input_line = raw_input # py2x +except NameError: + get_input_line = input # py3k + +class Stdin: + def __init__(self): + self.real_file = sys.stdin # NOTE: Likely to be None in py3k + self.buffer = "" + self.closed = False + + def __getattr__(self, name): + """Forward most functions to the real sys.stdin for absolute realism. + """ + if self.real_file is None: + raise AttributeError(name) + return getattr(self.real_file, name) + + def isatty(self): + """Return 1 if the file is connected to a tty(-like) device, else 0. + """ + return 1 + + def read(self, size = -1): + """Read at most size bytes from the file (less if the read + hits EOF or no more data is immediately available on a pipe, + tty or similar device). If the size argument is negative or + omitted, read all data until EOF is reached. The bytes are + returned as a string object. An empty string is returned when + EOF is encountered immediately. (For certain files, like ttys, + it makes sense to continue reading after an EOF is hit.)""" + result_size = self.__get_lines(size) + return self.__extract_from_buffer(result_size) + + def readline(self, size = -1): + """Read one entire line from the file. A trailing newline + character is kept in the string2.6 (but may be absent when a file ends + with an incomplete line). If the size argument is present and + non-negative, it is a maximum byte count (including the trailing + newline) and an incomplete line may be returned. An empty string is + returned when EOF is hit immediately. Note: unlike stdio's fgets(), + the returned string contains null characters ('\0') if they occurred + in the input. + """ + maximum_result_size = self.__get_lines(size, lambda buffer: '\n' in buffer) + + if '\n' in self.buffer[:maximum_result_size]: + result_size = self.buffer.find('\n', 0, maximum_result_size) + 1 + assert(result_size > 0) + else: + result_size = maximum_result_size + + return self.__extract_from_buffer(result_size) + + def __extract_from_buffer(self, character_count): + """Remove the first character_count characters from the internal buffer and + return them. + """ + result = self.buffer[:character_count] + self.buffer = self.buffer[character_count:] + return result + + def __get_lines(self, desired_size, done_reading = lambda buffer: False): + """Keep adding lines to our internal buffer until done_reading(self.buffer) + is true or EOF has been reached or we have desired_size bytes in the buffer. + If desired_size < 0, we are never satisfied until we reach EOF. If done_reading + is not supplied, it is not consulted. + + If desired_size < 0, returns the length of the internal buffer. Otherwise, + returns desired_size. + """ + while not done_reading(self.buffer) and (desired_size < 0 + or len(self.buffer) < desired_size): + try: + self.__get_line() + except (EOFError, KeyboardInterrupt): # deal with cancellation of get_input_line dialog + desired_size = len(self.buffer) # Be satisfied! + + if desired_size < 0: + return len(self.buffer) + else: + return desired_size + + def __get_line(self): + """Grab one line from get_input_line() and append it to the buffer. + """ + line = get_input_line() + print('>>>',line) # echo input to console + self.buffer = self.buffer + line + '\n' + + def readlines(self, *sizehint): + """Read until EOF using readline() and return a list containing the lines + thus read. If the optional sizehint argument is present, instead of + reading up to EOF, whole lines totalling approximately sizehint bytes + (possibly after rounding up to an internal buffer size) are read. + """ + result = [] + total_read = 0 + while sizehint == () or total_read < sizehint[0]: + line = self.readline() + if line == '': + break + total_read = total_read + len(line) + result.append(line) + return result + +if __name__ == "__main__": + test_input = r"""this is some test +input that I am hoping +~ +will be very instructive +and when I am done +I will have tested everything. +Twelve and twenty blackbirds +baked in a pie. Patty cake +patty cake so am I. +~ +Thirty-five niggling idiots! +Sell you soul to the devil, baby +""" + + def fake_raw_input(prompt=None): + """Replacement for raw_input() which pulls lines out of global test_input. + For testing only! + """ + global test_input + if '\n' not in test_input: + end_of_line_pos = len(test_input) + else: + end_of_line_pos = test_input.find('\n') + result = test_input[:end_of_line_pos] + test_input = test_input[end_of_line_pos + 1:] + if len(result) == 0 or result[0] == '~': + raise EOFError() + return result + + get_input_line = fake_raw_input + + # Some completely inadequate tests, just to make sure the code's not totally broken + try: + x = Stdin() + print(x.read()) + print(x.readline()) + print(x.read(12)) + print(x.readline(47)) + print(x.readline(3)) + print(x.readlines()) + finally: + get_input_line = raw_input +else: + import sys + sys.stdin = Stdin() + \ No newline at end of file diff --git a/Lib/site-packages/pythonwin/pywin/framework/toolmenu.py b/Lib/site-packages/pythonwin/pywin/framework/toolmenu.py new file mode 100644 index 0000000..ef8e1f3 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/toolmenu.py @@ -0,0 +1,256 @@ +# toolmenu.py + +import win32ui +import win32con +import win32api +from . import app +import sys +import string + +tools = {} +idPos = 100 + +# The default items should no tools menu exist in the INI file. +defaultToolMenuItems = [ + ('Browser', 'win32ui.GetApp().OnViewBrowse(0,0)'), + ('Browse PythonPath', 'from pywin.tools import browseProjects;browseProjects.Browse()'), + ('Edit Python Path', 'from pywin.tools import regedit;regedit.EditRegistry()'), + ('COM Makepy utility', 'from win32com.client import makepy;makepy.main()'), + ('COM Browser', 'from win32com.client import combrowse;combrowse.main()'), + ('Trace Collector Debugging tool', 'from pywin.tools import TraceCollector;TraceCollector.MakeOutputWindow()'), +] + +def LoadToolMenuItems(): + # Load from the registry. + items = [] + lookNo = 1 + while 1: + menu = win32ui.GetProfileVal("Tools Menu\\%s" % lookNo, "", "") + if menu=="": + break + cmd = win32ui.GetProfileVal("Tools Menu\\%s" % lookNo, "Command", "") + items.append((menu, cmd)) + lookNo = lookNo + 1 + + if len(items)==0: + items = defaultToolMenuItems + return items + +def WriteToolMenuItems( items ): + # Items is a list of (menu, command) + # Delete the entire registry tree. + try: + mainKey = win32ui.GetAppRegistryKey() + toolKey = win32api.RegOpenKey(mainKey, "Tools Menu") + except win32ui.error: + toolKey = None + if toolKey is not None: + while 1: + try: + subkey = win32api.RegEnumKey(toolKey, 0) + except win32api.error: + break + win32api.RegDeleteKey(toolKey, subkey) + # Keys are now removed - write the new ones. + # But first check if we have the defaults - and if so, dont write anything! + if items==defaultToolMenuItems: + return + itemNo = 1 + for menu, cmd in items: + win32ui.WriteProfileVal("Tools Menu\\%s" % itemNo, "", menu) + win32ui.WriteProfileVal("Tools Menu\\%s" % itemNo, "Command", cmd) + itemNo = itemNo + 1 + +def SetToolsMenu(menu, menuPos = None): + global tools + global idPos + + # todo - check the menu does not already exist. + # Create the new menu + toolsMenu = win32ui.CreatePopupMenu() + + # Load from the ini file. + items = LoadToolMenuItems() + for menuString, cmd in items: + tools[idPos] = (menuString, cmd, menuString) + toolsMenu.AppendMenu(win32con.MF_ENABLED|win32con.MF_STRING,idPos, menuString) + win32ui.GetMainFrame().HookCommand(HandleToolCommand, idPos) + idPos=idPos+1 + + # Find the correct spot to insert the new tools menu. + if menuPos is None: + menuPos = menu.GetMenuItemCount()-2 + if menuPos<0: menuPos=0 + + menu.InsertMenu(menuPos, win32con.MF_BYPOSITION|win32con.MF_ENABLED|win32con.MF_STRING|win32con.MF_POPUP, toolsMenu.GetHandle(), '&Tools') + +def HandleToolCommand(cmd, code): + import traceback + import re + global tools + (menuString, pyCmd, desc) = tools[cmd] + win32ui.SetStatusText("Executing tool %s" % desc, 1) + pyCmd = re.sub('\\\\n','\n', pyCmd) + win32ui.DoWaitCursor(1) + oldFlag = None + try: + oldFlag = sys.stdout.template.writeQueueing + sys.stdout.template.writeQueueing = 0 + except (NameError, AttributeError): + pass + + try: + exec("%s\n" % pyCmd) + worked=1 + except SystemExit: + # The program raised a SystemExit - ignore it. + worked = 1 + except: + print("Failed to execute command:\n%s" % pyCmd) + traceback.print_exc() + worked=0 + if oldFlag is not None: + sys.stdout.template.writeQueueing = oldFlag + win32ui.DoWaitCursor(0) + if worked: + text = "Completed successfully." + else: + text = "Error executing %s." % desc + win32ui.SetStatusText(text, 1) + +# The property page for maintaing the items on the Tools menu. +import commctrl +from pywin.mfc import dialog + +if win32ui.UNICODE: + LVN_ENDLABELEDIT = commctrl.LVN_ENDLABELEDITW +else: + LVN_ENDLABELEDIT = commctrl.LVN_ENDLABELEDITA + +class ToolMenuPropPage(dialog.PropertyPage): + def __init__(self): + self.bImChangingEditControls = 0 # Am I programatically changing the controls? + dialog.PropertyPage.__init__(self, win32ui.IDD_PP_TOOLMENU) + + def OnInitDialog(self): + self.editMenuCommand = self.GetDlgItem(win32ui.IDC_EDIT2) + self.butNew = self.GetDlgItem(win32ui.IDC_BUTTON3) + + # Now hook the change notification messages for the edit controls. + self.HookCommand(self.OnCommandEditControls, win32ui.IDC_EDIT1) + self.HookCommand(self.OnCommandEditControls, win32ui.IDC_EDIT2) + + self.HookNotify(self.OnNotifyListControl, commctrl.LVN_ITEMCHANGED) + self.HookNotify(self.OnNotifyListControlEndLabelEdit, commctrl.LVN_ENDLABELEDIT) + + # Hook the button clicks. + self.HookCommand(self.OnButtonNew, win32ui.IDC_BUTTON3) # New Item + self.HookCommand(self.OnButtonDelete, win32ui.IDC_BUTTON4) # Delete item + self.HookCommand(self.OnButtonMove, win32ui.IDC_BUTTON1) # Move up + self.HookCommand(self.OnButtonMove, win32ui.IDC_BUTTON2) # Move down + + # Setup the columns in the list control + lc = self.GetDlgItem(win32ui.IDC_LIST1) + rect = lc.GetWindowRect() + cx = rect[2] - rect[0] + colSize = cx/2 - win32api.GetSystemMetrics(win32con.SM_CXBORDER) - 1 + + item = commctrl.LVCFMT_LEFT, colSize, "Menu Text" + lc.InsertColumn(0, item) + + item = commctrl.LVCFMT_LEFT, colSize, "Python Command" + lc.InsertColumn(1, item) + + # Insert the existing tools menu + itemNo = 0 + for desc, cmd in LoadToolMenuItems(): + lc.InsertItem(itemNo, desc) + lc.SetItemText(itemNo, 1, cmd) + itemNo = itemNo + 1 + + self.listControl = lc + return dialog.PropertyPage.OnInitDialog(self) + + def OnOK(self): + # Write the menu back to the registry. + items = [] + itemLook = 0 + while 1: + try: + text = self.listControl.GetItemText(itemLook, 0); + if not text: + break + items.append( (text, self.listControl.GetItemText(itemLook, 1)) ) + except win32ui.error: + # no more items! + break + itemLook = itemLook + 1 + WriteToolMenuItems( items ) + return self._obj_.OnOK() + + def OnCommandEditControls(self, id, cmd): +# print "OnEditControls", id, cmd + if cmd==win32con.EN_CHANGE and not self.bImChangingEditControls: + itemNo = self.listControl.GetNextItem(-1, commctrl.LVNI_SELECTED) + newText = self.editMenuCommand.GetWindowText() + self.listControl.SetItemText(itemNo, 1, newText) + + return 0 + + def OnNotifyListControlEndLabelEdit(self, id, cmd): + newText = self.listControl.GetEditControl().GetWindowText() + itemNo = self.listControl.GetNextItem(-1, commctrl.LVNI_SELECTED) + self.listControl.SetItemText(itemNo, 0, newText) + + def OnNotifyListControl(self, id, cmd): +# print id, cmd + try: + itemNo = self.listControl.GetNextItem(-1, commctrl.LVNI_SELECTED) + except win32ui.error: # No selection! + return + + self.bImChangingEditControls = 1 + try: + item = self.listControl.GetItem(itemNo, 1) + self.editMenuCommand.SetWindowText(item[4]) + finally: + self.bImChangingEditControls = 0 + + return 0 # we have handled this! + + def OnButtonNew(self, id, cmd): + if cmd==win32con.BN_CLICKED: + newIndex = self.listControl.GetItemCount() + self.listControl.InsertItem(newIndex, "Click to edit the text") + self.listControl.EnsureVisible(newIndex, 0) + + def OnButtonMove(self, id, cmd): + if cmd==win32con.BN_CLICKED: + try: + itemNo = self.listControl.GetNextItem(-1, commctrl.LVNI_SELECTED) + except win32ui.error: + return + menu = self.listControl.GetItemText(itemNo, 0) + cmd = self.listControl.GetItemText(itemNo, 1) + if id == win32ui.IDC_BUTTON1: + # Move up + if itemNo > 0: + self.listControl.DeleteItem(itemNo) + # reinsert it. + self.listControl.InsertItem(itemNo-1, menu) + self.listControl.SetItemText(itemNo-1, 1, cmd) + else: + # Move down. + if itemNo < self.listControl.GetItemCount()-1: + self.listControl.DeleteItem(itemNo) + # reinsert it. + self.listControl.InsertItem(itemNo+1, menu) + self.listControl.SetItemText(itemNo+1, 1, cmd) + + def OnButtonDelete(self, id, cmd): + if cmd==win32con.BN_CLICKED: + try: + itemNo = self.listControl.GetNextItem(-1, commctrl.LVNI_SELECTED) + except win32ui.error: # No selection! + return + self.listControl.DeleteItem(itemNo) diff --git a/Lib/site-packages/pythonwin/pywin/framework/window.py b/Lib/site-packages/pythonwin/pywin/framework/window.py new file mode 100644 index 0000000..d59bd45 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/window.py @@ -0,0 +1,13 @@ +# Framework Window classes. + +# Most Pythonwin windows should use these classes rather than +# the raw MFC ones if they want Pythonwin specific functionality. +import pywin.mfc.window +import win32con + +class MDIChildWnd(pywin.mfc.window.MDIChildWnd): + def AutoRestore(self): + "If the window is minimised or maximised, restore it." + p = self.GetWindowPlacement() + if p[1]==win32con.SW_MINIMIZE or p[1]==win32con.SW_SHOWMINIMIZED: + self.SetWindowPlacement(p[0], win32con.SW_RESTORE, p[2], p[3], p[4]) diff --git a/Lib/site-packages/pythonwin/pywin/framework/winout.py b/Lib/site-packages/pythonwin/pywin/framework/winout.py new file mode 100644 index 0000000..e081bd2 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/framework/winout.py @@ -0,0 +1,518 @@ +# winout.py +# +# generic "output window" +# +# This Window will detect itself closing, and recreate next time output is +# written to it. + +# This has the option of writing output at idle time (by hooking the +# idle message, and queueing output) or writing as each +# write is executed. +# Updating the window directly gives a jerky appearance as many writes +# take place between commands, and the windows scrolls, and updates etc +# Updating at idle-time may defer all output of a long process, giving the +# appearence nothing is happening. +# There is a compromise "line" mode, which will output whenever +# a complete line is available. + +# behaviour depends on self.writeQueueing + +# This module is thread safe - output can originate from any thread. If any thread +# other than the main thread attempts to print, it is always queued until next idle time + +import sys, string, re +from pywin.mfc import docview +from pywin.framework import app, window +import win32ui, win32api, win32con +import queue + +debug = lambda msg: None + +##debug=win32ui.OutputDebugString +##import win32trace;win32trace.InitWrite() # for debugging - delete me! +##debug = win32trace.write + +class flags: + # queueing of output. + WQ_NONE = 0 + WQ_LINE = 1 + WQ_IDLE = 2 + +#WindowOutputDocumentParent=docview.RichEditDoc +#WindowOutputDocumentParent=docview.Document +import pywin.scintilla.document +from pywin.scintilla import scintillacon +from pywin import default_scintilla_encoding + +WindowOutputDocumentParent=pywin.scintilla.document.CScintillaDocument +class WindowOutputDocument(WindowOutputDocumentParent): + def SaveModified(self): + return 1 # say it is OK to destroy my document + + def OnSaveDocument( self, fileName ): + win32ui.SetStatusText("Saving file...",1) + try: + self.SaveFile(fileName) + except IOError as details: + win32ui.MessageBox("Error - could not save file\r\n\r\n%s"%details) + return 0 + win32ui.SetStatusText("Ready") + return 1 + +class WindowOutputFrame(window.MDIChildWnd): + def __init__(self, wnd = None): + window.MDIChildWnd.__init__(self, wnd) + self.HookMessage(self.OnSizeMove, win32con.WM_SIZE) + self.HookMessage(self.OnSizeMove, win32con.WM_MOVE) + + def LoadFrame( self, idResource, style, wndParent, context ): + self.template = context.template + return self._obj_.LoadFrame(idResource, style, wndParent, context) + + def PreCreateWindow(self, cc): + cc = self._obj_.PreCreateWindow(cc) + if self.template.defSize and self.template.defSize[0] != self.template.defSize[1]: + rect = app.RectToCreateStructRect(self.template.defSize) + cc = cc[0], cc[1], cc[2], cc[3], rect, cc[5], cc[6], cc[7], cc[8] + return cc + def OnSizeMove(self, msg): + # so recreate maintains position. + # Need to map coordinates from the + # frame windows first child. + mdiClient = self.GetParent() + self.template.defSize = mdiClient.ScreenToClient(self.GetWindowRect()) + def OnDestroy(self, message): + self.template.OnFrameDestroy(self) + return 1 + +class WindowOutputViewImpl: + def __init__(self): + self.patErrorMessage=re.compile('\W*File "(.*)", line ([0-9]+)') + self.template = self.GetDocument().GetDocTemplate() + + def HookHandlers(self): + # Hook for the right-click menu. + self.HookMessage(self.OnRClick,win32con.WM_RBUTTONDOWN) + + def OnDestroy(self, msg): + self.template.OnViewDestroy(self) + + def OnInitialUpdate(self): + self.RestoreKillBuffer() + self.SetSel(-2) # end of buffer + + def GetRightMenuItems(self): + ret = [] + flags=win32con.MF_STRING|win32con.MF_ENABLED + ret.append((flags, win32ui.ID_EDIT_COPY, '&Copy')) + ret.append((flags, win32ui.ID_EDIT_SELECT_ALL, '&Select all')) + return ret + + # + # Windows command handlers, virtuals, etc. + # + def OnRClick(self,params): + paramsList = self.GetRightMenuItems() + menu = win32ui.CreatePopupMenu() + for appendParams in paramsList: + if type(appendParams)!=type(()): + appendParams = (appendParams,) + menu.AppendMenu(*appendParams) + menu.TrackPopupMenu(params[5]) # track at mouse position. + return 0 + + # as this is often used as an output window, exeptions will often + # be printed. Therefore, we support this functionality at this level. + # Returns TRUE if the current line is an error message line, and will + # jump to it. FALSE if no error (and no action taken) + def HandleSpecialLine(self): + from . import scriptutils + line = self.GetLine() + if line[:11]=="com_error: ": + # An OLE Exception - pull apart the exception + # and try and locate a help file. + try: + import win32api, win32con + det = eval(line[line.find(":")+1:].strip()) + win32ui.SetStatusText("Opening help file on OLE error..."); + from . import help + help.OpenHelpFile(det[2][3],win32con.HELP_CONTEXT, det[2][4]) + return 1 + except win32api.error as details: + win32ui.SetStatusText("The help file could not be opened - %s" % details.strerror) + return 1 + except: + win32ui.SetStatusText("Line is a COM error, but no WinHelp details can be parsed"); + # Look for a Python traceback. + matchResult = self.patErrorMessage.match(line) + if matchResult is None: + # No match - try the previous line + lineNo = self.LineFromChar() + if lineNo > 0: + line = self.GetLine(lineNo-1) + matchResult = self.patErrorMessage.match(line) + if matchResult is not None: + # we have an error line. + fileName = matchResult.group(1) + if fileName[0]=="<": + win32ui.SetStatusText("Can not load this file") + return 1 # still was an error message. + else: + lineNoString = matchResult.group(2) + # Attempt to locate the file (in case it is a relative spec) + fileNameSpec = fileName + fileName = scriptutils.LocatePythonFile(fileName) + if fileName is None: + # Dont force update, so it replaces the idle prompt. + win32ui.SetStatusText("Cant locate the file '%s'" % (fileNameSpec), 0) + return 1 + + win32ui.SetStatusText("Jumping to line "+lineNoString+" of file "+fileName,1) + if not scriptutils.JumpToDocument(fileName, int(lineNoString)): + win32ui.SetStatusText("Could not open %s" % fileName) + return 1 # still was an error message. + return 1 + return 0 # not an error line + def write(self, msg): + return self.template.write(msg) + def writelines(self, lines): + for line in lines: + self.write(line) + def flush(self): + self.template.flush() + +class WindowOutputViewRTF(docview.RichEditView, WindowOutputViewImpl): + def __init__(self, doc): + docview.RichEditView.__init__(self, doc) + WindowOutputViewImpl.__init__(self) + + def OnInitialUpdate(self): + WindowOutputViewImpl.OnInitialUpdate(self) + return docview.RichEditView.OnInitialUpdate(self) + + def OnDestroy(self, msg): + WindowOutputViewImpl.OnDestroy(self, msg) + docview.RichEditView.OnDestroy(self, msg) + + def HookHandlers(self): + WindowOutputViewImpl.HookHandlers(self) + # Hook for finding and locating error messages + self.HookMessage(self.OnLDoubleClick,win32con.WM_LBUTTONDBLCLK) +# docview.RichEditView.HookHandlers(self) + + def OnLDoubleClick(self,params): + if self.HandleSpecialLine(): + return 0 # dont pass on + return 1 # pass it on by default. + + def RestoreKillBuffer(self): + if len(self.template.killBuffer): + self.StreamIn(win32con.SF_RTF, self._StreamRTFIn) + self.template.killBuffer = [] + + def SaveKillBuffer(self): + self.StreamOut(win32con.SF_RTFNOOBJS, self._StreamRTFOut) + + def _StreamRTFOut(self, data): + self.template.killBuffer.append(data) + return 1 # keep em coming! + + def _StreamRTFIn(self, bytes): + try: + item = self.template.killBuffer[0] + self.template.killBuffer.remove(item) + if bytes < len(item): + print("Warning - output buffer not big enough!") + return item + except IndexError: + return None + def dowrite(self, str): + self.SetSel(-2) + self.ReplaceSel(str) + +import pywin.scintilla.view +class WindowOutputViewScintilla(pywin.scintilla.view.CScintillaView, WindowOutputViewImpl): + def __init__(self, doc): + pywin.scintilla.view.CScintillaView.__init__(self, doc) + WindowOutputViewImpl.__init__(self) + + def OnInitialUpdate(self): + pywin.scintilla.view.CScintillaView.OnInitialUpdate(self) + self.SCISetMarginWidth(3) + WindowOutputViewImpl.OnInitialUpdate(self) + + def OnDestroy(self, msg): + WindowOutputViewImpl.OnDestroy(self, msg) + pywin.scintilla.view.CScintillaView.OnDestroy(self, msg) + + def HookHandlers(self): + WindowOutputViewImpl.HookHandlers(self) + pywin.scintilla.view.CScintillaView.HookHandlers(self) + self.GetParent().HookNotify(self.OnScintillaDoubleClick, scintillacon.SCN_DOUBLECLICK) +## self.HookMessage(self.OnLDoubleClick,win32con.WM_LBUTTONDBLCLK) + + def OnScintillaDoubleClick(self, std, extra): + self.HandleSpecialLine() + +## def OnLDoubleClick(self,params): +## return 0 # never dont pass on + + def RestoreKillBuffer(self): + assert len(self.template.killBuffer) in [0,1], "Unexpected killbuffer contents" + if self.template.killBuffer: + self.SCIAddText(self.template.killBuffer[0]) + self.template.killBuffer = [] + def SaveKillBuffer(self): + self.template.killBuffer = [self.GetTextRange(0,-1)] + def dowrite(self, str): + end = self.GetTextLength() + atEnd = end==self.GetSel()[0] + self.SCIInsertText(str, end) + if atEnd: + self.SetSel(self.GetTextLength()) + + def SetWordWrap(self, bWrapOn = 1): + if bWrapOn: + wrap_mode = scintillacon.SC_WRAP_WORD + else: + wrap_mode = scintillacon.SC_WRAP_NONE + self.SCISetWrapMode(wrap_mode) + + def _MakeColorizer(self): + return None # No colorizer for me! + +WindowOutputView = WindowOutputViewScintilla +# The WindowOutput class is actually an MFC template. This is a conventient way of +# making sure that my state can exist beyond the life of the windows themselves. +# This is primarily to support the functionality of a WindowOutput window automatically +# being recreated if necessary when written to. +class WindowOutput(docview.DocTemplate): + """ Looks like a general Output Window - text can be written by the 'write' method. + Will auto-create itself on first write, and also on next write after being closed """ + softspace=1 + def __init__(self, title=None, defSize=None, queueing = flags.WQ_LINE, \ + bAutoRestore = 1, style=None, + makeDoc = None, makeFrame = None, makeView = None): + """ init the output window - + Params + title=None -- What is the title of the window + defSize=None -- What is the default size for the window - if this + is a string, the size will be loaded from the ini file. + queueing = flags.WQ_LINE -- When should output be written + bAutoRestore=1 -- Should a minimized window be restored. + style -- Style for Window, or None for default. + makeDoc, makeFrame, makeView -- Classes for frame, view and window respectively. + """ + if makeDoc is None: makeDoc = WindowOutputDocument + if makeFrame is None: makeFrame = WindowOutputFrame + if makeView is None: makeView = WindowOutputViewScintilla + docview.DocTemplate.__init__(self, win32ui.IDR_PYTHONTYPE, \ + makeDoc, makeFrame, makeView) + self.SetDocStrings("\nOutput\n\nText Documents (*.txt)\n.txt\n\n\n") + win32ui.GetApp().AddDocTemplate(self) + self.writeQueueing = queueing + self.errorCantRecreate = 0 + self.killBuffer=[] + self.style = style + self.bAutoRestore = bAutoRestore + self.title = title + self.bCreating = 0 + self.interruptCount = 0 + if type(defSize)==type(''): # is a string - maintain size pos from ini file. + self.iniSizeSection = defSize + self.defSize = app.LoadWindowSize(defSize) + self.loadedSize = self.defSize + else: + self.iniSizeSection = None + self.defSize=defSize + self.currentView = None + self.outputQueue = queue.Queue(-1) + self.mainThreadId = win32api.GetCurrentThreadId() + self.idleHandlerSet = 0 + self.SetIdleHandler() + + def __del__(self): + self.Close() + + def Create(self, title=None, style = None): + self.bCreating = 1 + if title: self.title = title + if style: self.style = style + doc=self.OpenDocumentFile() + if doc is None: return + self.currentView = doc.GetFirstView() + self.bCreating = 0 + if self.title: doc.SetTitle(self.title) + + def Close(self): + self.RemoveIdleHandler() + try: + parent = self.currentView.GetParent() + except (AttributeError, win32ui.error): # Already closed + return + parent.DestroyWindow() + + def SetTitle(self, title): + self.title = title + if self.currentView: self.currentView.GetDocument().SetTitle(self.title) + + def OnViewDestroy(self, view): + self.currentView.SaveKillBuffer() + self.currentView = None + + def OnFrameDestroy(self, frame): + if self.iniSizeSection: + # use GetWindowPlacement(), as it works even when min'd or max'd + newSize = frame.GetWindowPlacement()[4] + if self.loadedSize!=newSize: + app.SaveWindowSize(self.iniSizeSection, newSize) + + def SetIdleHandler(self): + if not self.idleHandlerSet: + debug("Idle handler set\n") + win32ui.GetApp().AddIdleHandler(self.QueueIdleHandler) + self.idleHandlerSet = 1 + + def RemoveIdleHandler(self): + if self.idleHandlerSet: + debug("Idle handler reset\n") + if (win32ui.GetApp().DeleteIdleHandler(self.QueueIdleHandler)==0): + debug('Error deleting idle handler\n') + self.idleHandlerSet = 0 + + def RecreateWindow(self): + if self.errorCantRecreate: + debug("Error = not trying again") + return 0 + try: + # This will fail if app shutting down + win32ui.GetMainFrame().GetSafeHwnd() + self.Create() + return 1 + except (win32ui.error, AttributeError): + self.errorCantRecreate = 1 + debug("Winout can not recreate the Window!\n") + return 0 + + # this handles the idle message, and does the printing. + def QueueIdleHandler(self,handler,count): + try: + bEmpty = self.QueueFlush(20) + # If the queue is empty, then we are back to idle and restart interrupt logic. + if bEmpty: self.interruptCount = 0 + except KeyboardInterrupt: + # First interrupt since idle we just pass on. + # later ones we dump the queue and give up. + self.interruptCount = self.interruptCount + 1 + if self.interruptCount > 1: + # Drop the queue quickly as the user is already annoyed :-) + self.outputQueue = queue.Queue(-1) + print("Interrupted.") + bEmpty = 1 + else: + raise # re-raise the error so the users exception filters up. + return not bEmpty # More to do if not empty. + + # Returns true if the Window needs to be recreated. + def NeedRecreateWindow(self): + try: + if self.currentView is not None and self.currentView.IsWindow(): + return 0 + except (win32ui.error, AttributeError): # Attribute error if the win32ui object has died. + pass + return 1 + + # Returns true if the Window is OK (either cos it was, or because it was recreated + def CheckRecreateWindow(self): + if self.bCreating: return 1 + if not self.NeedRecreateWindow(): + return 1 + if self.bAutoRestore: + if self.RecreateWindow(): + return 1 + return 0 + + def QueueFlush(self, max = None): + # Returns true if the queue is empty after the flush +# debug("Queueflush - %d, %d\n" % (max, self.outputQueue.qsize())) + if self.bCreating: return 1 + items = [] + rc = 0 + while max is None or max > 0: + try: + item = self.outputQueue.get_nowait() + items.append(item) + except queue.Empty: + rc = 1 + break + if max is not None: + max = max - 1 + if len(items) != 0: + if not self.CheckRecreateWindow(): + debug(":Recreate failed!\n") + return 1 # In trouble - so say we have nothing to do. + win32ui.PumpWaitingMessages() # Pump paint messages + self.currentView.dowrite(''.join(items)) + return rc + + def HandleOutput(self,message): +# debug("QueueOutput on thread %d, flags %d with '%s'...\n" % (win32api.GetCurrentThreadId(), self.writeQueueing, message )) + self.outputQueue.put(message) + if win32api.GetCurrentThreadId() != self.mainThreadId: + pass +# debug("not my thread - ignoring queue options!\n") + elif self.writeQueueing==flags.WQ_LINE: + pos = message.rfind('\n') + if pos>=0: +# debug("Line queueing - forcing flush\n") + self.QueueFlush() + return + elif self.writeQueueing==flags.WQ_NONE: +# debug("WQ_NONE - flushing!\n") + self.QueueFlush() + return + # Let our idle handler get it - wake it up + try: + win32ui.GetMainFrame().PostMessage(win32con.WM_USER) # Kick main thread off. + except win32ui.error: + # This can happen as the app is shutting down, so we send it to the C++ debugger + win32api.OutputDebugString(message) + + # delegate certain fns to my view. + def writelines(self, lines): + for line in lines: + self.write(line) + + def write(self,message): + self.HandleOutput(message) + + def flush(self): + self.QueueFlush() + + def HandleSpecialLine(self): + self.currentView.HandleSpecialLine() + +def RTFWindowOutput(*args, **kw): + kw['makeView'] = WindowOutputViewRTF + return WindowOutput(*args, **kw) + + +def thread_test(o): + for i in range(5): + o.write("Hi from thread %d\n" % (win32api.GetCurrentThreadId())) + win32api.Sleep(100) + +def test(): + w = WindowOutput(queueing=flags.WQ_IDLE) + w.write("First bit of text\n") + import _thread + for i in range(5): + w.write("Hello from the main thread\n") + _thread.start_new(thread_test, (w,)) + for i in range(2): + w.write("Hello from the main thread\n") + win32api.Sleep(50) + return w + +if __name__=='__main__': + test() diff --git a/Lib/site-packages/pythonwin/pywin/idle/AutoExpand.py b/Lib/site-packages/pythonwin/pywin/idle/AutoExpand.py new file mode 100644 index 0000000..c7a55e3 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/idle/AutoExpand.py @@ -0,0 +1,92 @@ +import string +import re + +###$ event <> +###$ win +###$ unix + +class AutoExpand: + + keydefs = { + '<>': [''], + } + + unix_keydefs = { + '<>': [''], + } + + menudefs = [ + ('edit', [ + ('E_xpand word', '<>'), + ]), + ] + + wordchars = string.ascii_letters + string.digits + "_" + + def __init__(self, editwin): + self.text = editwin.text + self.text.wordlist = None # XXX what is this? + self.state = None + + def expand_word_event(self, event): + curinsert = self.text.index("insert") + curline = self.text.get("insert linestart", "insert lineend") + if not self.state: + words = self.getwords() + index = 0 + else: + words, index, insert, line = self.state + if insert != curinsert or line != curline: + words = self.getwords() + index = 0 + if not words: + self.text.bell() + return "break" + word = self.getprevword() + self.text.delete("insert - %d chars" % len(word), "insert") + newword = words[index] + index = (index + 1) % len(words) + if index == 0: + self.text.bell() # Warn we cycled around + self.text.insert("insert", newword) + curinsert = self.text.index("insert") + curline = self.text.get("insert linestart", "insert lineend") + self.state = words, index, curinsert, curline + return "break" + + def getwords(self): + word = self.getprevword() + if not word: + return [] + before = self.text.get("1.0", "insert wordstart") + wbefore = re.findall(r"\b" + word + r"\w+\b", before) + del before + after = self.text.get("insert wordend", "end") + wafter = re.findall(r"\b" + word + r"\w+\b", after) + del after + if not wbefore and not wafter: + return [] + words = [] + dict = {} + # search backwards through words before + wbefore.reverse() + for w in wbefore: + if dict.get(w): + continue + words.append(w) + dict[w] = w + # search onwards through words after + for w in wafter: + if dict.get(w): + continue + words.append(w) + dict[w] = w + words.append(word) + return words + + def getprevword(self): + line = self.text.get("insert linestart", "insert") + i = len(line) + while i > 0 and line[i-1] in self.wordchars: + i = i-1 + return line[i:] diff --git a/Lib/site-packages/pythonwin/pywin/idle/AutoIndent.py b/Lib/site-packages/pythonwin/pywin/idle/AutoIndent.py new file mode 100644 index 0000000..652ef58 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/idle/AutoIndent.py @@ -0,0 +1,529 @@ +import sys +import string, tokenize +from . import PyParse +from pywin import default_scintilla_encoding + +if sys.version_info < (3,): + # in py2k, tokenize() takes a 'token eater' callback, while + # generate_tokens is a generator that works with str objects. + token_generator = tokenize.generate_tokens +else: + # in py3k tokenize() is the generator working with 'byte' objects, and + # token_generator is the 'undocumented b/w compat' function that + # theoretically works with str objects - but actually seems to fail) + token_generator = tokenize.tokenize + +class AutoIndent: + + menudefs = [ + ('edit', [ + None, + ('_Indent region', '<>'), + ('_Dedent region', '<>'), + ('Comment _out region', '<>'), + ('U_ncomment region', '<>'), + ('Tabify region', '<>'), + ('Untabify region', '<>'), + ('Toggle tabs', '<>'), + ('New indent width', '<>'), + ]), + ] + + keydefs = { + '<>': [''], + '<>': ['', ''], + '<>': [''] + } + + windows_keydefs = { + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + } + + unix_keydefs = { + '<>': ['', + '', + ''], + '<>': ['', + '', + ''], + '<>': ['', ''], + '<>': ['', ''], + '<>': ['', ''], + '<>': ['', ''], + '<>': [''], + '<>': [''], + } + + # usetabs true -> literal tab characters are used by indent and + # dedent cmds, possibly mixed with spaces if + # indentwidth is not a multiple of tabwidth + # false -> tab characters are converted to spaces by indent + # and dedent cmds, and ditto TAB keystrokes + # indentwidth is the number of characters per logical indent level. + # tabwidth is the display width of a literal tab character. + # CAUTION: telling Tk to use anything other than its default + # tab setting causes it to use an entirely different tabbing algorithm, + # treating tab stops as fixed distances from the left margin. + # Nobody expects this, so for now tabwidth should never be changed. + usetabs = 1 + indentwidth = 4 + tabwidth = 8 # for IDLE use, must remain 8 until Tk is fixed + + # If context_use_ps1 is true, parsing searches back for a ps1 line; + # else searches for a popular (if, def, ...) Python stmt. + context_use_ps1 = 0 + + # When searching backwards for a reliable place to begin parsing, + # first start num_context_lines[0] lines back, then + # num_context_lines[1] lines back if that didn't work, and so on. + # The last value should be huge (larger than the # of lines in a + # conceivable file). + # Making the initial values larger slows things down more often. + num_context_lines = 50, 500, 5000000 + + def __init__(self, editwin): + self.editwin = editwin + self.text = editwin.text + + def config(self, **options): + for key, value in options.items(): + if key == 'usetabs': + self.usetabs = value + elif key == 'indentwidth': + self.indentwidth = value + elif key == 'tabwidth': + self.tabwidth = value + elif key == 'context_use_ps1': + self.context_use_ps1 = value + else: + raise KeyError("bad option name: %s" % repr(key)) + + # If ispythonsource and guess are true, guess a good value for + # indentwidth based on file content (if possible), and if + # indentwidth != tabwidth set usetabs false. + # In any case, adjust the Text widget's view of what a tab + # character means. + + def set_indentation_params(self, ispythonsource, guess=1): + if guess and ispythonsource: + i = self.guess_indent() + if 2 <= i <= 8: + self.indentwidth = i + if self.indentwidth != self.tabwidth: + self.usetabs = 0 + + self.editwin.set_tabwidth(self.tabwidth) + + def smart_backspace_event(self, event): + text = self.text + first, last = self.editwin.get_selection_indices() + if first and last: + text.delete(first, last) + text.mark_set("insert", first) + return "break" + # Delete whitespace left, until hitting a real char or closest + # preceding virtual tab stop. + chars = text.get("insert linestart", "insert") + if chars == '': + if text.compare("insert", ">", "1.0"): + # easy: delete preceding newline + text.delete("insert-1c") + else: + text.bell() # at start of buffer + return "break" + if chars[-1] not in " \t": + # easy: delete preceding real char + text.delete("insert-1c") + return "break" + # Ick. It may require *inserting* spaces if we back up over a + # tab character! This is written to be clear, not fast. + have = len(chars.expandtabs(self.tabwidth)) + assert have > 0 + want = int((have - 1) / self.indentwidth) * self.indentwidth + ncharsdeleted = 0 + while 1: + chars = chars[:-1] + ncharsdeleted = ncharsdeleted + 1 + have = len(chars.expandtabs(self.tabwidth)) + if have <= want or chars[-1] not in " \t": + break + text.undo_block_start() + text.delete("insert-%dc" % ncharsdeleted, "insert") + if have < want: + text.insert("insert", ' ' * (want - have)) + text.undo_block_stop() + return "break" + + def smart_indent_event(self, event): + # if intraline selection: + # delete it + # elif multiline selection: + # do indent-region & return + # indent one level + text = self.text + first, last = self.editwin.get_selection_indices() + text.undo_block_start() + try: + if first and last: + if index2line(first) != index2line(last): + return self.indent_region_event(event) + text.delete(first, last) + text.mark_set("insert", first) + prefix = text.get("insert linestart", "insert") + raw, effective = classifyws(prefix, self.tabwidth) + if raw == len(prefix): + # only whitespace to the left + self.reindent_to(effective + self.indentwidth) + else: + if self.usetabs: + pad = '\t' + else: + effective = len(prefix.expandtabs(self.tabwidth)) + n = self.indentwidth + pad = ' ' * (n - effective % n) + text.insert("insert", pad) + text.see("insert") + return "break" + finally: + text.undo_block_stop() + + def newline_and_indent_event(self, event): + text = self.text + first, last = self.editwin.get_selection_indices() + text.undo_block_start() + try: + if first and last: + text.delete(first, last) + text.mark_set("insert", first) + line = text.get("insert linestart", "insert") + i, n = 0, len(line) + while i < n and line[i] in " \t": + i = i+1 + if i == n: + # the cursor is in or at leading indentation; just inject + # an empty line at the start and strip space from current line + text.delete("insert - %d chars" % i, "insert") + text.insert("insert linestart", '\n') + return "break" + indent = line[:i] + # strip whitespace before insert point + i = 0 + while line and line[-1] in " \t": + line = line[:-1] + i = i+1 + if i: + text.delete("insert - %d chars" % i, "insert") + # strip whitespace after insert point + while text.get("insert") in " \t": + text.delete("insert") + # start new line + text.insert("insert", '\n') + + # adjust indentation for continuations and block + # open/close first need to find the last stmt + lno = index2line(text.index('insert')) + y = PyParse.Parser(self.indentwidth, self.tabwidth) + for context in self.num_context_lines: + startat = max(lno - context, 1) + startatindex = repr(startat) + ".0" + rawtext = text.get(startatindex, "insert") + y.set_str(rawtext) + bod = y.find_good_parse_start( + self.context_use_ps1, + self._build_char_in_string_func(startatindex)) + if bod is not None or startat == 1: + break + y.set_lo(bod or 0) + c = y.get_continuation_type() + if c != PyParse.C_NONE: + # The current stmt hasn't ended yet. + if c == PyParse.C_STRING: + # inside a string; just mimic the current indent + text.insert("insert", indent) + elif c == PyParse.C_BRACKET: + # line up with the first (if any) element of the + # last open bracket structure; else indent one + # level beyond the indent of the line with the + # last open bracket + self.reindent_to(y.compute_bracket_indent()) + elif c == PyParse.C_BACKSLASH: + # if more than one line in this stmt already, just + # mimic the current indent; else if initial line + # has a start on an assignment stmt, indent to + # beyond leftmost =; else to beyond first chunk of + # non-whitespace on initial line + if y.get_num_lines_in_stmt() > 1: + text.insert("insert", indent) + else: + self.reindent_to(y.compute_backslash_indent()) + else: + assert 0, "bogus continuation type " + repr(c) + return "break" + + # This line starts a brand new stmt; indent relative to + # indentation of initial line of closest preceding + # interesting stmt. + indent = y.get_base_indent_string() + text.insert("insert", indent) + if y.is_block_opener(): + self.smart_indent_event(event) + elif indent and y.is_block_closer(): + self.smart_backspace_event(event) + return "break" + finally: + text.see("insert") + text.undo_block_stop() + + auto_indent = newline_and_indent_event + + # Our editwin provides a is_char_in_string function that works + # with a Tk text index, but PyParse only knows about offsets into + # a string. This builds a function for PyParse that accepts an + # offset. + + def _build_char_in_string_func(self, startindex): + def inner(offset, _startindex=startindex, + _icis=self.editwin.is_char_in_string): + return _icis(_startindex + "+%dc" % offset) + return inner + + def indent_region_event(self, event): + head, tail, chars, lines = self.get_region() + for pos in range(len(lines)): + line = lines[pos] + if line: + raw, effective = classifyws(line, self.tabwidth) + effective = effective + self.indentwidth + lines[pos] = self._make_blanks(effective) + line[raw:] + self.set_region(head, tail, chars, lines) + return "break" + + def dedent_region_event(self, event): + head, tail, chars, lines = self.get_region() + for pos in range(len(lines)): + line = lines[pos] + if line: + raw, effective = classifyws(line, self.tabwidth) + effective = max(effective - self.indentwidth, 0) + lines[pos] = self._make_blanks(effective) + line[raw:] + self.set_region(head, tail, chars, lines) + return "break" + + def comment_region_event(self, event): + head, tail, chars, lines = self.get_region() + for pos in range(len(lines) - 1): + line = lines[pos] + lines[pos] = '##' + line + self.set_region(head, tail, chars, lines) + + def uncomment_region_event(self, event): + head, tail, chars, lines = self.get_region() + for pos in range(len(lines)): + line = lines[pos] + if not line: + continue + if line[:2] == '##': + line = line[2:] + elif line[:1] == '#': + line = line[1:] + lines[pos] = line + self.set_region(head, tail, chars, lines) + + def tabify_region_event(self, event): + head, tail, chars, lines = self.get_region() + tabwidth = self._asktabwidth() + for pos in range(len(lines)): + line = lines[pos] + if line: + raw, effective = classifyws(line, tabwidth) + ntabs, nspaces = divmod(effective, tabwidth) + lines[pos] = '\t' * ntabs + ' ' * nspaces + line[raw:] + self.set_region(head, tail, chars, lines) + + def untabify_region_event(self, event): + head, tail, chars, lines = self.get_region() + tabwidth = self._asktabwidth() + for pos in range(len(lines)): + lines[pos] = lines[pos].expandtabs(tabwidth) + self.set_region(head, tail, chars, lines) + + def toggle_tabs_event(self, event): + if self.editwin.askyesno( + "Toggle tabs", + "Turn tabs " + ("on", "off")[self.usetabs] + "?", + parent=self.text): + self.usetabs = not self.usetabs + return "break" + + # XXX this isn't bound to anything -- see class tabwidth comments + def change_tabwidth_event(self, event): + new = self._asktabwidth() + if new != self.tabwidth: + self.tabwidth = new + self.set_indentation_params(0, guess=0) + return "break" + + def change_indentwidth_event(self, event): + new = self.editwin.askinteger( + "Indent width", + "New indent width (1-16)", + parent=self.text, + initialvalue=self.indentwidth, + minvalue=1, + maxvalue=16) + if new and new != self.indentwidth: + self.indentwidth = new + return "break" + + def get_region(self): + text = self.text + first, last = self.editwin.get_selection_indices() + if first and last: + head = text.index(first + " linestart") + tail = text.index(last + "-1c lineend +1c") + else: + head = text.index("insert linestart") + tail = text.index("insert lineend +1c") + chars = text.get(head, tail) + lines = chars.split("\n") + return head, tail, chars, lines + + def set_region(self, head, tail, chars, lines): + text = self.text + newchars = "\n".join(lines) + if newchars == chars: + text.bell() + return + text.tag_remove("sel", "1.0", "end") + text.mark_set("insert", head) + text.undo_block_start() + text.delete(head, tail) + text.insert(head, newchars) + text.undo_block_stop() + text.tag_add("sel", head, "insert") + + # Make string that displays as n leading blanks. + + def _make_blanks(self, n): + if self.usetabs: + ntabs, nspaces = divmod(n, self.tabwidth) + return '\t' * ntabs + ' ' * nspaces + else: + return ' ' * n + + # Delete from beginning of line to insert point, then reinsert + # column logical (meaning use tabs if appropriate) spaces. + + def reindent_to(self, column): + text = self.text + text.undo_block_start() + if text.compare("insert linestart", "!=", "insert"): + text.delete("insert linestart", "insert") + if column: + text.insert("insert", self._make_blanks(column)) + text.undo_block_stop() + + def _asktabwidth(self): + return self.editwin.askinteger( + "Tab width", + "Spaces per tab?", + parent=self.text, + initialvalue=self.tabwidth, + minvalue=1, + maxvalue=16) or self.tabwidth + + # Guess indentwidth from text content. + # Return guessed indentwidth. This should not be believed unless + # it's in a reasonable range (e.g., it will be 0 if no indented + # blocks are found). + + def guess_indent(self): + opener, indented = IndentSearcher(self.text, self.tabwidth).run() + if opener and indented: + raw, indentsmall = classifyws(opener, self.tabwidth) + raw, indentlarge = classifyws(indented, self.tabwidth) + else: + indentsmall = indentlarge = 0 + return indentlarge - indentsmall + +# "line.col" -> line, as an int +def index2line(index): + return int(float(index)) + +# Look at the leading whitespace in s. +# Return pair (# of leading ws characters, +# effective # of leading blanks after expanding +# tabs to width tabwidth) + +def classifyws(s, tabwidth): + raw = effective = 0 + for ch in s: + if ch == ' ': + raw = raw + 1 + effective = effective + 1 + elif ch == '\t': + raw = raw + 1 + effective = (effective // tabwidth + 1) * tabwidth + else: + break + return raw, effective + +class IndentSearcher: + + # .run() chews over the Text widget, looking for a block opener + # and the stmt following it. Returns a pair, + # (line containing block opener, line containing stmt) + # Either or both may be None. + + def __init__(self, text, tabwidth): + self.text = text + self.tabwidth = tabwidth + self.i = self.finished = 0 + self.blkopenline = self.indentedline = None + + def readline(self): + if self.finished: + val = "" + else: + i = self.i = self.i + 1 + mark = repr(i) + ".0" + if self.text.compare(mark, ">=", "end"): + val = "" + else: + val = self.text.get(mark, mark + " lineend+1c") + # hrm - not sure this is correct in py3k - the source code may have + # an encoding declared, but the data will *always* be in + # default_scintilla_encoding - so if anyone looks at the encoding decl + # in the source they will be wrong. I think. Maybe. Or something... + return val.encode(default_scintilla_encoding) + + def run(self): + OPENERS=('class', 'def', 'for', 'if', 'try', 'while') + INDENT=tokenize.INDENT + NAME=tokenize.NAME + + save_tabsize = tokenize.tabsize + tokenize.tabsize = self.tabwidth + try: + try: + for (typ, token, start, end, line) in token_generator(self.readline): + if typ == NAME and token in OPENERS: + self.blkopenline = line + elif typ == INDENT and self.blkopenline: + self.indentedline = line + break + + except (tokenize.TokenError, IndentationError): + # since we cut off the tokenizer early, we can trigger + # spurious errors + pass + finally: + tokenize.tabsize = save_tabsize + return self.blkopenline, self.indentedline diff --git a/Lib/site-packages/pythonwin/pywin/idle/CallTips.py b/Lib/site-packages/pythonwin/pywin/idle/CallTips.py new file mode 100644 index 0000000..5ea1a92 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/idle/CallTips.py @@ -0,0 +1,188 @@ +# CallTips.py - An IDLE extension that provides "Call Tips" - ie, a floating window that +# displays parameter information as you open parens. + +import string +import sys +import inspect +import traceback + +class CallTips: + + menudefs = [ + ] + + keydefs = { + '<>': [''], + '<>': [''], + '<>': [''], + '<>': ['', ''], + } + + windows_keydefs = { + } + + unix_keydefs = { + } + + def __init__(self, editwin): + self.editwin = editwin + self.text = editwin.text + self.calltip = None + if hasattr(self.text, "make_calltip_window"): + self._make_calltip_window = self.text.make_calltip_window + else: + self._make_calltip_window = self._make_tk_calltip_window + + def close(self): + self._make_calltip_window = None + + # Makes a Tk based calltip window. Used by IDLE, but not Pythonwin. + # See __init__ above for how this is used. + def _make_tk_calltip_window(self): + import CallTipWindow + return CallTipWindow.CallTip(self.text) + + def _remove_calltip_window(self): + if self.calltip: + self.calltip.hidetip() + self.calltip = None + + def paren_open_event(self, event): + self._remove_calltip_window() + arg_text = get_arg_text(self.get_object_at_cursor()) + if arg_text: + self.calltip_start = self.text.index("insert") + self.calltip = self._make_calltip_window() + self.calltip.showtip(arg_text) + return "" #so the event is handled normally. + + def paren_close_event(self, event): + # Now just hides, but later we should check if other + # paren'd expressions remain open. + self._remove_calltip_window() + return "" #so the event is handled normally. + + def check_calltip_cancel_event(self, event): + if self.calltip: + # If we have moved before the start of the calltip, + # or off the calltip line, then cancel the tip. + # (Later need to be smarter about multi-line, etc) + if self.text.compare("insert", "<=", self.calltip_start) or \ + self.text.compare("insert", ">", self.calltip_start + " lineend"): + self._remove_calltip_window() + return "" #so the event is handled normally. + + def calltip_cancel_event(self, event): + self._remove_calltip_window() + return "" #so the event is handled normally. + + def get_object_at_cursor(self, + wordchars="._" + string.ascii_uppercase + string.ascii_lowercase + string.digits): + # XXX - This needs to be moved to a better place + # so the "." attribute lookup code can also use it. + text = self.text + chars = text.get("insert linestart", "insert") + i = len(chars) + while i and chars[i-1] in wordchars: + i = i-1 + word = chars[i:] + if word: + # How is this for a hack! + import sys, __main__ + namespace = sys.modules.copy() + namespace.update(__main__.__dict__) + try: + return eval(word, namespace) + except: + pass + return None # Can't find an object. + +def _find_constructor(class_ob): + # Given a class object, return a function object used for the + # constructor (ie, __init__() ) or None if we can't find one. + try: + if sys.version_info < (3,): + return class_ob.__init__.im_func + else: + return class_ob.__init__.__func__ + except AttributeError: + for base in class_ob.__bases__: + rc = _find_constructor(base) + if rc is not None: return rc + return None + +def get_arg_text(ob): + # Get a string describing the arguments for the given object. + argText = "" + if ob is not None: + argOffset = 0 + if inspect.isclass(ob): + # Look for the highest __init__ in the class chain. + fob = _find_constructor(ob) + if fob is None: + fob = lambda: None + else: + fob = ob + if inspect.isfunction(fob) or inspect.ismethod(fob): + try: + # py3k has a 'getfullargspec' which can handle py3k specific things. + arg_getter = getattr(inspect, "getfullargspec", inspect.getargspec) + argText = inspect.formatargspec(*arg_getter(fob)) + except: + print("Failed to format the args") + traceback.print_exc() + # See if we can use the docstring + if hasattr(ob, "__doc__"): + doc=ob.__doc__ + try: + doc = doc.strip() + pos = doc.find("\n") + except AttributeError: + ## New style classes may have __doc__ slot without actually + ## having a string assigned to it + pass + else: + if pos<0 or pos>70: pos=70 + if argText: argText = argText + "\n" + argText = argText + doc[:pos] + + return argText + +################################################# +# +# Test code +# +if __name__=='__main__': + + def t1(): "()" + def t2(a, b=None): "(a, b=None)" + def t3(a, *args): "(a, *args)" + def t4(*args): "(*args)" + def t5(a, *args): "(a, *args)" + def t6(a, b=None, *args, **kw): "(a, b=None, *args, **kw)" + + class TC: + "(self, a=None, *b)" + def __init__(self, a=None, *b): "(self, a=None, *b)" + def t1(self): "(self)" + def t2(self, a, b=None): "(self, a, b=None)" + def t3(self, a, *args): "(self, a, *args)" + def t4(self, *args): "(self, *args)" + def t5(self, a, *args): "(self, a, *args)" + def t6(self, a, b=None, *args, **kw): "(self, a, b=None, *args, **kw)" + + def test( tests ): + failed=[] + for t in tests: + expected = t.__doc__ + "\n" + t.__doc__ + if get_arg_text(t) != expected: + failed.append(t) + print("%s - expected %s, but got %s" % (t, repr(expected), repr(get_arg_text(t)))) + print("%d of %d tests failed" % (len(failed), len(tests))) + + tc = TC() + tests = t1, t2, t3, t4, t5, t6, \ + TC, tc.t1, tc.t2, tc.t3, tc.t4, tc.t5, tc.t6 + + test(tests) + diff --git a/Lib/site-packages/pythonwin/pywin/idle/FormatParagraph.py b/Lib/site-packages/pythonwin/pywin/idle/FormatParagraph.py new file mode 100644 index 0000000..cae8115 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/idle/FormatParagraph.py @@ -0,0 +1,155 @@ +# Extension to format a paragraph + +# Does basic, standard text formatting, and also understands Python +# comment blocks. Thus, for editing Python source code, this +# extension is really only suitable for reformatting these comment +# blocks or triple-quoted strings. + +# Known problems with comment reformatting: +# * If there is a selection marked, and the first line of the +# selection is not complete, the block will probably not be detected +# as comments, and will have the normal "text formatting" rules +# applied. +# * If a comment block has leading whitespace that mixes tabs and +# spaces, they will not be considered part of the same block. +# * Fancy comments, like this bulleted list, arent handled :-) + +import string +import re + +class FormatParagraph: + + menudefs = [ + ('edit', [ + ('Format Paragraph', '<>'), + ]) + ] + + keydefs = { + '<>': [''], + } + + unix_keydefs = { + '<>': [''], + } + + def __init__(self, editwin): + self.editwin = editwin + + def close(self): + self.editwin = None + + def format_paragraph_event(self, event): + text = self.editwin.text + first, last = self.editwin.get_selection_indices() + if first and last: + data = text.get(first, last) + comment_header = '' + else: + first, last, comment_header, data = \ + find_paragraph(text, text.index("insert")) + if comment_header: + # Reformat the comment lines - convert to text sans header. + lines = data.split("\n") + lines = map(lambda st, l=len(comment_header): st[l:], lines) + data = "\n".join(lines) + # Reformat to 70 chars or a 20 char width, whichever is greater. + format_width = max(70-len(comment_header), 20) + newdata = reformat_paragraph(data, format_width) + # re-split and re-insert the comment header. + newdata = newdata.split("\n") + # If the block ends in a \n, we dont want the comment + # prefix inserted after it. (Im not sure it makes sense to + # reformat a comment block that isnt made of complete + # lines, but whatever!) Can't think of a clean soltution, + # so we hack away + block_suffix = "" + if not newdata[-1]: + block_suffix = "\n" + newdata = newdata[:-1] + builder = lambda item, prefix=comment_header: prefix+item + newdata = '\n'.join([builder(d) for d in newdata]) + block_suffix + else: + # Just a normal text format + newdata = reformat_paragraph(data) + text.tag_remove("sel", "1.0", "end") + if newdata != data: + text.mark_set("insert", first) + text.undo_block_start() + text.delete(first, last) + text.insert(first, newdata) + text.undo_block_stop() + else: + text.mark_set("insert", last) + text.see("insert") + +def find_paragraph(text, mark): + lineno, col = list(map(int, mark.split("."))) + line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno) + while text.compare("%d.0" % lineno, "<", "end") and is_all_white(line): + lineno = lineno + 1 + line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno) + first_lineno = lineno + comment_header = get_comment_header(line) + comment_header_len = len(comment_header) + while get_comment_header(line)==comment_header and \ + not is_all_white(line[comment_header_len:]): + lineno = lineno + 1 + line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno) + last = "%d.0" % lineno + # Search back to beginning of paragraph + lineno = first_lineno - 1 + line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno) + while lineno > 0 and \ + get_comment_header(line)==comment_header and \ + not is_all_white(line[comment_header_len:]): + lineno = lineno - 1 + line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno) + first = "%d.0" % (lineno+1) + return first, last, comment_header, text.get(first, last) + +def reformat_paragraph(data, limit=70): + lines = data.split("\n") + i = 0 + n = len(lines) + while i < n and is_all_white(lines[i]): + i = i+1 + if i >= n: + return data + indent1 = get_indent(lines[i]) + if i+1 < n and not is_all_white(lines[i+1]): + indent2 = get_indent(lines[i+1]) + else: + indent2 = indent1 + new = lines[:i] + partial = indent1 + while i < n and not is_all_white(lines[i]): + # XXX Should take double space after period (etc.) into account + words = re.split("(\s+)", lines[i]) + for j in range(0, len(words), 2): + word = words[j] + if not word: + continue # Can happen when line ends in whitespace + if len((partial + word).expandtabs()) > limit and \ + partial != indent1: + new.append(partial.rstrip()) + partial = indent2 + partial = partial + word + " " + if j+1 < len(words) and words[j+1] != " ": + partial = partial + " " + i = i+1 + new.append(partial.rstrip()) + # XXX Should reformat remaining paragraphs as well + new.extend(lines[i:]) + return "\n".join(new) + +def is_all_white(line): + return re.match(r"^\s*$", line) is not None + +def get_indent(line): + return re.match(r"^(\s*)", line).group() + +def get_comment_header(line): + m = re.match(r"^(\s*#*)", line) + if m is None: return "" + return m.group(1) diff --git a/Lib/site-packages/pythonwin/pywin/idle/IdleHistory.py b/Lib/site-packages/pythonwin/pywin/idle/IdleHistory.py new file mode 100644 index 0000000..0f40a38 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/idle/IdleHistory.py @@ -0,0 +1,89 @@ +import string + +class History: + + def __init__(self, text, output_sep = "\n"): + self.text = text + self.history = [] + self.history_prefix = None + self.history_pointer = None + self.output_sep = output_sep + text.bind("<>", self.history_prev) + text.bind("<>", self.history_next) + + def history_next(self, event): + self.history_do(0) + return "break" + + def history_prev(self, event): + self.history_do(1) + return "break" + + def _get_source(self, start, end): + # Get source code from start index to end index. Lines in the + # text control may be separated by sys.ps2 . + lines = self.text.get(start, end).split(self.output_sep) + return "\n".join(lines) + + def _put_source(self, where, source): + output = self.output_sep.join(source.split("\n")) + self.text.insert(where, output) + + def history_do(self, reverse): + nhist = len(self.history) + pointer = self.history_pointer + prefix = self.history_prefix + if pointer is not None and prefix is not None: + if self.text.compare("insert", "!=", "end-1c") or \ + self._get_source("iomark", "end-1c") != self.history[pointer]: + pointer = prefix = None + if pointer is None or prefix is None: + prefix = self._get_source("iomark", "end-1c") + if reverse: + pointer = nhist + else: + pointer = -1 + nprefix = len(prefix) + while 1: + if reverse: + pointer = pointer - 1 + else: + pointer = pointer + 1 + if pointer < 0 or pointer >= nhist: + self.text.bell() + if self._get_source("iomark", "end-1c") != prefix: + self.text.delete("iomark", "end-1c") + self._put_source("iomark", prefix) + pointer = prefix = None + break + item = self.history[pointer] + if item[:nprefix] == prefix and len(item) > nprefix: + self.text.delete("iomark", "end-1c") + self._put_source("iomark", item) + break + self.text.mark_set("insert", "end-1c") + self.text.see("insert") + self.text.tag_remove("sel", "1.0", "end") + self.history_pointer = pointer + self.history_prefix = prefix + + def history_store(self, source): + source = source.strip() + if len(source) > 2: + # avoid duplicates + try: + self.history.remove(source) + except ValueError: + pass + self.history.append(source) + self.history_pointer = None + self.history_prefix = None + + def recall(self, s): + s = s.strip() + self.text.tag_remove("sel", "1.0", "end") + self.text.delete("iomark", "end-1c") + self.text.mark_set("insert", "end-1c") + self.text.insert("insert", s) + self.text.see("insert") + diff --git a/Lib/site-packages/pythonwin/pywin/idle/PyParse.py b/Lib/site-packages/pythonwin/pywin/idle/PyParse.py new file mode 100644 index 0000000..2e6e5cb --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/idle/PyParse.py @@ -0,0 +1,568 @@ +import string +import re +import sys + +# Reason last stmt is continued (or C_NONE if it's not). +C_NONE, C_BACKSLASH, C_STRING, C_BRACKET = list(range(4)) + +if 0: # for throwaway debugging output + def dump(*stuff): + sys.__stdout__.write(" ".join(map(str, stuff)) + "\n") + +# Find what looks like the start of a popular stmt. + +_synchre = re.compile(r""" + ^ + [ \t]* + (?: if + | for + | while + | else + | def + | return + | assert + | break + | class + | continue + | elif + | try + | except + | raise + | import + ) + \b +""", re.VERBOSE | re.MULTILINE).search + +# Match blank line or non-indenting comment line. + +_junkre = re.compile(r""" + [ \t]* + (?: \# \S .* )? + \n +""", re.VERBOSE).match + +# Match any flavor of string; the terminating quote is optional +# so that we're robust in the face of incomplete program text. + +_match_stringre = re.compile(r""" + \""" [^"\\]* (?: + (?: \\. | "(?!"") ) + [^"\\]* + )* + (?: \""" )? + +| " [^"\\\n]* (?: \\. [^"\\\n]* )* "? + +| ''' [^'\\]* (?: + (?: \\. | '(?!'') ) + [^'\\]* + )* + (?: ''' )? + +| ' [^'\\\n]* (?: \\. [^'\\\n]* )* '? +""", re.VERBOSE | re.DOTALL).match + +# Match a line that starts with something interesting; +# used to find the first item of a bracket structure. + +_itemre = re.compile(r""" + [ \t]* + [^\s#\\] # if we match, m.end()-1 is the interesting char +""", re.VERBOSE).match + +# Match start of stmts that should be followed by a dedent. + +_closere = re.compile(r""" + \s* + (?: return + | break + | continue + | raise + | pass + ) + \b +""", re.VERBOSE).match + +# Chew up non-special chars as quickly as possible. If match is +# successful, m.end() less 1 is the index of the last boring char +# matched. If match is unsuccessful, the string starts with an +# interesting char. + +_chew_ordinaryre = re.compile(r""" + [^[\](){}#'"\\]+ +""", re.VERBOSE).match + +# Build translation table to map uninteresting chars to "x", open +# brackets to "(", and close brackets to ")". + +_tran = ['x'] * 256 +for ch in "({[": + _tran[ord(ch)] = '(' +for ch in ")}]": + _tran[ord(ch)] = ')' +for ch in "\"'\\\n#": + _tran[ord(ch)] = ch +# We are called with unicode strings, and str.translate is one of the few +# py2k functions which can't 'do the right thing' - so take care to ensure +# _tran is full of unicode... +_tran = ''.join(_tran) +del ch + +class Parser: + + def __init__(self, indentwidth, tabwidth): + self.indentwidth = indentwidth + self.tabwidth = tabwidth + + def set_str(self, str): + assert len(str) == 0 or str[-1] == '\n', "Oops - have str %r" % (str,) + self.str = str + self.study_level = 0 + + # Return index of a good place to begin parsing, as close to the + # end of the string as possible. This will be the start of some + # popular stmt like "if" or "def". Return None if none found: + # the caller should pass more prior context then, if possible, or + # if not (the entire program text up until the point of interest + # has already been tried) pass 0 to set_lo. + # + # This will be reliable iff given a reliable is_char_in_string + # function, meaning that when it says "no", it's absolutely + # guaranteed that the char is not in a string. + # + # Ack, hack: in the shell window this kills us, because there's + # no way to tell the differences between output, >>> etc and + # user input. Indeed, IDLE's first output line makes the rest + # look like it's in an unclosed paren!: + # Python 1.5.2 (#0, Apr 13 1999, ... + + def find_good_parse_start(self, use_ps1, is_char_in_string=None): + str, pos = self.str, None + if use_ps1: + # shell window + ps1 = '\n' + sys.ps1 + i = str.rfind(ps1) + if i >= 0: + pos = i + len(ps1) + # make it look like there's a newline instead + # of ps1 at the start -- hacking here once avoids + # repeated hackery later + self.str = str[:pos-1] + '\n' + str[pos:] + return pos + + # File window -- real work. + if not is_char_in_string: + # no clue -- make the caller pass everything + return None + + # Peek back from the end for a good place to start, + # but don't try too often; pos will be left None, or + # bumped to a legitimate synch point. + limit = len(str) + for tries in range(5): + i = str.rfind(":\n", 0, limit) + if i < 0: + break + i = str.rfind('\n', 0, i) + 1 # start of colon line + m = _synchre(str, i, limit) + if m and not is_char_in_string(m.start()): + pos = m.start() + break + limit = i + if pos is None: + # Nothing looks like a block-opener, or stuff does + # but is_char_in_string keeps returning true; most likely + # we're in or near a giant string, the colorizer hasn't + # caught up enough to be helpful, or there simply *aren't* + # any interesting stmts. In any of these cases we're + # going to have to parse the whole thing to be sure, so + # give it one last try from the start, but stop wasting + # time here regardless of the outcome. + m = _synchre(str) + if m and not is_char_in_string(m.start()): + pos = m.start() + return pos + + # Peeking back worked; look forward until _synchre no longer + # matches. + i = pos + 1 + while 1: + m = _synchre(str, i) + if m: + s, i = m.span() + if not is_char_in_string(s): + pos = s + else: + break + return pos + + # Throw away the start of the string. Intended to be called with + # find_good_parse_start's result. + + def set_lo(self, lo): + assert lo == 0 or self.str[lo-1] == '\n' + if lo > 0: + self.str = self.str[lo:] + + # As quickly as humanly possible , find the line numbers (0- + # based) of the non-continuation lines. + # Creates self.{goodlines, continuation}. + + def _study1(self): + if self.study_level >= 1: + return + self.study_level = 1 + + # Map all uninteresting characters to "x", all open brackets + # to "(", all close brackets to ")", then collapse runs of + # uninteresting characters. This can cut the number of chars + # by a factor of 10-40, and so greatly speed the following loop. + str = self.str + str = str.translate(_tran) + str = str.replace('xxxxxxxx', 'x') + str = str.replace('xxxx', 'x') + str = str.replace('xx', 'x') + str = str.replace('xx', 'x') + str = str.replace('\nx', '\n') + # note that replacing x\n with \n would be incorrect, because + # x may be preceded by a backslash + + # March over the squashed version of the program, accumulating + # the line numbers of non-continued stmts, and determining + # whether & why the last stmt is a continuation. + continuation = C_NONE + level = lno = 0 # level is nesting level; lno is line number + self.goodlines = goodlines = [0] + push_good = goodlines.append + i, n = 0, len(str) + while i < n: + ch = str[i] + i = i+1 + + # cases are checked in decreasing order of frequency + if ch == 'x': + continue + + if ch == '\n': + lno = lno + 1 + if level == 0: + push_good(lno) + # else we're in an unclosed bracket structure + continue + + if ch == '(': + level = level + 1 + continue + + if ch == ')': + if level: + level = level - 1 + # else the program is invalid, but we can't complain + continue + + if ch == '"' or ch == "'": + # consume the string + quote = ch + if str[i-1:i+2] == quote * 3: + quote = quote * 3 + w = len(quote) - 1 + i = i+w + while i < n: + ch = str[i] + i = i+1 + + if ch == 'x': + continue + + if str[i-1:i+w] == quote: + i = i+w + break + + if ch == '\n': + lno = lno + 1 + if w == 0: + # unterminated single-quoted string + if level == 0: + push_good(lno) + break + continue + + if ch == '\\': + assert i < n + if str[i] == '\n': + lno = lno + 1 + i = i+1 + continue + + # else comment char or paren inside string + + else: + # didn't break out of the loop, so we're still + # inside a string + continuation = C_STRING + continue # with outer loop + + if ch == '#': + # consume the comment + i = str.find('\n', i) + assert i >= 0 + continue + + assert ch == '\\' + assert i < n + if str[i] == '\n': + lno = lno + 1 + if i+1 == n: + continuation = C_BACKSLASH + i = i+1 + + # The last stmt may be continued for all 3 reasons. + # String continuation takes precedence over bracket + # continuation, which beats backslash continuation. + if continuation != C_STRING and level > 0: + continuation = C_BRACKET + self.continuation = continuation + + # Push the final line number as a sentinel value, regardless of + # whether it's continued. + assert (continuation == C_NONE) == (goodlines[-1] == lno) + if goodlines[-1] != lno: + push_good(lno) + + def get_continuation_type(self): + self._study1() + return self.continuation + + # study1 was sufficient to determine the continuation status, + # but doing more requires looking at every character. study2 + # does this for the last interesting statement in the block. + # Creates: + # self.stmt_start, stmt_end + # slice indices of last interesting stmt + # self.lastch + # last non-whitespace character before optional trailing + # comment + # self.lastopenbracketpos + # if continuation is C_BRACKET, index of last open bracket + + def _study2(self): + _ws=string.whitespace + if self.study_level >= 2: + return + self._study1() + self.study_level = 2 + + # Set p and q to slice indices of last interesting stmt. + str, goodlines = self.str, self.goodlines + i = len(goodlines) - 1 + p = len(str) # index of newest line + while i: + assert p + # p is the index of the stmt at line number goodlines[i]. + # Move p back to the stmt at line number goodlines[i-1]. + q = p + for nothing in range(goodlines[i-1], goodlines[i]): + # tricky: sets p to 0 if no preceding newline + p = str.rfind('\n', 0, p-1) + 1 + # The stmt str[p:q] isn't a continuation, but may be blank + # or a non-indenting comment line. + if _junkre(str, p): + i = i-1 + else: + break + if i == 0: + # nothing but junk! + assert p == 0 + q = p + self.stmt_start, self.stmt_end = p, q + + # Analyze this stmt, to find the last open bracket (if any) + # and last interesting character (if any). + lastch = "" + stack = [] # stack of open bracket indices + push_stack = stack.append + while p < q: + # suck up all except ()[]{}'"#\\ + m = _chew_ordinaryre(str, p, q) + if m: + # we skipped at least one boring char + newp = m.end() + # back up over totally boring whitespace + i = newp - 1 # index of last boring char + while i >= p and str[i] in " \t\n": + i = i-1 + if i >= p: + lastch = str[i] + p = newp + if p >= q: + break + + ch = str[p] + + if ch in "([{": + push_stack(p) + lastch = ch + p = p+1 + continue + + if ch in ")]}": + if stack: + del stack[-1] + lastch = ch + p = p+1 + continue + + if ch == '"' or ch == "'": + # consume string + # Note that study1 did this with a Python loop, but + # we use a regexp here; the reason is speed in both + # cases; the string may be huge, but study1 pre-squashed + # strings to a couple of characters per line. study1 + # also needed to keep track of newlines, and we don't + # have to. + lastch = ch + p = _match_stringre(str, p, q).end() + continue + + if ch == '#': + # consume comment and trailing newline + p = str.find('\n', p, q) + 1 + assert p > 0 + continue + + assert ch == '\\' + p = p+1 # beyond backslash + assert p < q + if str[p] != '\n': + # the program is invalid, but can't complain + lastch = ch + str[p] + p = p+1 # beyond escaped char + + # end while p < q: + + self.lastch = lastch + if stack: + self.lastopenbracketpos = stack[-1] + + # Assuming continuation is C_BRACKET, return the number + # of spaces the next line should be indented. + + def compute_bracket_indent(self): + self._study2() + assert self.continuation == C_BRACKET + j = self.lastopenbracketpos + str = self.str + n = len(str) + origi = i = str.rfind('\n', 0, j) + 1 + j = j+1 # one beyond open bracket + # find first list item; set i to start of its line + while j < n: + m = _itemre(str, j) + if m: + j = m.end() - 1 # index of first interesting char + extra = 0 + break + else: + # this line is junk; advance to next line + i = j = str.find('\n', j) + 1 + else: + # nothing interesting follows the bracket; + # reproduce the bracket line's indentation + a level + j = i = origi + while str[j] in " \t": + j = j+1 + extra = self.indentwidth + return len(str[i:j].expandtabs(self.tabwidth)) + extra + + # Return number of physical lines in last stmt (whether or not + # it's an interesting stmt! this is intended to be called when + # continuation is C_BACKSLASH). + + def get_num_lines_in_stmt(self): + self._study1() + goodlines = self.goodlines + return goodlines[-1] - goodlines[-2] + + # Assuming continuation is C_BACKSLASH, return the number of spaces + # the next line should be indented. Also assuming the new line is + # the first one following the initial line of the stmt. + + def compute_backslash_indent(self): + self._study2() + assert self.continuation == C_BACKSLASH + str = self.str + i = self.stmt_start + while str[i] in " \t": + i = i+1 + startpos = i + + # See whether the initial line starts an assignment stmt; i.e., + # look for an = operator + endpos = str.find('\n', startpos) + 1 + found = level = 0 + while i < endpos: + ch = str[i] + if ch in "([{": + level = level + 1 + i = i+1 + elif ch in ")]}": + if level: + level = level - 1 + i = i+1 + elif ch == '"' or ch == "'": + i = _match_stringre(str, i, endpos).end() + elif ch == '#': + break + elif level == 0 and ch == '=' and \ + (i == 0 or str[i-1] not in "=<>!") and \ + str[i+1] != '=': + found = 1 + break + else: + i = i+1 + + if found: + # found a legit =, but it may be the last interesting + # thing on the line + i = i+1 # move beyond the = + found = re.match(r"\s*\\", str[i:endpos]) is None + + if not found: + # oh well ... settle for moving beyond the first chunk + # of non-whitespace chars + i = startpos + while str[i] not in " \t\n": + i = i+1 + + return len(str[self.stmt_start : i].expandtabs(self.tabwidth)) + 1 + + # Return the leading whitespace on the initial line of the last + # interesting stmt. + + def get_base_indent_string(self): + self._study2() + i, n = self.stmt_start, self.stmt_end + j = i + str = self.str + while j < n and str[j] in " \t": + j = j + 1 + return str[i:j] + + # Did the last interesting stmt open a block? + + def is_block_opener(self): + self._study2() + return self.lastch == ':' + + # Did the last interesting stmt close a block? + + def is_block_closer(self): + self._study2() + return _closere(self.str, self.stmt_start) is not None + + # index of last open bracket ({[, or None if none + lastopenbracketpos = None + + def get_last_open_bracket_pos(self): + self._study2() + return self.lastopenbracketpos diff --git a/Lib/site-packages/pythonwin/pywin/idle/__init__.py b/Lib/site-packages/pythonwin/pywin/idle/__init__.py new file mode 100644 index 0000000..c9c70df --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/idle/__init__.py @@ -0,0 +1 @@ +# This file denotes the directory as a Python package. \ No newline at end of file diff --git a/Lib/site-packages/pythonwin/pywin/mfc/__init__.py b/Lib/site-packages/pythonwin/pywin/mfc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Lib/site-packages/pythonwin/pywin/mfc/activex.py b/Lib/site-packages/pythonwin/pywin/mfc/activex.py new file mode 100644 index 0000000..2d77f19 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/mfc/activex.py @@ -0,0 +1,75 @@ +"""Support for ActiveX control hosting in Pythonwin. +""" +import win32ui, win32uiole +from . import window +# XXX - we are still "classic style" classes in py2x, so we need can't yet +# use 'type()' everywhere - revisit soon, as py2x will move to new-style too... +try: + from types import ClassType as new_type +except ImportError: + new_type = type # py3k + +class Control(window.Wnd): + """An ActiveX control base class. A new class must be derived from both + this class and the Events class. See the demos for more details. + """ + def __init__(self): + self.__dict__["_dispobj_"] = None + window.Wnd.__init__(self) + + def _GetControlCLSID( self ): + return self.CLSID + def _GetDispatchClass(self): + return self.default_interface + def _GetEventMap(self): + return self.default_source._dispid_to_func_ + + def CreateControl(self, windowTitle, style, rect, parent, id, lic_string=None): + clsid = str(self._GetControlCLSID()) + self.__dict__["_obj_"] = win32ui.CreateControl(clsid, windowTitle, style, rect, parent, id, None, False, lic_string) + klass = self._GetDispatchClass() + dispobj = klass(win32uiole.GetIDispatchForWindow(self._obj_)) + self.HookOleEvents() + self.__dict__["_dispobj_"] = dispobj + + def HookOleEvents(self): + dict = self._GetEventMap() + for dispid, methodName in dict.items(): + if hasattr(self, methodName): + self._obj_.HookOleEvent( getattr(self, methodName), dispid ) + + def __getattr__(self, attr): + # Delegate attributes to the windows and the Dispatch object for this class + try: + return window.Wnd.__getattr__(self, attr) + except AttributeError: + pass + return getattr(self._dispobj_, attr) + def __setattr__(self, attr, value): + if hasattr(self.__dict__, attr): + self.__dict__[attr] = value + return + try: + if self._dispobj_: + self._dispobj_.__setattr__(attr, value) + return + except AttributeError: + pass + self.__dict__[attr] = value + +def MakeControlClass( controlClass, name = None ): + """Given a CoClass in a generated .py file, this function will return a Class + object which can be used as an OCX control. + + This function is used when you do not want to handle any events from the OCX + control. If you need events, then you should derive a class from both the + activex.Control class and the CoClass + """ + if name is None: + name = controlClass.__name__ + return new_type("OCX" + name, (Control, controlClass), {}) + +def MakeControlInstance( controlClass, name = None ): + """As for MakeControlClass(), but returns an instance of the class. + """ + return MakeControlClass(controlClass, name)() diff --git a/Lib/site-packages/pythonwin/pywin/mfc/afxres.py b/Lib/site-packages/pythonwin/pywin/mfc/afxres.py new file mode 100644 index 0000000..6f39749 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/mfc/afxres.py @@ -0,0 +1,497 @@ +# Generated by h2py from stdin +TCS_MULTILINE = 0x0200 +CBRS_ALIGN_LEFT = 0x1000 +CBRS_ALIGN_TOP = 0x2000 +CBRS_ALIGN_RIGHT = 0x4000 +CBRS_ALIGN_BOTTOM = 0x8000 +CBRS_ALIGN_ANY = 0xF000 +CBRS_BORDER_LEFT = 0x0100 +CBRS_BORDER_TOP = 0x0200 +CBRS_BORDER_RIGHT = 0x0400 +CBRS_BORDER_BOTTOM = 0x0800 +CBRS_BORDER_ANY = 0x0F00 +CBRS_TOOLTIPS = 0x0010 +CBRS_FLYBY = 0x0020 +CBRS_FLOAT_MULTI = 0x0040 +CBRS_BORDER_3D = 0x0080 +CBRS_HIDE_INPLACE = 0x0008 +CBRS_SIZE_DYNAMIC = 0x0004 +CBRS_SIZE_FIXED = 0x0002 +CBRS_FLOATING = 0x0001 +CBRS_GRIPPER = 0x00400000 +CBRS_ORIENT_HORZ = (CBRS_ALIGN_TOP|CBRS_ALIGN_BOTTOM) +CBRS_ORIENT_VERT = (CBRS_ALIGN_LEFT|CBRS_ALIGN_RIGHT) +CBRS_ORIENT_ANY = (CBRS_ORIENT_HORZ|CBRS_ORIENT_VERT) +CBRS_ALL = 0xFFFF +CBRS_NOALIGN = 0x00000000 +CBRS_LEFT = (CBRS_ALIGN_LEFT|CBRS_BORDER_RIGHT) +CBRS_TOP = (CBRS_ALIGN_TOP|CBRS_BORDER_BOTTOM) +CBRS_RIGHT = (CBRS_ALIGN_RIGHT|CBRS_BORDER_LEFT) +CBRS_BOTTOM = (CBRS_ALIGN_BOTTOM|CBRS_BORDER_TOP) +SBPS_NORMAL = 0x0000 +SBPS_NOBORDERS = 0x0100 +SBPS_POPOUT = 0x0200 +SBPS_OWNERDRAW = 0x1000 +SBPS_DISABLED = 0x04000000 +SBPS_STRETCH = 0x08000000 +ID_INDICATOR_EXT = 0xE700 +ID_INDICATOR_CAPS = 0xE701 +ID_INDICATOR_NUM = 0xE702 +ID_INDICATOR_SCRL = 0xE703 +ID_INDICATOR_OVR = 0xE704 +ID_INDICATOR_REC = 0xE705 +ID_INDICATOR_KANA = 0xE706 +ID_SEPARATOR = 0 +AFX_IDW_CONTROLBAR_FIRST = 0xE800 +AFX_IDW_CONTROLBAR_LAST = 0xE8FF +AFX_IDW_TOOLBAR = 0xE800 +AFX_IDW_STATUS_BAR = 0xE801 +AFX_IDW_PREVIEW_BAR = 0xE802 +AFX_IDW_RESIZE_BAR = 0xE803 +AFX_IDW_DOCKBAR_TOP = 0xE81B +AFX_IDW_DOCKBAR_LEFT = 0xE81C +AFX_IDW_DOCKBAR_RIGHT = 0xE81D +AFX_IDW_DOCKBAR_BOTTOM = 0xE81E +AFX_IDW_DOCKBAR_FLOAT = 0xE81F +def AFX_CONTROLBAR_MASK(nIDC): return (1 << (nIDC - AFX_IDW_CONTROLBAR_FIRST)) + +AFX_IDW_PANE_FIRST = 0xE900 +AFX_IDW_PANE_LAST = 0xE9ff +AFX_IDW_HSCROLL_FIRST = 0xEA00 +AFX_IDW_VSCROLL_FIRST = 0xEA10 +AFX_IDW_SIZE_BOX = 0xEA20 +AFX_IDW_PANE_SAVE = 0xEA21 +AFX_IDS_APP_TITLE = 0xE000 +AFX_IDS_IDLEMESSAGE = 0xE001 +AFX_IDS_HELPMODEMESSAGE = 0xE002 +AFX_IDS_APP_TITLE_EMBEDDING = 0xE003 +AFX_IDS_COMPANY_NAME = 0xE004 +AFX_IDS_OBJ_TITLE_INPLACE = 0xE005 +ID_FILE_NEW = 0xE100 +ID_FILE_OPEN = 0xE101 +ID_FILE_CLOSE = 0xE102 +ID_FILE_SAVE = 0xE103 +ID_FILE_SAVE_AS = 0xE104 +ID_FILE_PAGE_SETUP = 0xE105 +ID_FILE_PRINT_SETUP = 0xE106 +ID_FILE_PRINT = 0xE107 +ID_FILE_PRINT_DIRECT = 0xE108 +ID_FILE_PRINT_PREVIEW = 0xE109 +ID_FILE_UPDATE = 0xE10A +ID_FILE_SAVE_COPY_AS = 0xE10B +ID_FILE_SEND_MAIL = 0xE10C +ID_FILE_MRU_FIRST = 0xE110 +ID_FILE_MRU_FILE1 = 0xE110 +ID_FILE_MRU_FILE2 = 0xE111 +ID_FILE_MRU_FILE3 = 0xE112 +ID_FILE_MRU_FILE4 = 0xE113 +ID_FILE_MRU_FILE5 = 0xE114 +ID_FILE_MRU_FILE6 = 0xE115 +ID_FILE_MRU_FILE7 = 0xE116 +ID_FILE_MRU_FILE8 = 0xE117 +ID_FILE_MRU_FILE9 = 0xE118 +ID_FILE_MRU_FILE10 = 0xE119 +ID_FILE_MRU_FILE11 = 0xE11A +ID_FILE_MRU_FILE12 = 0xE11B +ID_FILE_MRU_FILE13 = 0xE11C +ID_FILE_MRU_FILE14 = 0xE11D +ID_FILE_MRU_FILE15 = 0xE11E +ID_FILE_MRU_FILE16 = 0xE11F +ID_FILE_MRU_LAST = 0xE11F +ID_EDIT_CLEAR = 0xE120 +ID_EDIT_CLEAR_ALL = 0xE121 +ID_EDIT_COPY = 0xE122 +ID_EDIT_CUT = 0xE123 +ID_EDIT_FIND = 0xE124 +ID_EDIT_PASTE = 0xE125 +ID_EDIT_PASTE_LINK = 0xE126 +ID_EDIT_PASTE_SPECIAL = 0xE127 +ID_EDIT_REPEAT = 0xE128 +ID_EDIT_REPLACE = 0xE129 +ID_EDIT_SELECT_ALL = 0xE12A +ID_EDIT_UNDO = 0xE12B +ID_EDIT_REDO = 0xE12C +ID_WINDOW_NEW = 0xE130 +ID_WINDOW_ARRANGE = 0xE131 +ID_WINDOW_CASCADE = 0xE132 +ID_WINDOW_TILE_HORZ = 0xE133 +ID_WINDOW_TILE_VERT = 0xE134 +ID_WINDOW_SPLIT = 0xE135 +AFX_IDM_WINDOW_FIRST = 0xE130 +AFX_IDM_WINDOW_LAST = 0xE13F +AFX_IDM_FIRST_MDICHILD = 0xFF00 +ID_APP_ABOUT = 0xE140 +ID_APP_EXIT = 0xE141 +ID_HELP_INDEX = 0xE142 +ID_HELP_FINDER = 0xE143 +ID_HELP_USING = 0xE144 +ID_CONTEXT_HELP = 0xE145 +ID_HELP = 0xE146 +ID_DEFAULT_HELP = 0xE147 +ID_NEXT_PANE = 0xE150 +ID_PREV_PANE = 0xE151 +ID_FORMAT_FONT = 0xE160 +ID_OLE_INSERT_NEW = 0xE200 +ID_OLE_EDIT_LINKS = 0xE201 +ID_OLE_EDIT_CONVERT = 0xE202 +ID_OLE_EDIT_CHANGE_ICON = 0xE203 +ID_OLE_EDIT_PROPERTIES = 0xE204 +ID_OLE_VERB_FIRST = 0xE210 +ID_OLE_VERB_LAST = 0xE21F +AFX_ID_PREVIEW_CLOSE = 0xE300 +AFX_ID_PREVIEW_NUMPAGE = 0xE301 +AFX_ID_PREVIEW_NEXT = 0xE302 +AFX_ID_PREVIEW_PREV = 0xE303 +AFX_ID_PREVIEW_PRINT = 0xE304 +AFX_ID_PREVIEW_ZOOMIN = 0xE305 +AFX_ID_PREVIEW_ZOOMOUT = 0xE306 +ID_VIEW_TOOLBAR = 0xE800 +ID_VIEW_STATUS_BAR = 0xE801 +ID_RECORD_FIRST = 0xE900 +ID_RECORD_LAST = 0xE901 +ID_RECORD_NEXT = 0xE902 +ID_RECORD_PREV = 0xE903 +IDC_STATIC = (-1) +AFX_IDS_SCFIRST = 0xEF00 +AFX_IDS_SCSIZE = 0xEF00 +AFX_IDS_SCMOVE = 0xEF01 +AFX_IDS_SCMINIMIZE = 0xEF02 +AFX_IDS_SCMAXIMIZE = 0xEF03 +AFX_IDS_SCNEXTWINDOW = 0xEF04 +AFX_IDS_SCPREVWINDOW = 0xEF05 +AFX_IDS_SCCLOSE = 0xEF06 +AFX_IDS_SCRESTORE = 0xEF12 +AFX_IDS_SCTASKLIST = 0xEF13 +AFX_IDS_MDICHILD = 0xEF1F +AFX_IDS_DESKACCESSORY = 0xEFDA +AFX_IDS_OPENFILE = 0xF000 +AFX_IDS_SAVEFILE = 0xF001 +AFX_IDS_ALLFILTER = 0xF002 +AFX_IDS_UNTITLED = 0xF003 +AFX_IDS_SAVEFILECOPY = 0xF004 +AFX_IDS_PREVIEW_CLOSE = 0xF005 +AFX_IDS_UNNAMED_FILE = 0xF006 +AFX_IDS_ABOUT = 0xF010 +AFX_IDS_HIDE = 0xF011 +AFX_IDP_NO_ERROR_AVAILABLE = 0xF020 +AFX_IDS_NOT_SUPPORTED_EXCEPTION = 0xF021 +AFX_IDS_RESOURCE_EXCEPTION = 0xF022 +AFX_IDS_MEMORY_EXCEPTION = 0xF023 +AFX_IDS_USER_EXCEPTION = 0xF024 +AFX_IDS_PRINTONPORT = 0xF040 +AFX_IDS_ONEPAGE = 0xF041 +AFX_IDS_TWOPAGE = 0xF042 +AFX_IDS_PRINTPAGENUM = 0xF043 +AFX_IDS_PREVIEWPAGEDESC = 0xF044 +AFX_IDS_PRINTDEFAULTEXT = 0xF045 +AFX_IDS_PRINTDEFAULT = 0xF046 +AFX_IDS_PRINTFILTER = 0xF047 +AFX_IDS_PRINTCAPTION = 0xF048 +AFX_IDS_PRINTTOFILE = 0xF049 +AFX_IDS_OBJECT_MENUITEM = 0xF080 +AFX_IDS_EDIT_VERB = 0xF081 +AFX_IDS_ACTIVATE_VERB = 0xF082 +AFX_IDS_CHANGE_LINK = 0xF083 +AFX_IDS_AUTO = 0xF084 +AFX_IDS_MANUAL = 0xF085 +AFX_IDS_FROZEN = 0xF086 +AFX_IDS_ALL_FILES = 0xF087 +AFX_IDS_SAVE_MENU = 0xF088 +AFX_IDS_UPDATE_MENU = 0xF089 +AFX_IDS_SAVE_AS_MENU = 0xF08A +AFX_IDS_SAVE_COPY_AS_MENU = 0xF08B +AFX_IDS_EXIT_MENU = 0xF08C +AFX_IDS_UPDATING_ITEMS = 0xF08D +AFX_IDS_METAFILE_FORMAT = 0xF08E +AFX_IDS_DIB_FORMAT = 0xF08F +AFX_IDS_BITMAP_FORMAT = 0xF090 +AFX_IDS_LINKSOURCE_FORMAT = 0xF091 +AFX_IDS_EMBED_FORMAT = 0xF092 +AFX_IDS_PASTELINKEDTYPE = 0xF094 +AFX_IDS_UNKNOWNTYPE = 0xF095 +AFX_IDS_RTF_FORMAT = 0xF096 +AFX_IDS_TEXT_FORMAT = 0xF097 +AFX_IDS_INVALID_CURRENCY = 0xF098 +AFX_IDS_INVALID_DATETIME = 0xF099 +AFX_IDS_INVALID_DATETIMESPAN = 0xF09A +AFX_IDP_INVALID_FILENAME = 0xF100 +AFX_IDP_FAILED_TO_OPEN_DOC = 0xF101 +AFX_IDP_FAILED_TO_SAVE_DOC = 0xF102 +AFX_IDP_ASK_TO_SAVE = 0xF103 +AFX_IDP_FAILED_TO_CREATE_DOC = 0xF104 +AFX_IDP_FILE_TOO_LARGE = 0xF105 +AFX_IDP_FAILED_TO_START_PRINT = 0xF106 +AFX_IDP_FAILED_TO_LAUNCH_HELP = 0xF107 +AFX_IDP_INTERNAL_FAILURE = 0xF108 +AFX_IDP_COMMAND_FAILURE = 0xF109 +AFX_IDP_FAILED_MEMORY_ALLOC = 0xF10A +AFX_IDP_PARSE_INT = 0xF110 +AFX_IDP_PARSE_REAL = 0xF111 +AFX_IDP_PARSE_INT_RANGE = 0xF112 +AFX_IDP_PARSE_REAL_RANGE = 0xF113 +AFX_IDP_PARSE_STRING_SIZE = 0xF114 +AFX_IDP_PARSE_RADIO_BUTTON = 0xF115 +AFX_IDP_PARSE_BYTE = 0xF116 +AFX_IDP_PARSE_UINT = 0xF117 +AFX_IDP_PARSE_DATETIME = 0xF118 +AFX_IDP_PARSE_CURRENCY = 0xF119 +AFX_IDP_FAILED_INVALID_FORMAT = 0xF120 +AFX_IDP_FAILED_INVALID_PATH = 0xF121 +AFX_IDP_FAILED_DISK_FULL = 0xF122 +AFX_IDP_FAILED_ACCESS_READ = 0xF123 +AFX_IDP_FAILED_ACCESS_WRITE = 0xF124 +AFX_IDP_FAILED_IO_ERROR_READ = 0xF125 +AFX_IDP_FAILED_IO_ERROR_WRITE = 0xF126 +AFX_IDP_STATIC_OBJECT = 0xF180 +AFX_IDP_FAILED_TO_CONNECT = 0xF181 +AFX_IDP_SERVER_BUSY = 0xF182 +AFX_IDP_BAD_VERB = 0xF183 +AFX_IDP_FAILED_TO_NOTIFY = 0xF185 +AFX_IDP_FAILED_TO_LAUNCH = 0xF186 +AFX_IDP_ASK_TO_UPDATE = 0xF187 +AFX_IDP_FAILED_TO_UPDATE = 0xF188 +AFX_IDP_FAILED_TO_REGISTER = 0xF189 +AFX_IDP_FAILED_TO_AUTO_REGISTER = 0xF18A +AFX_IDP_FAILED_TO_CONVERT = 0xF18B +AFX_IDP_GET_NOT_SUPPORTED = 0xF18C +AFX_IDP_SET_NOT_SUPPORTED = 0xF18D +AFX_IDP_ASK_TO_DISCARD = 0xF18E +AFX_IDP_FAILED_TO_CREATE = 0xF18F +AFX_IDP_FAILED_MAPI_LOAD = 0xF190 +AFX_IDP_INVALID_MAPI_DLL = 0xF191 +AFX_IDP_FAILED_MAPI_SEND = 0xF192 +AFX_IDP_FILE_NONE = 0xF1A0 +AFX_IDP_FILE_GENERIC = 0xF1A1 +AFX_IDP_FILE_NOT_FOUND = 0xF1A2 +AFX_IDP_FILE_BAD_PATH = 0xF1A3 +AFX_IDP_FILE_TOO_MANY_OPEN = 0xF1A4 +AFX_IDP_FILE_ACCESS_DENIED = 0xF1A5 +AFX_IDP_FILE_INVALID_FILE = 0xF1A6 +AFX_IDP_FILE_REMOVE_CURRENT = 0xF1A7 +AFX_IDP_FILE_DIR_FULL = 0xF1A8 +AFX_IDP_FILE_BAD_SEEK = 0xF1A9 +AFX_IDP_FILE_HARD_IO = 0xF1AA +AFX_IDP_FILE_SHARING = 0xF1AB +AFX_IDP_FILE_LOCKING = 0xF1AC +AFX_IDP_FILE_DISKFULL = 0xF1AD +AFX_IDP_FILE_EOF = 0xF1AE +AFX_IDP_ARCH_NONE = 0xF1B0 +AFX_IDP_ARCH_GENERIC = 0xF1B1 +AFX_IDP_ARCH_READONLY = 0xF1B2 +AFX_IDP_ARCH_ENDOFFILE = 0xF1B3 +AFX_IDP_ARCH_WRITEONLY = 0xF1B4 +AFX_IDP_ARCH_BADINDEX = 0xF1B5 +AFX_IDP_ARCH_BADCLASS = 0xF1B6 +AFX_IDP_ARCH_BADSCHEMA = 0xF1B7 +AFX_IDS_OCC_SCALEUNITS_PIXELS = 0xF1C0 +AFX_IDS_STATUS_FONT = 0xF230 +AFX_IDS_TOOLTIP_FONT = 0xF231 +AFX_IDS_UNICODE_FONT = 0xF232 +AFX_IDS_MINI_FONT = 0xF233 +AFX_IDP_SQL_FIRST = 0xF280 +AFX_IDP_SQL_CONNECT_FAIL = 0xF281 +AFX_IDP_SQL_RECORDSET_FORWARD_ONLY = 0xF282 +AFX_IDP_SQL_EMPTY_COLUMN_LIST = 0xF283 +AFX_IDP_SQL_FIELD_SCHEMA_MISMATCH = 0xF284 +AFX_IDP_SQL_ILLEGAL_MODE = 0xF285 +AFX_IDP_SQL_MULTIPLE_ROWS_AFFECTED = 0xF286 +AFX_IDP_SQL_NO_CURRENT_RECORD = 0xF287 +AFX_IDP_SQL_NO_ROWS_AFFECTED = 0xF288 +AFX_IDP_SQL_RECORDSET_READONLY = 0xF289 +AFX_IDP_SQL_SQL_NO_TOTAL = 0xF28A +AFX_IDP_SQL_ODBC_LOAD_FAILED = 0xF28B +AFX_IDP_SQL_DYNASET_NOT_SUPPORTED = 0xF28C +AFX_IDP_SQL_SNAPSHOT_NOT_SUPPORTED = 0xF28D +AFX_IDP_SQL_API_CONFORMANCE = 0xF28E +AFX_IDP_SQL_SQL_CONFORMANCE = 0xF28F +AFX_IDP_SQL_NO_DATA_FOUND = 0xF290 +AFX_IDP_SQL_ROW_UPDATE_NOT_SUPPORTED = 0xF291 +AFX_IDP_SQL_ODBC_V2_REQUIRED = 0xF292 +AFX_IDP_SQL_NO_POSITIONED_UPDATES = 0xF293 +AFX_IDP_SQL_LOCK_MODE_NOT_SUPPORTED = 0xF294 +AFX_IDP_SQL_DATA_TRUNCATED = 0xF295 +AFX_IDP_SQL_ROW_FETCH = 0xF296 +AFX_IDP_SQL_INCORRECT_ODBC = 0xF297 +AFX_IDP_SQL_UPDATE_DELETE_FAILED = 0xF298 +AFX_IDP_SQL_DYNAMIC_CURSOR_NOT_SUPPORTED = 0xF299 +AFX_IDP_DAO_FIRST = 0xF2A0 +AFX_IDP_DAO_ENGINE_INITIALIZATION = 0xF2A0 +AFX_IDP_DAO_DFX_BIND = 0xF2A1 +AFX_IDP_DAO_OBJECT_NOT_OPEN = 0xF2A2 +AFX_IDP_DAO_ROWTOOSHORT = 0xF2A3 +AFX_IDP_DAO_BADBINDINFO = 0xF2A4 +AFX_IDP_DAO_COLUMNUNAVAILABLE = 0xF2A5 +AFX_IDC_LISTBOX = 100 +AFX_IDC_CHANGE = 101 +AFX_IDC_PRINT_DOCNAME = 201 +AFX_IDC_PRINT_PRINTERNAME = 202 +AFX_IDC_PRINT_PORTNAME = 203 +AFX_IDC_PRINT_PAGENUM = 204 +ID_APPLY_NOW = 0x3021 +ID_WIZBACK = 0x3023 +ID_WIZNEXT = 0x3024 +ID_WIZFINISH = 0x3025 +AFX_IDC_TAB_CONTROL = 0x3020 +AFX_IDD_FILEOPEN = 28676 +AFX_IDD_FILESAVE = 28677 +AFX_IDD_FONT = 28678 +AFX_IDD_COLOR = 28679 +AFX_IDD_PRINT = 28680 +AFX_IDD_PRINTSETUP = 28681 +AFX_IDD_FIND = 28682 +AFX_IDD_REPLACE = 28683 +AFX_IDD_NEWTYPEDLG = 30721 +AFX_IDD_PRINTDLG = 30722 +AFX_IDD_PREVIEW_TOOLBAR = 30723 +AFX_IDD_PREVIEW_SHORTTOOLBAR = 30731 +AFX_IDD_INSERTOBJECT = 30724 +AFX_IDD_CHANGEICON = 30725 +AFX_IDD_CONVERT = 30726 +AFX_IDD_PASTESPECIAL = 30727 +AFX_IDD_EDITLINKS = 30728 +AFX_IDD_FILEBROWSE = 30729 +AFX_IDD_BUSY = 30730 +AFX_IDD_OBJECTPROPERTIES = 30732 +AFX_IDD_CHANGESOURCE = 30733 +AFX_IDC_CONTEXTHELP = 30977 +AFX_IDC_MAGNIFY = 30978 +AFX_IDC_SMALLARROWS = 30979 +AFX_IDC_HSPLITBAR = 30980 +AFX_IDC_VSPLITBAR = 30981 +AFX_IDC_NODROPCRSR = 30982 +AFX_IDC_TRACKNWSE = 30983 +AFX_IDC_TRACKNESW = 30984 +AFX_IDC_TRACKNS = 30985 +AFX_IDC_TRACKWE = 30986 +AFX_IDC_TRACK4WAY = 30987 +AFX_IDC_MOVE4WAY = 30988 +AFX_IDB_MINIFRAME_MENU = 30994 +AFX_IDB_CHECKLISTBOX_NT = 30995 +AFX_IDB_CHECKLISTBOX_95 = 30996 +AFX_IDR_PREVIEW_ACCEL = 30997 +AFX_IDI_STD_MDIFRAME = 31233 +AFX_IDI_STD_FRAME = 31234 +AFX_IDC_FONTPROP = 1000 +AFX_IDC_FONTNAMES = 1001 +AFX_IDC_FONTSTYLES = 1002 +AFX_IDC_FONTSIZES = 1003 +AFX_IDC_STRIKEOUT = 1004 +AFX_IDC_UNDERLINE = 1005 +AFX_IDC_SAMPLEBOX = 1006 +AFX_IDC_COLOR_BLACK = 1100 +AFX_IDC_COLOR_WHITE = 1101 +AFX_IDC_COLOR_RED = 1102 +AFX_IDC_COLOR_GREEN = 1103 +AFX_IDC_COLOR_BLUE = 1104 +AFX_IDC_COLOR_YELLOW = 1105 +AFX_IDC_COLOR_MAGENTA = 1106 +AFX_IDC_COLOR_CYAN = 1107 +AFX_IDC_COLOR_GRAY = 1108 +AFX_IDC_COLOR_LIGHTGRAY = 1109 +AFX_IDC_COLOR_DARKRED = 1110 +AFX_IDC_COLOR_DARKGREEN = 1111 +AFX_IDC_COLOR_DARKBLUE = 1112 +AFX_IDC_COLOR_LIGHTBROWN = 1113 +AFX_IDC_COLOR_DARKMAGENTA = 1114 +AFX_IDC_COLOR_DARKCYAN = 1115 +AFX_IDC_COLORPROP = 1116 +AFX_IDC_SYSTEMCOLORS = 1117 +AFX_IDC_PROPNAME = 1201 +AFX_IDC_PICTURE = 1202 +AFX_IDC_BROWSE = 1203 +AFX_IDC_CLEAR = 1204 +AFX_IDD_PROPPAGE_COLOR = 32257 +AFX_IDD_PROPPAGE_FONT = 32258 +AFX_IDD_PROPPAGE_PICTURE = 32259 +AFX_IDB_TRUETYPE = 32384 +AFX_IDS_PROPPAGE_UNKNOWN = 0xFE01 +AFX_IDS_COLOR_DESKTOP = 0xFE04 +AFX_IDS_COLOR_APPWORKSPACE = 0xFE05 +AFX_IDS_COLOR_WNDBACKGND = 0xFE06 +AFX_IDS_COLOR_WNDTEXT = 0xFE07 +AFX_IDS_COLOR_MENUBAR = 0xFE08 +AFX_IDS_COLOR_MENUTEXT = 0xFE09 +AFX_IDS_COLOR_ACTIVEBAR = 0xFE0A +AFX_IDS_COLOR_INACTIVEBAR = 0xFE0B +AFX_IDS_COLOR_ACTIVETEXT = 0xFE0C +AFX_IDS_COLOR_INACTIVETEXT = 0xFE0D +AFX_IDS_COLOR_ACTIVEBORDER = 0xFE0E +AFX_IDS_COLOR_INACTIVEBORDER = 0xFE0F +AFX_IDS_COLOR_WNDFRAME = 0xFE10 +AFX_IDS_COLOR_SCROLLBARS = 0xFE11 +AFX_IDS_COLOR_BTNFACE = 0xFE12 +AFX_IDS_COLOR_BTNSHADOW = 0xFE13 +AFX_IDS_COLOR_BTNTEXT = 0xFE14 +AFX_IDS_COLOR_BTNHIGHLIGHT = 0xFE15 +AFX_IDS_COLOR_DISABLEDTEXT = 0xFE16 +AFX_IDS_COLOR_HIGHLIGHT = 0xFE17 +AFX_IDS_COLOR_HIGHLIGHTTEXT = 0xFE18 +AFX_IDS_REGULAR = 0xFE19 +AFX_IDS_BOLD = 0xFE1A +AFX_IDS_ITALIC = 0xFE1B +AFX_IDS_BOLDITALIC = 0xFE1C +AFX_IDS_SAMPLETEXT = 0xFE1D +AFX_IDS_DISPLAYSTRING_FONT = 0xFE1E +AFX_IDS_DISPLAYSTRING_COLOR = 0xFE1F +AFX_IDS_DISPLAYSTRING_PICTURE = 0xFE20 +AFX_IDS_PICTUREFILTER = 0xFE21 +AFX_IDS_PICTYPE_UNKNOWN = 0xFE22 +AFX_IDS_PICTYPE_NONE = 0xFE23 +AFX_IDS_PICTYPE_BITMAP = 0xFE24 +AFX_IDS_PICTYPE_METAFILE = 0xFE25 +AFX_IDS_PICTYPE_ICON = 0xFE26 +AFX_IDS_COLOR_PPG = 0xFE28 +AFX_IDS_COLOR_PPG_CAPTION = 0xFE29 +AFX_IDS_FONT_PPG = 0xFE2A +AFX_IDS_FONT_PPG_CAPTION = 0xFE2B +AFX_IDS_PICTURE_PPG = 0xFE2C +AFX_IDS_PICTURE_PPG_CAPTION = 0xFE2D +AFX_IDS_PICTUREBROWSETITLE = 0xFE30 +AFX_IDS_BORDERSTYLE_0 = 0xFE31 +AFX_IDS_BORDERSTYLE_1 = 0xFE32 +AFX_IDS_VERB_EDIT = 0xFE40 +AFX_IDS_VERB_PROPERTIES = 0xFE41 +AFX_IDP_PICTURECANTOPEN = 0xFE83 +AFX_IDP_PICTURECANTLOAD = 0xFE84 +AFX_IDP_PICTURETOOLARGE = 0xFE85 +AFX_IDP_PICTUREREADFAILED = 0xFE86 +AFX_IDP_E_ILLEGALFUNCTIONCALL = 0xFEA0 +AFX_IDP_E_OVERFLOW = 0xFEA1 +AFX_IDP_E_OUTOFMEMORY = 0xFEA2 +AFX_IDP_E_DIVISIONBYZERO = 0xFEA3 +AFX_IDP_E_OUTOFSTRINGSPACE = 0xFEA4 +AFX_IDP_E_OUTOFSTACKSPACE = 0xFEA5 +AFX_IDP_E_BADFILENAMEORNUMBER = 0xFEA6 +AFX_IDP_E_FILENOTFOUND = 0xFEA7 +AFX_IDP_E_BADFILEMODE = 0xFEA8 +AFX_IDP_E_FILEALREADYOPEN = 0xFEA9 +AFX_IDP_E_DEVICEIOERROR = 0xFEAA +AFX_IDP_E_FILEALREADYEXISTS = 0xFEAB +AFX_IDP_E_BADRECORDLENGTH = 0xFEAC +AFX_IDP_E_DISKFULL = 0xFEAD +AFX_IDP_E_BADRECORDNUMBER = 0xFEAE +AFX_IDP_E_BADFILENAME = 0xFEAF +AFX_IDP_E_TOOMANYFILES = 0xFEB0 +AFX_IDP_E_DEVICEUNAVAILABLE = 0xFEB1 +AFX_IDP_E_PERMISSIONDENIED = 0xFEB2 +AFX_IDP_E_DISKNOTREADY = 0xFEB3 +AFX_IDP_E_PATHFILEACCESSERROR = 0xFEB4 +AFX_IDP_E_PATHNOTFOUND = 0xFEB5 +AFX_IDP_E_INVALIDPATTERNSTRING = 0xFEB6 +AFX_IDP_E_INVALIDUSEOFNULL = 0xFEB7 +AFX_IDP_E_INVALIDFILEFORMAT = 0xFEB8 +AFX_IDP_E_INVALIDPROPERTYVALUE = 0xFEB9 +AFX_IDP_E_INVALIDPROPERTYARRAYINDEX = 0xFEBA +AFX_IDP_E_SETNOTSUPPORTEDATRUNTIME = 0xFEBB +AFX_IDP_E_SETNOTSUPPORTED = 0xFEBC +AFX_IDP_E_NEEDPROPERTYARRAYINDEX = 0xFEBD +AFX_IDP_E_SETNOTPERMITTED = 0xFEBE +AFX_IDP_E_GETNOTSUPPORTEDATRUNTIME = 0xFEBF +AFX_IDP_E_GETNOTSUPPORTED = 0xFEC0 +AFX_IDP_E_PROPERTYNOTFOUND = 0xFEC1 +AFX_IDP_E_INVALIDCLIPBOARDFORMAT = 0xFEC2 +AFX_IDP_E_INVALIDPICTURE = 0xFEC3 +AFX_IDP_E_PRINTERERROR = 0xFEC4 +AFX_IDP_E_CANTSAVEFILETOTEMP = 0xFEC5 +AFX_IDP_E_SEARCHTEXTNOTFOUND = 0xFEC6 +AFX_IDP_E_REPLACEMENTSTOOLONG = 0xFEC7 diff --git a/Lib/site-packages/pythonwin/pywin/mfc/dialog.py b/Lib/site-packages/pythonwin/pywin/mfc/dialog.py new file mode 100644 index 0000000..7743b3e --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/mfc/dialog.py @@ -0,0 +1,241 @@ +""" \ +Base class for Dialogs. Also contains a few useful utility functions +""" +# dialog.py +# Python class for Dialog Boxes in PythonWin. + +import win32ui +import win32con +# sob - 2to3 doesn't see this as a relative import :( +from pywin.mfc import window + +def dllFromDll(dllid): + " given a 'dll' (maybe a dll, filename, etc), return a DLL object " + if dllid==None: + return None + elif type('')==type(dllid): + return win32ui.LoadLibrary(dllid) + else: + try: + dllid.GetFileName() + except AttributeError: + raise TypeError("DLL parameter must be None, a filename or a dll object") + return dllid + +class Dialog(window.Wnd): + " Base class for a dialog" + def __init__( self, id, dllid=None ): + """ id is the resource ID, or a template + dllid may be None, a dll object, or a string with a dll name """ + # must take a reference to the DLL until InitDialog. + self.dll=dllFromDll(dllid) + if type(id)==type([]): # a template + dlg=win32ui.CreateDialogIndirect(id) + else: + dlg=win32ui.CreateDialog(id, self.dll) + window.Wnd.__init__(self, dlg) + self.HookCommands() + self.bHaveInit = None + + def HookCommands(self): + pass + + def OnAttachedObjectDeath(self): + self.data = self._obj_.data + window.Wnd.OnAttachedObjectDeath(self) + + # provide virtuals. + def OnOK(self): + self._obj_.OnOK() + def OnCancel(self): + self._obj_.OnCancel() + def OnInitDialog(self): + self.bHaveInit = 1 + if self._obj_.data: + self._obj_.UpdateData(0) + return 1 # I did NOT set focus to a child window. + def OnDestroy(self,msg): + self.dll = None # theoretically not needed if object destructs normally. + # DDX support + def AddDDX( self, *args ): + self._obj_.datalist.append(args) + # Make a dialog object look like a dictionary for the DDX support + def __bool__(self): + return True + def __len__(self): return len(self.data) + def __getitem__(self, key): return self.data[key] + def __setitem__(self, key, item): self._obj_.data[key] = item# self.UpdateData(0) + def keys(self): return list(self.data.keys()) + def items(self): return list(self.data.items()) + def values(self): return list(self.data.values()) + # XXX - needs py3k work! + def has_key(self, key): return key in self.data + +class PrintDialog(Dialog): + " Base class for a print dialog" + def __init__(self, pInfo, dlgID, + printSetupOnly = 0, + flags=(win32ui.PD_ALLPAGES| + win32ui.PD_USEDEVMODECOPIES| + win32ui.PD_NOPAGENUMS| + win32ui.PD_HIDEPRINTTOFILE| + win32ui.PD_NOSELECTION), + parent=None, + dllid=None): + self.dll=dllFromDll(dllid) + if type(dlgID)==type([]): # a template + raise TypeError("dlgID parameter must be an integer resource ID") + dlg=win32ui.CreatePrintDialog(dlgID, printSetupOnly, + flags, parent, + self.dll) + window.Wnd.__init__(self, dlg) + self.HookCommands() + self.bHaveInit = None + self.pInfo = pInfo + # init values (if PrintSetup is called, values still available) + flags = pInfo.GetFlags() + self['toFile'] = (flags&win32ui.PD_PRINTTOFILE != 0) + self['direct'] = pInfo.GetDirect() + self['preview'] = pInfo.GetPreview() + self['continuePrinting'] = pInfo.GetContinuePrinting() + self['curPage'] = pInfo.GetCurPage() + self['numPreviewPages'] = pInfo.GetNumPreviewPages() + self['userData'] = pInfo.GetUserData() + self['draw'] = pInfo.GetDraw() + self['pageDesc'] = pInfo.GetPageDesc() + self['minPage'] = pInfo.GetMinPage() + self['maxPage'] = pInfo.GetMaxPage() + self['offsetPage'] = pInfo.GetOffsetPage() + self['fromPage'] = pInfo.GetFromPage() + self['toPage'] = pInfo.GetToPage() + # these values updated after OnOK + self['copies'] = 0 + self['deviceName'] = '' + self['driverName'] = '' + self['printAll'] = 0 + self['printCollate'] = 0 + self['printRange'] = 0 + self['printSelection'] = 0 + + def OnInitDialog(self): + self.pInfo.CreatePrinterDC() # This also sets the hDC of the pInfo structure. + return self._obj_.OnInitDialog() + + def OnCancel(self): + del self.pInfo + def OnOK(self): + '''DoModal has finished. Can now access the users choices''' + self._obj_.OnOK() + pInfo = self.pInfo + # user values + flags = pInfo.GetFlags() + self['toFile'] = (flags&win32ui.PD_PRINTTOFILE != 0) + self['direct'] = pInfo.GetDirect() + self['preview'] = pInfo.GetPreview() + self['continuePrinting'] = pInfo.GetContinuePrinting() + self['curPage'] = pInfo.GetCurPage() + self['numPreviewPages'] = pInfo.GetNumPreviewPages() + self['userData'] = pInfo.GetUserData() + self['draw'] = pInfo.GetDraw() + self['pageDesc'] = pInfo.GetPageDesc() + self['minPage'] = pInfo.GetMinPage() + self['maxPage'] = pInfo.GetMaxPage() + self['offsetPage'] = pInfo.GetOffsetPage() + self['fromPage'] = pInfo.GetFromPage() + self['toPage'] = pInfo.GetToPage() + self['copies'] = pInfo.GetCopies() + self['deviceName'] = pInfo.GetDeviceName() + self['driverName'] = pInfo.GetDriverName() + self['printAll'] = pInfo.PrintAll() + self['printCollate'] = pInfo.PrintCollate() + self['printRange'] = pInfo.PrintRange() + self['printSelection'] = pInfo.PrintSelection() + del self.pInfo + +class PropertyPage(Dialog): + " Base class for a Property Page" + def __init__( self, id, dllid=None, caption=0 ): + """ id is the resource ID + dllid may be None, a dll object, or a string with a dll name """ + + self.dll = dllFromDll(dllid) + if self.dll: + oldRes = win32ui.SetResource(self.dll) + if type(id)==type([]): + dlg=win32ui.CreatePropertyPageIndirect(id) + else: + dlg=win32ui.CreatePropertyPage(id, caption) + if self.dll: + win32ui.SetResource(oldRes) + # dont call dialog init! + window.Wnd.__init__(self, dlg) + self.HookCommands() + +class PropertySheet(window.Wnd): + def __init__(self, caption, dll=None, pageList=None ):# parent=None, style,etc): + " Initialize a property sheet. pageList is a list of ID's " + # must take a reference to the DLL until InitDialog. + self.dll=dllFromDll(dll) + self.sheet = win32ui.CreatePropertySheet(caption) + window.Wnd.__init__(self, self.sheet) + if not pageList is None: + self.AddPage(pageList) + + def OnInitDialog(self): + return self._obj_.OnInitDialog() + + def DoModal(self): + if self.dll: + oldRes = win32ui.SetResource(self.dll) + rc = self.sheet.DoModal() + if self.dll: + win32ui.SetResource(oldRes) + return rc + + def AddPage(self, pages): + if self.dll: + oldRes = win32ui.SetResource(self.dll) + try: # try list style access + pages[0] + isSeq = 1 + except (TypeError,KeyError): + isSeq = 0 + if isSeq: + for page in pages: + self.DoAddSinglePage(page) + else: + self.DoAddSinglePage(pages) + if self.dll: + win32ui.SetResource(oldRes) + + def DoAddSinglePage(self, page): + "Page may be page, or int ID. Assumes DLL setup " + if type(page)==type(0): + self.sheet.AddPage(win32ui.CreatePropertyPage(page)) + else: + self.sheet.AddPage(page) + +# define some app utility functions. +def GetSimpleInput(prompt, defValue='', title=None ): + """ displays a dialog, and returns a string, or None if cancelled. + args prompt, defValue='', title=main frames title """ + # uses a simple dialog to return a string object. + if title is None: title=win32ui.GetMainFrame().GetWindowText() + # 2to3 insists on converting 'Dialog.__init__' to 'tkinter.dialog...' + DlgBaseClass = Dialog + class DlgSimpleInput(DlgBaseClass): + def __init__(self, prompt, defValue, title ): + self.title=title + DlgBaseClass.__init__(self, win32ui.IDD_SIMPLE_INPUT) + self.AddDDX(win32ui.IDC_EDIT1,'result') + self.AddDDX(win32ui.IDC_PROMPT1, 'prompt') + self._obj_.data['result']=defValue + self._obj_.data['prompt']=prompt + def OnInitDialog(self): + self.SetWindowText(self.title) + return DlgBaseClass.OnInitDialog(self) + + dlg=DlgSimpleInput( prompt, defValue, title) + if dlg.DoModal() != win32con.IDOK: + return None + return dlg['result'] diff --git a/Lib/site-packages/pythonwin/pywin/mfc/docview.py b/Lib/site-packages/pythonwin/pywin/mfc/docview.py new file mode 100644 index 0000000..d0d999f --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/mfc/docview.py @@ -0,0 +1,116 @@ +# document and view classes for MFC. +import win32ui +import win32con +from . import object +from . import window + +class View(window.Wnd): + def __init__(self, initobj): + window.Wnd.__init__(self, initobj) + def OnInitialUpdate(self): + pass + +# Simple control based views. +class CtrlView(View): + def __init__(self, doc, wndclass, style=0): + View.__init__(self, win32ui.CreateCtrlView(doc, wndclass, style)) + +class EditView(CtrlView): + def __init__(self, doc): + View.__init__(self, win32ui.CreateEditView(doc)) + +class RichEditView(CtrlView): + def __init__(self, doc): + View.__init__(self, win32ui.CreateRichEditView(doc)) + +class ListView(CtrlView): + def __init__(self, doc): + View.__init__(self, win32ui.CreateListView(doc)) + +class TreeView(CtrlView): + def __init__(self, doc): + View.__init__(self, win32ui.CreateTreeView(doc)) + +# Other more advanced views. +class ScrollView(View): + def __init__(self, doc): + View.__init__(self, win32ui.CreateView(doc)) + +class FormView(View): + def __init__(self, doc, id): + View.__init__(self, win32ui.CreateFormView(doc, id)) + +class Document(object.CmdTarget): + def __init__(self, template, docobj=None): + if docobj is None: + docobj = template.DoCreateDoc() + object.CmdTarget.__init__(self, docobj) + +class RichEditDoc(object.CmdTarget): + def __init__(self, template): + object.CmdTarget.__init__(self, template.DoCreateRichEditDoc()) + +class CreateContext: + "A transient base class used as a CreateContext" + def __init__(self, template, doc = None): + self.template = template + self.doc = doc + def __del__(self): + self.close() + def close(self): + self.doc = None + self.template = None + +class DocTemplate(object.CmdTarget): + def __init__(self, resourceId=None, MakeDocument=None, MakeFrame=None, MakeView=None): + if resourceId is None: resourceId = win32ui.IDR_PYTHONTYPE + object.CmdTarget.__init__(self, self._CreateDocTemplate(resourceId)) + self.MakeDocument=MakeDocument + self.MakeFrame=MakeFrame + self.MakeView=MakeView + self._SetupSharedMenu_() + def _SetupSharedMenu_(self): + pass # to be overridden by each "app" + def _CreateDocTemplate(self, resourceId): + return win32ui.CreateDocTemplate(resourceId) + def __del__(self): + object.CmdTarget.__del__(self) + def CreateCreateContext(self, doc=None): + return CreateContext(self, doc) + def CreateNewFrame(self, doc): + makeFrame = self.MakeFrame + if makeFrame is None: makeFrame = window.MDIChildWnd + wnd = makeFrame() + context = self.CreateCreateContext(doc) + wnd.LoadFrame(self.GetResourceID(), -1, None, context) # triggers OnCreateClient... + return wnd + def CreateNewDocument(self): + makeDocument = self.MakeDocument + if makeDocument is None: + makeDocument = Document + return makeDocument(self) + def CreateView(self, frame, context): + makeView = self.MakeView + if makeView is None: makeView = EditView + view = makeView(context.doc) + view.CreateWindow(frame) + +class RichEditDocTemplate(DocTemplate): + def __init__(self, resourceId=None, MakeDocument=None, MakeFrame=None, MakeView=None): + if MakeView is None: MakeView = RichEditView + if MakeDocument is None: MakeDocument = RichEditDoc + DocTemplate.__init__(self, resourceId, MakeDocument, MakeFrame, MakeView) + + def _CreateDocTemplate(self, resourceId): + return win32ui.CreateRichEditDocTemplate(resourceId) + +def t(): + class FormTemplate(DocTemplate): + def CreateView(self, frame, context): + makeView = self.MakeView +# view = FormView(context.doc, win32ui.IDD_PROPDEMO1) + view = ListView(context.doc) + view.CreateWindow(frame) + + t=FormTemplate() + return t.OpenDocumentFile(None) diff --git a/Lib/site-packages/pythonwin/pywin/mfc/object.py b/Lib/site-packages/pythonwin/pywin/mfc/object.py new file mode 100644 index 0000000..151436c --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/mfc/object.py @@ -0,0 +1,55 @@ +# MFC base classes. +import sys +import win32ui + +class Object: + def __init__(self, initObj = None): + self.__dict__['_obj_'] = initObj +# self._obj_ = initObj + if initObj is not None: initObj.AttachObject(self) + def __del__(self): + self.close() + def __getattr__(self, attr): # Make this object look like the underlying win32ui one. + # During cleanup __dict__ is not available, causing recursive death. + if not attr.startswith('__'): + try: + o = self.__dict__['_obj_'] + if o is not None: + return getattr(o, attr) + # Only raise this error for non "internal" names - + # Python may be calling __len__, __nonzero__, etc, so + # we dont want this exception + if attr[0]!= '_' and attr[-1] != '_': + raise win32ui.error("The MFC object has died.") + except KeyError: + # No _obj_ at all - dont report MFC object died when there isnt one! + pass + raise AttributeError(attr) + + def OnAttachedObjectDeath(self): +# print "object", self.__class__.__name__, "dieing" + self._obj_ = None + def close(self): + if '_obj_' in self.__dict__: + if self._obj_ is not None: + self._obj_.AttachObject(None) + self._obj_ = None + +class CmdTarget(Object): + def __init__(self, initObj): + Object.__init__(self, initObj) + def HookNotifyRange(self, handler, firstID, lastID): + oldhandlers = [] + for i in range(firstID, lastID + 1): + oldhandlers.append(self.HookNotify(handler, i)) + return oldhandlers + def HookCommandRange(self, handler, firstID, lastID): + oldhandlers = [] + for i in range(firstID, lastID + 1): + oldhandlers.append(self.HookCommand(handler, i)) + return oldhandlers + def HookCommandUpdateRange(self, handler, firstID, lastID): + oldhandlers = [] + for i in range(firstID, lastID + 1): + oldhandlers.append(self.HookCommandUpdate(handler, i)) + return oldhandlers diff --git a/Lib/site-packages/pythonwin/pywin/mfc/thread.py b/Lib/site-packages/pythonwin/pywin/mfc/thread.py new file mode 100644 index 0000000..1fcf7b2 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/mfc/thread.py @@ -0,0 +1,22 @@ +# Thread and application objects + +from . import object +import win32ui + +class WinThread(object.CmdTarget): + def __init__(self, initObj = None): + if initObj is None: + initObj = win32ui.CreateThread() + object.CmdTarget.__init__(self, initObj) + + def InitInstance(self): + pass # Default None/0 return indicates success for InitInstance() + def ExitInstance(self): + pass + + +class WinApp(WinThread): + def __init__(self, initApp = None): + if initApp is None: + initApp = win32ui.GetApp() + WinThread.__init__(self, initApp) diff --git a/Lib/site-packages/pythonwin/pywin/mfc/window.py b/Lib/site-packages/pythonwin/pywin/mfc/window.py new file mode 100644 index 0000000..3db9e3f --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/mfc/window.py @@ -0,0 +1,41 @@ +# The MFCish window classes. +from . import object +import win32ui +import win32con + +class Wnd(object.CmdTarget): + def __init__(self, initobj=None): + object.CmdTarget.__init__(self, initobj) + if self._obj_: self._obj_.HookMessage(self.OnDestroy, win32con.WM_DESTROY) + def OnDestroy(self, msg): + pass + +# NOTE NOTE - This facility is currently disabled in Pythonwin!!!!! +# Note - to process all messages for your window, add the following method +# to a derived class. This code provides default message handling (ie, is +# identical, except presumably in speed, as if the method did not exist at +# all, so presumably will be modified to test for specific messages to be +# useful! +# def WindowProc(self, msg, wParam, lParam): +# rc, lResult = self._obj_.OnWndMsg(msg, wParam, lParam) +# if not rc: lResult = self._obj_.DefWindowProc(msg, wParam, lParam) +# return lResult + +class FrameWnd(Wnd): + def __init__(self, wnd): + Wnd.__init__(self, wnd) + +class MDIChildWnd(FrameWnd): + def __init__(self, wnd = None): + if wnd is None: + wnd=win32ui.CreateMDIChild() + FrameWnd.__init__(self, wnd) + def OnCreateClient(self, cp, context): + if context is not None and context.template is not None: + context.template.CreateView(self, context) + +class MDIFrameWnd(FrameWnd): + def __init__(self, wnd = None): + if wnd is None: + wnd=win32ui.CreateMDIFrame() + FrameWnd.__init__(self, wnd) diff --git a/Lib/site-packages/pythonwin/pywin/scintilla/IDLEenvironment.py b/Lib/site-packages/pythonwin/pywin/scintilla/IDLEenvironment.py new file mode 100644 index 0000000..3e9d5e3 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/scintilla/IDLEenvironment.py @@ -0,0 +1,528 @@ +# Code that allows Pythonwin to pretend it is IDLE +# (at least as far as most IDLE extensions are concerned) + +import string +import win32api +import win32ui +import win32con +import sys + +from pywin.mfc.dialog import GetSimpleInput +from pywin import default_scintilla_encoding + +wordchars = string.ascii_uppercase + string.ascii_lowercase + string.digits + +class TextError(Exception): # When a TclError would normally be raised. + pass + + +class EmptyRange(Exception): # Internally raised. + pass + +def GetIDLEModule(module): + try: + # First get it from Pythonwin it is exists. + modname = "pywin.idle." + module + __import__(modname) + except ImportError as details: + msg = "The IDLE extension '%s' can not be located.\r\n\r\n" \ + "Please correct the installation and restart the" \ + " application.\r\n\r\n%s" % (module, details) + win32ui.MessageBox(msg) + return None + mod=sys.modules[modname] + mod.TclError = TextError # A hack that can go soon! + return mod + +# A class that is injected into the IDLE auto-indent extension. +# It allows for decent performance when opening a new file, +# as auto-indent uses the tokenizer module to determine indents. +# The default AutoIndent readline method works OK, but it goes through +# this layer of Tk index indirection for every single line. For large files +# without indents (and even small files with indents :-) it was pretty slow! +def fast_readline(self): + if self.finished: + val = "" + else: + if "_scint_lines" not in self.__dict__: + # XXX - note - assumes this is only called once the file is loaded! + self._scint_lines = self.text.edit.GetTextRange().split("\n") + sl = self._scint_lines + i = self.i = self.i + 1 + if i >= len(sl): + val = "" + else: + val = sl[i]+"\n" + return val.encode(default_scintilla_encoding) + +try: + GetIDLEModule("AutoIndent").IndentSearcher.readline = fast_readline +except AttributeError: # GetIDLEModule may return None + pass + +# A class that attempts to emulate an IDLE editor window. +# Construct with a Pythonwin view. +class IDLEEditorWindow: + def __init__(self, edit): + self.edit = edit + self.text = TkText(edit) + self.extensions = {} + self.extension_menus = {} + + def close(self): + self.edit = self.text = None + self.extension_menus = None + try: + for ext in self.extensions.values(): + closer = getattr(ext, "close", None) + if closer is not None: + closer() + finally: + self.extensions = {} + + def IDLEExtension(self, extension): + ext = self.extensions.get(extension) + if ext is not None: return ext + mod = GetIDLEModule(extension) + if mod is None: return None + klass = getattr(mod, extension) + ext = self.extensions[extension] = klass(self) + # Find and bind all the events defined in the extension. + events = [item for item in dir(klass) if item[-6:]=="_event"] + for event in events: + name = "<<%s>>" % (event[:-6].replace("_", "-"), ) + self.edit.bindings.bind(name, getattr(ext, event)) + return ext + + def GetMenuItems(self, menu_name): + # Get all menu items for the menu name (eg, "edit") + bindings = self.edit.bindings + ret = [] + for ext in self.extensions.values(): + menudefs = getattr(ext, "menudefs", []) + for name, items in menudefs: + if name == menu_name: + for text, event in [item for item in items if item is not None]: + text = text.replace("&", "&&") + text = text.replace("_", "&") + ret.append((text, event)) + return ret + + ###################################################################### + # The IDLE "Virtual UI" methods that are exposed to the IDLE extensions. + # + def askinteger(self, caption, prompt, parent=None, initialvalue=0, minvalue=None, maxvalue=None): + while 1: + rc = GetSimpleInput(prompt, str(initialvalue), caption) + if rc is None: return 0 # Correct "cancel" semantics? + err = None + try: + rc = int(rc) + except ValueError: + err = "Please enter an integer" + if not err and minvalue is not None and rc < minvalue: + err = "Please enter an integer greater then or equal to %s" % (minvalue,) + if not err and maxvalue is not None and rc > maxvalue: + err = "Please enter an integer less then or equal to %s" % (maxvalue,) + if err: + win32ui.MessageBox(err, caption, win32con.MB_OK) + continue + return rc + def askyesno(self, caption, prompt, parent=None): + return win32ui.MessageBox(prompt, caption, win32con.MB_YESNO)==win32con.IDYES + + ###################################################################### + # The IDLE "Virtual Text Widget" methods that are exposed to the IDLE extensions. + # + + # Is character at text_index in a Python string? Return 0 for + # "guaranteed no", true for anything else. + def is_char_in_string(self, text_index): + # A helper for the code analyser - we need internal knowledge of + # the colorizer to get this information + # This assumes the colorizer has got to this point! + text_index = self.text._getoffset(text_index) + c = self.text.edit._GetColorizer() + if c and c.GetStringStyle(text_index) is None: + return 0 + return 1 + + # If a selection is defined in the text widget, return + # (start, end) as Tkinter text indices, otherwise return + # (None, None) + def get_selection_indices(self): + try: + first = self.text.index("sel.first") + last = self.text.index("sel.last") + return first, last + except TextError: + return None, None + + def set_tabwidth(self, width ): + self.edit.SCISetTabWidth(width) + + def get_tabwidth(self): + return self.edit.GetTabWidth() + +# A class providing the generic "Call Tips" interface +class CallTips: + def __init__(self, edit): + self.edit = edit + def showtip(self, tip_text): + self.edit.SCICallTipShow(tip_text) + def hidetip(self): + self.edit.SCICallTipCancel() + +######################################## +# +# Helpers for the TkText emulation. +def TkOffsetToIndex(offset, edit): + lineoff = 0 + # May be 1 > actual end if we pretended there was a trailing '\n' + offset = min(offset, edit.GetTextLength()) + line = edit.LineFromChar(offset) + lineIndex = edit.LineIndex(line) + return "%d.%d" % (line+1, offset-lineIndex) + +def _NextTok(str, pos): + # Returns (token, endPos) + end = len(str) + if pos>=end: return None, 0 + while pos < end and str[pos] in string.whitespace: + pos = pos + 1 + # Special case for +- + if str[pos] in '+-': + return str[pos],pos+1 + # Digits also a special case. + endPos = pos + while endPos < end and str[endPos] in string.digits+".": + endPos = endPos + 1 + if pos!=endPos: return str[pos:endPos], endPos + endPos = pos + while endPos < end and str[endPos] not in string.whitespace + string.digits + "+-": + endPos = endPos + 1 + if pos!=endPos: return str[pos:endPos], endPos + return None, 0 + +def TkIndexToOffset(bm, edit, marks): + base, nextTokPos = _NextTok(bm, 0) + if base is None: raise ValueError("Empty bookmark ID!") + if base.find(".")>0: + try: + line, col = base.split(".", 2) + if col=="first" or col=="last": + # Tag name + if line != "sel": raise ValueError("Tags arent here!") + sel = edit.GetSel() + if sel[0]==sel[1]: + raise EmptyRange + if col=="first": + pos = sel[0] + else: + pos = sel[1] + else: + # Lines are 1 based for tkinter + line = int(line)-1 + if line > edit.GetLineCount(): + pos = edit.GetTextLength()+1 + else: + pos = edit.LineIndex(line) + if pos==-1: pos = edit.GetTextLength() + pos = pos + int(col) + except (ValueError, IndexError): + raise ValueError("Unexpected literal in '%s'" % base) + elif base == 'insert': + pos = edit.GetSel()[0] + elif base=='end': + pos = edit.GetTextLength() + # Pretend there is a trailing '\n' if necessary + if pos and edit.SCIGetCharAt(pos-1) != "\n": + pos = pos+1 + else: + try: + pos = marks[base] + except KeyError: + raise ValueError("Unsupported base offset or undefined mark '%s'" % base) + + while 1: + word, nextTokPos = _NextTok(bm, nextTokPos) + if word is None: break + if word in ['+','-']: + num, nextTokPos = _NextTok(bm, nextTokPos) + if num is None: raise ValueError("+/- operator needs 2 args") + what, nextTokPos = _NextTok(bm, nextTokPos) + if what is None: raise ValueError("+/- operator needs 2 args") + if what[0] != "c": raise ValueError("+/- only supports chars") + if word=='+': + pos = pos + int(num) + else: + pos = pos - int(num) + elif word=='wordstart': + while pos > 0 and edit.SCIGetCharAt(pos-1) in wordchars: + pos = pos - 1 + elif word=='wordend': + end = edit.GetTextLength() + while pos < end and edit.SCIGetCharAt(pos) in wordchars: + pos = pos + 1 + elif word=='linestart': + while pos > 0 and edit.SCIGetCharAt(pos-1) not in '\n\r': + pos = pos - 1 + elif word=='lineend': + end = edit.GetTextLength() + while pos < end and edit.SCIGetCharAt(pos) not in '\n\r': + pos = pos + 1 + else: + raise ValueError("Unsupported relative offset '%s'" % word) + return max(pos, 0) # Tkinter is tollerant of -ve indexes - we aren't + +# A class that resembles an IDLE (ie, a Tk) text widget. +# Construct with an edit object (eg, an editor view) +class TkText: + def __init__(self, edit): + self.calltips = None + self.edit = edit + self.marks = {} +## def __getattr__(self, attr): +## if attr=="tk": return self # So text.tk.call works. +## if attr=="master": return None # ditto! +## raise AttributeError, attr +## def __getitem__(self, item): +## if item=="tabs": +## size = self.edit.GetTabWidth() +## if size==8: return "" # Tk default +## return size # correct semantics? +## elif item=="font": # Used for measurements we dont need to do! +## return "Dont know the font" +## raise IndexError, "Invalid index '%s'" % item + def make_calltip_window(self): + if self.calltips is None: + self.calltips = CallTips(self.edit) + return self.calltips + def _getoffset(self, index): + return TkIndexToOffset(index, self.edit, self.marks) + def _getindex(self, off): + return TkOffsetToIndex(off, self.edit) + def _fix_indexes(self, start, end): + # first some magic to handle skipping over utf8 extended chars. + while start > 0 and ord(self.edit.SCIGetCharAt(start)) & 0xC0 == 0x80: + start -= 1 + while end < self.edit.GetTextLength() and ord(self.edit.SCIGetCharAt(end)) & 0xC0 == 0x80: + end += 1 + # now handling fixing \r\n->\n disparities... + if start>0 and self.edit.SCIGetCharAt(start)=='\n' and self.edit.SCIGetCharAt(start-1)=='\r': + start = start - 1 + if end < self.edit.GetTextLength() and self.edit.SCIGetCharAt(end-1)=='\r' and self.edit.SCIGetCharAt(end)=='\n': + end = end + 1 + return start, end +## def get_tab_width(self): +## return self.edit.GetTabWidth() +## def call(self, *rest): +## # Crap to support Tk measurement hacks for tab widths +## if rest[0] != "font" or rest[1] != "measure": +## raise ValueError, "Unsupport call type" +## return len(rest[5]) +## def configure(self, **kw): +## for name, val in kw.items(): +## if name=="tabs": +## self.edit.SCISetTabWidth(int(val)) +## else: +## raise ValueError, "Unsupported configuration item %s" % kw + def bind(self, binding, handler): + self.edit.bindings.bind(binding, handler) + def get(self, start, end = None): + try: + start = self._getoffset(start) + if end is None: + end = start+1 + else: + end = self._getoffset(end) + except EmptyRange: + return "" + # Simple semantic checks to conform to the Tk text interface + if end <= start: return "" + max = self.edit.GetTextLength() + checkEnd = 0 + if end > max: + end = max + checkEnd = 1 + start, end = self._fix_indexes(start, end) + ret = self.edit.GetTextRange(start, end) + # pretend a trailing '\n' exists if necessary. + if checkEnd and (not ret or ret[-1] != '\n'): ret = ret + '\n' + return ret.replace("\r", "") + def index(self, spec): + try: + return self._getindex(self._getoffset(spec)) + except EmptyRange: + return "" + def insert(self, pos, text): + try: + pos = self._getoffset(pos) + except EmptyRange: + raise TextError("Empty range") + self.edit.SetSel((pos, pos)) + # IDLE only deals with "\n" - we will be nicer + + bits = text.split('\n') + self.edit.SCIAddText(bits[0]) + for bit in bits[1:]: + self.edit.SCINewline() + self.edit.SCIAddText(bit) + + def delete(self, start, end=None): + try: + start = self._getoffset(start) + if end is not None: end = self._getoffset(end) + except EmptyRange: + raise TextError("Empty range") + # If end is specified and == start, then we must delete nothing. + if start==end: return + # If end is not specified, delete one char + if end is None: + end = start+1 + else: + # Tk says not to delete in this case, but our control would. + if end=start and old=end: + old = old - (end-start) + self.edit.SetSel(old) + + def bell(self): + win32api.MessageBeep() + + def see(self, pos): + # Most commands we use in Scintilla actually force the selection + # to be seen, making this unnecessary. + pass + + def mark_set(self, name, pos): + try: + pos = self._getoffset(pos) + except EmptyRange: + raise TextError("Empty range '%s'" % pos) + if name == "insert": + self.edit.SetSel( pos ) + else: + self.marks[name]=pos + + def tag_add(self, name, start, end): + if name != "sel": raise ValueError("Only sel tag is supported") + try: + start = self._getoffset(start) + end = self._getoffset(end) + except EmptyRange: + raise TextError("Empty range") + self.edit.SetSel( start, end ) + + def tag_remove(self, name, start, end): + if name !="sel" or start != "1.0" or end != "end": + raise ValueError("Cant remove this tag") + # Turn the sel into a cursor + self.edit.SetSel(self.edit.GetSel()[0]) + + def compare(self, i1, op, i2): + try: + i1=self._getoffset(i1) + except EmptyRange: + i1 = "" + try: + i2=self._getoffset(i2) + except EmptyRange: + i2 = "" + return eval("%d%s%d" % (i1,op,i2)) + + def undo_block_start(self): + self.edit.SCIBeginUndoAction() + + def undo_block_stop(self): + self.edit.SCIEndUndoAction() + +###################################################################### +# +# Test related code. +# +###################################################################### +def TestCheck(index, edit, expected=None): + rc = TkIndexToOffset(index, edit, {}) + if rc != expected: + print("ERROR: Index", index,", expected", expected, "but got", rc) + +def TestGet(fr, to, t, expected): + got = t.get(fr, to) + if got != expected: + print("ERROR: get(%s, %s) expected %s, but got %s" % (repr(fr), repr(to), repr(expected), repr(got))) + +def test(): + import pywin.framework.editor + d=pywin.framework.editor.editorTemplate.OpenDocumentFile(None) + e=d.GetFirstView() + t = TkText(e) + e.SCIAddText("hi there how\nare you today\r\nI hope you are well") + e.SetSel((4,4)) + + skip = """ + TestCheck("insert", e, 4) + TestCheck("insert wordstart", e, 3) + TestCheck("insert wordend", e, 8) + TestCheck("insert linestart", e, 0) + TestCheck("insert lineend", e, 12) + TestCheck("insert + 4 chars", e, 8) + TestCheck("insert +4c", e, 8) + TestCheck("insert - 2 chars", e, 2) + TestCheck("insert -2c", e, 2) + TestCheck("insert-2c", e, 2) + TestCheck("insert-2 c", e, 2) + TestCheck("insert- 2c", e, 2) + TestCheck("1.1", e, 1) + TestCheck("1.0", e, 0) + TestCheck("2.0", e, 13) + try: + TestCheck("sel.first", e, 0) + print "*** sel.first worked with an empty selection" + except TextError: + pass + e.SetSel((4,5)) + TestCheck("sel.first- 2c", e, 2) + TestCheck("sel.last- 2c", e, 3) + """ + # Check EOL semantics + e.SetSel((4,4)) + TestGet("insert lineend", "insert lineend +1c", t, "\n") + e.SetSel((20, 20)) + TestGet("insert lineend", "insert lineend +1c", t, "\n") + e.SetSel((35, 35)) + TestGet("insert lineend", "insert lineend +1c", t, "\n") + +class IDLEWrapper: + def __init__(self, control): + self.text = control + +def IDLETest(extension): + import sys, os + modname = "pywin.idle." + extension + __import__(modname) + mod=sys.modules[modname] + mod.TclError = TextError + klass = getattr(mod, extension) + + # Create a new Scintilla Window. + import pywin.framework.editor + d=pywin.framework.editor.editorTemplate.OpenDocumentFile(None) + v=d.GetFirstView() + fname=os.path.splitext(__file__)[0] + ".py" + v.SCIAddText(open(fname).read()) + d.SetModifiedFlag(0) + r=klass( IDLEWrapper( TkText(v) ) ) + return r + +if __name__=='__main__': + test() + diff --git a/Lib/site-packages/pythonwin/pywin/scintilla/__init__.py b/Lib/site-packages/pythonwin/pywin/scintilla/__init__.py new file mode 100644 index 0000000..8d8ea47 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/scintilla/__init__.py @@ -0,0 +1 @@ +# package init. \ No newline at end of file diff --git a/Lib/site-packages/pythonwin/pywin/scintilla/bindings.py b/Lib/site-packages/pythonwin/pywin/scintilla/bindings.py new file mode 100644 index 0000000..309b061 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/scintilla/bindings.py @@ -0,0 +1,172 @@ +from . import IDLEenvironment +import string +import win32ui +import win32api +import win32con +from . import keycodes +import sys +import traceback + +HANDLER_ARGS_GUESS=0 +HANDLER_ARGS_NATIVE=1 +HANDLER_ARGS_IDLE=2 +HANDLER_ARGS_EXTENSION=3 + +next_id = 5000 + +event_to_commands = {}# dict of integer IDs to event names. +command_to_events = {}# dict of event names to int IDs + +def assign_command_id(event, id = 0): + global next_id + if id == 0: + id = event_to_commands.get(event, 0) + if id == 0: + id = next_id + next_id = next_id + 1 + # Only map the ones we allocated - specified ones are assumed to have a handler + command_to_events[id] = event + event_to_commands[event] = id + return id + +class SendCommandHandler: + def __init__(self, cmd): + self.cmd = cmd + def __call__(self, *args): + win32ui.GetMainFrame().SendMessage(win32con.WM_COMMAND, self.cmd) + +class Binding: + def __init__(self, handler, handler_args_type): + self.handler = handler + self.handler_args_type = handler_args_type + +class BindingsManager: + def __init__(self, parent_view): + self.parent_view = parent_view + self.bindings = {} # dict of Binding instances. + self.keymap = {} + + def prepare_configure(self): + self.keymap = {} + + def complete_configure(self): + for id in command_to_events.keys(): + self.parent_view.HookCommand(self._OnCommand, id) + + def close(self): + self.parent_view = self.bindings = self.keymap = None + + def report_error(self, problem): + try: + win32ui.SetStatusText(problem, 1) + except win32ui.error: + # No status bar! + print(problem) + + def update_keymap(self, keymap): + self.keymap.update(keymap) + + def bind(self, event, handler, handler_args_type = HANDLER_ARGS_GUESS, cid = 0): + if handler is None: + handler = SendCommandHandler(cid) + self.bindings[event] = self._new_binding(handler, handler_args_type) + self.bind_command(event, cid) + + def bind_command(self, event, id = 0): + "Binds an event to a Windows control/command ID" + id = assign_command_id(event, id) + return id + + def get_command_id(self, event): + id = event_to_commands.get(event) + if id is None: + # See if we even have an event of that name!? + if event not in self.bindings: + return None + id = self.bind_command(event) + return id + + def _OnCommand(self, id, code): + event = command_to_events.get(id) + if event is None: + self.report_error("No event associated with event ID %d" % id) + return 1 + return self.fire(event) + + def _new_binding(self, event, handler_args_type): + return Binding(event, handler_args_type) + + def _get_IDLE_handler(self, ext, handler): + try: + instance = self.parent_view.idle.IDLEExtension(ext) + name = handler.replace("-", "_") + "_event" + return getattr(instance, name) + except (ImportError, AttributeError): + msg = "Can not find event '%s' in IDLE extension '%s'" % (handler, ext) + self.report_error(msg) + return None + + def fire(self, event, event_param = None): + # Fire the specified event. Result is native Pythonwin result + # (ie, 1==pass one, 0 or None==handled) + + # First look up the event directly - if there, we are set. + binding = self.bindings.get(event) + if binding is None: + # If possible, find it! + # A native method name + handler = getattr(self.parent_view, event + "Event", None) + if handler is None: + # Can't decide if I should report an error?? + self.report_error("The event name '%s' can not be found." % event) + # Either way, just let the default handlers grab it. + return 1 + binding = self._new_binding(handler, HANDLER_ARGS_NATIVE) + # Cache it. + self.bindings[event] = binding + + handler_args_type = binding.handler_args_type + # Now actually fire it. + if handler_args_type==HANDLER_ARGS_GUESS: + # Can't be native, as natives are never added with "guess". + # Must be extension or IDLE. + if event[0]=="<": + handler_args_type = HANDLER_ARGS_IDLE + else: + handler_args_type = HANDLER_ARGS_EXTENSION + try: + if handler_args_type==HANDLER_ARGS_EXTENSION: + args = self.parent_view.idle, event_param + else: + args = (event_param,) + rc = binding.handler(*args) + if handler_args_type==HANDLER_ARGS_IDLE: + # Convert to our return code. + if rc in [None, "break"]: + rc = 0 + else: + rc = 1 + except: + message = "Firing event '%s' failed." % event + print(message) + traceback.print_exc() + self.report_error(message) + rc = 1 # Let any default handlers have a go! + return rc + + def fire_key_event(self, msg): + key = msg[2] + keyState = 0 + if win32api.GetKeyState(win32con.VK_CONTROL) & 0x8000: + keyState = keyState | win32con.RIGHT_CTRL_PRESSED | win32con.LEFT_CTRL_PRESSED + if win32api.GetKeyState(win32con.VK_SHIFT) & 0x8000: + keyState = keyState | win32con.SHIFT_PRESSED + if win32api.GetKeyState(win32con.VK_MENU) & 0x8000: + keyState = keyState | win32con.LEFT_ALT_PRESSED | win32con.RIGHT_ALT_PRESSED + keyinfo = key, keyState + # Special hacks for the dead-char key on non-US keyboards. + # (XXX - which do not work :-( + event = self.keymap.get( keyinfo ) + if event is None: + return 1 + return self.fire(event, None) diff --git a/Lib/site-packages/pythonwin/pywin/scintilla/config.py b/Lib/site-packages/pythonwin/pywin/scintilla/config.py new file mode 100644 index 0000000..47d3f33 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/scintilla/config.py @@ -0,0 +1,322 @@ +# config.py - deals with loading configuration information. + +# Loads config data from a .cfg file. Also caches the compiled +# data back into a .cfc file. + +# If you are wondering how to avoid needing .cfg files (eg, +# if you are freezing Pythonwin etc) I suggest you create a +# .py file, and put the config info in a docstring. Then +# pass a CStringIO file (rather than a filename) to the +# config manager. +import sys +import string +from . import keycodes +import marshal +import stat +import os +import types +import traceback +import pywin +import glob +import imp + +import win32api + +debugging = 0 +if debugging: + import win32traceutil # Some trace statements fire before the interactive window is open. + def trace(*args): + sys.stderr.write(" ".join(map(str, args)) + "\n") +else: + trace = lambda *args: None + +compiled_config_version = 3 + +def split_line(line, lineno): + comment_pos = line.find("#") + if comment_pos>=0: line = line[:comment_pos] + sep_pos = line.rfind("=") + if sep_pos == -1: + if line.strip(): + print("Warning: Line %d: %s is an invalid entry" % (lineno, repr(line))) + return None, None + return "", "" + return line[:sep_pos].strip(), line[sep_pos+1:].strip() + +def get_section_header(line): + # Returns the section if the line is a section header, else None + if line[0] == "[": + end = line.find("]") + if end==-1: end=len(line) + rc = line[1:end].lower() + try: + i = rc.index(":") + return rc[:i], rc[i+1:] + except ValueError: + return rc, "" + return None, None + +def find_config_file(f): + return os.path.join(pywin.__path__[0], f + ".cfg") + +def find_config_files(): + return [os.path.split(x)[1] + for x in [os.path.splitext(x)[0] for x in glob.glob(os.path.join(pywin.__path__[0], "*.cfg"))] + ] + +class ConfigManager: + def __init__(self, f): + self.filename = "unknown" + self.last_error = None + self.key_to_events = {} + if hasattr(f, "readline"): + fp = f + self.filename = "" + compiled_name = None + else: + try: + f = find_config_file(f) + src_stat = os.stat(f) + except os.error: + self.report_error("Config file '%s' not found" % f) + return + self.filename = f + self.basename = os.path.basename(f) + trace("Loading configuration", self.basename) + compiled_name = os.path.splitext(f)[0] + ".cfc" + try: + cf = open(compiled_name, "rb") + try: + ver = marshal.load(cf) + ok = compiled_config_version == ver + if ok: + kblayoutname = marshal.load(cf) + magic = marshal.load(cf) + size = marshal.load(cf) + mtime = marshal.load(cf) + if magic == imp.get_magic() and \ + win32api.GetKeyboardLayoutName() == kblayoutname and \ + src_stat[stat.ST_MTIME] == mtime and \ + src_stat[stat.ST_SIZE] == size: + self.cache = marshal.load(cf) + trace("Configuration loaded cached", compiled_name) + return # We are ready to roll! + finally: + cf.close() + except (os.error, IOError, EOFError): + pass + fp = open(f) + self.cache = {} + lineno = 1 + line = fp.readline() + while line: + # Skip to the next section (maybe already there!) + section, subsection = get_section_header(line) + while line and section is None: + line = fp.readline() + if not line: break + lineno = lineno + 1 + section, subsection = get_section_header(line) + if not line: break + + if section=="keys": + line, lineno = self._load_keys(subsection, fp, lineno) + elif section == "extensions": + line, lineno = self._load_extensions(subsection, fp, lineno) + elif section == "idle extensions": + line, lineno = self._load_idle_extensions(subsection, fp, lineno) + elif section == "general": + line, lineno = self._load_general(subsection, fp, lineno) + else: + self.report_error("Unrecognised section header '%s:%s'" % (section,subsection)) + line = fp.readline() + lineno = lineno + 1 + # Check critical data. + if not self.cache.get("keys"): + self.report_error("No keyboard definitions were loaded") + if not self.last_error and compiled_name: + try: + cf = open(compiled_name, "wb") + marshal.dump(compiled_config_version, cf) + marshal.dump(win32api.GetKeyboardLayoutName(), cf) + marshal.dump(imp.get_magic(), cf) + marshal.dump(src_stat[stat.ST_SIZE], cf) + marshal.dump(src_stat[stat.ST_MTIME], cf) + marshal.dump(self.cache, cf) + cf.close() + except (IOError, EOFError): + pass # Ignore errors - may be read only. + + def configure(self, editor, subsections = None): + # Execute the extension code, and find any events. + # First, we "recursively" connect any we are based on. + if subsections is None: subsections = [] + subsections = [''] + subsections + general = self.get_data("general") + if general: + parents = general.get("based on", []) + for parent in parents: + trace("Configuration based on", parent, "- loading.") + parent = self.__class__(parent) + parent.configure(editor, subsections) + if parent.last_error: + self.report_error(parent.last_error) + + bindings = editor.bindings + codeob = self.get_data("extension code") + if codeob is not None: + ns = {} + try: + exec(codeob, ns) + except: + traceback.print_exc() + self.report_error("Executing extension code failed") + ns = None + if ns: + num = 0 + for name, func in list(ns.items()): + if type(func)==types.FunctionType and name[:1] != '_': + bindings.bind(name, func) + num = num + 1 + trace("Configuration Extension code loaded", num, "events") + # Load the idle extensions + for subsection in subsections: + for ext in self.get_data("idle extensions", {}).get(subsection, []): + try: + editor.idle.IDLEExtension(ext) + trace("Loaded IDLE extension", ext) + except: + self.report_error("Can not load the IDLE extension '%s'" % ext) + + # Now bind up the key-map (remembering a reverse map + subsection_keymap = self.get_data("keys") + num_bound = 0 + for subsection in subsections: + keymap = subsection_keymap.get(subsection, {}) + bindings.update_keymap(keymap) + num_bound = num_bound + len(keymap) + trace("Configuration bound", num_bound, "keys") + + def get_key_binding(self, event, subsections = None): + if subsections is None: subsections = [] + subsections = [''] + subsections + + subsection_keymap = self.get_data("keys") + for subsection in subsections: + map = self.key_to_events.get(subsection) + if map is None: # Build it + map = {} + keymap = subsection_keymap.get(subsection, {}) + for key_info, map_event in list(keymap.items()): + map[map_event] = key_info + self.key_to_events[subsection] = map + + info = map.get(event) + if info is not None: + return keycodes.make_key_name( info[0], info[1] ) + return None + + def report_error(self, msg): + self.last_error = msg + print("Error in %s: %s" % (self.filename, msg)) + def report_warning(self, msg): + print("Warning in %s: %s" % (self.filename, msg)) + + def _readline(self, fp, lineno, bStripComments = 1): + line = fp.readline() + lineno = lineno + 1 + if line: + bBreak = get_section_header(line)[0] is not None # A new section is starting + if bStripComments and not bBreak: + pos = line.find("#") + if pos>=0: line=line[:pos]+"\n" + else: + bBreak=1 + return line, lineno, bBreak + + def get_data(self, name, default=None): + return self.cache.get(name, default) + + def _save_data(self, name, data): + self.cache[name] = data + return data + + def _load_general(self, sub_section, fp, lineno): + map = {} + while 1: + line, lineno, bBreak = self._readline(fp, lineno) + if bBreak: break + + key, val = split_line(line, lineno) + if not key: continue + key = key.lower() + l = map.get(key, []) + l.append(val) + map[key]=l + self._save_data("general", map) + return line, lineno + + def _load_keys(self, sub_section, fp, lineno): + # Builds a nested dictionary of + # (scancode, flags) = event_name + main_map = self.get_data("keys", {}) + map = main_map.get(sub_section, {}) + while 1: + line, lineno, bBreak = self._readline(fp, lineno) + if bBreak: break + + key, event = split_line(line, lineno) + if not event: continue + sc, flag = keycodes.parse_key_name(key) + if sc is None: + self.report_warning("Line %d: Invalid key name '%s'" % (lineno, key)) + else: + map[sc, flag] = event + main_map[sub_section] = map + self._save_data("keys", main_map) + return line, lineno + + def _load_extensions(self, sub_section, fp, lineno): + start_lineno = lineno + lines = [] + while 1: + line, lineno, bBreak = self._readline(fp, lineno, 0) + if bBreak: break + lines.append(line) + try: + c = compile( + "\n" * start_lineno + # produces correct tracebacks + "".join(lines), self.filename, "exec") + self._save_data("extension code", c) + except SyntaxError as details: + errlineno = details.lineno + start_lineno + # Should handle syntax errors better here, and offset the lineno. + self.report_error("Compiling extension code failed:\r\nFile: %s\r\nLine %d\r\n%s" \ + % (details.filename, errlineno, details.msg)) + return line, lineno + + def _load_idle_extensions(self, sub_section, fp, lineno): + extension_map = self.get_data("idle extensions") + if extension_map is None: extension_map = {} + extensions = [] + while 1: + line, lineno, bBreak = self._readline(fp, lineno) + if bBreak: break + line = line.strip() + if line: + extensions.append(line) + extension_map[sub_section] = extensions + self._save_data("idle extensions", extension_map) + return line, lineno + +def test(): + import time + start = time.clock() + f="default" + cm = ConfigManager(f) + map = cm.get_data("keys") + took = time.clock()-start + print("Loaded %s items in %.4f secs" % (len(map), took)) + +if __name__=='__main__': + test() diff --git a/Lib/site-packages/pythonwin/pywin/scintilla/configui.py b/Lib/site-packages/pythonwin/pywin/scintilla/configui.py new file mode 100644 index 0000000..883b42b --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/scintilla/configui.py @@ -0,0 +1,266 @@ +from pywin.mfc import dialog +import win32api +import win32con +import win32ui +import copy +import string +from . import scintillacon + +# Used to indicate that style should use default color +from win32con import CLR_INVALID + +###################################################### +# Property Page for syntax formatting options + +# The standard 16 color VGA palette should always be possible +paletteVGA = ( + ("Black", win32api.RGB(0,0,0)), + ("Navy", win32api.RGB(0,0,128)), + ("Green", win32api.RGB(0,128,0)), + ("Cyan", win32api.RGB(0,128,128)), + ("Maroon", win32api.RGB(128,0,0)), + ("Purple", win32api.RGB(128,0,128)), + ("Olive", win32api.RGB(128,128,0)), + ("Gray", win32api.RGB(128,128,128)), + ("Silver", win32api.RGB(192,192,192)), + ("Blue", win32api.RGB(0,0,255)), + ("Lime", win32api.RGB(0,255,0)), + ("Aqua", win32api.RGB(0,255,255)), + ("Red", win32api.RGB(255,0,0)), + ("Fuchsia", win32api.RGB(255,0,255)), + ("Yellow", win32api.RGB(255,255,0)), + ("White", win32api.RGB(255,255,255)), +# and a few others will generally be possible. + ("DarkGrey", win32api.RGB(64,64,64)), + ("PurpleBlue", win32api.RGB(64,64,192)), + ("DarkGreen", win32api.RGB(0,96,0)), + ("DarkOlive", win32api.RGB(128,128,64)), + ("MediumBlue", win32api.RGB(0,0,192)), + ("DarkNavy", win32api.RGB(0,0,96)), + ("Magenta", win32api.RGB(96,0,96)), + ("OffWhite", win32api.RGB(255,255,220)), + ("LightPurple", win32api.RGB(220,220,255)), + ("", win32con.CLR_INVALID) +) + +class ScintillaFormatPropertyPage(dialog.PropertyPage): + def __init__(self, scintillaClass = None, caption = 0): + self.scintillaClass = scintillaClass + dialog.PropertyPage.__init__(self, win32ui.IDD_PP_FORMAT, caption=caption) + + def OnInitDialog(self): + try: + if self.scintillaClass is None: + from . import control + sc = control.CScintillaEdit + else: + sc = self.scintillaClass + + self.scintilla = sc() + style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.ES_MULTILINE + # Convert the rect size + rect = self.MapDialogRect( (5, 5, 120, 75)) + self.scintilla.CreateWindow(style, rect, self, 111) + self.HookNotify(self.OnBraceMatch, scintillacon.SCN_CHECKBRACE) + self.scintilla.HookKeyStroke(self.OnEsc, 27) + self.scintilla.SCISetViewWS(1) + self.pos_bstart = self.pos_bend = self.pos_bbad = 0 + + colorizer = self.scintilla._GetColorizer() + text = colorizer.GetSampleText() + items = text.split('|', 2) + pos = len(items[0]) + self.scintilla.SCIAddText(''.join(items)) + self.scintilla.SetSel(pos, pos) + self.scintilla.ApplyFormattingStyles() + self.styles = self.scintilla._GetColorizer().styles + + self.cbo = self.GetDlgItem(win32ui.IDC_COMBO1) + for c in paletteVGA: + self.cbo.AddString(c[0]) + + self.cboBoldItalic = self.GetDlgItem(win32ui.IDC_COMBO2) + for item in ["Bold Italic", "Bold", "Italic", "Regular"]: + self.cboBoldItalic.InsertString(0, item) + + self.butIsDefault = self.GetDlgItem(win32ui.IDC_CHECK1) + self.butIsDefaultBackground = self.GetDlgItem(win32ui.IDC_CHECK2) + self.listbox = self.GetDlgItem(win32ui.IDC_LIST1) + self.HookCommand(self.OnListCommand, win32ui.IDC_LIST1) + names = list(self.styles.keys()) + names.sort() + for name in names: + if self.styles[name].aliased is None: + self.listbox.AddString(name) + self.listbox.SetCurSel(0) + + idc = win32ui.IDC_RADIO1 + if not self.scintilla._GetColorizer().bUseFixed: idc = win32ui.IDC_RADIO2 + self.GetDlgItem(idc).SetCheck(1) + self.UpdateUIForStyle(self.styles[names[0]]) + + self.scintilla.HookFormatter(self) + self.HookCommand(self.OnButDefaultFixedFont, win32ui.IDC_BUTTON1) + self.HookCommand(self.OnButDefaultPropFont, win32ui.IDC_BUTTON2) + self.HookCommand(self.OnButThisFont, win32ui.IDC_BUTTON3) + self.HookCommand(self.OnButUseDefaultFont, win32ui.IDC_CHECK1) + self.HookCommand(self.OnButThisBackground, win32ui.IDC_BUTTON4) + self.HookCommand(self.OnButUseDefaultBackground, win32ui.IDC_CHECK2) + self.HookCommand(self.OnStyleUIChanged, win32ui.IDC_COMBO1) + self.HookCommand(self.OnStyleUIChanged, win32ui.IDC_COMBO2) + self.HookCommand(self.OnButFixedOrDefault, win32ui.IDC_RADIO1) + self.HookCommand(self.OnButFixedOrDefault, win32ui.IDC_RADIO2) + except: + import traceback + traceback.print_exc() + + def OnEsc(self, ch): + self.GetParent().EndDialog(win32con.IDCANCEL) + + def OnBraceMatch(self, std, extra): + import pywin.scintilla.view + pywin.scintilla.view.DoBraceMatch(self.scintilla) + + def GetSelectedStyle(self): + return self.styles[self.listbox.GetText(self.listbox.GetCurSel())] + + def _DoButDefaultFont(self, extra_flags, attr): + baseFormat = getattr(self.scintilla._GetColorizer(), attr) + flags = extra_flags | win32con.CF_SCREENFONTS | win32con.CF_EFFECTS | win32con.CF_FORCEFONTEXIST + d=win32ui.CreateFontDialog(baseFormat, flags, None, self) + if d.DoModal()==win32con.IDOK: + setattr(self.scintilla._GetColorizer(), attr, d.GetCharFormat()) + self.OnStyleUIChanged(0, win32con.BN_CLICKED) + + def OnButDefaultFixedFont(self, id, code): + if code==win32con.BN_CLICKED: + self._DoButDefaultFont(win32con.CF_FIXEDPITCHONLY, "baseFormatFixed") + return 1 + + def OnButDefaultPropFont(self, id, code): + if code==win32con.BN_CLICKED: + self._DoButDefaultFont(win32con.CF_SCALABLEONLY, "baseFormatProp") + return 1 + + def OnButFixedOrDefault(self, id, code): + if code==win32con.BN_CLICKED: + bUseFixed = id == win32ui.IDC_RADIO1 + self.GetDlgItem(win32ui.IDC_RADIO1).GetCheck() != 0 + self.scintilla._GetColorizer().bUseFixed = bUseFixed + self.scintilla.ApplyFormattingStyles(0) + return 1 + + def OnButThisFont(self, id, code): + if code==win32con.BN_CLICKED: + flags = win32con.CF_SCREENFONTS | win32con.CF_EFFECTS | win32con.CF_FORCEFONTEXIST + style = self.GetSelectedStyle() + # If the selected style is based on the default, we need to apply + # the default to it. + def_format = self.scintilla._GetColorizer().GetDefaultFormat() + format = style.GetCompleteFormat(def_format) + d=win32ui.CreateFontDialog(format, flags, None, self) + if d.DoModal()==win32con.IDOK: + style.format = d.GetCharFormat() + self.scintilla.ApplyFormattingStyles(0) + return 1 + + def OnButUseDefaultFont(self, id, code): + if code == win32con.BN_CLICKED: + isDef = self.butIsDefault.GetCheck() + self.GetDlgItem(win32ui.IDC_BUTTON3).EnableWindow(not isDef) + if isDef: # Being reset to the default font. + style = self.GetSelectedStyle() + style.ForceAgainstDefault() + self.UpdateUIForStyle(style) + self.scintilla.ApplyFormattingStyles(0) + else: + # User wants to override default - + # do nothing! + pass + + def OnButThisBackground(self, id, code): + if code==win32con.BN_CLICKED: + style = self.GetSelectedStyle() + bg = win32api.RGB(0xff, 0xff, 0xff) + if style.background != CLR_INVALID: + bg = style.background + d=win32ui.CreateColorDialog(bg, 0, self) + if d.DoModal()==win32con.IDOK: + style.background = d.GetColor() + self.scintilla.ApplyFormattingStyles(0) + return 1 + + def OnButUseDefaultBackground(self, id, code): + if code == win32con.BN_CLICKED: + isDef = self.butIsDefaultBackground.GetCheck() + self.GetDlgItem(win32ui.IDC_BUTTON4).EnableWindow(not isDef) + if isDef: # Being reset to the default color + style = self.GetSelectedStyle() + style.background = style.default_background + self.UpdateUIForStyle(style) + self.scintilla.ApplyFormattingStyles(0) + else: + # User wants to override default - + # do nothing! + pass + + + def OnListCommand(self, id, code): + if code==win32con.LBN_SELCHANGE: + style = self.GetSelectedStyle() + self.UpdateUIForStyle(style) + return 1 + + def UpdateUIForStyle(self, style ): + format = style.format + sel = 0 + for c in paletteVGA: + if format[4] == c[1]: +# print "Style", style.name, "is", c[0] + break + sel = sel + 1 + else: + sel = -1 + self.cbo.SetCurSel(sel) + self.butIsDefault.SetCheck(style.IsBasedOnDefault()) + self.GetDlgItem(win32ui.IDC_BUTTON3).EnableWindow(not style.IsBasedOnDefault()) + + self.butIsDefaultBackground.SetCheck(style.background == style.default_background) + self.GetDlgItem(win32ui.IDC_BUTTON4).EnableWindow(style.background != style.default_background) + + bold = format[1] & win32con.CFE_BOLD != 0; italic = format[1] & win32con.CFE_ITALIC != 0 + self.cboBoldItalic.SetCurSel( bold*2 + italic ) + + def OnStyleUIChanged(self, id, code): + if code in [win32con.BN_CLICKED, win32con.CBN_SELCHANGE]: + style = self.GetSelectedStyle() + self.ApplyUIFormatToStyle(style) + self.scintilla.ApplyFormattingStyles(0) + return 0 + return 1 + + def ApplyUIFormatToStyle(self, style): + format = style.format + color = paletteVGA[self.cbo.GetCurSel()] + effect = 0 + sel = self.cboBoldItalic.GetCurSel() + if sel==0: + effect = 0 + elif sel==1: + effect = win32con.CFE_ITALIC + elif sel==2: + effect = win32con.CFE_BOLD + else: + effect = win32con.CFE_BOLD | win32con.CFE_ITALIC + maskFlags=format[0]|win32con.CFM_COLOR|win32con.CFM_BOLD|win32con.CFM_ITALIC + style.format = (maskFlags, effect, style.format[2], style.format[3], color[1]) + style.format[5:] + + def OnOK(self): + self.scintilla._GetColorizer().SavePreferences() + return 1 + +def test(): + page = ColorEditorPropertyPage() + sheet = pywin.mfc.dialog.PropertySheet("Test") + sheet.AddPage(page) + sheet.CreateWindow() diff --git a/Lib/site-packages/pythonwin/pywin/scintilla/control.py b/Lib/site-packages/pythonwin/pywin/scintilla/control.py new file mode 100644 index 0000000..4413e3c --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/scintilla/control.py @@ -0,0 +1,434 @@ +# An Python interface to the Scintilla control. +# +# Exposes Python classes that allow you to use Scintilla as +# a "standard" MFC edit control (eg, control.GetTextLength(), control.GetSel() +# plus many Scintilla specific features (eg control.SCIAddStyledText()) + +from pywin.mfc import window +from pywin import default_scintilla_encoding +import win32con +import win32ui +import win32api +import array +import struct +import string +import os +from . import scintillacon + +# Load Scintilla.dll to get access to the control. +# We expect to find this in the same directory as win32ui.pyd +dllid = None +if win32ui.debug: # If running _d version of Pythonwin... + try: + dllid = win32api.LoadLibrary(os.path.join(os.path.split(win32ui.__file__)[0], "Scintilla_d.DLL")) + except win32api.error: # Not there - we dont _need_ a debug ver, so ignore this error. + pass +if dllid is None: + try: + dllid = win32api.LoadLibrary(os.path.join(os.path.split(win32ui.__file__)[0], "Scintilla.DLL")) + except win32api.error: + pass +if dllid is None: + # Still not there - lets see if Windows can find it by searching? + dllid = win32api.LoadLibrary("Scintilla.DLL") + +# null_byte is str in py2k, bytes on py3k +null_byte = "\0".encode('ascii') + +## These are from Richedit.h - need to add to win32con or commctrl +EM_GETTEXTRANGE = 1099 +EM_EXLINEFROMCHAR = 1078 +EM_FINDTEXTEX = 1103 +EM_GETSELTEXT = 1086 +EM_EXSETSEL = win32con.WM_USER + 55 + +class ScintillaNotification: + def __init__(self, **args): + self.__dict__.update(args) + +class ScintillaControlInterface: + def SCIUnpackNotifyMessage(self, msg): + format = "iiiiPiiiPPiiii" + bytes = win32ui.GetBytes( msg, struct.calcsize(format) ) + position, ch, modifiers, modificationType, text_ptr, \ + length, linesAdded, msg, wParam, lParam, line, \ + foldLevelNow, foldLevelPrev, margin \ + = struct.unpack(format, bytes) + return ScintillaNotification(position=position,ch=ch, + modifiers=modifiers, modificationType=modificationType, + text_ptr = text_ptr, length=length, linesAdded=linesAdded, + msg = msg, wParam = wParam, lParam = lParam, + line = line, foldLevelNow = foldLevelNow, foldLevelPrev = foldLevelPrev, + margin = margin) + + def SCIAddText(self, text): + self.SendMessage(scintillacon.SCI_ADDTEXT, text.encode(default_scintilla_encoding)) + def SCIAddStyledText(self, text, style = None): + # If style is None, text is assumed to be a "native" Scintilla buffer. + # If style is specified, text is a normal string, and the style is + # assumed to apply to the entire string. + if style is not None: + text = list(map(lambda char, style=style: char+chr(style), text)) + text = ''.join(text) + self.SendMessage(scintillacon.SCI_ADDSTYLEDTEXT, text.encode(default_scintilla_encoding)) + def SCIInsertText(self, text, pos=-1): + # SCIInsertText allows unicode or bytes - but if they are bytes, + # the caller must ensure it is encoded correctly. + if isinstance(text, str): + text = text.encode(default_scintilla_encoding) + self.SendScintilla(scintillacon.SCI_INSERTTEXT, pos, text + null_byte) + def SCISetSavePoint(self): + self.SendScintilla(scintillacon.SCI_SETSAVEPOINT) + def SCISetUndoCollection(self, collectFlag): + self.SendScintilla(scintillacon.SCI_SETUNDOCOLLECTION, collectFlag) + def SCIBeginUndoAction(self): + self.SendScintilla(scintillacon.SCI_BEGINUNDOACTION) + def SCIEndUndoAction(self): + self.SendScintilla(scintillacon.SCI_ENDUNDOACTION) + + def SCIGetCurrentPos(self): + return self.SendScintilla(scintillacon.SCI_GETCURRENTPOS) + def SCIGetCharAt(self, pos): + # Must ensure char is unsigned! + return chr(self.SendScintilla(scintillacon.SCI_GETCHARAT, pos) & 0xFF) + def SCIGotoLine(self, line): + self.SendScintilla(scintillacon.SCI_GOTOLINE, line) + def SCIBraceMatch(self, pos, maxReStyle): + return self.SendScintilla(scintillacon.SCI_BRACEMATCH, pos, maxReStyle) + def SCIBraceHighlight(self, pos, posOpposite): + return self.SendScintilla(scintillacon.SCI_BRACEHIGHLIGHT, pos, posOpposite) + def SCIBraceBadHighlight(self, pos): + return self.SendScintilla(scintillacon.SCI_BRACEBADLIGHT, pos) + + #################################### + # Styling +# def SCIColourise(self, start=0, end=-1): +# NOTE - dependent on of we use builtin lexer, so handled below. + def SCIGetEndStyled(self): + return self.SendScintilla(scintillacon.SCI_GETENDSTYLED) + def SCIStyleSetFore(self, num, v): + return self.SendScintilla(scintillacon.SCI_STYLESETFORE, num, v) + def SCIStyleSetBack(self, num, v): + return self.SendScintilla(scintillacon.SCI_STYLESETBACK, num, v) + def SCIStyleSetEOLFilled(self, num, v): + return self.SendScintilla(scintillacon.SCI_STYLESETEOLFILLED, num, v) + def SCIStyleSetFont(self, num, name, characterset=0): + buff = (name + "\0").encode(default_scintilla_encoding) + self.SendScintilla(scintillacon.SCI_STYLESETFONT, num, buff) + self.SendScintilla(scintillacon.SCI_STYLESETCHARACTERSET, num, characterset) + def SCIStyleSetBold(self, num, bBold): + self.SendScintilla(scintillacon.SCI_STYLESETBOLD, num, bBold) + def SCIStyleSetItalic(self, num, bItalic): + self.SendScintilla(scintillacon.SCI_STYLESETITALIC, num, bItalic) + def SCIStyleSetSize(self, num, size): + self.SendScintilla(scintillacon.SCI_STYLESETSIZE, num, size) + def SCIGetViewWS(self): + return self.SendScintilla(scintillacon.SCI_GETVIEWWS) + def SCISetViewWS(self, val): + self.SendScintilla(scintillacon.SCI_SETVIEWWS, not (val==0)) + self.InvalidateRect() + def SCISetIndentationGuides(self, val): + self.SendScintilla(scintillacon.SCI_SETINDENTATIONGUIDES, val) + def SCIGetIndentationGuides(self): + return self.SendScintilla(scintillacon.SCI_GETINDENTATIONGUIDES) + def SCISetIndent(self, val): + self.SendScintilla(scintillacon.SCI_SETINDENT, val) + def SCIGetIndent(self, val): + return self.SendScintilla(scintillacon.SCI_GETINDENT) + + def SCIGetViewEOL(self): + return self.SendScintilla(scintillacon.SCI_GETVIEWEOL) + def SCISetViewEOL(self, val): + self.SendScintilla(scintillacon.SCI_SETVIEWEOL, not(val==0)) + self.InvalidateRect() + def SCISetTabWidth(self, width): + self.SendScintilla(scintillacon.SCI_SETTABWIDTH, width, 0) + def SCIStartStyling(self, pos, mask): + self.SendScintilla(scintillacon.SCI_STARTSTYLING, pos, mask) + def SCISetStyling(self, pos, attr): + self.SendScintilla(scintillacon.SCI_SETSTYLING, pos, attr) + def SCISetStylingEx(self, ray): # ray is an array. + address, length = ray.buffer_info() + self.SendScintilla(scintillacon.SCI_SETSTYLINGEX, length, address) + def SCIGetStyleAt(self, pos): + return self.SendScintilla(scintillacon.SCI_GETSTYLEAT, pos) + def SCISetMarginWidth(self, width): + self.SendScintilla(scintillacon.SCI_SETMARGINWIDTHN, 1, width) + def SCISetMarginWidthN(self, n, width): + self.SendScintilla(scintillacon.SCI_SETMARGINWIDTHN, n, width) + def SCISetFoldFlags(self, flags): + self.SendScintilla(scintillacon.SCI_SETFOLDFLAGS, flags) + # Markers + def SCIMarkerDefineAll(self, markerNum, markerType, fore, back): + self.SCIMarkerDefine(markerNum, markerType) + self.SCIMarkerSetFore(markerNum, fore) + self.SCIMarkerSetBack(markerNum, back) + def SCIMarkerDefine(self, markerNum, markerType): + self.SendScintilla(scintillacon.SCI_MARKERDEFINE, markerNum, markerType) + def SCIMarkerSetFore(self, markerNum, fore): + self.SendScintilla(scintillacon.SCI_MARKERSETFORE, markerNum, fore) + def SCIMarkerSetBack(self, markerNum, back): + self.SendScintilla(scintillacon.SCI_MARKERSETBACK, markerNum, back) + def SCIMarkerAdd(self, lineNo, markerNum): + self.SendScintilla(scintillacon.SCI_MARKERADD, lineNo, markerNum) + def SCIMarkerDelete(self, lineNo, markerNum): + self.SendScintilla(scintillacon.SCI_MARKERDELETE, lineNo, markerNum) + def SCIMarkerDeleteAll(self, markerNum=-1): + self.SendScintilla(scintillacon.SCI_MARKERDELETEALL, markerNum) + def SCIMarkerGet(self, lineNo): + return self.SendScintilla(scintillacon.SCI_MARKERGET, lineNo) + def SCIMarkerNext(self, lineNo, markerNum): + return self.SendScintilla(scintillacon.SCI_MARKERNEXT, lineNo, markerNum) + def SCICancel(self): + self.SendScintilla(scintillacon.SCI_CANCEL) + # AutoComplete + def SCIAutoCShow(self, text): + if type(text) in [type([]), type(())]: + text = ' '.join(text) + buff = (text + "\0").encode(default_scintilla_encoding) + return self.SendScintilla(scintillacon.SCI_AUTOCSHOW, 0, buff) + def SCIAutoCCancel(self): + self.SendScintilla(scintillacon.SCI_AUTOCCANCEL) + def SCIAutoCActive(self): + return self.SendScintilla(scintillacon.SCI_AUTOCACTIVE) + def SCIAutoCComplete(self): + return self.SendScintilla(scintillacon.SCI_AUTOCCOMPLETE) + def SCIAutoCStops(self, stops): + buff = (stops + "\0").encode(default_scintilla_encoding) + self.SendScintilla(scintillacon.SCI_AUTOCSTOPS, 0, buff) + def SCIAutoCSetAutoHide(self, hide): + self.SendScintilla(scintillacon.SCI_AUTOCSETAUTOHIDE, hide) + def SCIAutoCSetFillups(self, fillups): + self.SendScintilla(scintillacon.SCI_AUTOCSETFILLUPS, fillups) + # Call tips + def SCICallTipShow(self, text, pos=-1): + if pos==-1: pos = self.GetSel()[0] + buff = (text + "\0").encode(default_scintilla_encoding) + self.SendScintilla(scintillacon.SCI_CALLTIPSHOW, pos, buff) + def SCICallTipCancel(self): + self.SendScintilla(scintillacon.SCI_CALLTIPCANCEL) + def SCICallTipActive(self): + return self.SendScintilla(scintillacon.SCI_CALLTIPACTIVE) + def SCICallTipPosStart(self): + return self.SendScintilla(scintillacon.SCI_CALLTIPPOSSTART) + def SCINewline(self): + self.SendScintilla(scintillacon.SCI_NEWLINE) + # Lexer etc + def SCISetKeywords(self, keywords, kw_list_no = 0): + buff = (keywords+"\0").encode(default_scintilla_encoding) + self.SendScintilla(scintillacon.SCI_SETKEYWORDS, kw_list_no, buff) + def SCISetProperty(self, name, value): + name_buff = array.array('b', (name + '\0').encode(default_scintilla_encoding)) + val_buff = array.array("b", (str(value)+'\0').encode(default_scintilla_encoding)) + address_name_buffer = name_buff.buffer_info()[0] + address_val_buffer = val_buff.buffer_info()[0] + self.SendScintilla(scintillacon.SCI_SETPROPERTY, address_name_buffer, address_val_buffer) + def SCISetStyleBits(self, nbits): + self.SendScintilla(scintillacon.SCI_SETSTYLEBITS, nbits) + # Folding + def SCIGetFoldLevel(self, lineno): + return self.SendScintilla(scintillacon.SCI_GETFOLDLEVEL, lineno) + def SCIToggleFold(self, lineno): + return self.SendScintilla(scintillacon.SCI_TOGGLEFOLD, lineno) + def SCIEnsureVisible(self, lineno): + self.SendScintilla(scintillacon.SCI_ENSUREVISIBLE, lineno) + def SCIGetFoldExpanded(self, lineno): + return self.SendScintilla(scintillacon.SCI_GETFOLDEXPANDED, lineno) + # right edge + def SCISetEdgeColumn(self, edge): + self.SendScintilla(scintillacon.SCI_SETEDGECOLUMN, edge) + def SCIGetEdgeColumn(self): + return self.SendScintilla(scintillacon.SCI_GETEDGECOLUMN) + def SCISetEdgeMode(self, mode): + self.SendScintilla(scintillacon.SCI_SETEDGEMODE, mode) + def SCIGetEdgeMode(self): + return self.SendScintilla(scintillacon.SCI_GETEDGEMODE) + def SCISetEdgeColor(self, color): + self.SendScintilla(scintillacon.SCI_SETEDGECOLOUR, color) + def SCIGetEdgeColor(self): + return self.SendScintilla(scintillacon.SCI_GETEDGECOLOR) + # Multi-doc + def SCIGetDocPointer(self): + return self.SendScintilla(scintillacon.SCI_GETDOCPOINTER) + def SCISetDocPointer(self, p): + return self.SendScintilla(scintillacon.SCI_SETDOCPOINTER, 0, p) + def SCISetWrapMode(self, mode): + return self.SendScintilla(scintillacon.SCI_SETWRAPMODE, mode) + def SCIGetWrapMode(self): + return self.SendScintilla(scintillacon.SCI_GETWRAPMODE) + +class CScintillaEditInterface(ScintillaControlInterface): + def close(self): + self.colorizer = None + def Clear(self): + self.SendScintilla(win32con.WM_CLEAR) + def Clear(self): + self.SendScintilla(win32con.WM_CLEAR) + def FindText(self, flags, range, findText): + """ LPARAM for EM_FINDTEXTEX: + typedef struct _findtextex { + CHARRANGE chrg; + LPCTSTR lpstrText; + CHARRANGE chrgText;} FINDTEXTEX; + typedef struct _charrange { + LONG cpMin; + LONG cpMax;} CHARRANGE; + """ + findtextex_fmt='llPll' + ## Scintilla does not handle unicode in EM_FINDTEXT msg (FINDTEXTEX struct) + txt_buff = (findText+'\0').encode(default_scintilla_encoding) + txt_array = array.array('b', txt_buff) + ft_buff = struct.pack(findtextex_fmt, range[0], range[1], txt_array.buffer_info()[0], 0, 0) + ft_array = array.array('b', ft_buff) + rc = self.SendScintilla(EM_FINDTEXTEX, flags, ft_array.buffer_info()[0]) + ftUnpacked = struct.unpack(findtextex_fmt, ft_array) + return rc, (ftUnpacked[3], ftUnpacked[4]) + + def GetSel(self): + currentPos = self.SendScintilla(scintillacon.SCI_GETCURRENTPOS) + anchorPos = self.SendScintilla(scintillacon.SCI_GETANCHOR) + if currentPos < anchorPos: + return (currentPos, anchorPos) + else: + return (anchorPos, currentPos) + return currentPos; + + def GetSelText(self): + start, end = self.GetSel() + txtBuf = array.array('b', null_byte * (end-start+1)) + addressTxtBuf = txtBuf.buffer_info()[0] + # EM_GETSELTEXT is documented as returning the number of chars + # not including the NULL, but scintilla includes the NULL. A + # quick glance at the scintilla impl doesn't make this + # obvious - the NULL is included in the 'selection' object + # and reflected in the length of that 'selection' object. + # I expect that is a bug in scintilla and may be fixed by now, + # but we just blindly assume that the last char is \0 and + # strip it. + self.SendScintilla(EM_GETSELTEXT, 0, addressTxtBuf) + return txtBuf.tostring()[:-1].decode(default_scintilla_encoding) + + def SetSel(self, start=0, end=None): + if type(start)==type(()): + assert end is None, "If you pass a point in the first param, the second must be None" + start, end = start + elif end is None: + end = start + if start < 0: start = self.GetTextLength() + if end < 0: end = self.GetTextLength() + assert start <= self.GetTextLength(), "The start postion is invalid (%d/%d)" % (start, self.GetTextLength()) + assert end <= self.GetTextLength(), "The end postion is invalid (%d/%d)" % (end, self.GetTextLength()) + cr = struct.pack('ll', start, end) + crBuff = array.array('b', cr) + addressCrBuff = crBuff.buffer_info()[0] + rc = self.SendScintilla(EM_EXSETSEL, 0, addressCrBuff) + + def GetLineCount(self): + return self.SendScintilla(win32con.EM_GETLINECOUNT) + + def LineFromChar(self, charPos=-1): + if charPos==-1: charPos = self.GetSel()[0] + assert charPos >= 0 and charPos <= self.GetTextLength(), "The charPos postion (%s) is invalid (max=%s)" % (charPos, self.GetTextLength()) + #return self.SendScintilla(EM_EXLINEFROMCHAR, charPos) + # EM_EXLINEFROMCHAR puts charPos in lParam, not wParam + return self.SendScintilla(EM_EXLINEFROMCHAR, 0, charPos) + + def LineIndex(self, line): + return self.SendScintilla(win32con.EM_LINEINDEX, line) + + def ScrollCaret(self): + return self.SendScintilla(win32con.EM_SCROLLCARET) + + def GetCurLineNumber(self): + return self.LineFromChar(self.SCIGetCurrentPos()) + + def GetTextLength(self): + return self.SendScintilla(scintillacon.SCI_GETTEXTLENGTH) + + def GetTextRange(self, start = 0, end = -1, decode = True): + if end == -1: end = self.SendScintilla(scintillacon.SCI_GETTEXTLENGTH) + assert end>=start, "Negative index requested (%d/%d)" % (start, end) + assert start >= 0 and start <= self.GetTextLength(), "The start postion is invalid" + assert end >= 0 and end <= self.GetTextLength(), "The end postion is invalid" + initer = null_byte * (end - start + 1) + buff = array.array('b', initer) + addressBuffer = buff.buffer_info()[0] + tr = struct.pack('llP', start, end, addressBuffer) + trBuff = array.array('b', tr) + addressTrBuff = trBuff.buffer_info()[0] + num_bytes = self.SendScintilla(EM_GETTEXTRANGE, 0, addressTrBuff) + ret = buff.tostring()[:num_bytes] + if decode: + ret = ret.decode(default_scintilla_encoding) + return ret + + def ReplaceSel(self, str): + buff = (str + "\0").encode(default_scintilla_encoding) + self.SendScintilla(scintillacon.SCI_REPLACESEL, 0, buff) + + def GetLine(self, line=-1): + if line == -1: line = self.GetCurLineNumber() + start = self.LineIndex(line) + end = self.LineIndex(line+1) + return self.GetTextRange(start, end) + + def SetReadOnly(self, flag = 1): + return self.SendScintilla(win32con.EM_SETREADONLY, flag) + + def LineScroll(self, lines, cols=0): + return self.SendScintilla(win32con.EM_LINESCROLL, cols, lines) + + def GetFirstVisibleLine(self): + return self.SendScintilla(win32con.EM_GETFIRSTVISIBLELINE) + + def SetWordWrap(self, mode): + if mode != win32ui.CRichEditView_WrapNone: + raise ValueError("We dont support word-wrap (I dont think :-)") + +class CScintillaColorEditInterface(CScintillaEditInterface): + ################################ + # Plug-in colorizer support + def _GetColorizer(self): + if not hasattr(self, "colorizer"): + self.colorizer = self._MakeColorizer() + return self.colorizer + def _MakeColorizer(self): + # Give parent a chance to hook. + parent_func = getattr(self.GetParentFrame(), "_MakeColorizer", None) + if parent_func is not None: + return parent_func() + from . import formatter +## return formatter.PythonSourceFormatter(self) + return formatter.BuiltinPythonSourceFormatter(self) + + def Colorize(self, start=0, end=-1): + c = self._GetColorizer() + if c is not None: c.Colorize(start, end) + + def ApplyFormattingStyles(self, bReload=1): + c = self._GetColorizer() + if c is not None: c.ApplyFormattingStyles(bReload) + + # The Parent window will normally hook + def HookFormatter(self, parent = None): + c = self._GetColorizer() + if c is not None: # No need if we have no color! + c.HookFormatter(parent) + +class CScintillaEdit(window.Wnd, CScintillaColorEditInterface): + def __init__(self, wnd=None): + if wnd is None: + wnd = win32ui.CreateWnd() + window.Wnd.__init__(self, wnd) + def SendScintilla(self, msg, w=0, l=0): + return self.SendMessage(msg, w, l) + def CreateWindow(self, style, rect, parent, id): + self._obj_.CreateWindow( + "Scintilla", + "Scintilla", + style, + rect, + parent, + id, + None) + diff --git a/Lib/site-packages/pythonwin/pywin/scintilla/document.py b/Lib/site-packages/pythonwin/pywin/scintilla/document.py new file mode 100644 index 0000000..95e6b11 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/scintilla/document.py @@ -0,0 +1,274 @@ +import win32ui +from pywin.mfc import docview +from pywin import default_scintilla_encoding +from . import scintillacon +import win32con +import string +import os +import codecs +import re + +crlf_bytes = "\r\n".encode("ascii") +lf_bytes = "\n".encode("ascii") + +# re from pep263 - but we use it both on bytes and strings. +re_encoding_bytes = re.compile("coding[:=]\s*([-\w.]+)".encode("ascii")) +re_encoding_text = re.compile("coding[:=]\s*([-\w.]+)") + +ParentScintillaDocument=docview.Document +class CScintillaDocument(ParentScintillaDocument): + "A SyntEdit document. " + def __init__(self, *args): + self.bom = None # the BOM, if any, read from the file. + # the encoding we detected from the source. Might have + # detected via the BOM or an encoding decl. Note that in + # the latter case (ie, while self.bom is None), it can't be + # trusted - the user may have edited the encoding decl between + # open and save. + self.source_encoding = None + ParentScintillaDocument.__init__(self, *args) + + def DeleteContents(self): + pass + + def OnOpenDocument(self, filename): + # init data members + #print "Opening", filename + self.SetPathName(filename) # Must set this early! + try: + # load the text as binary we can get smart + # about detecting any existing EOL conventions. + f = open(filename, 'rb') + try: + self._LoadTextFromFile(f) + finally: + f.close() + except IOError: + rc = win32ui.MessageBox("Could not load the file from %s\n\nDo you want to create a new file?" % filename, + "Pythonwin", win32con.MB_YESNO | win32con.MB_ICONWARNING) + if rc == win32con.IDNO: + return 0 + assert rc == win32con.IDYES, rc + try: + f = open(filename, 'wb+') + try: + self._LoadTextFromFile(f) + finally: + f.close() + except IOError as e: + rc = win32ui.MessageBox("Cannot create the file %s" % filename) + return 1 + + def SaveFile(self, fileName, encoding=None): + view = self.GetFirstView() + ok = view.SaveTextFile(fileName, encoding=encoding) + if ok: + view.SCISetSavePoint() + return ok + + def ApplyFormattingStyles(self): + self._ApplyOptionalToViews("ApplyFormattingStyles") + + # ##################### + # File related functions + # Helper to transfer text from the MFC document to the control. + def _LoadTextFromFile(self, f): + # detect EOL mode - we don't support \r only - so find the + # first '\n' and guess based on the char before. + l = f.readline() + l2 = f.readline() + # If line ends with \r\n or has no line ending, use CRLF. + if l.endswith(crlf_bytes) or not l.endswith(lf_bytes): + eol_mode = scintillacon.SC_EOL_CRLF + else: + eol_mode = scintillacon.SC_EOL_LF + + # Detect the encoding - first look for a BOM, and if not found, + # look for a pep263 encoding declaration. + for bom, encoding in ( + (codecs.BOM_UTF8, "utf8"), + (codecs.BOM_UTF16_LE, "utf_16_le"), + (codecs.BOM_UTF16_BE, "utf_16_be"), + ): + if l.startswith(bom): + self.bom = bom + self.source_encoding = encoding + l = l[len(bom):] # remove it. + break + else: + # no bom detected - look for pep263 encoding decl. + for look in (l, l2): + # Note we are looking at raw bytes here: so + # both the re itself uses bytes and the result + # is bytes - but we need the result as a string. + match = re_encoding_bytes.search(look) + if match is not None: + self.source_encoding = match.group(1).decode("ascii") + break + + # reading by lines would be too slow? Maybe we can use the + # incremental encoders? For now just stick with loading the + # entire file in memory. + text = l + l2 + f.read() + + # Translate from source encoding to UTF-8 bytes for Scintilla + source_encoding = self.source_encoding + # If we don't know an encoding, just use latin-1 to treat + # it as bytes... + if source_encoding is None: + source_encoding = 'latin1' + # we could optimize this by avoiding utf8 to-ing and from-ing, + # but then we would lose the ability to handle invalid utf8 + # (and even then, the use of encoding aliases makes this tricky) + # To create an invalid utf8 file: + # >>> open(filename, "wb").write(codecs.BOM_UTF8+"bad \xa9har\r\n") + try: + dec = text.decode(source_encoding) + except UnicodeError: + print("WARNING: Failed to decode bytes from '%s' encoding - treating as latin1" % source_encoding) + dec = text.decode('latin1') + except LookupError: + print("WARNING: Invalid encoding '%s' specified - treating as latin1" % source_encoding) + dec = text.decode('latin1') + # and put it back as utf8 - this shouldn't fail. + text = dec.encode(default_scintilla_encoding) + + view = self.GetFirstView() + if view.IsWindow(): + # Turn off undo collection while loading + view.SendScintilla(scintillacon.SCI_SETUNDOCOLLECTION, 0, 0) + # Make sure the control isnt read-only + view.SetReadOnly(0) + view.SendScintilla(scintillacon.SCI_CLEARALL) + view.SendMessage(scintillacon.SCI_ADDTEXT, text) + view.SendScintilla(scintillacon.SCI_SETUNDOCOLLECTION, 1, 0) + view.SendScintilla(win32con.EM_EMPTYUNDOBUFFER, 0, 0) + # set EOL mode + view.SendScintilla(scintillacon.SCI_SETEOLMODE, eol_mode) + + def _SaveTextToFile(self, view, filename, encoding=None): + s = view.GetTextRange() # already decoded from scintilla's encoding + source_encoding = encoding + if source_encoding is None: + if self.bom: + source_encoding = self.source_encoding + else: + # no BOM - look for an encoding. + bits = re.split("[\r\n]*", s, 3) + for look in bits[:-1]: + match = re_encoding_text.search(look) + if match is not None: + source_encoding = match.group(1) + self.source_encoding = source_encoding + break + + if source_encoding is None: + source_encoding = 'latin1' + + ## encode data before opening file so script is not lost if encoding fails + file_contents = s.encode(source_encoding) + # Open in binary mode as scintilla itself ensures the + # line endings are already appropriate + f = open(filename, 'wb') + try: + if self.bom: + f.write(self.bom) + f.write(file_contents) + finally: + f.close() + self.SetModifiedFlag(0) + + def FinalizeViewCreation(self, view): + pass + + def HookViewNotifications(self, view): + parent = view.GetParentFrame() + parent.HookNotify(ViewNotifyDelegate(self, "OnBraceMatch"), scintillacon.SCN_CHECKBRACE) + parent.HookNotify(ViewNotifyDelegate(self, "OnMarginClick"), scintillacon.SCN_MARGINCLICK) + parent.HookNotify(ViewNotifyDelegate(self, "OnNeedShown"), scintillacon.SCN_NEEDSHOWN) + + parent.HookNotify(DocumentNotifyDelegate(self, "OnSavePointReached"), scintillacon.SCN_SAVEPOINTREACHED) + parent.HookNotify(DocumentNotifyDelegate(self, "OnSavePointLeft"), scintillacon.SCN_SAVEPOINTLEFT) + parent.HookNotify(DocumentNotifyDelegate(self, "OnModifyAttemptRO"), scintillacon.SCN_MODIFYATTEMPTRO) + # Tell scintilla what characters should abort auto-complete. + view.SCIAutoCStops(string.whitespace+"()[]:;+-/*=\\?'!#@$%^&,<>\"'|" ) + + if view != self.GetFirstView(): + view.SCISetDocPointer(self.GetFirstView().SCIGetDocPointer()) + + + def OnSavePointReached(self, std, extra): + self.SetModifiedFlag(0) + + def OnSavePointLeft(self, std, extra): + self.SetModifiedFlag(1) + + def OnModifyAttemptRO(self, std, extra): + self.MakeDocumentWritable() + + # All Marker functions are 1 based. + def MarkerAdd( self, lineNo, marker ): + self.GetEditorView().SCIMarkerAdd(lineNo-1, marker) + + def MarkerCheck(self, lineNo, marker ): + v = self.GetEditorView() + lineNo = lineNo - 1 # Make 0 based + markerState = v.SCIMarkerGet(lineNo) + return markerState & (1<= 0: + rc = FOUND_NORMAL + lineno = control.LineFromChar(posFind) + control.SCIEnsureVisible(lineno) + control.SetSel(foundSel) + control.SetFocus() + win32ui.SetStatusText(win32ui.LoadString(afxres.AFX_IDS_IDLEMESSAGE)) + if rc == FOUND_NOTHING and lastSearch.acrossFiles: + # Loop around all documents. First find this document. + try: + try: + doc = control.GetDocument() + except AttributeError: + try: + doc = control.GetParent().GetDocument() + except AttributeError: + print("Cant find a document for the control!") + doc = None + if doc is not None: + template = doc.GetDocTemplate() + alldocs = template.GetDocumentList() + mypos = lookpos = alldocs.index(doc) + while 1: + lookpos = (lookpos+1) % len(alldocs) + if lookpos == mypos: + break + view = alldocs[lookpos].GetFirstView() + posFind, foundSel = view.FindText(flags, (0, view.GetTextLength()), searchParams.findText) + if posFind >= 0: + nChars = foundSel[1]-foundSel[0] + lineNo = view.LineFromChar(posFind) # zero based. + lineStart = view.LineIndex(lineNo) + colNo = posFind - lineStart # zero based. + scriptutils.JumpToDocument(alldocs[lookpos].GetPathName(), lineNo+1, colNo+1, nChars) + rc = FOUND_NEXT_FILE + break + except win32ui.error: + pass + if rc == FOUND_NOTHING: + # Loop around this control - attempt to find from the start of the control. + posFind, foundSel = control.FindText(flags, (0, sel[0]-1), searchParams.findText) + if posFind >= 0: + control.SCIEnsureVisible(control.LineFromChar(foundSel[0])) + control.SetSel(foundSel) + control.SetFocus() + win32ui.SetStatusText("Not found! Searching from the top of the file.") + rc = FOUND_LOOPED_BACK + else: + lastSearch.sel=-1,-1 + win32ui.SetStatusText("Can not find '%s'" % searchParams.findText ) + + if rc != FOUND_NOTHING: + lastSearch.sel = foundSel + + if lastSearch.remember: + defaultSearch = lastSearch + + # track search history + try: + ix = searchHistory.index(searchParams.findText) + except ValueError: + if len(searchHistory) > 50: + searchHistory[50:] = [] + else: + del searchHistory[ix] + searchHistory.insert(0, searchParams.findText) + + return rc + +def _ReplaceIt(control): + control = _GetControl(control) + statusText = "Can not find '%s'." % lastSearch.findText + rc = FOUND_NOTHING + if control is not None and lastSearch.sel != (-1,-1): + control.ReplaceSel(lastSearch.replaceText) + rc = FindNext() + if rc !=FOUND_NOTHING: + statusText = win32ui.LoadString(afxres.AFX_IDS_IDLEMESSAGE) + win32ui.SetStatusText(statusText) + return rc + +class FindReplaceDialog(dialog.Dialog): + def __init__(self): + dialog.Dialog.__init__(self,self._GetDialogTemplate()) + self.HookCommand(self.OnFindNext, 109) + + def OnInitDialog(self): + self.editFindText = self.GetDlgItem(102) + self.butMatchWords = self.GetDlgItem(105) + self.butMatchCase = self.GetDlgItem(107) + self.butKeepDialogOpen = self.GetDlgItem(115) + self.butAcrossFiles = self.GetDlgItem(116) + self.butRemember = self.GetDlgItem(117) + + self.editFindText.SetWindowText(defaultSearch.findText) + control = _GetControl() + # _GetControl only gets normal MDI windows; if the interactive + # window is docked and no document open, we get None. + if control: + # If we have a selection, default to that. + sel = control.GetSelText() + if (len(sel) != 0): + self.editFindText.SetWindowText(sel) + if (defaultSearch.remember): + defaultSearch.findText = sel + for hist in searchHistory: + self.editFindText.AddString(hist) + + if hasattr(self.editFindText, 'SetEditSel'): + self.editFindText.SetEditSel(0, -2) + else: + self.editFindText.SetSel(0, -2) + self.editFindText.SetFocus() + self.butMatchWords.SetCheck(defaultSearch.matchWords) + self.butMatchCase.SetCheck(defaultSearch.matchCase) + self.butKeepDialogOpen.SetCheck(defaultSearch.keepDialogOpen) + self.butAcrossFiles.SetCheck(defaultSearch.acrossFiles) + self.butRemember.SetCheck(defaultSearch.remember) + return dialog.Dialog.OnInitDialog(self) + + def OnDestroy(self, msg): + global curDialog + curDialog = None + return dialog.Dialog.OnDestroy(self, msg) + + def DoFindNext(self): + params = SearchParams() + params.findText = self.editFindText.GetWindowText() + params.matchCase = self.butMatchCase.GetCheck() + params.matchWords = self.butMatchWords.GetCheck() + params.acrossFiles = self.butAcrossFiles.GetCheck() + params.remember = self.butRemember.GetCheck() + return _FindIt(None, params) + + def OnFindNext(self, id, code): + if not self.editFindText.GetWindowText(): + win32api.MessageBeep() + return + if self.DoFindNext() != FOUND_NOTHING: + if not self.butKeepDialogOpen.GetCheck(): + self.DestroyWindow() + +class FindDialog(FindReplaceDialog): + def _GetDialogTemplate(self): + style = win32con.DS_MODALFRAME | win32con.WS_POPUP | win32con.WS_VISIBLE | win32con.WS_CAPTION | win32con.WS_SYSMENU | win32con.DS_SETFONT + visible = win32con.WS_CHILD | win32con.WS_VISIBLE + dt = [ + ["Find", (0, 2, 240, 75), style, None, (8, "MS Sans Serif")], + ["Static", "Fi&nd What:", 101, (5, 8, 40, 10), visible], + ["ComboBox", "", 102, (50, 7, 120, 120), visible | win32con.WS_BORDER | win32con.WS_TABSTOP | + win32con.WS_VSCROLL |win32con.CBS_DROPDOWN |win32con.CBS_AUTOHSCROLL], + ["Button", "Match &whole word only", 105, (5, 23, 100, 10), visible | win32con.BS_AUTOCHECKBOX | win32con.WS_TABSTOP], + ["Button", "Match &case", 107, (5, 33, 100, 10), visible | win32con.BS_AUTOCHECKBOX | win32con.WS_TABSTOP], + ["Button", "Keep &dialog open", 115, (5, 43, 100, 10), visible | win32con.BS_AUTOCHECKBOX | win32con.WS_TABSTOP], + ["Button", "Across &open files", 116, (5, 52, 100, 10), visible | win32con.BS_AUTOCHECKBOX | win32con.WS_TABSTOP], + ["Button", "&Remember as default search", 117, (5, 61, 150, 10), visible | win32con.BS_AUTOCHECKBOX | win32con.WS_TABSTOP], + ["Button", "&Find Next", 109, (185, 5, 50, 14), visible | win32con.BS_DEFPUSHBUTTON | win32con.WS_TABSTOP], + ["Button", "Cancel", win32con.IDCANCEL, (185, 23, 50, 14), visible | win32con.WS_TABSTOP], + ] + return dt + +class ReplaceDialog(FindReplaceDialog): + def _GetDialogTemplate(self): + style = win32con.DS_MODALFRAME | win32con.WS_POPUP | win32con.WS_VISIBLE | win32con.WS_CAPTION | win32con.WS_SYSMENU | win32con.DS_SETFONT + visible = win32con.WS_CHILD | win32con.WS_VISIBLE + dt = [ + ["Replace", (0, 2, 240, 95), style, 0, (8, "MS Sans Serif")], + ["Static", "Fi&nd What:", 101, (5, 8, 40, 10), visible], + ["ComboBox", "", 102, (60, 7, 110, 120), visible | win32con.WS_BORDER | win32con.WS_TABSTOP | + win32con.WS_VSCROLL |win32con.CBS_DROPDOWN |win32con.CBS_AUTOHSCROLL], + ["Static", "Re&place with:", 103, (5, 25, 50, 10), visible], + ["ComboBox", "", 104, (60, 24, 110, 120), visible | win32con.WS_BORDER | win32con.WS_TABSTOP | + win32con.WS_VSCROLL |win32con.CBS_DROPDOWN |win32con.CBS_AUTOHSCROLL], + ["Button", "Match &whole word only", 105, (5, 42, 100, 10), visible | win32con.BS_AUTOCHECKBOX | win32con.WS_TABSTOP], + ["Button", "Match &case", 107, (5, 52, 100, 10), visible | win32con.BS_AUTOCHECKBOX | win32con.WS_TABSTOP], + ["Button", "Keep &dialog open", 115, (5, 62, 100, 10), visible | win32con.BS_AUTOCHECKBOX | win32con.WS_TABSTOP], + ["Button", "Across &open files", 116, (5, 72, 100, 10), visible | win32con.BS_AUTOCHECKBOX | win32con.WS_TABSTOP], + ["Button", "&Remember as default search", 117, (5, 81, 150, 10), visible | win32con.BS_AUTOCHECKBOX | win32con.WS_TABSTOP], + ["Button", "&Find Next", 109, (185, 5, 50, 14), visible | win32con.BS_DEFPUSHBUTTON | win32con.WS_TABSTOP], + ["Button", "&Replace", 110, (185, 23, 50, 14), visible | win32con.WS_TABSTOP], + ["Button", "Replace &All", 111, (185, 41, 50, 14), visible | win32con.WS_TABSTOP], + ["Button", "Cancel", win32con.IDCANCEL, (185, 59, 50, 14), visible | win32con.WS_TABSTOP], + + + ] + return dt + + def OnInitDialog(self): + rc = FindReplaceDialog.OnInitDialog(self) + self.HookCommand(self.OnReplace, 110) + self.HookCommand(self.OnReplaceAll, 111) + self.HookMessage(self.OnActivate, win32con.WM_ACTIVATE) + self.editReplaceText = self.GetDlgItem(104) + self.editReplaceText.SetWindowText(lastSearch.replaceText) + if hasattr(self.editReplaceText, 'SetEditSel'): + self.editReplaceText.SetEditSel(0, -2) + else: + self.editReplaceText.SetSel(0, -2) + self.butReplace = self.GetDlgItem(110) + self.butReplaceAll = self.GetDlgItem(111) + self.CheckButtonStates() + return rc + + def CheckButtonStates(self): + # We can do a "Replace" or "Replace All" if the current selection + # is the same as the search text. + ft = self.editFindText.GetWindowText() + control = _GetControl() +# bCanReplace = len(ft)>0 and control.GetSelText() == ft + bCanReplace = control is not None and lastSearch.sel == control.GetSel() + self.butReplace.EnableWindow(bCanReplace) +# self.butReplaceAll.EnableWindow(bCanReplace) + + def OnActivate(self, msg): + wparam = msg[2] + fActive = win32api.LOWORD(wparam) + if fActive != win32con.WA_INACTIVE: + self.CheckButtonStates() + + def OnFindNext(self, id, code): + self.DoFindNext() + self.CheckButtonStates() + + def OnReplace(self, id, code): + lastSearch.replaceText = self.editReplaceText.GetWindowText() + _ReplaceIt(None) + + def OnReplaceAll(self, id, code): + control = _GetControl(None) + if control is not None: + control.SetSel(0) + num = 0 + if self.DoFindNext() == FOUND_NORMAL: + num = 1 + lastSearch.replaceText = self.editReplaceText.GetWindowText() + while _ReplaceIt(control) == FOUND_NORMAL: + num = num + 1 + + win32ui.SetStatusText("Replaced %d occurrences" % num) + if num > 0 and not self.butKeepDialogOpen.GetCheck(): + self.DestroyWindow() + +if __name__=='__main__': + ShowFindDialog() diff --git a/Lib/site-packages/pythonwin/pywin/scintilla/formatter.py b/Lib/site-packages/pythonwin/pywin/scintilla/formatter.py new file mode 100644 index 0000000..fd8650e --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/scintilla/formatter.py @@ -0,0 +1,587 @@ +# Does Python source formatting for Scintilla controls. +import win32ui +import win32api +import win32con +import winerror +import string +import array +from . import scintillacon + +WM_KICKIDLE = 0x036A + +# Used to indicate that style should use default color +from win32con import CLR_INVALID + +debugging = 0 +if debugging: + # Output must go to another process else the result of + # the printing itself will trigger again trigger a trace. + import sys, win32traceutil, win32trace + def trace(*args): + win32trace.write(' '.join(map(str, args)) + "\n") +else: + trace = lambda *args: None + +class Style: + """Represents a single format + """ + def __init__(self, name, format, background = CLR_INVALID): + self.name = name # Name the format representes eg, "String", "Class" + # Default background for each style is only used when there are no + # saved settings (generally on first startup) + self.background = self.default_background = background + if type(format)==type(''): + self.aliased = format + self.format = None + else: + self.format = format + self.aliased = None + self.stylenum = None # Not yet registered. + def IsBasedOnDefault(self): + return len(self.format)==5 + # If the currently extended font defintion matches the + # default format, restore the format to the "simple" format. + def NormalizeAgainstDefault(self, defaultFormat): + if self.IsBasedOnDefault(): + return 0 # No more to do, and not changed. + bIsDefault = self.format[7] == defaultFormat[7] and \ + self.format[2] == defaultFormat[2] + if bIsDefault: + self.ForceAgainstDefault() + return bIsDefault + def ForceAgainstDefault(self): + self.format = self.format[:5] + def GetCompleteFormat(self, defaultFormat): + # Get the complete style after applying any relevant defaults. + if len(self.format)==5: # It is a default one + fmt = self.format + defaultFormat[5:] + else: + fmt = self.format + flags = win32con.CFM_BOLD | win32con.CFM_CHARSET | win32con.CFM_COLOR | win32con.CFM_FACE | win32con.CFM_ITALIC | win32con.CFM_SIZE + return (flags,) + fmt[1:] + +# The Formatter interface +# used primarily when the actual formatting is done by Scintilla! +class FormatterBase: + def __init__(self, scintilla): + self.scintilla = scintilla + self.baseFormatFixed = (-402653169, 0, 200, 0, 0, 0, 49, 'Courier New') + self.baseFormatProp = (-402653169, 0, 200, 0, 0, 0, 49, 'Arial') + self.bUseFixed = 1 + self.styles = {} # Indexed by name + self.styles_by_id = {} # Indexed by allocated ID. + self.SetStyles() + + def HookFormatter(self, parent = None): + raise NotImplementedError() + + # Used by the IDLE extensions to quickly determine if a character is a string. + def GetStringStyle(self, pos): + try: + style = self.styles_by_id[self.scintilla.SCIGetStyleAt(pos)] + except KeyError: + # A style we dont know about - probably not even a .py file - can't be a string + return None + if style.name in self.string_style_names: + return style + return None + + def RegisterStyle(self, style, stylenum): + assert stylenum is not None, "We must have a style number" + assert style.stylenum is None, "Style has already been registered" + assert stylenum not in self.styles, "We are reusing a style number!" + style.stylenum = stylenum + self.styles[style.name] = style + self.styles_by_id[stylenum] = style + + def SetStyles(self): + raise NotImplementedError() + + def GetSampleText(self): + return "Sample Text for the Format Dialog" + + def GetDefaultFormat(self): + if self.bUseFixed: + return self.baseFormatFixed + return self.baseFormatProp + + # Update the control with the new style format. + def _ReformatStyle(self, style): + ## Selection (background only for now) + ## Passing False for WPARAM to SCI_SETSELBACK is documented as resetting to scintilla default, + ## but does not work - selection background is not visible at all. + ## Default value in SPECIAL_STYLES taken from scintilla source. + if style.name == STYLE_SELECTION: + clr = style.background + self.scintilla.SendScintilla(scintillacon.SCI_SETSELBACK, True, clr) + + ## Can't change font for selection, but could set color + ## However, the font color dropbox has no option for default, and thus would + ## always override syntax coloring + ## clr = style.format[4] + ## self.scintilla.SendScintilla(scintillacon.SCI_SETSELFORE, clr != CLR_INVALID, clr) + return + + assert style.stylenum is not None, "Unregistered style." + #print "Reformat style", style.name, style.stylenum + scintilla=self.scintilla + stylenum = style.stylenum + # Now we have the style number, indirect for the actual style. + if style.aliased is not None: + style = self.styles[style.aliased] + f=style.format + if style.IsBasedOnDefault(): + baseFormat = self.GetDefaultFormat() + else: baseFormat = f + scintilla.SCIStyleSetFore(stylenum, f[4]) + scintilla.SCIStyleSetFont(stylenum, baseFormat[7], baseFormat[5]) + if f[1] & 1: scintilla.SCIStyleSetBold(stylenum, 1) + else: scintilla.SCIStyleSetBold(stylenum, 0) + if f[1] & 2: scintilla.SCIStyleSetItalic(stylenum, 1) + else: scintilla.SCIStyleSetItalic(stylenum, 0) + scintilla.SCIStyleSetSize(stylenum, int(baseFormat[2]/20)) + scintilla.SCIStyleSetEOLFilled(stylenum, 1) # Only needed for unclosed strings. + + ## Default style background to whitespace background if set, + ## otherwise use system window color + bg = style.background + if bg == CLR_INVALID: + bg = self.styles[STYLE_DEFAULT].background + if bg == CLR_INVALID: + bg = win32api.GetSysColor(win32con.COLOR_WINDOW) + scintilla.SCIStyleSetBack(stylenum, bg) + + + + def GetStyleByNum(self, stylenum): + return self.styles_by_id[stylenum] + + def ApplyFormattingStyles(self, bReload=1): + if bReload: + self.LoadPreferences() + baseFormat = self.GetDefaultFormat() + defaultStyle = Style("default", baseFormat) + defaultStyle.stylenum = scintillacon.STYLE_DEFAULT + self._ReformatStyle(defaultStyle) + for style in list(self.styles.values()): + if style.aliased is None: + style.NormalizeAgainstDefault(baseFormat) + self._ReformatStyle(style) + self.scintilla.InvalidateRect() + + # Some functions for loading and saving preferences. By default + # an INI file (well, MFC maps this to the registry) is used. + def LoadPreferences(self): + self.baseFormatFixed = eval(self.LoadPreference("Base Format Fixed", str(self.baseFormatFixed))) + self.baseFormatProp = eval(self.LoadPreference("Base Format Proportional", str(self.baseFormatProp))) + self.bUseFixed = int(self.LoadPreference("Use Fixed", 1)) + + for style in list(self.styles.values()): + new = self.LoadPreference(style.name, str(style.format)) + try: + style.format = eval(new) + except: + print("Error loading style data for", style.name) + # Use "vanilla" background hardcoded in PYTHON_STYLES if no settings in registry + style.background = int(self.LoadPreference(style.name + " background", style.default_background)) + + def LoadPreference(self, name, default): + return win32ui.GetProfileVal("Format", name, default) + + def SavePreferences(self): + self.SavePreference("Base Format Fixed", str(self.baseFormatFixed)) + self.SavePreference("Base Format Proportional", str(self.baseFormatProp)) + self.SavePreference("Use Fixed", self.bUseFixed) + for style in list(self.styles.values()): + if style.aliased is None: + self.SavePreference(style.name, str(style.format)) + bg_name = style.name + " background" + self.SavePreference(bg_name, style.background) + + def SavePreference(self, name, value): + win32ui.WriteProfileVal("Format", name, value) + +# An abstract formatter +# For all formatters we actually implement here. +# (as opposed to those formatters built in to Scintilla) +class Formatter(FormatterBase): + def __init__(self, scintilla): + self.bCompleteWhileIdle = 0 + self.bHaveIdleHandler = 0 # Dont currently have an idle handle + self.nextstylenum = 0 + FormatterBase.__init__(self, scintilla) + + def HookFormatter(self, parent = None): + if parent is None: parent = self.scintilla.GetParent() # was GetParentFrame()!? + parent.HookNotify(self.OnStyleNeeded, scintillacon.SCN_STYLENEEDED) + + def OnStyleNeeded(self, std, extra): + notify = self.scintilla.SCIUnpackNotifyMessage(extra) + endStyledChar = self.scintilla.SendScintilla(scintillacon.SCI_GETENDSTYLED) + lineEndStyled = self.scintilla.LineFromChar(endStyledChar) + endStyled = self.scintilla.LineIndex(lineEndStyled) + #print "enPosPaint %d endStyledChar %d lineEndStyled %d endStyled %d" % (endPosPaint, endStyledChar, lineEndStyled, endStyled) + self.Colorize(endStyled, notify.position) + + def ColorSeg(self, start, end, styleName): + end = end+1 +# assert end-start>=0, "Can't have negative styling" + stylenum = self.styles[styleName].stylenum + while start 0: + stylenum = scintilla.SCIGetStyleAt(start - 1) + styleStart = self.GetStyleByNum(stylenum).name + else: + styleStart = None +# trace("Coloring", start, end, end-start, len(stringVal), styleStart, self.scintilla.SCIGetCharAt(start)) + scintilla.SCIStartStyling(start, 31) + self.style_buffer = array.array("b", (0,)*len(stringVal)) + self.ColorizeString(stringVal, styleStart) + scintilla.SCISetStylingEx(self.style_buffer) + self.style_buffer = None +# trace("After styling, end styled is", self.scintilla.SCIGetEndStyled()) + if self.bCompleteWhileIdle and not self.bHaveIdleHandler and end!=-1 and end < scintilla.GetTextLength(): + self.bHaveIdleHandler = 1 + win32ui.GetApp().AddIdleHandler(self.DoMoreColoring) + # Kicking idle makes the app seem slower when initially repainting! +# win32ui.GetMainFrame().PostMessage(WM_KICKIDLE, 0, 0) + + def DoMoreColoring(self, handler, count): + try: + scintilla = self.scintilla + endStyled = scintilla.SCIGetEndStyled() + lineStartStyled = scintilla.LineFromChar(endStyled) + start = scintilla.LineIndex(lineStartStyled) + end = scintilla.LineIndex(lineStartStyled+1) + textlen = scintilla.GetTextLength() + if end < 0: end = textlen + + finished = end >= textlen + self.Colorize(start, end) + except (win32ui.error, AttributeError): + # Window may have closed before we finished - no big deal! + finished = 1 + + if finished: + self.bHaveIdleHandler = 0 + win32ui.GetApp().DeleteIdleHandler(handler) + return not finished + +# A Formatter that knows how to format Python source +from keyword import iskeyword, kwlist + +wordstarts = '_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' +wordchars = '._0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' +operators = '%^&*()-+=|{}[]:;<>,/?!.~' + +STYLE_DEFAULT = "Whitespace" +STYLE_COMMENT = "Comment" +STYLE_COMMENT_BLOCK = "Comment Blocks" +STYLE_NUMBER = "Number" +STYLE_STRING = "String" +STYLE_SQSTRING = "SQ String" +STYLE_TQSSTRING = "TQS String" +STYLE_TQDSTRING = "TQD String" +STYLE_KEYWORD = "Keyword" +STYLE_CLASS = "Class" +STYLE_METHOD = "Method" +STYLE_OPERATOR = "Operator" +STYLE_IDENTIFIER = "Identifier" +STYLE_BRACE = "Brace/Paren - matching" +STYLE_BRACEBAD = "Brace/Paren - unmatched" +STYLE_STRINGEOL = "String with no terminator" +STYLE_LINENUMBER = "Line numbers" +STYLE_INDENTGUIDE = "Indent guide" +STYLE_SELECTION = "Selection" + +STRING_STYLES = [STYLE_STRING, STYLE_SQSTRING, STYLE_TQSSTRING, STYLE_TQDSTRING, STYLE_STRINGEOL] + +# These styles can have any ID - they are not special to scintilla itself. +# However, if we use the built-in lexer, then we must use its style numbers +# so in that case, they _are_ special. +# (name, format, background, scintilla id) +PYTHON_STYLES = [ + (STYLE_DEFAULT, (0, 0, 200, 0, 0x808080), CLR_INVALID, scintillacon.SCE_P_DEFAULT ), + (STYLE_COMMENT, (0, 2, 200, 0, 0x008000), CLR_INVALID, scintillacon.SCE_P_COMMENTLINE ), + (STYLE_COMMENT_BLOCK,(0, 2, 200, 0, 0x808080), CLR_INVALID, scintillacon.SCE_P_COMMENTBLOCK ), + (STYLE_NUMBER, (0, 0, 200, 0, 0x808000), CLR_INVALID, scintillacon.SCE_P_NUMBER ), + (STYLE_STRING, (0, 0, 200, 0, 0x008080), CLR_INVALID, scintillacon.SCE_P_STRING ), + (STYLE_SQSTRING, STYLE_STRING, CLR_INVALID, scintillacon.SCE_P_CHARACTER ), + (STYLE_TQSSTRING, STYLE_STRING, CLR_INVALID, scintillacon.SCE_P_TRIPLE ), + (STYLE_TQDSTRING, STYLE_STRING, CLR_INVALID, scintillacon.SCE_P_TRIPLEDOUBLE), + (STYLE_STRINGEOL, (0, 0, 200, 0, 0x000000), 0x008080, scintillacon.SCE_P_STRINGEOL), + (STYLE_KEYWORD, (0, 1, 200, 0, 0x800000), CLR_INVALID, scintillacon.SCE_P_WORD), + (STYLE_CLASS, (0, 1, 200, 0, 0xFF0000), CLR_INVALID, scintillacon.SCE_P_CLASSNAME ), + (STYLE_METHOD, (0, 1, 200, 0, 0x808000), CLR_INVALID, scintillacon.SCE_P_DEFNAME), + (STYLE_OPERATOR, (0, 0, 200, 0, 0x000000), CLR_INVALID, scintillacon.SCE_P_OPERATOR), + (STYLE_IDENTIFIER, (0, 0, 200, 0, 0x000000), CLR_INVALID, scintillacon.SCE_P_IDENTIFIER ), +] + +# These styles _always_ have this specific style number, regardless of +# internal or external formatter. +SPECIAL_STYLES = [ + (STYLE_BRACE, (0, 0, 200, 0, 0x000000), 0xffff80, scintillacon.STYLE_BRACELIGHT), + (STYLE_BRACEBAD, (0, 0, 200, 0, 0x000000), 0x8ea5f2, scintillacon.STYLE_BRACEBAD), + (STYLE_LINENUMBER, (0, 0, 200, 0, 0x000000), win32api.GetSysColor(win32con.COLOR_3DFACE), scintillacon.STYLE_LINENUMBER), + (STYLE_INDENTGUIDE, (0, 0, 200, 0, 0x000000), CLR_INVALID, scintillacon.STYLE_INDENTGUIDE), + ## Not actually a style; requires special handling to send appropriate messages to scintilla + (STYLE_SELECTION, (0, 0, 200, 0, CLR_INVALID), win32api.RGB(0xc0, 0xc0, 0xc0), 999999), +] + +PythonSampleCode = """\ +# Some Python +class Sample(Super): + def Fn(self): +\tself.v = 1024 +dest = 'dest.html' +x = func(a + 1)|) +s = "I forget... +## A large +## comment block""" + +class PythonSourceFormatter(Formatter): + string_style_names = STRING_STYLES + def GetSampleText(self): + return PythonSampleCode + + def LoadStyles(self): + pass + + def SetStyles(self): + for name, format, bg, ignore in PYTHON_STYLES: + self.RegisterStyle( Style(name, format, bg) ) + for name, format, bg, sc_id in SPECIAL_STYLES: + self.RegisterStyle( Style(name, format, bg), sc_id ) + + def ClassifyWord(self, cdoc, start, end, prevWord): + word = cdoc[start:end+1].decode('latin-1') + attr = STYLE_IDENTIFIER + if prevWord == "class": + attr = STYLE_CLASS + elif prevWord == "def": + attr = STYLE_METHOD + elif word[0] in string.digits: + attr = STYLE_NUMBER + elif iskeyword(word): + attr = STYLE_KEYWORD + self.ColorSeg(start, end, attr) + return word + + def ColorizeString(self, str, styleStart): + if styleStart is None: styleStart = STYLE_DEFAULT + return self.ColorizePythonCode(str, 0, styleStart) + + def ColorizePythonCode(self, cdoc, charStart, styleStart): + # Straight translation of C++, should do better + lengthDoc = len(cdoc) + if lengthDoc <= charStart: return + prevWord = "" + state = styleStart + chPrev = chPrev2 = chPrev3 = ' ' + chNext2 = chNext = cdoc[charStart:charStart+1].decode('latin-1') + startSeg = i = charStart + while i < lengthDoc: + ch = chNext + chNext = ' ' + if i+1 < lengthDoc: chNext = cdoc[i+1:i+2].decode('latin-1') + chNext2 = ' ' + if i+2 < lengthDoc: chNext2 = cdoc[i+2:i+3].decode('latin-1') + if state == STYLE_DEFAULT: + if ch in wordstarts: + self.ColorSeg(startSeg, i - 1, STYLE_DEFAULT) + state = STYLE_KEYWORD + startSeg = i + elif ch == '#': + self.ColorSeg(startSeg, i - 1, STYLE_DEFAULT) + if chNext == '#': + state = STYLE_COMMENT_BLOCK + else: + state = STYLE_COMMENT + startSeg = i + elif ch == '\"': + self.ColorSeg(startSeg, i - 1, STYLE_DEFAULT) + startSeg = i + state = STYLE_COMMENT + if chNext == '\"' and chNext2 == '\"': + i = i + 2 + state = STYLE_TQDSTRING + ch = ' ' + chPrev = ' ' + chNext = ' ' + if i+1 < lengthDoc: chNext = cdoc[i+1] + else: + state = STYLE_STRING + elif ch == '\'': + self.ColorSeg(startSeg, i - 1, STYLE_DEFAULT) + startSeg = i + state = STYLE_COMMENT + if chNext == '\'' and chNext2 == '\'': + i = i + 2 + state = STYLE_TQSSTRING + ch = ' ' + chPrev = ' ' + chNext = ' ' + if i+1 < lengthDoc: chNext = cdoc[i+1] + else: + state = STYLE_SQSTRING + elif ch in operators: + self.ColorSeg(startSeg, i - 1, STYLE_DEFAULT) + self.ColorSeg(i, i, STYLE_OPERATOR) + startSeg = i+1 + elif state == STYLE_KEYWORD: + if ch not in wordchars: + prevWord = self.ClassifyWord(cdoc, startSeg, i-1, prevWord) + state = STYLE_DEFAULT + startSeg = i + if ch == '#': + if chNext == '#': + state = STYLE_COMMENT_BLOCK + else: + state = STYLE_COMMENT + elif ch == '\"': + if chNext == '\"' and chNext2 == '\"': + i = i + 2 + state = STYLE_TQDSTRING + ch = ' ' + chPrev = ' ' + chNext = ' ' + if i+1 < lengthDoc: chNext = cdoc[i+1] + else: + state = STYLE_STRING + elif ch == '\'': + if chNext == '\'' and chNext2 == '\'': + i = i + 2 + state = STYLE_TQSSTRING + ch = ' ' + chPrev = ' ' + chNext = ' ' + if i+1 < lengthDoc: chNext = cdoc[i+1] + else: + state = STYLE_SQSTRING + elif ch in operators: + self.ColorSeg(startSeg, i, STYLE_OPERATOR) + startSeg = i+1 + elif state == STYLE_COMMENT or state == STYLE_COMMENT_BLOCK: + if ch == '\r' or ch == '\n': + self.ColorSeg(startSeg, i-1, state) + state = STYLE_DEFAULT + startSeg = i + elif state == STYLE_STRING: + if ch == '\\': + if chNext == '\"' or chNext == '\'' or chNext == '\\': + i = i + 1 + ch = chNext + chNext = ' ' + if i+1 < lengthDoc: chNext = cdoc[i+1] + elif ch == '\"': + self.ColorSeg(startSeg, i, STYLE_STRING) + state = STYLE_DEFAULT + startSeg = i+1 + elif state == STYLE_SQSTRING: + if ch == '\\': + if chNext == '\"' or chNext == '\'' or chNext == '\\': + i = i+1 + ch = chNext + chNext = ' ' + if i+1 < lengthDoc: chNext = cdoc[i+1] + elif ch == '\'': + self.ColorSeg(startSeg, i, STYLE_SQSTRING) + state = STYLE_DEFAULT + startSeg = i+1 + elif state == STYLE_TQSSTRING: + if ch == '\'' and chPrev == '\'' and chPrev2 == '\'' and chPrev3 != '\\': + self.ColorSeg(startSeg, i, STYLE_TQSSTRING) + state = STYLE_DEFAULT + startSeg = i+1 + elif state == STYLE_TQDSTRING and ch == '\"' and chPrev == '\"' and chPrev2 == '\"' and chPrev3 != '\\': + self.ColorSeg(startSeg, i, STYLE_TQDSTRING) + state = STYLE_DEFAULT + startSeg = i+1 + chPrev3 = chPrev2 + chPrev2 = chPrev + chPrev = ch + i = i + 1 + if startSeg < lengthDoc: + if state == STYLE_KEYWORD: + self.ClassifyWord(cdoc, startSeg, lengthDoc-1, prevWord) + else: + self.ColorSeg(startSeg, lengthDoc-1, state) + + +# These taken from the SciTE properties file. +source_formatter_extensions = [ + ( ".py .pys .pyw".split(), scintillacon.SCLEX_PYTHON ), + ( ".html .htm .asp .shtml".split(), scintillacon.SCLEX_HTML ), + ( "c .cc .cpp .cxx .h .hh .hpp .hxx .idl .odl .php3 .phtml .inc .js".split(), scintillacon.SCLEX_CPP ), + ( ".vbs .frm .ctl .cls".split(), scintillacon.SCLEX_VB ), + ( ".pl .pm .cgi .pod".split(), scintillacon.SCLEX_PERL ), + ( ".sql .spec .body .sps .spb .sf .sp".split(), scintillacon.SCLEX_SQL ), + ( ".tex .sty".split(), scintillacon.SCLEX_LATEX ), + ( ".xml .xul".split(), scintillacon.SCLEX_XML ), + ( ".err".split(), scintillacon.SCLEX_ERRORLIST ), + ( ".mak".split(), scintillacon.SCLEX_MAKEFILE ), + ( ".bat .cmd".split(), scintillacon.SCLEX_BATCH ), +] + +class BuiltinSourceFormatter(FormatterBase): + # A class that represents a formatter built-in to Scintilla + def __init__(self, scintilla, ext): + self.ext = ext + FormatterBase.__init__(self, scintilla) + + def Colorize(self, start=0, end=-1): + self.scintilla.SendScintilla(scintillacon.SCI_COLOURISE, start, end) + def RegisterStyle(self, style, stylenum = None): + assert style.stylenum is None, "Style has already been registered" + if stylenum is None: + stylenum = self.nextstylenum + self.nextstylenum = self.nextstylenum + 1 + assert self.styles.get(stylenum) is None, "We are reusing a style number!" + style.stylenum = stylenum + self.styles[style.name] = style + self.styles_by_id[stylenum] = style + + def HookFormatter(self, parent = None): + sc = self.scintilla + for exts, formatter in source_formatter_extensions: + if self.ext in exts: + formatter_use = formatter + break + else: + formatter_use = scintillacon.SCLEX_PYTHON + sc.SendScintilla(scintillacon.SCI_SETLEXER, formatter_use) + keywords = ' '.join(kwlist) + sc.SCISetKeywords(keywords) + +class BuiltinPythonSourceFormatter(BuiltinSourceFormatter): + sci_lexer_name = scintillacon.SCLEX_PYTHON + string_style_names = STRING_STYLES + def __init__(self, sc, ext = ".py"): + BuiltinSourceFormatter.__init__(self, sc, ext) + def SetStyles(self): + for name, format, bg, sc_id in PYTHON_STYLES: + self.RegisterStyle( Style(name, format, bg), sc_id ) + for name, format, bg, sc_id in SPECIAL_STYLES: + self.RegisterStyle( Style(name, format, bg), sc_id ) + def GetSampleText(self): + return PythonSampleCode diff --git a/Lib/site-packages/pythonwin/pywin/scintilla/keycodes.py b/Lib/site-packages/pythonwin/pywin/scintilla/keycodes.py new file mode 100644 index 0000000..7434beb --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/scintilla/keycodes.py @@ -0,0 +1,177 @@ +import string +import win32con +import win32api +import win32ui + +MAPVK_VK_TO_CHAR = 2 + +key_name_to_vk = {} +key_code_to_name = {} + +_better_names = { + "escape": "esc", + "return": "enter", + "back": "pgup", + "next": "pgdn", +} + +def _fillvkmap(): + # Pull the VK_names from win32con + names = [entry for entry in win32con.__dict__ if entry.startswith("VK_")] + for name in names: + code = getattr(win32con, name) + n = name[3:].lower() + key_name_to_vk[n] = code + if n in _better_names: + n = _better_names[n] + key_name_to_vk[n] = code + key_code_to_name[code] = n + + +_fillvkmap() + +def get_vk(chardesc): + if len(chardesc)==1: + # it is a character. + info = win32api.VkKeyScan(chardesc) + if info==-1: + return None, None + vk = win32api.LOBYTE(info) + state = win32api.HIBYTE(info) + modifiers = 0 + if state & 0x1: + modifiers |= win32con.SHIFT_PRESSED + if state & 0x2: + modifiers |= win32con.LEFT_CTRL_PRESSED | win32con.RIGHT_CTRL_PRESSED + if state & 0x4: + modifiers |= win32con.LEFT_ALT_PRESSED | win32con.RIGHT_ALT_PRESSED + return vk, modifiers + # must be a 'key name' + return key_name_to_vk.get(chardesc.lower()), 0 + +modifiers = { + "alt" : win32con.LEFT_ALT_PRESSED | win32con.RIGHT_ALT_PRESSED, + "lalt" : win32con.LEFT_ALT_PRESSED, + "ralt" : win32con.RIGHT_ALT_PRESSED, + "ctrl" : win32con.LEFT_CTRL_PRESSED | win32con.RIGHT_CTRL_PRESSED, + "ctl" : win32con.LEFT_CTRL_PRESSED | win32con.RIGHT_CTRL_PRESSED, + "control" : win32con.LEFT_CTRL_PRESSED | win32con.RIGHT_CTRL_PRESSED, + "lctrl" : win32con.LEFT_CTRL_PRESSED, + "lctl" : win32con.LEFT_CTRL_PRESSED, + "rctrl" : win32con.RIGHT_CTRL_PRESSED, + "rctl" : win32con.RIGHT_CTRL_PRESSED, + "shift" : win32con.SHIFT_PRESSED, + "key" : 0, # ignore key tag. +} + +def parse_key_name(name): + name = name + "-" # Add a sentinal + start = pos = 0 + max = len(name) + toks = [] + while pos") + else: + try: + parts.append(key_code_to_name[vk]) + except KeyError: + # Not in our virtual key map - ask Windows what character this + # key corresponds to. + scancode = win32api.MapVirtualKey(vk, MAPVK_VK_TO_CHAR) + parts.append(chr(scancode)) + sep = "+" + if sep in parts: sep = "-" + return sep.join([p.capitalize() for p in parts]) + +def _psc(char): + sc, mods = get_vk(char) + print("Char %s -> %d -> %s" % (repr(char), sc, key_code_to_name.get(sc))) + +def test1(): + for ch in """aA0/?[{}];:'"`~_-+=\\|,<.>/?""": + _psc(ch) + for code in ["Home", "End", "Left", "Right", "Up", "Down", "Menu", "Next"]: + _psc(code) + +def _pkn(n): + vk, flags = parse_key_name(n) + print("%s -> %s,%s -> %s" % (n, vk, flags, make_key_name(vk, flags))) + +def test2(): + _pkn("ctrl+alt-shift+x") + _pkn("ctrl-home") + _pkn("Shift-+") + _pkn("Shift--") + _pkn("Shift+-") + _pkn("Shift++") + _pkn("LShift-+") + _pkn("ctl+home") + _pkn("ctl+enter") + _pkn("alt+return") + _pkn("Alt+/") + _pkn("Alt+BadKeyName") + _pkn("A") # an ascii char - should be seen as 'a' + _pkn("a") + _pkn("Shift-A") + _pkn("Shift-a") + _pkn("a") + _pkn("(") + _pkn("Ctrl+(") + _pkn("Ctrl+Shift-8") + _pkn("Ctrl+*") + _pkn("{") + _pkn("!") + _pkn(".") + +if __name__=='__main__': + test2() diff --git a/Lib/site-packages/pythonwin/pywin/scintilla/scintillacon.py b/Lib/site-packages/pythonwin/pywin/scintilla/scintillacon.py new file mode 100644 index 0000000..ae64105 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/scintilla/scintillacon.py @@ -0,0 +1,1992 @@ +# Generated by h2py from Include\scintilla.h + +# Included from BaseTsd.h +def HandleToUlong(h): return HandleToULong(h) + +def UlongToHandle(ul): return ULongToHandle(ul) + +def UlongToPtr(ul): return ULongToPtr(ul) + +def UintToPtr(ui): return UIntToPtr(ui) + +INVALID_POSITION = -1 +SCI_START = 2000 +SCI_OPTIONAL_START = 3000 +SCI_LEXER_START = 4000 +SCI_ADDTEXT = 2001 +SCI_ADDSTYLEDTEXT = 2002 +SCI_INSERTTEXT = 2003 +SCI_CLEARALL = 2004 +SCI_CLEARDOCUMENTSTYLE = 2005 +SCI_GETLENGTH = 2006 +SCI_GETCHARAT = 2007 +SCI_GETCURRENTPOS = 2008 +SCI_GETANCHOR = 2009 +SCI_GETSTYLEAT = 2010 +SCI_REDO = 2011 +SCI_SETUNDOCOLLECTION = 2012 +SCI_SELECTALL = 2013 +SCI_SETSAVEPOINT = 2014 +SCI_GETSTYLEDTEXT = 2015 +SCI_CANREDO = 2016 +SCI_MARKERLINEFROMHANDLE = 2017 +SCI_MARKERDELETEHANDLE = 2018 +SCI_GETUNDOCOLLECTION = 2019 +SCWS_INVISIBLE = 0 +SCWS_VISIBLEALWAYS = 1 +SCWS_VISIBLEAFTERINDENT = 2 +SCI_GETVIEWWS = 2020 +SCI_SETVIEWWS = 2021 +SCI_POSITIONFROMPOINT = 2022 +SCI_POSITIONFROMPOINTCLOSE = 2023 +SCI_GOTOLINE = 2024 +SCI_GOTOPOS = 2025 +SCI_SETANCHOR = 2026 +SCI_GETCURLINE = 2027 +SCI_GETENDSTYLED = 2028 +SC_EOL_CRLF = 0 +SC_EOL_CR = 1 +SC_EOL_LF = 2 +SCI_CONVERTEOLS = 2029 +SCI_GETEOLMODE = 2030 +SCI_SETEOLMODE = 2031 +SCI_STARTSTYLING = 2032 +SCI_SETSTYLING = 2033 +SCI_GETBUFFEREDDRAW = 2034 +SCI_SETBUFFEREDDRAW = 2035 +SCI_SETTABWIDTH = 2036 +SCI_GETTABWIDTH = 2121 +SC_CP_UTF8 = 65001 +SC_CP_DBCS = 1 +SCI_SETCODEPAGE = 2037 +SCI_SETUSEPALETTE = 2039 +MARKER_MAX = 31 +SC_MARK_CIRCLE = 0 +SC_MARK_ROUNDRECT = 1 +SC_MARK_ARROW = 2 +SC_MARK_SMALLRECT = 3 +SC_MARK_SHORTARROW = 4 +SC_MARK_EMPTY = 5 +SC_MARK_ARROWDOWN = 6 +SC_MARK_MINUS = 7 +SC_MARK_PLUS = 8 +SC_MARK_VLINE = 9 +SC_MARK_LCORNER = 10 +SC_MARK_TCORNER = 11 +SC_MARK_BOXPLUS = 12 +SC_MARK_BOXPLUSCONNECTED = 13 +SC_MARK_BOXMINUS = 14 +SC_MARK_BOXMINUSCONNECTED = 15 +SC_MARK_LCORNERCURVE = 16 +SC_MARK_TCORNERCURVE = 17 +SC_MARK_CIRCLEPLUS = 18 +SC_MARK_CIRCLEPLUSCONNECTED = 19 +SC_MARK_CIRCLEMINUS = 20 +SC_MARK_CIRCLEMINUSCONNECTED = 21 +SC_MARK_BACKGROUND = 22 +SC_MARK_DOTDOTDOT = 23 +SC_MARK_ARROWS = 24 +SC_MARK_PIXMAP = 25 +SC_MARK_FULLRECT = 26 +SC_MARK_LEFTRECT = 27 +SC_MARK_CHARACTER = 10000 +SC_MARKNUM_FOLDEREND = 25 +SC_MARKNUM_FOLDEROPENMID = 26 +SC_MARKNUM_FOLDERMIDTAIL = 27 +SC_MARKNUM_FOLDERTAIL = 28 +SC_MARKNUM_FOLDERSUB = 29 +SC_MARKNUM_FOLDER = 30 +SC_MARKNUM_FOLDEROPEN = 31 +SC_MASK_FOLDERS = (-33554432) +SCI_MARKERDEFINE = 2040 +SCI_MARKERSETFORE = 2041 +SCI_MARKERSETBACK = 2042 +SCI_MARKERADD = 2043 +SCI_MARKERDELETE = 2044 +SCI_MARKERDELETEALL = 2045 +SCI_MARKERGET = 2046 +SCI_MARKERNEXT = 2047 +SCI_MARKERPREVIOUS = 2048 +SCI_MARKERDEFINEPIXMAP = 2049 +SCI_MARKERADDSET = 2466 +SCI_MARKERSETALPHA = 2476 +SC_MARGIN_SYMBOL = 0 +SC_MARGIN_NUMBER = 1 +SC_MARGIN_BACK = 2 +SC_MARGIN_FORE = 3 +SCI_SETMARGINTYPEN = 2240 +SCI_GETMARGINTYPEN = 2241 +SCI_SETMARGINWIDTHN = 2242 +SCI_GETMARGINWIDTHN = 2243 +SCI_SETMARGINMASKN = 2244 +SCI_GETMARGINMASKN = 2245 +SCI_SETMARGINSENSITIVEN = 2246 +SCI_GETMARGINSENSITIVEN = 2247 +STYLE_DEFAULT = 32 +STYLE_LINENUMBER = 33 +STYLE_BRACELIGHT = 34 +STYLE_BRACEBAD = 35 +STYLE_CONTROLCHAR = 36 +STYLE_INDENTGUIDE = 37 +STYLE_CALLTIP = 38 +STYLE_LASTPREDEFINED = 39 +STYLE_MAX = 255 +SC_CHARSET_ANSI = 0 +SC_CHARSET_DEFAULT = 1 +SC_CHARSET_BALTIC = 186 +SC_CHARSET_CHINESEBIG5 = 136 +SC_CHARSET_EASTEUROPE = 238 +SC_CHARSET_GB2312 = 134 +SC_CHARSET_GREEK = 161 +SC_CHARSET_HANGUL = 129 +SC_CHARSET_MAC = 77 +SC_CHARSET_OEM = 255 +SC_CHARSET_RUSSIAN = 204 +SC_CHARSET_CYRILLIC = 1251 +SC_CHARSET_SHIFTJIS = 128 +SC_CHARSET_SYMBOL = 2 +SC_CHARSET_TURKISH = 162 +SC_CHARSET_JOHAB = 130 +SC_CHARSET_HEBREW = 177 +SC_CHARSET_ARABIC = 178 +SC_CHARSET_VIETNAMESE = 163 +SC_CHARSET_THAI = 222 +SC_CHARSET_8859_15 = 1000 +SCI_STYLECLEARALL = 2050 +SCI_STYLESETFORE = 2051 +SCI_STYLESETBACK = 2052 +SCI_STYLESETBOLD = 2053 +SCI_STYLESETITALIC = 2054 +SCI_STYLESETSIZE = 2055 +SCI_STYLESETFONT = 2056 +SCI_STYLESETEOLFILLED = 2057 +SCI_STYLERESETDEFAULT = 2058 +SCI_STYLESETUNDERLINE = 2059 +SC_CASE_MIXED = 0 +SC_CASE_UPPER = 1 +SC_CASE_LOWER = 2 +SCI_STYLEGETFORE = 2481 +SCI_STYLEGETBACK = 2482 +SCI_STYLEGETBOLD = 2483 +SCI_STYLEGETITALIC = 2484 +SCI_STYLEGETSIZE = 2485 +SCI_STYLEGETFONT = 2486 +SCI_STYLEGETEOLFILLED = 2487 +SCI_STYLEGETUNDERLINE = 2488 +SCI_STYLEGETCASE = 2489 +SCI_STYLEGETCHARACTERSET = 2490 +SCI_STYLEGETVISIBLE = 2491 +SCI_STYLEGETCHANGEABLE = 2492 +SCI_STYLEGETHOTSPOT = 2493 +SCI_STYLESETCASE = 2060 +SCI_STYLESETCHARACTERSET = 2066 +SCI_STYLESETHOTSPOT = 2409 +SCI_SETSELFORE = 2067 +SCI_SETSELBACK = 2068 +SCI_GETSELALPHA = 2477 +SCI_SETSELALPHA = 2478 +SCI_GETSELEOLFILLED = 2479 +SCI_SETSELEOLFILLED = 2480 +SCI_SETCARETFORE = 2069 +SCI_ASSIGNCMDKEY = 2070 +SCI_CLEARCMDKEY = 2071 +SCI_CLEARALLCMDKEYS = 2072 +SCI_SETSTYLINGEX = 2073 +SCI_STYLESETVISIBLE = 2074 +SCI_GETCARETPERIOD = 2075 +SCI_SETCARETPERIOD = 2076 +SCI_SETWORDCHARS = 2077 +SCI_BEGINUNDOACTION = 2078 +SCI_ENDUNDOACTION = 2079 +INDIC_PLAIN = 0 +INDIC_SQUIGGLE = 1 +INDIC_TT = 2 +INDIC_DIAGONAL = 3 +INDIC_STRIKE = 4 +INDIC_HIDDEN = 5 +INDIC_BOX = 6 +INDIC_ROUNDBOX = 7 +INDIC_MAX = 31 +INDIC_CONTAINER = 8 +INDIC0_MASK = 0x20 +INDIC1_MASK = 0x40 +INDIC2_MASK = 0x80 +INDICS_MASK = 0xE0 +SCI_INDICSETSTYLE = 2080 +SCI_INDICGETSTYLE = 2081 +SCI_INDICSETFORE = 2082 +SCI_INDICGETFORE = 2083 +SCI_INDICSETUNDER = 2510 +SCI_INDICGETUNDER = 2511 +SCI_SETWHITESPACEFORE = 2084 +SCI_SETWHITESPACEBACK = 2085 +SCI_SETSTYLEBITS = 2090 +SCI_GETSTYLEBITS = 2091 +SCI_SETLINESTATE = 2092 +SCI_GETLINESTATE = 2093 +SCI_GETMAXLINESTATE = 2094 +SCI_GETCARETLINEVISIBLE = 2095 +SCI_SETCARETLINEVISIBLE = 2096 +SCI_GETCARETLINEBACK = 2097 +SCI_SETCARETLINEBACK = 2098 +SCI_STYLESETCHANGEABLE = 2099 +SCI_AUTOCSHOW = 2100 +SCI_AUTOCCANCEL = 2101 +SCI_AUTOCACTIVE = 2102 +SCI_AUTOCPOSSTART = 2103 +SCI_AUTOCCOMPLETE = 2104 +SCI_AUTOCSTOPS = 2105 +SCI_AUTOCSETSEPARATOR = 2106 +SCI_AUTOCGETSEPARATOR = 2107 +SCI_AUTOCSELECT = 2108 +SCI_AUTOCSETCANCELATSTART = 2110 +SCI_AUTOCGETCANCELATSTART = 2111 +SCI_AUTOCSETFILLUPS = 2112 +SCI_AUTOCSETCHOOSESINGLE = 2113 +SCI_AUTOCGETCHOOSESINGLE = 2114 +SCI_AUTOCSETIGNORECASE = 2115 +SCI_AUTOCGETIGNORECASE = 2116 +SCI_USERLISTSHOW = 2117 +SCI_AUTOCSETAUTOHIDE = 2118 +SCI_AUTOCGETAUTOHIDE = 2119 +SCI_AUTOCSETDROPRESTOFWORD = 2270 +SCI_AUTOCGETDROPRESTOFWORD = 2271 +SCI_REGISTERIMAGE = 2405 +SCI_CLEARREGISTEREDIMAGES = 2408 +SCI_AUTOCGETTYPESEPARATOR = 2285 +SCI_AUTOCSETTYPESEPARATOR = 2286 +SCI_AUTOCSETMAXWIDTH = 2208 +SCI_AUTOCGETMAXWIDTH = 2209 +SCI_AUTOCSETMAXHEIGHT = 2210 +SCI_AUTOCGETMAXHEIGHT = 2211 +SCI_SETINDENT = 2122 +SCI_GETINDENT = 2123 +SCI_SETUSETABS = 2124 +SCI_GETUSETABS = 2125 +SCI_SETLINEINDENTATION = 2126 +SCI_GETLINEINDENTATION = 2127 +SCI_GETLINEINDENTPOSITION = 2128 +SCI_GETCOLUMN = 2129 +SCI_SETHSCROLLBAR = 2130 +SCI_GETHSCROLLBAR = 2131 +SC_IV_NONE = 0 +SC_IV_REAL = 1 +SC_IV_LOOKFORWARD = 2 +SC_IV_LOOKBOTH = 3 +SCI_SETINDENTATIONGUIDES = 2132 +SCI_GETINDENTATIONGUIDES = 2133 +SCI_SETHIGHLIGHTGUIDE = 2134 +SCI_GETHIGHLIGHTGUIDE = 2135 +SCI_GETLINEENDPOSITION = 2136 +SCI_GETCODEPAGE = 2137 +SCI_GETCARETFORE = 2138 +SCI_GETUSEPALETTE = 2139 +SCI_GETREADONLY = 2140 +SCI_SETCURRENTPOS = 2141 +SCI_SETSELECTIONSTART = 2142 +SCI_GETSELECTIONSTART = 2143 +SCI_SETSELECTIONEND = 2144 +SCI_GETSELECTIONEND = 2145 +SCI_SETPRINTMAGNIFICATION = 2146 +SCI_GETPRINTMAGNIFICATION = 2147 +SC_PRINT_NORMAL = 0 +SC_PRINT_INVERTLIGHT = 1 +SC_PRINT_BLACKONWHITE = 2 +SC_PRINT_COLOURONWHITE = 3 +SC_PRINT_COLOURONWHITEDEFAULTBG = 4 +SCI_SETPRINTCOLOURMODE = 2148 +SCI_GETPRINTCOLOURMODE = 2149 +SCFIND_WHOLEWORD = 2 +SCFIND_MATCHCASE = 4 +SCFIND_WORDSTART = 0x00100000 +SCFIND_REGEXP = 0x00200000 +SCFIND_POSIX = 0x00400000 +SCI_FINDTEXT = 2150 +SCI_FORMATRANGE = 2151 +SCI_GETFIRSTVISIBLELINE = 2152 +SCI_GETLINE = 2153 +SCI_GETLINECOUNT = 2154 +SCI_SETMARGINLEFT = 2155 +SCI_GETMARGINLEFT = 2156 +SCI_SETMARGINRIGHT = 2157 +SCI_GETMARGINRIGHT = 2158 +SCI_GETMODIFY = 2159 +SCI_SETSEL = 2160 +SCI_GETSELTEXT = 2161 +SCI_GETTEXTRANGE = 2162 +SCI_HIDESELECTION = 2163 +SCI_POINTXFROMPOSITION = 2164 +SCI_POINTYFROMPOSITION = 2165 +SCI_LINEFROMPOSITION = 2166 +SCI_POSITIONFROMLINE = 2167 +SCI_LINESCROLL = 2168 +SCI_SCROLLCARET = 2169 +SCI_REPLACESEL = 2170 +SCI_SETREADONLY = 2171 +SCI_NULL = 2172 +SCI_CANPASTE = 2173 +SCI_CANUNDO = 2174 +SCI_EMPTYUNDOBUFFER = 2175 +SCI_UNDO = 2176 +SCI_CUT = 2177 +SCI_COPY = 2178 +SCI_PASTE = 2179 +SCI_CLEAR = 2180 +SCI_SETTEXT = 2181 +SCI_GETTEXT = 2182 +SCI_GETTEXTLENGTH = 2183 +SCI_GETDIRECTFUNCTION = 2184 +SCI_GETDIRECTPOINTER = 2185 +SCI_SETOVERTYPE = 2186 +SCI_GETOVERTYPE = 2187 +SCI_SETCARETWIDTH = 2188 +SCI_GETCARETWIDTH = 2189 +SCI_SETTARGETSTART = 2190 +SCI_GETTARGETSTART = 2191 +SCI_SETTARGETEND = 2192 +SCI_GETTARGETEND = 2193 +SCI_REPLACETARGET = 2194 +SCI_REPLACETARGETRE = 2195 +SCI_SEARCHINTARGET = 2197 +SCI_SETSEARCHFLAGS = 2198 +SCI_GETSEARCHFLAGS = 2199 +SCI_CALLTIPSHOW = 2200 +SCI_CALLTIPCANCEL = 2201 +SCI_CALLTIPACTIVE = 2202 +SCI_CALLTIPPOSSTART = 2203 +SCI_CALLTIPSETHLT = 2204 +SCI_CALLTIPSETBACK = 2205 +SCI_CALLTIPSETFORE = 2206 +SCI_CALLTIPSETFOREHLT = 2207 +SCI_CALLTIPUSESTYLE = 2212 +SCI_VISIBLEFROMDOCLINE = 2220 +SCI_DOCLINEFROMVISIBLE = 2221 +SCI_WRAPCOUNT = 2235 +SC_FOLDLEVELBASE = 0x400 +SC_FOLDLEVELWHITEFLAG = 0x1000 +SC_FOLDLEVELHEADERFLAG = 0x2000 +SC_FOLDLEVELBOXHEADERFLAG = 0x4000 +SC_FOLDLEVELBOXFOOTERFLAG = 0x8000 +SC_FOLDLEVELCONTRACTED = 0x10000 +SC_FOLDLEVELUNINDENT = 0x20000 +SC_FOLDLEVELNUMBERMASK = 0x0FFF +SCI_SETFOLDLEVEL = 2222 +SCI_GETFOLDLEVEL = 2223 +SCI_GETLASTCHILD = 2224 +SCI_GETFOLDPARENT = 2225 +SCI_SHOWLINES = 2226 +SCI_HIDELINES = 2227 +SCI_GETLINEVISIBLE = 2228 +SCI_SETFOLDEXPANDED = 2229 +SCI_GETFOLDEXPANDED = 2230 +SCI_TOGGLEFOLD = 2231 +SCI_ENSUREVISIBLE = 2232 +SC_FOLDFLAG_LINEBEFORE_EXPANDED = 0x0002 +SC_FOLDFLAG_LINEBEFORE_CONTRACTED = 0x0004 +SC_FOLDFLAG_LINEAFTER_EXPANDED = 0x0008 +SC_FOLDFLAG_LINEAFTER_CONTRACTED = 0x0010 +SC_FOLDFLAG_LEVELNUMBERS = 0x0040 +SC_FOLDFLAG_BOX = 0x0001 +SCI_SETFOLDFLAGS = 2233 +SCI_ENSUREVISIBLEENFORCEPOLICY = 2234 +SCI_SETTABINDENTS = 2260 +SCI_GETTABINDENTS = 2261 +SCI_SETBACKSPACEUNINDENTS = 2262 +SCI_GETBACKSPACEUNINDENTS = 2263 +SC_TIME_FOREVER = 10000000 +SCI_SETMOUSEDWELLTIME = 2264 +SCI_GETMOUSEDWELLTIME = 2265 +SCI_WORDSTARTPOSITION = 2266 +SCI_WORDENDPOSITION = 2267 +SC_WRAP_NONE = 0 +SC_WRAP_WORD = 1 +SC_WRAP_CHAR = 2 +SCI_SETWRAPMODE = 2268 +SCI_GETWRAPMODE = 2269 +SC_WRAPVISUALFLAG_NONE = 0x0000 +SC_WRAPVISUALFLAG_END = 0x0001 +SC_WRAPVISUALFLAG_START = 0x0002 +SCI_SETWRAPVISUALFLAGS = 2460 +SCI_GETWRAPVISUALFLAGS = 2461 +SC_WRAPVISUALFLAGLOC_DEFAULT = 0x0000 +SC_WRAPVISUALFLAGLOC_END_BY_TEXT = 0x0001 +SC_WRAPVISUALFLAGLOC_START_BY_TEXT = 0x0002 +SCI_SETWRAPVISUALFLAGSLOCATION = 2462 +SCI_GETWRAPVISUALFLAGSLOCATION = 2463 +SCI_SETWRAPSTARTINDENT = 2464 +SCI_GETWRAPSTARTINDENT = 2465 +SC_CACHE_NONE = 0 +SC_CACHE_CARET = 1 +SC_CACHE_PAGE = 2 +SC_CACHE_DOCUMENT = 3 +SCI_SETLAYOUTCACHE = 2272 +SCI_GETLAYOUTCACHE = 2273 +SCI_SETSCROLLWIDTH = 2274 +SCI_GETSCROLLWIDTH = 2275 +SCI_SETSCROLLWIDTHTRACKING = 2516 +SCI_GETSCROLLWIDTHTRACKING = 2517 +SCI_TEXTWIDTH = 2276 +SCI_SETENDATLASTLINE = 2277 +SCI_GETENDATLASTLINE = 2278 +SCI_TEXTHEIGHT = 2279 +SCI_SETVSCROLLBAR = 2280 +SCI_GETVSCROLLBAR = 2281 +SCI_APPENDTEXT = 2282 +SCI_GETTWOPHASEDRAW = 2283 +SCI_SETTWOPHASEDRAW = 2284 +SCI_TARGETFROMSELECTION = 2287 +SCI_LINESJOIN = 2288 +SCI_LINESSPLIT = 2289 +SCI_SETFOLDMARGINCOLOUR = 2290 +SCI_SETFOLDMARGINHICOLOUR = 2291 +SCI_LINEDOWN = 2300 +SCI_LINEDOWNEXTEND = 2301 +SCI_LINEUP = 2302 +SCI_LINEUPEXTEND = 2303 +SCI_CHARLEFT = 2304 +SCI_CHARLEFTEXTEND = 2305 +SCI_CHARRIGHT = 2306 +SCI_CHARRIGHTEXTEND = 2307 +SCI_WORDLEFT = 2308 +SCI_WORDLEFTEXTEND = 2309 +SCI_WORDRIGHT = 2310 +SCI_WORDRIGHTEXTEND = 2311 +SCI_HOME = 2312 +SCI_HOMEEXTEND = 2313 +SCI_LINEEND = 2314 +SCI_LINEENDEXTEND = 2315 +SCI_DOCUMENTSTART = 2316 +SCI_DOCUMENTSTARTEXTEND = 2317 +SCI_DOCUMENTEND = 2318 +SCI_DOCUMENTENDEXTEND = 2319 +SCI_PAGEUP = 2320 +SCI_PAGEUPEXTEND = 2321 +SCI_PAGEDOWN = 2322 +SCI_PAGEDOWNEXTEND = 2323 +SCI_EDITTOGGLEOVERTYPE = 2324 +SCI_CANCEL = 2325 +SCI_DELETEBACK = 2326 +SCI_TAB = 2327 +SCI_BACKTAB = 2328 +SCI_NEWLINE = 2329 +SCI_FORMFEED = 2330 +SCI_VCHOME = 2331 +SCI_VCHOMEEXTEND = 2332 +SCI_ZOOMIN = 2333 +SCI_ZOOMOUT = 2334 +SCI_DELWORDLEFT = 2335 +SCI_DELWORDRIGHT = 2336 +SCI_DELWORDRIGHTEND = 2518 +SCI_LINECUT = 2337 +SCI_LINEDELETE = 2338 +SCI_LINETRANSPOSE = 2339 +SCI_LINEDUPLICATE = 2404 +SCI_LOWERCASE = 2340 +SCI_UPPERCASE = 2341 +SCI_LINESCROLLDOWN = 2342 +SCI_LINESCROLLUP = 2343 +SCI_DELETEBACKNOTLINE = 2344 +SCI_HOMEDISPLAY = 2345 +SCI_HOMEDISPLAYEXTEND = 2346 +SCI_LINEENDDISPLAY = 2347 +SCI_LINEENDDISPLAYEXTEND = 2348 +SCI_HOMEWRAP = 2349 +SCI_HOMEWRAPEXTEND = 2450 +SCI_LINEENDWRAP = 2451 +SCI_LINEENDWRAPEXTEND = 2452 +SCI_VCHOMEWRAP = 2453 +SCI_VCHOMEWRAPEXTEND = 2454 +SCI_LINECOPY = 2455 +SCI_MOVECARETINSIDEVIEW = 2401 +SCI_LINELENGTH = 2350 +SCI_BRACEHIGHLIGHT = 2351 +SCI_BRACEBADLIGHT = 2352 +SCI_BRACEMATCH = 2353 +SCI_GETVIEWEOL = 2355 +SCI_SETVIEWEOL = 2356 +SCI_GETDOCPOINTER = 2357 +SCI_SETDOCPOINTER = 2358 +SCI_SETMODEVENTMASK = 2359 +EDGE_NONE = 0 +EDGE_LINE = 1 +EDGE_BACKGROUND = 2 +SCI_GETEDGECOLUMN = 2360 +SCI_SETEDGECOLUMN = 2361 +SCI_GETEDGEMODE = 2362 +SCI_SETEDGEMODE = 2363 +SCI_GETEDGECOLOUR = 2364 +SCI_SETEDGECOLOUR = 2365 +SCI_SEARCHANCHOR = 2366 +SCI_SEARCHNEXT = 2367 +SCI_SEARCHPREV = 2368 +SCI_LINESONSCREEN = 2370 +SCI_USEPOPUP = 2371 +SCI_SELECTIONISRECTANGLE = 2372 +SCI_SETZOOM = 2373 +SCI_GETZOOM = 2374 +SCI_CREATEDOCUMENT = 2375 +SCI_ADDREFDOCUMENT = 2376 +SCI_RELEASEDOCUMENT = 2377 +SCI_GETMODEVENTMASK = 2378 +SCI_SETFOCUS = 2380 +SCI_GETFOCUS = 2381 +SCI_SETSTATUS = 2382 +SCI_GETSTATUS = 2383 +SCI_SETMOUSEDOWNCAPTURES = 2384 +SCI_GETMOUSEDOWNCAPTURES = 2385 +SC_CURSORNORMAL = -1 +SC_CURSORWAIT = 4 +SCI_SETCURSOR = 2386 +SCI_GETCURSOR = 2387 +SCI_SETCONTROLCHARSYMBOL = 2388 +SCI_GETCONTROLCHARSYMBOL = 2389 +SCI_WORDPARTLEFT = 2390 +SCI_WORDPARTLEFTEXTEND = 2391 +SCI_WORDPARTRIGHT = 2392 +SCI_WORDPARTRIGHTEXTEND = 2393 +VISIBLE_SLOP = 0x01 +VISIBLE_STRICT = 0x04 +SCI_SETVISIBLEPOLICY = 2394 +SCI_DELLINELEFT = 2395 +SCI_DELLINERIGHT = 2396 +SCI_SETXOFFSET = 2397 +SCI_GETXOFFSET = 2398 +SCI_CHOOSECARETX = 2399 +SCI_GRABFOCUS = 2400 +CARET_SLOP = 0x01 +CARET_STRICT = 0x04 +CARET_JUMPS = 0x10 +CARET_EVEN = 0x08 +SCI_SETXCARETPOLICY = 2402 +SCI_SETYCARETPOLICY = 2403 +SCI_SETPRINTWRAPMODE = 2406 +SCI_GETPRINTWRAPMODE = 2407 +SCI_SETHOTSPOTACTIVEFORE = 2410 +SCI_GETHOTSPOTACTIVEFORE = 2494 +SCI_SETHOTSPOTACTIVEBACK = 2411 +SCI_GETHOTSPOTACTIVEBACK = 2495 +SCI_SETHOTSPOTACTIVEUNDERLINE = 2412 +SCI_GETHOTSPOTACTIVEUNDERLINE = 2496 +SCI_SETHOTSPOTSINGLELINE = 2421 +SCI_GETHOTSPOTSINGLELINE = 2497 +SCI_PARADOWN = 2413 +SCI_PARADOWNEXTEND = 2414 +SCI_PARAUP = 2415 +SCI_PARAUPEXTEND = 2416 +SCI_POSITIONBEFORE = 2417 +SCI_POSITIONAFTER = 2418 +SCI_COPYRANGE = 2419 +SCI_COPYTEXT = 2420 +SC_SEL_STREAM = 0 +SC_SEL_RECTANGLE = 1 +SC_SEL_LINES = 2 +SCI_SETSELECTIONMODE = 2422 +SCI_GETSELECTIONMODE = 2423 +SCI_GETLINESELSTARTPOSITION = 2424 +SCI_GETLINESELENDPOSITION = 2425 +SCI_LINEDOWNRECTEXTEND = 2426 +SCI_LINEUPRECTEXTEND = 2427 +SCI_CHARLEFTRECTEXTEND = 2428 +SCI_CHARRIGHTRECTEXTEND = 2429 +SCI_HOMERECTEXTEND = 2430 +SCI_VCHOMERECTEXTEND = 2431 +SCI_LINEENDRECTEXTEND = 2432 +SCI_PAGEUPRECTEXTEND = 2433 +SCI_PAGEDOWNRECTEXTEND = 2434 +SCI_STUTTEREDPAGEUP = 2435 +SCI_STUTTEREDPAGEUPEXTEND = 2436 +SCI_STUTTEREDPAGEDOWN = 2437 +SCI_STUTTEREDPAGEDOWNEXTEND = 2438 +SCI_WORDLEFTEND = 2439 +SCI_WORDLEFTENDEXTEND = 2440 +SCI_WORDRIGHTEND = 2441 +SCI_WORDRIGHTENDEXTEND = 2442 +SCI_SETWHITESPACECHARS = 2443 +SCI_SETCHARSDEFAULT = 2444 +SCI_AUTOCGETCURRENT = 2445 +SCI_ALLOCATE = 2446 +SCI_TARGETASUTF8 = 2447 +SCI_SETLENGTHFORENCODE = 2448 +SCI_ENCODEDFROMUTF8 = 2449 +SCI_FINDCOLUMN = 2456 +SCI_GETCARETSTICKY = 2457 +SCI_SETCARETSTICKY = 2458 +SCI_TOGGLECARETSTICKY = 2459 +SCI_SETPASTECONVERTENDINGS = 2467 +SCI_GETPASTECONVERTENDINGS = 2468 +SCI_SELECTIONDUPLICATE = 2469 +SC_ALPHA_TRANSPARENT = 0 +SC_ALPHA_OPAQUE = 255 +SC_ALPHA_NOALPHA = 256 +SCI_SETCARETLINEBACKALPHA = 2470 +SCI_GETCARETLINEBACKALPHA = 2471 +CARETSTYLE_INVISIBLE = 0 +CARETSTYLE_LINE = 1 +CARETSTYLE_BLOCK = 2 +SCI_SETCARETSTYLE = 2512 +SCI_GETCARETSTYLE = 2513 +SCI_SETINDICATORCURRENT = 2500 +SCI_GETINDICATORCURRENT = 2501 +SCI_SETINDICATORVALUE = 2502 +SCI_GETINDICATORVALUE = 2503 +SCI_INDICATORFILLRANGE = 2504 +SCI_INDICATORCLEARRANGE = 2505 +SCI_INDICATORALLONFOR = 2506 +SCI_INDICATORVALUEAT = 2507 +SCI_INDICATORSTART = 2508 +SCI_INDICATOREND = 2509 +SCI_SETPOSITIONCACHE = 2514 +SCI_GETPOSITIONCACHE = 2515 +SCI_COPYALLOWLINE = 2519 +SCI_GETCHARACTERPOINTER = 2520 +SCI_SETKEYSUNICODE = 2521 +SCI_GETKEYSUNICODE = 2522 +SCI_STARTRECORD = 3001 +SCI_STOPRECORD = 3002 +SCI_SETLEXER = 4001 +SCI_GETLEXER = 4002 +SCI_COLOURISE = 4003 +SCI_SETPROPERTY = 4004 +KEYWORDSET_MAX = 8 +SCI_SETKEYWORDS = 4005 +SCI_SETLEXERLANGUAGE = 4006 +SCI_LOADLEXERLIBRARY = 4007 +SCI_GETPROPERTY = 4008 +SCI_GETPROPERTYEXPANDED = 4009 +SCI_GETPROPERTYINT = 4010 +SCI_GETSTYLEBITSNEEDED = 4011 +SC_MOD_INSERTTEXT = 0x1 +SC_MOD_DELETETEXT = 0x2 +SC_MOD_CHANGESTYLE = 0x4 +SC_MOD_CHANGEFOLD = 0x8 +SC_PERFORMED_USER = 0x10 +SC_PERFORMED_UNDO = 0x20 +SC_PERFORMED_REDO = 0x40 +SC_MULTISTEPUNDOREDO = 0x80 +SC_LASTSTEPINUNDOREDO = 0x100 +SC_MOD_CHANGEMARKER = 0x200 +SC_MOD_BEFOREINSERT = 0x400 +SC_MOD_BEFOREDELETE = 0x800 +SC_MULTILINEUNDOREDO = 0x1000 +SC_STARTACTION = 0x2000 +SC_MOD_CHANGEINDICATOR = 0x4000 +SC_MOD_CHANGELINESTATE = 0x8000 +SC_MODEVENTMASKALL = 0xFFFF +SCEN_CHANGE = 768 +SCEN_SETFOCUS = 512 +SCEN_KILLFOCUS = 256 +SCK_DOWN = 300 +SCK_UP = 301 +SCK_LEFT = 302 +SCK_RIGHT = 303 +SCK_HOME = 304 +SCK_END = 305 +SCK_PRIOR = 306 +SCK_NEXT = 307 +SCK_DELETE = 308 +SCK_INSERT = 309 +SCK_ESCAPE = 7 +SCK_BACK = 8 +SCK_TAB = 9 +SCK_RETURN = 13 +SCK_ADD = 310 +SCK_SUBTRACT = 311 +SCK_DIVIDE = 312 +SCK_WIN = 313 +SCK_RWIN = 314 +SCK_MENU = 315 +SCMOD_NORM = 0 +SCMOD_SHIFT = 1 +SCMOD_CTRL = 2 +SCMOD_ALT = 4 +SCN_STYLENEEDED = 2000 +SCN_CHARADDED = 2001 +SCN_SAVEPOINTREACHED = 2002 +SCN_SAVEPOINTLEFT = 2003 +SCN_MODIFYATTEMPTRO = 2004 +SCN_KEY = 2005 +SCN_DOUBLECLICK = 2006 +SCN_UPDATEUI = 2007 +SCN_MODIFIED = 2008 +SCN_MACRORECORD = 2009 +SCN_MARGINCLICK = 2010 +SCN_NEEDSHOWN = 2011 +SCN_PAINTED = 2013 +SCN_USERLISTSELECTION = 2014 +SCN_URIDROPPED = 2015 +SCN_DWELLSTART = 2016 +SCN_DWELLEND = 2017 +SCN_ZOOM = 2018 +SCN_HOTSPOTCLICK = 2019 +SCN_HOTSPOTDOUBLECLICK = 2020 +SCN_CALLTIPCLICK = 2021 +SCN_AUTOCSELECTION = 2022 +SCN_INDICATORCLICK = 2023 +SCN_INDICATORRELEASE = 2024 +SCN_AUTOCCANCELLED = 2025 +SCI_SETCARETPOLICY = 2369 +CARET_CENTER = 0x02 +CARET_XEVEN = 0x08 +CARET_XJUMPS = 0x10 +SCN_POSCHANGED = 2012 +SCN_CHECKBRACE = 2007 +# Generated by h2py from Include\scilexer.h +SCLEX_CONTAINER = 0 +SCLEX_NULL = 1 +SCLEX_PYTHON = 2 +SCLEX_CPP = 3 +SCLEX_HTML = 4 +SCLEX_XML = 5 +SCLEX_PERL = 6 +SCLEX_SQL = 7 +SCLEX_VB = 8 +SCLEX_PROPERTIES = 9 +SCLEX_ERRORLIST = 10 +SCLEX_MAKEFILE = 11 +SCLEX_BATCH = 12 +SCLEX_XCODE = 13 +SCLEX_LATEX = 14 +SCLEX_LUA = 15 +SCLEX_DIFF = 16 +SCLEX_CONF = 17 +SCLEX_PASCAL = 18 +SCLEX_AVE = 19 +SCLEX_ADA = 20 +SCLEX_LISP = 21 +SCLEX_RUBY = 22 +SCLEX_EIFFEL = 23 +SCLEX_EIFFELKW = 24 +SCLEX_TCL = 25 +SCLEX_NNCRONTAB = 26 +SCLEX_BULLANT = 27 +SCLEX_VBSCRIPT = 28 +SCLEX_BAAN = 31 +SCLEX_MATLAB = 32 +SCLEX_SCRIPTOL = 33 +SCLEX_ASM = 34 +SCLEX_CPPNOCASE = 35 +SCLEX_FORTRAN = 36 +SCLEX_F77 = 37 +SCLEX_CSS = 38 +SCLEX_POV = 39 +SCLEX_LOUT = 40 +SCLEX_ESCRIPT = 41 +SCLEX_PS = 42 +SCLEX_NSIS = 43 +SCLEX_MMIXAL = 44 +SCLEX_CLW = 45 +SCLEX_CLWNOCASE = 46 +SCLEX_LOT = 47 +SCLEX_YAML = 48 +SCLEX_TEX = 49 +SCLEX_METAPOST = 50 +SCLEX_POWERBASIC = 51 +SCLEX_FORTH = 52 +SCLEX_ERLANG = 53 +SCLEX_OCTAVE = 54 +SCLEX_MSSQL = 55 +SCLEX_VERILOG = 56 +SCLEX_KIX = 57 +SCLEX_GUI4CLI = 58 +SCLEX_SPECMAN = 59 +SCLEX_AU3 = 60 +SCLEX_APDL = 61 +SCLEX_BASH = 62 +SCLEX_ASN1 = 63 +SCLEX_VHDL = 64 +SCLEX_CAML = 65 +SCLEX_BLITZBASIC = 66 +SCLEX_PUREBASIC = 67 +SCLEX_HASKELL = 68 +SCLEX_PHPSCRIPT = 69 +SCLEX_TADS3 = 70 +SCLEX_REBOL = 71 +SCLEX_SMALLTALK = 72 +SCLEX_FLAGSHIP = 73 +SCLEX_CSOUND = 74 +SCLEX_FREEBASIC = 75 +SCLEX_INNOSETUP = 76 +SCLEX_OPAL = 77 +SCLEX_SPICE = 78 +SCLEX_D = 79 +SCLEX_CMAKE = 80 +SCLEX_GAP = 81 +SCLEX_PLM = 82 +SCLEX_PROGRESS = 83 +SCLEX_ABAQUS = 84 +SCLEX_ASYMPTOTE = 85 +SCLEX_R = 86 +SCLEX_MAGIK = 87 +SCLEX_POWERSHELL = 88 +SCLEX_MYSQL = 89 +SCLEX_PO = 90 +SCLEX_AUTOMATIC = 1000 +SCE_P_DEFAULT = 0 +SCE_P_COMMENTLINE = 1 +SCE_P_NUMBER = 2 +SCE_P_STRING = 3 +SCE_P_CHARACTER = 4 +SCE_P_WORD = 5 +SCE_P_TRIPLE = 6 +SCE_P_TRIPLEDOUBLE = 7 +SCE_P_CLASSNAME = 8 +SCE_P_DEFNAME = 9 +SCE_P_OPERATOR = 10 +SCE_P_IDENTIFIER = 11 +SCE_P_COMMENTBLOCK = 12 +SCE_P_STRINGEOL = 13 +SCE_P_WORD2 = 14 +SCE_P_DECORATOR = 15 +SCE_C_DEFAULT = 0 +SCE_C_COMMENT = 1 +SCE_C_COMMENTLINE = 2 +SCE_C_COMMENTDOC = 3 +SCE_C_NUMBER = 4 +SCE_C_WORD = 5 +SCE_C_STRING = 6 +SCE_C_CHARACTER = 7 +SCE_C_UUID = 8 +SCE_C_PREPROCESSOR = 9 +SCE_C_OPERATOR = 10 +SCE_C_IDENTIFIER = 11 +SCE_C_STRINGEOL = 12 +SCE_C_VERBATIM = 13 +SCE_C_REGEX = 14 +SCE_C_COMMENTLINEDOC = 15 +SCE_C_WORD2 = 16 +SCE_C_COMMENTDOCKEYWORD = 17 +SCE_C_COMMENTDOCKEYWORDERROR = 18 +SCE_C_GLOBALCLASS = 19 +SCE_D_DEFAULT = 0 +SCE_D_COMMENT = 1 +SCE_D_COMMENTLINE = 2 +SCE_D_COMMENTDOC = 3 +SCE_D_COMMENTNESTED = 4 +SCE_D_NUMBER = 5 +SCE_D_WORD = 6 +SCE_D_WORD2 = 7 +SCE_D_WORD3 = 8 +SCE_D_TYPEDEF = 9 +SCE_D_STRING = 10 +SCE_D_STRINGEOL = 11 +SCE_D_CHARACTER = 12 +SCE_D_OPERATOR = 13 +SCE_D_IDENTIFIER = 14 +SCE_D_COMMENTLINEDOC = 15 +SCE_D_COMMENTDOCKEYWORD = 16 +SCE_D_COMMENTDOCKEYWORDERROR = 17 +SCE_TCL_DEFAULT = 0 +SCE_TCL_COMMENT = 1 +SCE_TCL_COMMENTLINE = 2 +SCE_TCL_NUMBER = 3 +SCE_TCL_WORD_IN_QUOTE = 4 +SCE_TCL_IN_QUOTE = 5 +SCE_TCL_OPERATOR = 6 +SCE_TCL_IDENTIFIER = 7 +SCE_TCL_SUBSTITUTION = 8 +SCE_TCL_SUB_BRACE = 9 +SCE_TCL_MODIFIER = 10 +SCE_TCL_EXPAND = 11 +SCE_TCL_WORD = 12 +SCE_TCL_WORD2 = 13 +SCE_TCL_WORD3 = 14 +SCE_TCL_WORD4 = 15 +SCE_TCL_WORD5 = 16 +SCE_TCL_WORD6 = 17 +SCE_TCL_WORD7 = 18 +SCE_TCL_WORD8 = 19 +SCE_TCL_COMMENT_BOX = 20 +SCE_TCL_BLOCK_COMMENT = 21 +SCE_H_DEFAULT = 0 +SCE_H_TAG = 1 +SCE_H_TAGUNKNOWN = 2 +SCE_H_ATTRIBUTE = 3 +SCE_H_ATTRIBUTEUNKNOWN = 4 +SCE_H_NUMBER = 5 +SCE_H_DOUBLESTRING = 6 +SCE_H_SINGLESTRING = 7 +SCE_H_OTHER = 8 +SCE_H_COMMENT = 9 +SCE_H_ENTITY = 10 +SCE_H_TAGEND = 11 +SCE_H_XMLSTART = 12 +SCE_H_XMLEND = 13 +SCE_H_SCRIPT = 14 +SCE_H_ASP = 15 +SCE_H_ASPAT = 16 +SCE_H_CDATA = 17 +SCE_H_QUESTION = 18 +SCE_H_VALUE = 19 +SCE_H_XCCOMMENT = 20 +SCE_H_SGML_DEFAULT = 21 +SCE_H_SGML_COMMAND = 22 +SCE_H_SGML_1ST_PARAM = 23 +SCE_H_SGML_DOUBLESTRING = 24 +SCE_H_SGML_SIMPLESTRING = 25 +SCE_H_SGML_ERROR = 26 +SCE_H_SGML_SPECIAL = 27 +SCE_H_SGML_ENTITY = 28 +SCE_H_SGML_COMMENT = 29 +SCE_H_SGML_1ST_PARAM_COMMENT = 30 +SCE_H_SGML_BLOCK_DEFAULT = 31 +SCE_HJ_START = 40 +SCE_HJ_DEFAULT = 41 +SCE_HJ_COMMENT = 42 +SCE_HJ_COMMENTLINE = 43 +SCE_HJ_COMMENTDOC = 44 +SCE_HJ_NUMBER = 45 +SCE_HJ_WORD = 46 +SCE_HJ_KEYWORD = 47 +SCE_HJ_DOUBLESTRING = 48 +SCE_HJ_SINGLESTRING = 49 +SCE_HJ_SYMBOLS = 50 +SCE_HJ_STRINGEOL = 51 +SCE_HJ_REGEX = 52 +SCE_HJA_START = 55 +SCE_HJA_DEFAULT = 56 +SCE_HJA_COMMENT = 57 +SCE_HJA_COMMENTLINE = 58 +SCE_HJA_COMMENTDOC = 59 +SCE_HJA_NUMBER = 60 +SCE_HJA_WORD = 61 +SCE_HJA_KEYWORD = 62 +SCE_HJA_DOUBLESTRING = 63 +SCE_HJA_SINGLESTRING = 64 +SCE_HJA_SYMBOLS = 65 +SCE_HJA_STRINGEOL = 66 +SCE_HJA_REGEX = 67 +SCE_HB_START = 70 +SCE_HB_DEFAULT = 71 +SCE_HB_COMMENTLINE = 72 +SCE_HB_NUMBER = 73 +SCE_HB_WORD = 74 +SCE_HB_STRING = 75 +SCE_HB_IDENTIFIER = 76 +SCE_HB_STRINGEOL = 77 +SCE_HBA_START = 80 +SCE_HBA_DEFAULT = 81 +SCE_HBA_COMMENTLINE = 82 +SCE_HBA_NUMBER = 83 +SCE_HBA_WORD = 84 +SCE_HBA_STRING = 85 +SCE_HBA_IDENTIFIER = 86 +SCE_HBA_STRINGEOL = 87 +SCE_HP_START = 90 +SCE_HP_DEFAULT = 91 +SCE_HP_COMMENTLINE = 92 +SCE_HP_NUMBER = 93 +SCE_HP_STRING = 94 +SCE_HP_CHARACTER = 95 +SCE_HP_WORD = 96 +SCE_HP_TRIPLE = 97 +SCE_HP_TRIPLEDOUBLE = 98 +SCE_HP_CLASSNAME = 99 +SCE_HP_DEFNAME = 100 +SCE_HP_OPERATOR = 101 +SCE_HP_IDENTIFIER = 102 +SCE_HPHP_COMPLEX_VARIABLE = 104 +SCE_HPA_START = 105 +SCE_HPA_DEFAULT = 106 +SCE_HPA_COMMENTLINE = 107 +SCE_HPA_NUMBER = 108 +SCE_HPA_STRING = 109 +SCE_HPA_CHARACTER = 110 +SCE_HPA_WORD = 111 +SCE_HPA_TRIPLE = 112 +SCE_HPA_TRIPLEDOUBLE = 113 +SCE_HPA_CLASSNAME = 114 +SCE_HPA_DEFNAME = 115 +SCE_HPA_OPERATOR = 116 +SCE_HPA_IDENTIFIER = 117 +SCE_HPHP_DEFAULT = 118 +SCE_HPHP_HSTRING = 119 +SCE_HPHP_SIMPLESTRING = 120 +SCE_HPHP_WORD = 121 +SCE_HPHP_NUMBER = 122 +SCE_HPHP_VARIABLE = 123 +SCE_HPHP_COMMENT = 124 +SCE_HPHP_COMMENTLINE = 125 +SCE_HPHP_HSTRING_VARIABLE = 126 +SCE_HPHP_OPERATOR = 127 +SCE_PL_DEFAULT = 0 +SCE_PL_ERROR = 1 +SCE_PL_COMMENTLINE = 2 +SCE_PL_POD = 3 +SCE_PL_NUMBER = 4 +SCE_PL_WORD = 5 +SCE_PL_STRING = 6 +SCE_PL_CHARACTER = 7 +SCE_PL_PUNCTUATION = 8 +SCE_PL_PREPROCESSOR = 9 +SCE_PL_OPERATOR = 10 +SCE_PL_IDENTIFIER = 11 +SCE_PL_SCALAR = 12 +SCE_PL_ARRAY = 13 +SCE_PL_HASH = 14 +SCE_PL_SYMBOLTABLE = 15 +SCE_PL_VARIABLE_INDEXER = 16 +SCE_PL_REGEX = 17 +SCE_PL_REGSUBST = 18 +SCE_PL_LONGQUOTE = 19 +SCE_PL_BACKTICKS = 20 +SCE_PL_DATASECTION = 21 +SCE_PL_HERE_DELIM = 22 +SCE_PL_HERE_Q = 23 +SCE_PL_HERE_QQ = 24 +SCE_PL_HERE_QX = 25 +SCE_PL_STRING_Q = 26 +SCE_PL_STRING_QQ = 27 +SCE_PL_STRING_QX = 28 +SCE_PL_STRING_QR = 29 +SCE_PL_STRING_QW = 30 +SCE_PL_POD_VERB = 31 +SCE_PL_SUB_PROTOTYPE = 40 +SCE_PL_FORMAT_IDENT = 41 +SCE_PL_FORMAT = 42 +SCE_RB_DEFAULT = 0 +SCE_RB_ERROR = 1 +SCE_RB_COMMENTLINE = 2 +SCE_RB_POD = 3 +SCE_RB_NUMBER = 4 +SCE_RB_WORD = 5 +SCE_RB_STRING = 6 +SCE_RB_CHARACTER = 7 +SCE_RB_CLASSNAME = 8 +SCE_RB_DEFNAME = 9 +SCE_RB_OPERATOR = 10 +SCE_RB_IDENTIFIER = 11 +SCE_RB_REGEX = 12 +SCE_RB_GLOBAL = 13 +SCE_RB_SYMBOL = 14 +SCE_RB_MODULE_NAME = 15 +SCE_RB_INSTANCE_VAR = 16 +SCE_RB_CLASS_VAR = 17 +SCE_RB_BACKTICKS = 18 +SCE_RB_DATASECTION = 19 +SCE_RB_HERE_DELIM = 20 +SCE_RB_HERE_Q = 21 +SCE_RB_HERE_QQ = 22 +SCE_RB_HERE_QX = 23 +SCE_RB_STRING_Q = 24 +SCE_RB_STRING_QQ = 25 +SCE_RB_STRING_QX = 26 +SCE_RB_STRING_QR = 27 +SCE_RB_STRING_QW = 28 +SCE_RB_WORD_DEMOTED = 29 +SCE_RB_STDIN = 30 +SCE_RB_STDOUT = 31 +SCE_RB_STDERR = 40 +SCE_RB_UPPER_BOUND = 41 +SCE_B_DEFAULT = 0 +SCE_B_COMMENT = 1 +SCE_B_NUMBER = 2 +SCE_B_KEYWORD = 3 +SCE_B_STRING = 4 +SCE_B_PREPROCESSOR = 5 +SCE_B_OPERATOR = 6 +SCE_B_IDENTIFIER = 7 +SCE_B_DATE = 8 +SCE_B_STRINGEOL = 9 +SCE_B_KEYWORD2 = 10 +SCE_B_KEYWORD3 = 11 +SCE_B_KEYWORD4 = 12 +SCE_B_CONSTANT = 13 +SCE_B_ASM = 14 +SCE_B_LABEL = 15 +SCE_B_ERROR = 16 +SCE_B_HEXNUMBER = 17 +SCE_B_BINNUMBER = 18 +SCE_PROPS_DEFAULT = 0 +SCE_PROPS_COMMENT = 1 +SCE_PROPS_SECTION = 2 +SCE_PROPS_ASSIGNMENT = 3 +SCE_PROPS_DEFVAL = 4 +SCE_PROPS_KEY = 5 +SCE_L_DEFAULT = 0 +SCE_L_COMMAND = 1 +SCE_L_TAG = 2 +SCE_L_MATH = 3 +SCE_L_COMMENT = 4 +SCE_LUA_DEFAULT = 0 +SCE_LUA_COMMENT = 1 +SCE_LUA_COMMENTLINE = 2 +SCE_LUA_COMMENTDOC = 3 +SCE_LUA_NUMBER = 4 +SCE_LUA_WORD = 5 +SCE_LUA_STRING = 6 +SCE_LUA_CHARACTER = 7 +SCE_LUA_LITERALSTRING = 8 +SCE_LUA_PREPROCESSOR = 9 +SCE_LUA_OPERATOR = 10 +SCE_LUA_IDENTIFIER = 11 +SCE_LUA_STRINGEOL = 12 +SCE_LUA_WORD2 = 13 +SCE_LUA_WORD3 = 14 +SCE_LUA_WORD4 = 15 +SCE_LUA_WORD5 = 16 +SCE_LUA_WORD6 = 17 +SCE_LUA_WORD7 = 18 +SCE_LUA_WORD8 = 19 +SCE_ERR_DEFAULT = 0 +SCE_ERR_PYTHON = 1 +SCE_ERR_GCC = 2 +SCE_ERR_MS = 3 +SCE_ERR_CMD = 4 +SCE_ERR_BORLAND = 5 +SCE_ERR_PERL = 6 +SCE_ERR_NET = 7 +SCE_ERR_LUA = 8 +SCE_ERR_CTAG = 9 +SCE_ERR_DIFF_CHANGED = 10 +SCE_ERR_DIFF_ADDITION = 11 +SCE_ERR_DIFF_DELETION = 12 +SCE_ERR_DIFF_MESSAGE = 13 +SCE_ERR_PHP = 14 +SCE_ERR_ELF = 15 +SCE_ERR_IFC = 16 +SCE_ERR_IFORT = 17 +SCE_ERR_ABSF = 18 +SCE_ERR_TIDY = 19 +SCE_ERR_JAVA_STACK = 20 +SCE_ERR_VALUE = 21 +SCE_BAT_DEFAULT = 0 +SCE_BAT_COMMENT = 1 +SCE_BAT_WORD = 2 +SCE_BAT_LABEL = 3 +SCE_BAT_HIDE = 4 +SCE_BAT_COMMAND = 5 +SCE_BAT_IDENTIFIER = 6 +SCE_BAT_OPERATOR = 7 +SCE_MAKE_DEFAULT = 0 +SCE_MAKE_COMMENT = 1 +SCE_MAKE_PREPROCESSOR = 2 +SCE_MAKE_IDENTIFIER = 3 +SCE_MAKE_OPERATOR = 4 +SCE_MAKE_TARGET = 5 +SCE_MAKE_IDEOL = 9 +SCE_DIFF_DEFAULT = 0 +SCE_DIFF_COMMENT = 1 +SCE_DIFF_COMMAND = 2 +SCE_DIFF_HEADER = 3 +SCE_DIFF_POSITION = 4 +SCE_DIFF_DELETED = 5 +SCE_DIFF_ADDED = 6 +SCE_DIFF_CHANGED = 7 +SCE_CONF_DEFAULT = 0 +SCE_CONF_COMMENT = 1 +SCE_CONF_NUMBER = 2 +SCE_CONF_IDENTIFIER = 3 +SCE_CONF_EXTENSION = 4 +SCE_CONF_PARAMETER = 5 +SCE_CONF_STRING = 6 +SCE_CONF_OPERATOR = 7 +SCE_CONF_IP = 8 +SCE_CONF_DIRECTIVE = 9 +SCE_AVE_DEFAULT = 0 +SCE_AVE_COMMENT = 1 +SCE_AVE_NUMBER = 2 +SCE_AVE_WORD = 3 +SCE_AVE_STRING = 6 +SCE_AVE_ENUM = 7 +SCE_AVE_STRINGEOL = 8 +SCE_AVE_IDENTIFIER = 9 +SCE_AVE_OPERATOR = 10 +SCE_AVE_WORD1 = 11 +SCE_AVE_WORD2 = 12 +SCE_AVE_WORD3 = 13 +SCE_AVE_WORD4 = 14 +SCE_AVE_WORD5 = 15 +SCE_AVE_WORD6 = 16 +SCE_ADA_DEFAULT = 0 +SCE_ADA_WORD = 1 +SCE_ADA_IDENTIFIER = 2 +SCE_ADA_NUMBER = 3 +SCE_ADA_DELIMITER = 4 +SCE_ADA_CHARACTER = 5 +SCE_ADA_CHARACTEREOL = 6 +SCE_ADA_STRING = 7 +SCE_ADA_STRINGEOL = 8 +SCE_ADA_LABEL = 9 +SCE_ADA_COMMENTLINE = 10 +SCE_ADA_ILLEGAL = 11 +SCE_BAAN_DEFAULT = 0 +SCE_BAAN_COMMENT = 1 +SCE_BAAN_COMMENTDOC = 2 +SCE_BAAN_NUMBER = 3 +SCE_BAAN_WORD = 4 +SCE_BAAN_STRING = 5 +SCE_BAAN_PREPROCESSOR = 6 +SCE_BAAN_OPERATOR = 7 +SCE_BAAN_IDENTIFIER = 8 +SCE_BAAN_STRINGEOL = 9 +SCE_BAAN_WORD2 = 10 +SCE_LISP_DEFAULT = 0 +SCE_LISP_COMMENT = 1 +SCE_LISP_NUMBER = 2 +SCE_LISP_KEYWORD = 3 +SCE_LISP_KEYWORD_KW = 4 +SCE_LISP_SYMBOL = 5 +SCE_LISP_STRING = 6 +SCE_LISP_STRINGEOL = 8 +SCE_LISP_IDENTIFIER = 9 +SCE_LISP_OPERATOR = 10 +SCE_LISP_SPECIAL = 11 +SCE_LISP_MULTI_COMMENT = 12 +SCE_EIFFEL_DEFAULT = 0 +SCE_EIFFEL_COMMENTLINE = 1 +SCE_EIFFEL_NUMBER = 2 +SCE_EIFFEL_WORD = 3 +SCE_EIFFEL_STRING = 4 +SCE_EIFFEL_CHARACTER = 5 +SCE_EIFFEL_OPERATOR = 6 +SCE_EIFFEL_IDENTIFIER = 7 +SCE_EIFFEL_STRINGEOL = 8 +SCE_NNCRONTAB_DEFAULT = 0 +SCE_NNCRONTAB_COMMENT = 1 +SCE_NNCRONTAB_TASK = 2 +SCE_NNCRONTAB_SECTION = 3 +SCE_NNCRONTAB_KEYWORD = 4 +SCE_NNCRONTAB_MODIFIER = 5 +SCE_NNCRONTAB_ASTERISK = 6 +SCE_NNCRONTAB_NUMBER = 7 +SCE_NNCRONTAB_STRING = 8 +SCE_NNCRONTAB_ENVIRONMENT = 9 +SCE_NNCRONTAB_IDENTIFIER = 10 +SCE_FORTH_DEFAULT = 0 +SCE_FORTH_COMMENT = 1 +SCE_FORTH_COMMENT_ML = 2 +SCE_FORTH_IDENTIFIER = 3 +SCE_FORTH_CONTROL = 4 +SCE_FORTH_KEYWORD = 5 +SCE_FORTH_DEFWORD = 6 +SCE_FORTH_PREWORD1 = 7 +SCE_FORTH_PREWORD2 = 8 +SCE_FORTH_NUMBER = 9 +SCE_FORTH_STRING = 10 +SCE_FORTH_LOCALE = 11 +SCE_MATLAB_DEFAULT = 0 +SCE_MATLAB_COMMENT = 1 +SCE_MATLAB_COMMAND = 2 +SCE_MATLAB_NUMBER = 3 +SCE_MATLAB_KEYWORD = 4 +SCE_MATLAB_STRING = 5 +SCE_MATLAB_OPERATOR = 6 +SCE_MATLAB_IDENTIFIER = 7 +SCE_MATLAB_DOUBLEQUOTESTRING = 8 +SCE_SCRIPTOL_DEFAULT = 0 +SCE_SCRIPTOL_WHITE = 1 +SCE_SCRIPTOL_COMMENTLINE = 2 +SCE_SCRIPTOL_PERSISTENT = 3 +SCE_SCRIPTOL_CSTYLE = 4 +SCE_SCRIPTOL_COMMENTBLOCK = 5 +SCE_SCRIPTOL_NUMBER = 6 +SCE_SCRIPTOL_STRING = 7 +SCE_SCRIPTOL_CHARACTER = 8 +SCE_SCRIPTOL_STRINGEOL = 9 +SCE_SCRIPTOL_KEYWORD = 10 +SCE_SCRIPTOL_OPERATOR = 11 +SCE_SCRIPTOL_IDENTIFIER = 12 +SCE_SCRIPTOL_TRIPLE = 13 +SCE_SCRIPTOL_CLASSNAME = 14 +SCE_SCRIPTOL_PREPROCESSOR = 15 +SCE_ASM_DEFAULT = 0 +SCE_ASM_COMMENT = 1 +SCE_ASM_NUMBER = 2 +SCE_ASM_STRING = 3 +SCE_ASM_OPERATOR = 4 +SCE_ASM_IDENTIFIER = 5 +SCE_ASM_CPUINSTRUCTION = 6 +SCE_ASM_MATHINSTRUCTION = 7 +SCE_ASM_REGISTER = 8 +SCE_ASM_DIRECTIVE = 9 +SCE_ASM_DIRECTIVEOPERAND = 10 +SCE_ASM_COMMENTBLOCK = 11 +SCE_ASM_CHARACTER = 12 +SCE_ASM_STRINGEOL = 13 +SCE_ASM_EXTINSTRUCTION = 14 +SCE_F_DEFAULT = 0 +SCE_F_COMMENT = 1 +SCE_F_NUMBER = 2 +SCE_F_STRING1 = 3 +SCE_F_STRING2 = 4 +SCE_F_STRINGEOL = 5 +SCE_F_OPERATOR = 6 +SCE_F_IDENTIFIER = 7 +SCE_F_WORD = 8 +SCE_F_WORD2 = 9 +SCE_F_WORD3 = 10 +SCE_F_PREPROCESSOR = 11 +SCE_F_OPERATOR2 = 12 +SCE_F_LABEL = 13 +SCE_F_CONTINUATION = 14 +SCE_CSS_DEFAULT = 0 +SCE_CSS_TAG = 1 +SCE_CSS_CLASS = 2 +SCE_CSS_PSEUDOCLASS = 3 +SCE_CSS_UNKNOWN_PSEUDOCLASS = 4 +SCE_CSS_OPERATOR = 5 +SCE_CSS_IDENTIFIER = 6 +SCE_CSS_UNKNOWN_IDENTIFIER = 7 +SCE_CSS_VALUE = 8 +SCE_CSS_COMMENT = 9 +SCE_CSS_ID = 10 +SCE_CSS_IMPORTANT = 11 +SCE_CSS_DIRECTIVE = 12 +SCE_CSS_DOUBLESTRING = 13 +SCE_CSS_SINGLESTRING = 14 +SCE_CSS_IDENTIFIER2 = 15 +SCE_CSS_ATTRIBUTE = 16 +SCE_CSS_IDENTIFIER3 = 17 +SCE_CSS_PSEUDOELEMENT = 18 +SCE_CSS_EXTENDED_IDENTIFIER = 19 +SCE_CSS_EXTENDED_PSEUDOCLASS = 20 +SCE_CSS_EXTENDED_PSEUDOELEMENT = 21 +SCE_POV_DEFAULT = 0 +SCE_POV_COMMENT = 1 +SCE_POV_COMMENTLINE = 2 +SCE_POV_NUMBER = 3 +SCE_POV_OPERATOR = 4 +SCE_POV_IDENTIFIER = 5 +SCE_POV_STRING = 6 +SCE_POV_STRINGEOL = 7 +SCE_POV_DIRECTIVE = 8 +SCE_POV_BADDIRECTIVE = 9 +SCE_POV_WORD2 = 10 +SCE_POV_WORD3 = 11 +SCE_POV_WORD4 = 12 +SCE_POV_WORD5 = 13 +SCE_POV_WORD6 = 14 +SCE_POV_WORD7 = 15 +SCE_POV_WORD8 = 16 +SCE_LOUT_DEFAULT = 0 +SCE_LOUT_COMMENT = 1 +SCE_LOUT_NUMBER = 2 +SCE_LOUT_WORD = 3 +SCE_LOUT_WORD2 = 4 +SCE_LOUT_WORD3 = 5 +SCE_LOUT_WORD4 = 6 +SCE_LOUT_STRING = 7 +SCE_LOUT_OPERATOR = 8 +SCE_LOUT_IDENTIFIER = 9 +SCE_LOUT_STRINGEOL = 10 +SCE_ESCRIPT_DEFAULT = 0 +SCE_ESCRIPT_COMMENT = 1 +SCE_ESCRIPT_COMMENTLINE = 2 +SCE_ESCRIPT_COMMENTDOC = 3 +SCE_ESCRIPT_NUMBER = 4 +SCE_ESCRIPT_WORD = 5 +SCE_ESCRIPT_STRING = 6 +SCE_ESCRIPT_OPERATOR = 7 +SCE_ESCRIPT_IDENTIFIER = 8 +SCE_ESCRIPT_BRACE = 9 +SCE_ESCRIPT_WORD2 = 10 +SCE_ESCRIPT_WORD3 = 11 +SCE_PS_DEFAULT = 0 +SCE_PS_COMMENT = 1 +SCE_PS_DSC_COMMENT = 2 +SCE_PS_DSC_VALUE = 3 +SCE_PS_NUMBER = 4 +SCE_PS_NAME = 5 +SCE_PS_KEYWORD = 6 +SCE_PS_LITERAL = 7 +SCE_PS_IMMEVAL = 8 +SCE_PS_PAREN_ARRAY = 9 +SCE_PS_PAREN_DICT = 10 +SCE_PS_PAREN_PROC = 11 +SCE_PS_TEXT = 12 +SCE_PS_HEXSTRING = 13 +SCE_PS_BASE85STRING = 14 +SCE_PS_BADSTRINGCHAR = 15 +SCE_NSIS_DEFAULT = 0 +SCE_NSIS_COMMENT = 1 +SCE_NSIS_STRINGDQ = 2 +SCE_NSIS_STRINGLQ = 3 +SCE_NSIS_STRINGRQ = 4 +SCE_NSIS_FUNCTION = 5 +SCE_NSIS_VARIABLE = 6 +SCE_NSIS_LABEL = 7 +SCE_NSIS_USERDEFINED = 8 +SCE_NSIS_SECTIONDEF = 9 +SCE_NSIS_SUBSECTIONDEF = 10 +SCE_NSIS_IFDEFINEDEF = 11 +SCE_NSIS_MACRODEF = 12 +SCE_NSIS_STRINGVAR = 13 +SCE_NSIS_NUMBER = 14 +SCE_NSIS_SECTIONGROUP = 15 +SCE_NSIS_PAGEEX = 16 +SCE_NSIS_FUNCTIONDEF = 17 +SCE_NSIS_COMMENTBOX = 18 +SCE_MMIXAL_LEADWS = 0 +SCE_MMIXAL_COMMENT = 1 +SCE_MMIXAL_LABEL = 2 +SCE_MMIXAL_OPCODE = 3 +SCE_MMIXAL_OPCODE_PRE = 4 +SCE_MMIXAL_OPCODE_VALID = 5 +SCE_MMIXAL_OPCODE_UNKNOWN = 6 +SCE_MMIXAL_OPCODE_POST = 7 +SCE_MMIXAL_OPERANDS = 8 +SCE_MMIXAL_NUMBER = 9 +SCE_MMIXAL_REF = 10 +SCE_MMIXAL_CHAR = 11 +SCE_MMIXAL_STRING = 12 +SCE_MMIXAL_REGISTER = 13 +SCE_MMIXAL_HEX = 14 +SCE_MMIXAL_OPERATOR = 15 +SCE_MMIXAL_SYMBOL = 16 +SCE_MMIXAL_INCLUDE = 17 +SCE_CLW_DEFAULT = 0 +SCE_CLW_LABEL = 1 +SCE_CLW_COMMENT = 2 +SCE_CLW_STRING = 3 +SCE_CLW_USER_IDENTIFIER = 4 +SCE_CLW_INTEGER_CONSTANT = 5 +SCE_CLW_REAL_CONSTANT = 6 +SCE_CLW_PICTURE_STRING = 7 +SCE_CLW_KEYWORD = 8 +SCE_CLW_COMPILER_DIRECTIVE = 9 +SCE_CLW_RUNTIME_EXPRESSIONS = 10 +SCE_CLW_BUILTIN_PROCEDURES_FUNCTION = 11 +SCE_CLW_STRUCTURE_DATA_TYPE = 12 +SCE_CLW_ATTRIBUTE = 13 +SCE_CLW_STANDARD_EQUATE = 14 +SCE_CLW_ERROR = 15 +SCE_CLW_DEPRECATED = 16 +SCE_LOT_DEFAULT = 0 +SCE_LOT_HEADER = 1 +SCE_LOT_BREAK = 2 +SCE_LOT_SET = 3 +SCE_LOT_PASS = 4 +SCE_LOT_FAIL = 5 +SCE_LOT_ABORT = 6 +SCE_YAML_DEFAULT = 0 +SCE_YAML_COMMENT = 1 +SCE_YAML_IDENTIFIER = 2 +SCE_YAML_KEYWORD = 3 +SCE_YAML_NUMBER = 4 +SCE_YAML_REFERENCE = 5 +SCE_YAML_DOCUMENT = 6 +SCE_YAML_TEXT = 7 +SCE_YAML_ERROR = 8 +SCE_YAML_OPERATOR = 9 +SCE_TEX_DEFAULT = 0 +SCE_TEX_SPECIAL = 1 +SCE_TEX_GROUP = 2 +SCE_TEX_SYMBOL = 3 +SCE_TEX_COMMAND = 4 +SCE_TEX_TEXT = 5 +SCE_METAPOST_DEFAULT = 0 +SCE_METAPOST_SPECIAL = 1 +SCE_METAPOST_GROUP = 2 +SCE_METAPOST_SYMBOL = 3 +SCE_METAPOST_COMMAND = 4 +SCE_METAPOST_TEXT = 5 +SCE_METAPOST_EXTRA = 6 +SCE_ERLANG_DEFAULT = 0 +SCE_ERLANG_COMMENT = 1 +SCE_ERLANG_VARIABLE = 2 +SCE_ERLANG_NUMBER = 3 +SCE_ERLANG_KEYWORD = 4 +SCE_ERLANG_STRING = 5 +SCE_ERLANG_OPERATOR = 6 +SCE_ERLANG_ATOM = 7 +SCE_ERLANG_FUNCTION_NAME = 8 +SCE_ERLANG_CHARACTER = 9 +SCE_ERLANG_MACRO = 10 +SCE_ERLANG_RECORD = 11 +SCE_ERLANG_SEPARATOR = 12 +SCE_ERLANG_NODE_NAME = 13 +SCE_ERLANG_UNKNOWN = 31 +SCE_MSSQL_DEFAULT = 0 +SCE_MSSQL_COMMENT = 1 +SCE_MSSQL_LINE_COMMENT = 2 +SCE_MSSQL_NUMBER = 3 +SCE_MSSQL_STRING = 4 +SCE_MSSQL_OPERATOR = 5 +SCE_MSSQL_IDENTIFIER = 6 +SCE_MSSQL_VARIABLE = 7 +SCE_MSSQL_COLUMN_NAME = 8 +SCE_MSSQL_STATEMENT = 9 +SCE_MSSQL_DATATYPE = 10 +SCE_MSSQL_SYSTABLE = 11 +SCE_MSSQL_GLOBAL_VARIABLE = 12 +SCE_MSSQL_FUNCTION = 13 +SCE_MSSQL_STORED_PROCEDURE = 14 +SCE_MSSQL_DEFAULT_PREF_DATATYPE = 15 +SCE_MSSQL_COLUMN_NAME_2 = 16 +SCE_V_DEFAULT = 0 +SCE_V_COMMENT = 1 +SCE_V_COMMENTLINE = 2 +SCE_V_COMMENTLINEBANG = 3 +SCE_V_NUMBER = 4 +SCE_V_WORD = 5 +SCE_V_STRING = 6 +SCE_V_WORD2 = 7 +SCE_V_WORD3 = 8 +SCE_V_PREPROCESSOR = 9 +SCE_V_OPERATOR = 10 +SCE_V_IDENTIFIER = 11 +SCE_V_STRINGEOL = 12 +SCE_V_USER = 19 +SCE_KIX_DEFAULT = 0 +SCE_KIX_COMMENT = 1 +SCE_KIX_STRING1 = 2 +SCE_KIX_STRING2 = 3 +SCE_KIX_NUMBER = 4 +SCE_KIX_VAR = 5 +SCE_KIX_MACRO = 6 +SCE_KIX_KEYWORD = 7 +SCE_KIX_FUNCTIONS = 8 +SCE_KIX_OPERATOR = 9 +SCE_KIX_IDENTIFIER = 31 +SCE_GC_DEFAULT = 0 +SCE_GC_COMMENTLINE = 1 +SCE_GC_COMMENTBLOCK = 2 +SCE_GC_GLOBAL = 3 +SCE_GC_EVENT = 4 +SCE_GC_ATTRIBUTE = 5 +SCE_GC_CONTROL = 6 +SCE_GC_COMMAND = 7 +SCE_GC_STRING = 8 +SCE_GC_OPERATOR = 9 +SCE_SN_DEFAULT = 0 +SCE_SN_CODE = 1 +SCE_SN_COMMENTLINE = 2 +SCE_SN_COMMENTLINEBANG = 3 +SCE_SN_NUMBER = 4 +SCE_SN_WORD = 5 +SCE_SN_STRING = 6 +SCE_SN_WORD2 = 7 +SCE_SN_WORD3 = 8 +SCE_SN_PREPROCESSOR = 9 +SCE_SN_OPERATOR = 10 +SCE_SN_IDENTIFIER = 11 +SCE_SN_STRINGEOL = 12 +SCE_SN_REGEXTAG = 13 +SCE_SN_SIGNAL = 14 +SCE_SN_USER = 19 +SCE_AU3_DEFAULT = 0 +SCE_AU3_COMMENT = 1 +SCE_AU3_COMMENTBLOCK = 2 +SCE_AU3_NUMBER = 3 +SCE_AU3_FUNCTION = 4 +SCE_AU3_KEYWORD = 5 +SCE_AU3_MACRO = 6 +SCE_AU3_STRING = 7 +SCE_AU3_OPERATOR = 8 +SCE_AU3_VARIABLE = 9 +SCE_AU3_SENT = 10 +SCE_AU3_PREPROCESSOR = 11 +SCE_AU3_SPECIAL = 12 +SCE_AU3_EXPAND = 13 +SCE_AU3_COMOBJ = 14 +SCE_AU3_UDF = 15 +SCE_APDL_DEFAULT = 0 +SCE_APDL_COMMENT = 1 +SCE_APDL_COMMENTBLOCK = 2 +SCE_APDL_NUMBER = 3 +SCE_APDL_STRING = 4 +SCE_APDL_OPERATOR = 5 +SCE_APDL_WORD = 6 +SCE_APDL_PROCESSOR = 7 +SCE_APDL_COMMAND = 8 +SCE_APDL_SLASHCOMMAND = 9 +SCE_APDL_STARCOMMAND = 10 +SCE_APDL_ARGUMENT = 11 +SCE_APDL_FUNCTION = 12 +SCE_SH_DEFAULT = 0 +SCE_SH_ERROR = 1 +SCE_SH_COMMENTLINE = 2 +SCE_SH_NUMBER = 3 +SCE_SH_WORD = 4 +SCE_SH_STRING = 5 +SCE_SH_CHARACTER = 6 +SCE_SH_OPERATOR = 7 +SCE_SH_IDENTIFIER = 8 +SCE_SH_SCALAR = 9 +SCE_SH_PARAM = 10 +SCE_SH_BACKTICKS = 11 +SCE_SH_HERE_DELIM = 12 +SCE_SH_HERE_Q = 13 +SCE_ASN1_DEFAULT = 0 +SCE_ASN1_COMMENT = 1 +SCE_ASN1_IDENTIFIER = 2 +SCE_ASN1_STRING = 3 +SCE_ASN1_OID = 4 +SCE_ASN1_SCALAR = 5 +SCE_ASN1_KEYWORD = 6 +SCE_ASN1_ATTRIBUTE = 7 +SCE_ASN1_DESCRIPTOR = 8 +SCE_ASN1_TYPE = 9 +SCE_ASN1_OPERATOR = 10 +SCE_VHDL_DEFAULT = 0 +SCE_VHDL_COMMENT = 1 +SCE_VHDL_COMMENTLINEBANG = 2 +SCE_VHDL_NUMBER = 3 +SCE_VHDL_STRING = 4 +SCE_VHDL_OPERATOR = 5 +SCE_VHDL_IDENTIFIER = 6 +SCE_VHDL_STRINGEOL = 7 +SCE_VHDL_KEYWORD = 8 +SCE_VHDL_STDOPERATOR = 9 +SCE_VHDL_ATTRIBUTE = 10 +SCE_VHDL_STDFUNCTION = 11 +SCE_VHDL_STDPACKAGE = 12 +SCE_VHDL_STDTYPE = 13 +SCE_VHDL_USERWORD = 14 +SCE_CAML_DEFAULT = 0 +SCE_CAML_IDENTIFIER = 1 +SCE_CAML_TAGNAME = 2 +SCE_CAML_KEYWORD = 3 +SCE_CAML_KEYWORD2 = 4 +SCE_CAML_KEYWORD3 = 5 +SCE_CAML_LINENUM = 6 +SCE_CAML_OPERATOR = 7 +SCE_CAML_NUMBER = 8 +SCE_CAML_CHAR = 9 +SCE_CAML_STRING = 11 +SCE_CAML_COMMENT = 12 +SCE_CAML_COMMENT1 = 13 +SCE_CAML_COMMENT2 = 14 +SCE_CAML_COMMENT3 = 15 +SCE_HA_DEFAULT = 0 +SCE_HA_IDENTIFIER = 1 +SCE_HA_KEYWORD = 2 +SCE_HA_NUMBER = 3 +SCE_HA_STRING = 4 +SCE_HA_CHARACTER = 5 +SCE_HA_CLASS = 6 +SCE_HA_MODULE = 7 +SCE_HA_CAPITAL = 8 +SCE_HA_DATA = 9 +SCE_HA_IMPORT = 10 +SCE_HA_OPERATOR = 11 +SCE_HA_INSTANCE = 12 +SCE_HA_COMMENTLINE = 13 +SCE_HA_COMMENTBLOCK = 14 +SCE_HA_COMMENTBLOCK2 = 15 +SCE_HA_COMMENTBLOCK3 = 16 +SCE_T3_DEFAULT = 0 +SCE_T3_X_DEFAULT = 1 +SCE_T3_PREPROCESSOR = 2 +SCE_T3_BLOCK_COMMENT = 3 +SCE_T3_LINE_COMMENT = 4 +SCE_T3_OPERATOR = 5 +SCE_T3_KEYWORD = 6 +SCE_T3_NUMBER = 7 +SCE_T3_IDENTIFIER = 8 +SCE_T3_S_STRING = 9 +SCE_T3_D_STRING = 10 +SCE_T3_X_STRING = 11 +SCE_T3_LIB_DIRECTIVE = 12 +SCE_T3_MSG_PARAM = 13 +SCE_T3_HTML_TAG = 14 +SCE_T3_HTML_DEFAULT = 15 +SCE_T3_HTML_STRING = 16 +SCE_T3_USER1 = 17 +SCE_T3_USER2 = 18 +SCE_T3_USER3 = 19 +SCE_T3_BRACE = 20 +SCE_REBOL_DEFAULT = 0 +SCE_REBOL_COMMENTLINE = 1 +SCE_REBOL_COMMENTBLOCK = 2 +SCE_REBOL_PREFACE = 3 +SCE_REBOL_OPERATOR = 4 +SCE_REBOL_CHARACTER = 5 +SCE_REBOL_QUOTEDSTRING = 6 +SCE_REBOL_BRACEDSTRING = 7 +SCE_REBOL_NUMBER = 8 +SCE_REBOL_PAIR = 9 +SCE_REBOL_TUPLE = 10 +SCE_REBOL_BINARY = 11 +SCE_REBOL_MONEY = 12 +SCE_REBOL_ISSUE = 13 +SCE_REBOL_TAG = 14 +SCE_REBOL_FILE = 15 +SCE_REBOL_EMAIL = 16 +SCE_REBOL_URL = 17 +SCE_REBOL_DATE = 18 +SCE_REBOL_TIME = 19 +SCE_REBOL_IDENTIFIER = 20 +SCE_REBOL_WORD = 21 +SCE_REBOL_WORD2 = 22 +SCE_REBOL_WORD3 = 23 +SCE_REBOL_WORD4 = 24 +SCE_REBOL_WORD5 = 25 +SCE_REBOL_WORD6 = 26 +SCE_REBOL_WORD7 = 27 +SCE_REBOL_WORD8 = 28 +SCE_SQL_DEFAULT = 0 +SCE_SQL_COMMENT = 1 +SCE_SQL_COMMENTLINE = 2 +SCE_SQL_COMMENTDOC = 3 +SCE_SQL_NUMBER = 4 +SCE_SQL_WORD = 5 +SCE_SQL_STRING = 6 +SCE_SQL_CHARACTER = 7 +SCE_SQL_SQLPLUS = 8 +SCE_SQL_SQLPLUS_PROMPT = 9 +SCE_SQL_OPERATOR = 10 +SCE_SQL_IDENTIFIER = 11 +SCE_SQL_SQLPLUS_COMMENT = 13 +SCE_SQL_COMMENTLINEDOC = 15 +SCE_SQL_WORD2 = 16 +SCE_SQL_COMMENTDOCKEYWORD = 17 +SCE_SQL_COMMENTDOCKEYWORDERROR = 18 +SCE_SQL_USER1 = 19 +SCE_SQL_USER2 = 20 +SCE_SQL_USER3 = 21 +SCE_SQL_USER4 = 22 +SCE_SQL_QUOTEDIDENTIFIER = 23 +SCE_ST_DEFAULT = 0 +SCE_ST_STRING = 1 +SCE_ST_NUMBER = 2 +SCE_ST_COMMENT = 3 +SCE_ST_SYMBOL = 4 +SCE_ST_BINARY = 5 +SCE_ST_BOOL = 6 +SCE_ST_SELF = 7 +SCE_ST_SUPER = 8 +SCE_ST_NIL = 9 +SCE_ST_GLOBAL = 10 +SCE_ST_RETURN = 11 +SCE_ST_SPECIAL = 12 +SCE_ST_KWSEND = 13 +SCE_ST_ASSIGN = 14 +SCE_ST_CHARACTER = 15 +SCE_ST_SPEC_SEL = 16 +SCE_FS_DEFAULT = 0 +SCE_FS_COMMENT = 1 +SCE_FS_COMMENTLINE = 2 +SCE_FS_COMMENTDOC = 3 +SCE_FS_COMMENTLINEDOC = 4 +SCE_FS_COMMENTDOCKEYWORD = 5 +SCE_FS_COMMENTDOCKEYWORDERROR = 6 +SCE_FS_KEYWORD = 7 +SCE_FS_KEYWORD2 = 8 +SCE_FS_KEYWORD3 = 9 +SCE_FS_KEYWORD4 = 10 +SCE_FS_NUMBER = 11 +SCE_FS_STRING = 12 +SCE_FS_PREPROCESSOR = 13 +SCE_FS_OPERATOR = 14 +SCE_FS_IDENTIFIER = 15 +SCE_FS_DATE = 16 +SCE_FS_STRINGEOL = 17 +SCE_FS_CONSTANT = 18 +SCE_FS_ASM = 19 +SCE_FS_LABEL = 20 +SCE_FS_ERROR = 21 +SCE_FS_HEXNUMBER = 22 +SCE_FS_BINNUMBER = 23 +SCE_CSOUND_DEFAULT = 0 +SCE_CSOUND_COMMENT = 1 +SCE_CSOUND_NUMBER = 2 +SCE_CSOUND_OPERATOR = 3 +SCE_CSOUND_INSTR = 4 +SCE_CSOUND_IDENTIFIER = 5 +SCE_CSOUND_OPCODE = 6 +SCE_CSOUND_HEADERSTMT = 7 +SCE_CSOUND_USERKEYWORD = 8 +SCE_CSOUND_COMMENTBLOCK = 9 +SCE_CSOUND_PARAM = 10 +SCE_CSOUND_ARATE_VAR = 11 +SCE_CSOUND_KRATE_VAR = 12 +SCE_CSOUND_IRATE_VAR = 13 +SCE_CSOUND_GLOBAL_VAR = 14 +SCE_CSOUND_STRINGEOL = 15 +SCE_INNO_DEFAULT = 0 +SCE_INNO_COMMENT = 1 +SCE_INNO_KEYWORD = 2 +SCE_INNO_PARAMETER = 3 +SCE_INNO_SECTION = 4 +SCE_INNO_PREPROC = 5 +SCE_INNO_PREPROC_INLINE = 6 +SCE_INNO_COMMENT_PASCAL = 7 +SCE_INNO_KEYWORD_PASCAL = 8 +SCE_INNO_KEYWORD_USER = 9 +SCE_INNO_STRING_DOUBLE = 10 +SCE_INNO_STRING_SINGLE = 11 +SCE_INNO_IDENTIFIER = 12 +SCE_OPAL_SPACE = 0 +SCE_OPAL_COMMENT_BLOCK = 1 +SCE_OPAL_COMMENT_LINE = 2 +SCE_OPAL_INTEGER = 3 +SCE_OPAL_KEYWORD = 4 +SCE_OPAL_SORT = 5 +SCE_OPAL_STRING = 6 +SCE_OPAL_PAR = 7 +SCE_OPAL_BOOL_CONST = 8 +SCE_OPAL_DEFAULT = 32 +SCE_SPICE_DEFAULT = 0 +SCE_SPICE_IDENTIFIER = 1 +SCE_SPICE_KEYWORD = 2 +SCE_SPICE_KEYWORD2 = 3 +SCE_SPICE_KEYWORD3 = 4 +SCE_SPICE_NUMBER = 5 +SCE_SPICE_DELIMITER = 6 +SCE_SPICE_VALUE = 7 +SCE_SPICE_COMMENTLINE = 8 +SCE_CMAKE_DEFAULT = 0 +SCE_CMAKE_COMMENT = 1 +SCE_CMAKE_STRINGDQ = 2 +SCE_CMAKE_STRINGLQ = 3 +SCE_CMAKE_STRINGRQ = 4 +SCE_CMAKE_COMMANDS = 5 +SCE_CMAKE_PARAMETERS = 6 +SCE_CMAKE_VARIABLE = 7 +SCE_CMAKE_USERDEFINED = 8 +SCE_CMAKE_WHILEDEF = 9 +SCE_CMAKE_FOREACHDEF = 10 +SCE_CMAKE_IFDEFINEDEF = 11 +SCE_CMAKE_MACRODEF = 12 +SCE_CMAKE_STRINGVAR = 13 +SCE_CMAKE_NUMBER = 14 +SCE_GAP_DEFAULT = 0 +SCE_GAP_IDENTIFIER = 1 +SCE_GAP_KEYWORD = 2 +SCE_GAP_KEYWORD2 = 3 +SCE_GAP_KEYWORD3 = 4 +SCE_GAP_KEYWORD4 = 5 +SCE_GAP_STRING = 6 +SCE_GAP_CHAR = 7 +SCE_GAP_OPERATOR = 8 +SCE_GAP_COMMENT = 9 +SCE_GAP_NUMBER = 10 +SCE_GAP_STRINGEOL = 11 +SCE_PLM_DEFAULT = 0 +SCE_PLM_COMMENT = 1 +SCE_PLM_STRING = 2 +SCE_PLM_NUMBER = 3 +SCE_PLM_IDENTIFIER = 4 +SCE_PLM_OPERATOR = 5 +SCE_PLM_CONTROL = 6 +SCE_PLM_KEYWORD = 7 +SCE_4GL_DEFAULT = 0 +SCE_4GL_NUMBER = 1 +SCE_4GL_WORD = 2 +SCE_4GL_STRING = 3 +SCE_4GL_CHARACTER = 4 +SCE_4GL_PREPROCESSOR = 5 +SCE_4GL_OPERATOR = 6 +SCE_4GL_IDENTIFIER = 7 +SCE_4GL_BLOCK = 8 +SCE_4GL_END = 9 +SCE_4GL_COMMENT1 = 10 +SCE_4GL_COMMENT2 = 11 +SCE_4GL_COMMENT3 = 12 +SCE_4GL_COMMENT4 = 13 +SCE_4GL_COMMENT5 = 14 +SCE_4GL_COMMENT6 = 15 +SCE_4GL_DEFAULT_ = 16 +SCE_4GL_NUMBER_ = 17 +SCE_4GL_WORD_ = 18 +SCE_4GL_STRING_ = 19 +SCE_4GL_CHARACTER_ = 20 +SCE_4GL_PREPROCESSOR_ = 21 +SCE_4GL_OPERATOR_ = 22 +SCE_4GL_IDENTIFIER_ = 23 +SCE_4GL_BLOCK_ = 24 +SCE_4GL_END_ = 25 +SCE_4GL_COMMENT1_ = 26 +SCE_4GL_COMMENT2_ = 27 +SCE_4GL_COMMENT3_ = 28 +SCE_4GL_COMMENT4_ = 29 +SCE_4GL_COMMENT5_ = 30 +SCE_4GL_COMMENT6_ = 31 +SCE_ABAQUS_DEFAULT = 0 +SCE_ABAQUS_COMMENT = 1 +SCE_ABAQUS_COMMENTBLOCK = 2 +SCE_ABAQUS_NUMBER = 3 +SCE_ABAQUS_STRING = 4 +SCE_ABAQUS_OPERATOR = 5 +SCE_ABAQUS_WORD = 6 +SCE_ABAQUS_PROCESSOR = 7 +SCE_ABAQUS_COMMAND = 8 +SCE_ABAQUS_SLASHCOMMAND = 9 +SCE_ABAQUS_STARCOMMAND = 10 +SCE_ABAQUS_ARGUMENT = 11 +SCE_ABAQUS_FUNCTION = 12 +SCE_ASY_DEFAULT = 0 +SCE_ASY_COMMENT = 1 +SCE_ASY_COMMENTLINE = 2 +SCE_ASY_NUMBER = 3 +SCE_ASY_WORD = 4 +SCE_ASY_STRING = 5 +SCE_ASY_CHARACTER = 6 +SCE_ASY_OPERATOR = 7 +SCE_ASY_IDENTIFIER = 8 +SCE_ASY_STRINGEOL = 9 +SCE_ASY_COMMENTLINEDOC = 10 +SCE_ASY_WORD2 = 11 +SCE_R_DEFAULT = 0 +SCE_R_COMMENT = 1 +SCE_R_KWORD = 2 +SCE_R_BASEKWORD = 3 +SCE_R_OTHERKWORD = 4 +SCE_R_NUMBER = 5 +SCE_R_STRING = 6 +SCE_R_STRING2 = 7 +SCE_R_OPERATOR = 8 +SCE_R_IDENTIFIER = 9 +SCE_R_INFIX = 10 +SCE_R_INFIXEOL = 11 +SCE_MAGIK_DEFAULT = 0 +SCE_MAGIK_COMMENT = 1 +SCE_MAGIK_HYPER_COMMENT = 16 +SCE_MAGIK_STRING = 2 +SCE_MAGIK_CHARACTER = 3 +SCE_MAGIK_NUMBER = 4 +SCE_MAGIK_IDENTIFIER = 5 +SCE_MAGIK_OPERATOR = 6 +SCE_MAGIK_FLOW = 7 +SCE_MAGIK_CONTAINER = 8 +SCE_MAGIK_BRACKET_BLOCK = 9 +SCE_MAGIK_BRACE_BLOCK = 10 +SCE_MAGIK_SQBRACKET_BLOCK = 11 +SCE_MAGIK_UNKNOWN_KEYWORD = 12 +SCE_MAGIK_KEYWORD = 13 +SCE_MAGIK_PRAGMA = 14 +SCE_MAGIK_SYMBOL = 15 +SCE_POWERSHELL_DEFAULT = 0 +SCE_POWERSHELL_COMMENT = 1 +SCE_POWERSHELL_STRING = 2 +SCE_POWERSHELL_CHARACTER = 3 +SCE_POWERSHELL_NUMBER = 4 +SCE_POWERSHELL_VARIABLE = 5 +SCE_POWERSHELL_OPERATOR = 6 +SCE_POWERSHELL_IDENTIFIER = 7 +SCE_POWERSHELL_KEYWORD = 8 +SCE_POWERSHELL_CMDLET = 9 +SCE_POWERSHELL_ALIAS = 10 +SCE_MYSQL_DEFAULT = 0 +SCE_MYSQL_COMMENT = 1 +SCE_MYSQL_COMMENTLINE = 2 +SCE_MYSQL_VARIABLE = 3 +SCE_MYSQL_SYSTEMVARIABLE = 4 +SCE_MYSQL_KNOWNSYSTEMVARIABLE = 5 +SCE_MYSQL_NUMBER = 6 +SCE_MYSQL_MAJORKEYWORD = 7 +SCE_MYSQL_KEYWORD = 8 +SCE_MYSQL_DATABASEOBJECT = 9 +SCE_MYSQL_PROCEDUREKEYWORD = 10 +SCE_MYSQL_STRING = 11 +SCE_MYSQL_SQSTRING = 12 +SCE_MYSQL_DQSTRING = 13 +SCE_MYSQL_OPERATOR = 14 +SCE_MYSQL_FUNCTION = 15 +SCE_MYSQL_IDENTIFIER = 16 +SCE_MYSQL_QUOTEDIDENTIFIER = 17 +SCE_MYSQL_USER1 = 18 +SCE_MYSQL_USER2 = 19 +SCE_MYSQL_USER3 = 20 +SCE_PO_DEFAULT = 0 +SCE_PO_COMMENT = 1 +SCE_PO_MSGID = 2 +SCE_PO_MSGID_TEXT = 3 +SCE_PO_MSGSTR = 4 +SCE_PO_MSGSTR_TEXT = 5 +SCE_PO_MSGCTXT = 6 +SCE_PO_MSGCTXT_TEXT = 7 +SCE_PO_FUZZY = 8 +SCLEX_ASP = 29 +SCLEX_PHP = 30 diff --git a/Lib/site-packages/pythonwin/pywin/scintilla/view.py b/Lib/site-packages/pythonwin/pywin/scintilla/view.py new file mode 100644 index 0000000..9f15905 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/scintilla/view.py @@ -0,0 +1,722 @@ +# A general purpose MFC CCtrlView view that uses Scintilla. + +from . import control +from . import IDLEenvironment # IDLE emulation. +from pywin.mfc import docview +from pywin.mfc import dialog +from . import scintillacon +import win32con +import win32ui +import afxres +import string +import array +import sys +import types +import __main__ # for attribute lookup +from . import bindings +from . import keycodes +import struct +import re +import os + +PRINTDLGORD = 1538 +IDC_PRINT_MAG_EDIT = 1010 +EM_FORMATRANGE = win32con.WM_USER+57 + +wordbreaks = "._" + string.ascii_uppercase + string.ascii_lowercase + string.digits + +patImport=re.compile('import (?P.*)') + +_event_commands = [ + # File menu + "win32ui.ID_FILE_LOCATE", "win32ui.ID_FILE_CHECK", "afxres.ID_FILE_CLOSE", + "afxres.ID_FILE_NEW", "afxres.ID_FILE_OPEN", "afxres.ID_FILE_SAVE", + "afxres.ID_FILE_SAVE_AS", "win32ui.ID_FILE_SAVE_ALL", + # Edit menu + "afxres.ID_EDIT_UNDO", "afxres.ID_EDIT_REDO", "afxres.ID_EDIT_CUT", + "afxres.ID_EDIT_COPY", "afxres.ID_EDIT_PASTE", "afxres.ID_EDIT_SELECT_ALL", + "afxres.ID_EDIT_FIND", "afxres.ID_EDIT_REPEAT", "afxres.ID_EDIT_REPLACE", + # View menu + "win32ui.ID_VIEW_WHITESPACE", "win32ui.ID_VIEW_FIXED_FONT", + "win32ui.ID_VIEW_BROWSE", "win32ui.ID_VIEW_INTERACTIVE", + # Window menu + "afxres.ID_WINDOW_ARRANGE", "afxres.ID_WINDOW_CASCADE", + "afxres.ID_WINDOW_NEW", "afxres.ID_WINDOW_SPLIT", + "afxres.ID_WINDOW_TILE_HORZ", "afxres.ID_WINDOW_TILE_VERT", + # Others + "afxres.ID_APP_EXIT", "afxres.ID_APP_ABOUT", +] + +_extra_event_commands = [ + ("EditDelete", afxres.ID_EDIT_CLEAR), + ("LocateModule", win32ui.ID_FILE_LOCATE), + ("GotoLine", win32ui.ID_EDIT_GOTO_LINE), + ("DbgBreakpointToggle", win32ui.IDC_DBG_ADD), + ("DbgGo", win32ui.IDC_DBG_GO), + ("DbgStepOver", win32ui.IDC_DBG_STEPOVER), + ("DbgStep", win32ui.IDC_DBG_STEP), + ("DbgStepOut", win32ui.IDC_DBG_STEPOUT), + ("DbgBreakpointClearAll", win32ui.IDC_DBG_CLEAR), + ("DbgClose", win32ui.IDC_DBG_CLOSE), +] + +event_commands = [] +def _CreateEvents(): + for name in _event_commands: + val = eval(name) + name_parts = name.split("_")[1:] + name_parts = [p.capitalize() for p in name_parts] + event = ''.join(name_parts) + event_commands.append((event, val)) + for name, id in _extra_event_commands: + event_commands.append((name, id)) + +_CreateEvents() +del _event_commands; del _extra_event_commands + +command_reflectors = [ + (win32ui.ID_EDIT_UNDO, win32con.WM_UNDO), + (win32ui.ID_EDIT_REDO, scintillacon.SCI_REDO), + (win32ui.ID_EDIT_CUT, win32con.WM_CUT), + (win32ui.ID_EDIT_COPY, win32con.WM_COPY), + (win32ui.ID_EDIT_PASTE, win32con.WM_PASTE), + (win32ui.ID_EDIT_CLEAR, win32con.WM_CLEAR), + (win32ui.ID_EDIT_SELECT_ALL, scintillacon.SCI_SELECTALL), +] + +def DoBraceMatch(control): + curPos = control.SCIGetCurrentPos() + charBefore = ' ' + if curPos: charBefore = control.SCIGetCharAt(curPos-1) + charAt = control.SCIGetCharAt(curPos) + braceAtPos = braceOpposite = -1 + if charBefore in "[](){}": braceAtPos = curPos-1 + if braceAtPos==-1: + if charAt in "[](){}": braceAtPos = curPos + if braceAtPos != -1: + braceOpposite = control.SCIBraceMatch(braceAtPos, 0) + if braceAtPos != -1 and braceOpposite==-1: + control.SCIBraceBadHighlight(braceAtPos) + else: + # either clear them both or set them both. + control.SCIBraceHighlight(braceAtPos, braceOpposite) + +def _get_class_attributes(ob): + # Recurse into base classes looking for attributes + items = [] + try: + items = items + dir(ob) + for i in ob.__bases__: + for item in _get_class_attributes(i): + if item not in items: + items.append(item) + except AttributeError: + pass + return items + +# Supposed to look like an MFC CEditView, but +# also supports IDLE extensions and other source code generic features. +class CScintillaView(docview.CtrlView, control.CScintillaColorEditInterface): + def __init__(self, doc): + docview.CtrlView.__init__(self, doc, "Scintilla", win32con.WS_CHILD | win32con.WS_VSCROLL | win32con.WS_HSCROLL | win32con.WS_CLIPCHILDREN | win32con.WS_VISIBLE) + self._tabWidth = 8 # Mirror of what we send to Scintilla - never change this directly + self.bAutoCompleteAttributes = 1 + self.bShowCallTips = 1 + self.bMatchBraces = 0 # Editor option will default this to true later! + self.bindings = bindings.BindingsManager(self) + + self.idle = IDLEenvironment.IDLEEditorWindow(self) + self.idle.IDLEExtension("AutoExpand") + # SendScintilla is called so frequently it is worth optimizing. + self.SendScintilla = self._obj_.SendMessage + + def OnDestroy(self, msg): + self.SendScintilla = None + return docview.CtrlView.OnDestroy(self, msg) + + def _MakeColorizer(self): + ext = os.path.splitext(self.GetDocument().GetPathName())[1] + from . import formatter + return formatter.BuiltinPythonSourceFormatter(self, ext) + + +# def SendScintilla(self, msg, w=0, l=0): +# return self._obj_.SendMessage(msg, w, l) + + def SCISetTabWidth(self, width): + # I need to remember the tab-width for the AutoIndent extension. This may go. + self._tabWidth = width + control.CScintillaEditInterface.SCISetTabWidth(self, width) + + def GetTabWidth(self): + return self._tabWidth + + def HookHandlers(self): + # Create events for all the menu names. + for name, val in event_commands: +# handler = lambda id, code, tosend=val, parent=parent: parent.OnCommand(tosend, 0) and 0 + self.bindings.bind(name, None, cid=val) + + # Hook commands that do nothing other than send Scintilla messages. + for command, reflection in command_reflectors: + handler = lambda id, code, ss=self.SendScintilla, tosend=reflection: ss(tosend) and 0 + self.HookCommand(handler, command) + + self.HookCommand(self.OnCmdViewWS, win32ui.ID_VIEW_WHITESPACE) + self.HookCommandUpdate(self.OnUpdateViewWS, win32ui.ID_VIEW_WHITESPACE) + self.HookCommand(self.OnCmdViewIndentationGuides, win32ui.ID_VIEW_INDENTATIONGUIDES) + self.HookCommandUpdate(self.OnUpdateViewIndentationGuides, win32ui.ID_VIEW_INDENTATIONGUIDES) + self.HookCommand(self.OnCmdViewRightEdge, win32ui.ID_VIEW_RIGHT_EDGE) + self.HookCommandUpdate(self.OnUpdateViewRightEdge, win32ui.ID_VIEW_RIGHT_EDGE) + self.HookCommand(self.OnCmdViewEOL, win32ui.ID_VIEW_EOL) + self.HookCommandUpdate(self.OnUpdateViewEOL, win32ui.ID_VIEW_EOL) + self.HookCommand(self.OnCmdViewFixedFont, win32ui.ID_VIEW_FIXED_FONT) + self.HookCommandUpdate(self.OnUpdateViewFixedFont, win32ui.ID_VIEW_FIXED_FONT) + self.HookCommand(self.OnCmdFileLocate, win32ui.ID_FILE_LOCATE) + self.HookCommand(self.OnCmdEditFind, win32ui.ID_EDIT_FIND) + self.HookCommand(self.OnCmdEditRepeat, win32ui.ID_EDIT_REPEAT) + self.HookCommand(self.OnCmdEditReplace, win32ui.ID_EDIT_REPLACE) + self.HookCommand(self.OnCmdGotoLine, win32ui.ID_EDIT_GOTO_LINE) + self.HookCommand(self.OnFilePrint, afxres.ID_FILE_PRINT) + self.HookCommand(self.OnFilePrint, afxres.ID_FILE_PRINT_DIRECT) + self.HookCommand(self.OnFilePrintPreview, + win32ui.ID_FILE_PRINT_PREVIEW) + # Key bindings. + self.HookMessage(self.OnKeyDown, win32con.WM_KEYDOWN) + self.HookMessage(self.OnKeyDown, win32con.WM_SYSKEYDOWN) + # Hook wheeley mouse events +# self.HookMessage(self.OnMouseWheel, win32con.WM_MOUSEWHEEL) + self.HookFormatter() + + def OnInitialUpdate(self): + doc = self.GetDocument() + + # Enable Unicode + self.SendScintilla(scintillacon.SCI_SETCODEPAGE, scintillacon.SC_CP_UTF8, 0) + self.SendScintilla(scintillacon.SCI_SETKEYSUNICODE, 1, 0) + + # Create margins + self.SendScintilla(scintillacon.SCI_SETMARGINTYPEN, 1, scintillacon.SC_MARGIN_SYMBOL); + self.SendScintilla(scintillacon.SCI_SETMARGINMASKN, 1, 0xF); + self.SendScintilla(scintillacon.SCI_SETMARGINTYPEN, 2, scintillacon.SC_MARGIN_SYMBOL); + self.SendScintilla(scintillacon.SCI_SETMARGINMASKN, 2, scintillacon.SC_MASK_FOLDERS); + self.SendScintilla(scintillacon.SCI_SETMARGINSENSITIVEN, 2, 1); + + self.GetDocument().HookViewNotifications(self) # is there an MFC way to grab this? + self.HookHandlers() + + # Load the configuration information. + self.OnWinIniChange(None) + + self.SetSel() + + self.GetDocument().FinalizeViewCreation(self) # is there an MFC way to grab this? + + + def _GetSubConfigNames(self): + return None # By default we use only sections without sub-sections. + + def OnWinIniChange(self, section = None): + self.bindings.prepare_configure() + try: + self.DoConfigChange() + finally: + self.bindings.complete_configure() + + def DoConfigChange(self): + # Bit of a hack I dont kow what to do about - these should be "editor options" + from pywin.framework.editor import GetEditorOption + self.bAutoCompleteAttributes = GetEditorOption("Autocomplete Attributes", 1) + self.bShowCallTips = GetEditorOption("Show Call Tips", 1) + # Update the key map and extension data. + configManager.configure(self, self._GetSubConfigNames()) + if configManager.last_error: + win32ui.MessageBox(configManager.last_error, "Configuration Error") + self.bMatchBraces = GetEditorOption("Match Braces", 1) + self.ApplyFormattingStyles(1) + + def OnDestroy(self, msg): + self.bindings.close() + self.bindings = None + self.idle.close() + self.idle = None + control.CScintillaColorEditInterface.close(self) + return docview.CtrlView.OnDestroy(self, msg) + + def OnMouseWheel(self, msg): + zDelta = msg[2] >> 16 + vpos = self.GetScrollPos(win32con.SB_VERT) + vpos = vpos - zDelta/40 # 3 lines per notch + self.SetScrollPos(win32con.SB_VERT, vpos) + self.SendScintilla(win32con.WM_VSCROLL, + (vpos<<16) | win32con.SB_THUMBPOSITION, + 0) + + def OnBraceMatch(self, std, extra): + if not self.bMatchBraces: return + DoBraceMatch(self) + + def OnNeedShown(self, std, extra): + notify = self.SCIUnpackNotifyMessage(extra) + # OnNeedShown is called before an edit operation when + # text is folded (as it is possible the text insertion will happen + # in a folded region.) As this happens _before_ the insert, + # we ignore the length (if we are at EOF, pos + length may + # actually be beyond the end of buffer) + self.EnsureCharsVisible(notify.position) + + def EnsureCharsVisible(self, start, end = None): + if end is None: end = start + lineStart = self.LineFromChar(min(start, end)) + lineEnd = self.LineFromChar(max(start, end)) + while lineStart <= lineEnd: + self.SCIEnsureVisible(lineStart) + lineStart = lineStart + 1 + + # Helper to add an event to a menu. + def AppendMenu(self, menu, text="", event=None, flags = None, checked=0): + if event is None: + assert flags is not None, "No event or custom flags!" + cmdid = 0 + else: + cmdid = self.bindings.get_command_id(event) + if cmdid is None: + # No event of that name - no point displaying it. + print('View.AppendMenu(): Unknown event "%s" specified for menu text "%s" - ignored' % (event, text)) + return + keyname = configManager.get_key_binding( event, self._GetSubConfigNames() ) + if keyname is not None: + text = text + "\t" + keyname + if flags is None: flags = win32con.MF_STRING|win32con.MF_ENABLED + if checked: flags = flags | win32con.MF_CHECKED + menu.AppendMenu(flags, cmdid, text) + + def OnKeyDown(self, msg): + return self.bindings.fire_key_event( msg ) + + def GotoEndOfFileEvent(self, event): + self.SetSel(-1) + + def KeyDotEvent(self, event): + ## Don't trigger autocomplete if any text is selected + s,e = self.GetSel() + if s!=e: + return 1 + self.SCIAddText(".") + if self.bAutoCompleteAttributes: + self._AutoComplete() + + # View Whitespace/EOL/Indentation UI. + + def OnCmdViewWS(self, cmd, code): # Handle the menu command + viewWS = self.SCIGetViewWS() + self.SCISetViewWS(not viewWS) + def OnUpdateViewWS(self, cmdui): # Update the tick on the UI. + cmdui.SetCheck(self.SCIGetViewWS()) + cmdui.Enable() + def OnCmdViewIndentationGuides(self, cmd, code): # Handle the menu command + viewIG = self.SCIGetIndentationGuides() + self.SCISetIndentationGuides(not viewIG) + def OnUpdateViewIndentationGuides(self, cmdui): # Update the tick on the UI. + cmdui.SetCheck(self.SCIGetIndentationGuides()) + cmdui.Enable() + def OnCmdViewRightEdge(self, cmd, code): # Handle the menu command + if self.SCIGetEdgeMode() == scintillacon.EDGE_NONE: + mode = scintillacon.EDGE_BACKGROUND + else: + mode = scintillacon.EDGE_NONE + self.SCISetEdgeMode(mode) + def OnUpdateViewRightEdge(self, cmdui): # Update the tick on the UI. + cmdui.SetCheck(self.SCIGetEdgeMode() != scintillacon.EDGE_NONE) + cmdui.Enable() + def OnCmdViewEOL(self, cmd, code): # Handle the menu command + viewEOL = self.SCIGetViewEOL() + self.SCISetViewEOL(not viewEOL) + def OnUpdateViewEOL(self, cmdui): # Update the tick on the UI. + cmdui.SetCheck(self.SCIGetViewEOL()) + cmdui.Enable() + + def OnCmdViewFixedFont(self, cmd, code): # Handle the menu command + self._GetColorizer().bUseFixed = not self._GetColorizer().bUseFixed + self.ApplyFormattingStyles(0) + # Ensure the selection is visible! + self.ScrollCaret() + + def OnUpdateViewFixedFont(self, cmdui): # Update the tick on the UI. + c = self._GetColorizer() + if c is not None: cmdui.SetCheck(c.bUseFixed) + cmdui.Enable(c is not None) + + def OnCmdEditFind(self, cmd, code): + from . import find + find.ShowFindDialog() + def OnCmdEditRepeat(self, cmd, code): + from . import find + find.FindNext() + def OnCmdEditReplace(self, cmd, code): + from . import find + find.ShowReplaceDialog() + + def OnCmdFileLocate(self, cmd, id): + line = self.GetLine().strip() + import pywin.framework.scriptutils + m = patImport.match(line) + if m: + # Module name on this line - locate that! + modName = m.group('name') + fileName = pywin.framework.scriptutils.LocatePythonFile(modName) + if fileName is None: + win32ui.SetStatusText("Can't locate module %s" % modName) + return 1 # Let the default get it. + else: + win32ui.GetApp().OpenDocumentFile(fileName) + else: + # Just to a "normal" locate - let the default handler get it. + return 1 + return 0 + + def OnCmdGotoLine(self, cmd, id): + try: + lineNo = int(input("Enter Line Number"))-1 + except (ValueError, KeyboardInterrupt): + return 0 + self.SCIEnsureVisible(lineNo) + self.SCIGotoLine(lineNo) + return 0 + + def SaveTextFile(self, filename, encoding=None): + doc = self.GetDocument() + doc._SaveTextToFile(self, filename, encoding=encoding) + doc.SetModifiedFlag(0) + return 1 + + def _AutoComplete(self): + def list2dict(l): + ret={} + for i in l: + ret[i] = None + return ret + + self.SCIAutoCCancel() # Cancel old auto-complete lists. + # First try and get an object without evaluating calls + ob = self._GetObjectAtPos(bAllowCalls = 0) + # If that failed, try and process call or indexing to get the object. + if ob is None: + ob = self._GetObjectAtPos(bAllowCalls = 1) + items_dict = {} + if ob is not None: + try: # Catch unexpected errors when fetching attribute names from the object + # extra attributes of win32ui objects + if hasattr(ob, "_obj_"): + try: + items_dict.update(list2dict(dir(ob._obj_))) + except AttributeError: + pass # object has no __dict__ + + # normal attributes + try: + items_dict.update(list2dict(dir(ob))) + except AttributeError: + pass # object has no __dict__ + if hasattr(ob, "__class__"): + items_dict.update(list2dict(_get_class_attributes(ob.__class__))) + # The object may be a COM object with typelib support - lets see if we can get its props. + # (contributed by Stefan Migowsky) + try: + # Get the automation attributes + items_dict.update(ob.__class__._prop_map_get_) + # See if there is an write only property + # could be optimized + items_dict.update(ob.__class__._prop_map_put_) + # append to the already evaluated list + except AttributeError: + pass + # The object might be a pure COM dynamic dispatch with typelib support - lets see if we can get its props. + if hasattr(ob, "_oleobj_"): + try: + for iTI in range(0,ob._oleobj_.GetTypeInfoCount()): + typeInfo = ob._oleobj_.GetTypeInfo(iTI) + self._UpdateWithITypeInfo (items_dict, typeInfo) + except: + pass + except: + win32ui.SetStatusText("Error attempting to get object attributes - %s" % (repr(sys.exc_info()[0]),)) + + # ensure all keys are strings. + items = [str(k) for k in items_dict.keys()] + # All names that start with "_" go! + items = [k for k in items if not k.startswith('_')] + + if not items: + # Heuristics a-la AutoExpand + # The idea is to find other usages of the current binding + # and assume, that it refers to the same object (or at least, + # to an object of the same type) + # Contributed by Vadim Chugunov [vadimch@yahoo.com] + left, right = self._GetWordSplit() + if left=="": # Ignore standalone dots + return None + # We limit our search to the current class, if that + # information is available + minline, maxline, curclass = self._GetClassInfoFromBrowser() + endpos = self.LineIndex(maxline) + text = self.GetTextRange(self.LineIndex(minline),endpos) + try: + l = re.findall(r"\b"+left+"\.\w+",text) + except re.error: + # parens etc may make an invalid RE, but this code wouldnt + # benefit even if the RE did work :-) + l = [] + prefix = len(left)+1 + unique = {} + for li in l: + unique[li[prefix:]] = 1 + # Assuming traditional usage of self... + if curclass and left=="self": + self._UpdateWithClassMethods(unique,curclass) + + items = [word for word in unique.keys() if word[:2]!='__' or word[-2:]!='__'] + # Ignore the word currently to the right of the dot - probably a red-herring. + try: + items.remove(right[1:]) + except ValueError: + pass + if items: + items.sort() + self.SCIAutoCSetAutoHide(0) + self.SCIAutoCShow(items) + + def _UpdateWithITypeInfo (self, items_dict, typeInfo): + import pythoncom + typeInfos = [typeInfo] + # suppress IDispatch and IUnknown methods + inspectedIIDs = {pythoncom.IID_IDispatch:None} + + while len(typeInfos)>0: + typeInfo = typeInfos.pop() + typeAttr = typeInfo.GetTypeAttr() + + if typeAttr.iid not in inspectedIIDs: + inspectedIIDs[typeAttr.iid] = None + for iFun in range(0,typeAttr.cFuncs): + funDesc = typeInfo.GetFuncDesc(iFun) + funName = typeInfo.GetNames(funDesc.memid)[0] + if funName not in items_dict: + items_dict[funName] = None + + # Inspect the type info of all implemented types + # E.g. IShellDispatch5 implements IShellDispatch4 which implements IShellDispatch3 ... + for iImplType in range(0,typeAttr.cImplTypes): + iRefType = typeInfo.GetRefTypeOfImplType(iImplType) + refTypeInfo = typeInfo.GetRefTypeInfo(iRefType) + typeInfos.append(refTypeInfo) + + # TODO: This is kinda slow. Probably need some kind of cache + # here that is flushed upon file save + # Or maybe we don't need the superclass methods at all ? + def _UpdateWithClassMethods(self,dict,classinfo): + if not hasattr(classinfo,"methods"): + # No 'methods' - probably not what we think it is. + return + dict.update(classinfo.methods) + for super in classinfo.super: + if hasattr(super,"methods"): + self._UpdateWithClassMethods(dict,super) + + # Find which class definition caret is currently in and return + # indexes of the the first and the last lines of that class definition + # Data is obtained from module browser (if enabled) + def _GetClassInfoFromBrowser(self,pos=-1): + minline = 0 + maxline = self.GetLineCount()-1 + doc = self.GetParentFrame().GetActiveDocument() + browser = None + try: + if doc is not None: + browser = doc.GetAllViews()[1] + except IndexError: + pass + if browser is None: + return (minline,maxline,None) # Current window has no browser + if not browser.list: return (minline,maxline,None) # Not initialized + path = self.GetDocument().GetPathName() + if not path: return (minline,maxline,None) # No current path + + import pywin.framework.scriptutils + curmodule, path = pywin.framework.scriptutils.GetPackageModuleName(path) + try: + clbrdata = browser.list.root.clbrdata + except AttributeError: + return (minline,maxline,None) # No class data for this module. + curline = self.LineFromChar(pos) + curclass = None + # Find out which class we are in + for item in clbrdata.values(): + if item.module==curmodule: + item_lineno = item.lineno - 1 # Scintilla counts lines from 0, whereas pyclbr - from 1 + if minline < item_lineno <= curline: + minline = item_lineno + curclass = item + if curline < item_lineno < maxline: + maxline = item_lineno + return (minline,maxline,curclass) + + + def _GetObjectAtPos(self, pos = -1, bAllowCalls = 0): + left, right = self._GetWordSplit(pos, bAllowCalls) + if left: # It is an attribute lookup + # How is this for a hack! + namespace = sys.modules.copy() + namespace.update(__main__.__dict__) + # Get the debugger's context. + try: + from pywin.framework import interact + if interact.edit is not None and interact.edit.currentView is not None: + globs, locs = interact.edit.currentView.GetContext()[:2] + if globs: namespace.update(globs) + if locs: namespace.update(locs) + except ImportError: + pass + try: + return eval(left, namespace) + except: + pass + return None + + def _GetWordSplit(self, pos = -1, bAllowCalls = 0): + if pos==-1: pos = self.GetSel()[0]-1 # Character before current one + limit = self.GetTextLength() + before = [] + after = [] + index = pos-1 + wordbreaks_use = wordbreaks + if bAllowCalls: wordbreaks_use = wordbreaks_use + "()[]" + while index>=0: + char = self.SCIGetCharAt(index) + if char not in wordbreaks_use: break + before.insert(0, char) + index = index-1 + index = pos + while index<=limit: + char = self.SCIGetCharAt(index) + if char not in wordbreaks_use: break + after.append(char) + index=index+1 + return ''.join(before), ''.join(after) + + def OnPrepareDC (self, dc, pInfo): +# print "OnPrepareDC for page", pInfo.GetCurPage(), "of", pInfo.GetFromPage(), "to", pInfo.GetToPage(), ", starts=", self.starts + if dc.IsPrinting(): + # Check if we are beyond the end. + # (only do this when actually printing, else messes up print preview!) + if not pInfo.GetPreview() and self.starts is not None: + prevPage = pInfo.GetCurPage() - 1 + if prevPage > 0 and self.starts[prevPage] >= self.GetTextLength(): + # All finished. + pInfo.SetContinuePrinting(0) + return + dc.SetMapMode(win32con.MM_TEXT); + + def OnPreparePrinting(self, pInfo): + flags = win32ui.PD_USEDEVMODECOPIES | \ + win32ui.PD_ALLPAGES | \ + win32ui.PD_NOSELECTION # Dont support printing just a selection. +# NOTE: Custom print dialogs are stopping the user's values from coming back :-( +# self.prtDlg = PrintDialog(pInfo, PRINTDLGORD, flags) +# pInfo.SetPrintDialog(self.prtDlg) + pInfo.SetMinPage(1) + # max page remains undefined for now. + pInfo.SetFromPage(1) + pInfo.SetToPage(1) + ret = self.DoPreparePrinting(pInfo) + return ret + + def OnBeginPrinting(self, dc, pInfo): + self.starts = None + return self._obj_.OnBeginPrinting(dc, pInfo) + + def CalculatePageRanges(self, dc, pInfo): + # Calculate page ranges and max page + self.starts = {0:0} + metrics = dc.GetTextMetrics() + left, top, right, bottom = pInfo.GetDraw() + # Leave space at the top for the header. + rc = (left, top + int((9*metrics['tmHeight'])/2), right, bottom) + pageStart = 0 + maxPage = 0 + textLen = self.GetTextLength() + while pageStart < textLen: + pageStart = self.FormatRange(dc, pageStart, textLen, rc, 0) + maxPage = maxPage + 1 + self.starts[maxPage] = pageStart + # And a sentinal for one page past the end + self.starts[maxPage+1] = textLen + # When actually printing, maxPage doesnt have any effect at this late state. + # but is needed to make the Print Preview work correctly. + pInfo.SetMaxPage(maxPage) + + def OnFilePrintPreview(self, *arg): + self._obj_.OnFilePrintPreview() + + def OnFilePrint(self, *arg): + self._obj_.OnFilePrint() + + def FormatRange(self, dc, pageStart, lengthDoc, rc, draw): + """ + typedef struct _formatrange { + HDC hdc; + HDC hdcTarget; + RECT rc; + RECT rcPage; + CHARRANGE chrg;} FORMATRANGE; + """ + fmt='PPIIIIIIIIll' + hdcRender = dc.GetHandleOutput() + hdcFormat = dc.GetHandleAttrib() + fr = struct.pack(fmt, hdcRender, hdcFormat, rc[0], rc[1], rc[2], rc[3], rc[0], rc[1], rc[2], rc[3], pageStart, lengthDoc) + nextPageStart = self.SendScintilla(EM_FORMATRANGE, draw, fr) + return nextPageStart + + def OnPrint(self, dc, pInfo): + metrics = dc.GetTextMetrics() +# print "dev", w, h, l, metrics['tmAscent'], metrics['tmDescent'] + if self.starts is None: + self.CalculatePageRanges(dc, pInfo) + pageNum = pInfo.GetCurPage() - 1 + # Setup the header of the page - docname on left, pagenum on right. + doc = self.GetDocument() + cxChar = metrics['tmAveCharWidth'] + cyChar = metrics['tmHeight'] + left, top, right, bottom = pInfo.GetDraw() + dc.TextOut(0, 2*cyChar, doc.GetTitle()) + pagenum_str = win32ui.LoadString(afxres.AFX_IDS_PRINTPAGENUM) % (pageNum+1,) + dc.SetTextAlign(win32con.TA_RIGHT) + dc.TextOut(right, 2*cyChar, pagenum_str) + dc.SetTextAlign(win32con.TA_LEFT) + top = top + int((7*cyChar)/2) + dc.MoveTo(left, top) + dc.LineTo(right, top) + top = top + cyChar + rc = (left, top, right, bottom) + nextPageStart = self.FormatRange(dc, self.starts[pageNum], self.starts[pageNum+1], rc, 1) + +def LoadConfiguration(): + global configManager + # Bit of a hack I dont kow what to do about? + from .config import ConfigManager + configName = rc = win32ui.GetProfileVal("Editor", "Keyboard Config", "default") + configManager = ConfigManager(configName) + if configManager.last_error: + bTryDefault = 0 + msg = "Error loading configuration '%s'\n\n%s" % (configName, configManager.last_error) + if configName != "default": + msg = msg + "\n\nThe default configuration will be loaded." + bTryDefault = 1 + win32ui.MessageBox(msg) + if bTryDefault: + configManager = ConfigManager("default") + if configManager.last_error: + win32ui.MessageBox("Error loading configuration 'default'\n\n%s" % (configManager.last_error)) + +configManager = None +LoadConfiguration() diff --git a/Lib/site-packages/pythonwin/pywin/tools/TraceCollector.py b/Lib/site-packages/pythonwin/pywin/tools/TraceCollector.py new file mode 100644 index 0000000..041fbb0 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/tools/TraceCollector.py @@ -0,0 +1,66 @@ +# win32traceutil like utility for Pythonwin +import _thread +import win32trace, win32event, win32api +from pywin.framework import winout + +outputWindow = None + +def CollectorThread(stopEvent, file): + win32trace.InitRead() + handle = win32trace.GetHandle() + # Run this thread at a lower priority to the main message-loop (and printing output) + # thread can keep up + import win32process + win32process.SetThreadPriority(win32api.GetCurrentThread(), win32process.THREAD_PRIORITY_BELOW_NORMAL) + + try: + while 1: + rc = win32event.WaitForMultipleObjects((handle, stopEvent), 0, win32event.INFINITE) + if rc == win32event.WAIT_OBJECT_0: + # About the only char we can't live with is \0! + file.write(win32trace.read().replace("\0", "")) + else: + # Stop event + break + finally: + win32trace.TermRead() + print("Thread dieing") + +class WindowOutput(winout.WindowOutput): + def __init__(self, *args): + winout.WindowOutput.__init__(*(self,)+args) + self.hStopThread = win32event.CreateEvent(None, 0, 0, None) + _thread.start_new(CollectorThread, (self.hStopThread, self)) + def _StopThread(self): + win32event.SetEvent(self.hStopThread) + self.hStopThread = None + def Close(self): + self._StopThread() + winout.WindowOutput.Close(self) +# def OnViewDestroy(self, frame): +# return winout.WindowOutput.OnViewDestroy(self, frame) +# def Create(self, title=None, style = None): +# rc = winout.WindowOutput.Create(self, title, style) + return rc + + +def MakeOutputWindow(): + # Note that it will not show until the first string written or + # you pass bShow = 1 + global outputWindow + if outputWindow is None: + title = "Python Trace Collector" + # queueingFlag doesnt matter, as all output will come from new thread + outputWindow = WindowOutput(title, title) + # Let people know what this does! + msg = """\ +# This window will display output from any programs that import win32traceutil +# win32com servers registered with '--debug' are in this category. +""" + outputWindow.write(msg) + # force existing window open + outputWindow.write('') + return outputWindow + +if __name__=='__main__': + MakeOutputWindow() diff --git a/Lib/site-packages/pythonwin/pywin/tools/__init__.py b/Lib/site-packages/pythonwin/pywin/tools/__init__.py new file mode 100644 index 0000000..99a8091 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/tools/__init__.py @@ -0,0 +1,2 @@ + + diff --git a/Lib/site-packages/pythonwin/pywin/tools/browseProjects.py b/Lib/site-packages/pythonwin/pywin/tools/browseProjects.py new file mode 100644 index 0000000..3437aa3 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/tools/browseProjects.py @@ -0,0 +1,260 @@ +import regutil, os +from . import hierlist +import win32con, win32ui, win32api +import commctrl +from pywin.mfc import dialog +import glob +import pyclbr +import pywin.framework.scriptutils +import afxres + +class HLIErrorItem(hierlist.HierListItem): + def __init__(self, text): + self.text = text + hierlist.HierListItem.__init__(self) + def GetText(self): + return self.text + +class HLICLBRItem(hierlist.HierListItem): + def __init__(self, name, file, lineno, suffix = ""): + # If the 'name' object itself has a .name, use it. Not sure + # how this happens, but seems pyclbr related. + # See PyWin32 bug 817035 + self.name = getattr(name, "name", name) + self.file = file + self.lineno = lineno + self.suffix = suffix + def __lt__(self, other): + return self.name < other.name + def __eq__(self, other): + return self.name == other.name + def GetText(self): + return self.name + self.suffix + def TakeDefaultAction(self): + if self.file: + pywin.framework.scriptutils.JumpToDocument(self.file, self.lineno, bScrollToTop=1) + else: + win32ui.SetStatusText("The source of this object is unknown") + def PerformItemSelected(self): + if self.file is None: + msg = "%s - source can not be located." % (self.name, ) + else: + msg = "%s defined at line %d of %s" % (self.name, self.lineno, self.file) + win32ui.SetStatusText(msg) + +class HLICLBRClass(HLICLBRItem): + def __init__(self, clbrclass, suffix = ""): + try: + name = clbrclass.name + file = clbrclass.file + lineno = clbrclass.lineno + self.super = clbrclass.super + self.methods = clbrclass.methods + except AttributeError: + name = clbrclass + file = lineno = None + self.super = []; self.methods = {} + HLICLBRItem.__init__(self, name, file, lineno, suffix) + def GetSubList(self): + ret = [] + for c in self.super: + ret.append(HLICLBRClass(c, " (Parent class)")) + for meth, lineno in self.methods.items(): + ret.append(HLICLBRMethod(meth, self.file, lineno, " (method)")) + return ret + def IsExpandable(self): + return len(self.methods) + len(self.super) + def GetBitmapColumn(self): + return 21 + +class HLICLBRFunction(HLICLBRClass): + def GetBitmapColumn(self): + return 22 +class HLICLBRMethod(HLICLBRItem): + def GetBitmapColumn(self): + return 22 + +class HLIModuleItem(hierlist.HierListItem): + def __init__(self, path): + hierlist.HierListItem.__init__(self) + self.path = path + def GetText(self): + return os.path.split(self.path)[1] + " (module)" + def IsExpandable(self): + return 1 + def TakeDefaultAction(self): + win32ui.GetApp().OpenDocumentFile( self.path ) + def GetBitmapColumn(self): + col = 4 # Default + try: + if win32api.GetFileAttributes(self.path) & win32con.FILE_ATTRIBUTE_READONLY: + col = 5 + except win32api.error: + pass + return col + def GetSubList(self): + mod, path = pywin.framework.scriptutils.GetPackageModuleName(self.path) + win32ui.SetStatusText("Building class list - please wait...", 1) + win32ui.DoWaitCursor(1) + try: + try: + reader = pyclbr.readmodule_ex # Post 1.5.2 interface. + extra_msg = " or functions" + except AttributeError: + reader = pyclbr.readmodule + extra_msg = "" + data = reader(mod, [path]) + if data: + ret = [] + for item in data.values(): + if item.__class__ != pyclbr.Class: # ie, it is a pyclbr Function instance (only introduced post 1.5.2) + ret.append(HLICLBRFunction( item, " (function)" ) ) + else: + ret.append(HLICLBRClass( item, " (class)") ) + ret.sort() + return ret + else: + return [HLIErrorItem("No Python classes%s in module." % (extra_msg,))] + finally: + win32ui.DoWaitCursor(0) + win32ui.SetStatusText(win32ui.LoadString(afxres.AFX_IDS_IDLEMESSAGE)) + +def MakePathSubList(path): + ret = [] + for filename in glob.glob(os.path.join(path,'*')): + if os.path.isdir(filename) and os.path.isfile(os.path.join(filename, "__init__.py")): + ret.append(HLIDirectoryItem(filename, os.path.split(filename)[1])) + else: + if os.path.splitext(filename)[1].lower() in ['.py', '.pyw']: + ret.append(HLIModuleItem(filename)) + return ret + +class HLIDirectoryItem(hierlist.HierListItem): + def __init__(self, path, displayName = None, bSubDirs = 0): + hierlist.HierListItem.__init__(self) + self.path = path + self.bSubDirs = bSubDirs + if displayName: + self.displayName = displayName + else: + self.displayName = path + def IsExpandable(self): + return 1 + def GetText(self): + return self.displayName + + def GetSubList(self): + ret = MakePathSubList(self.path) + if os.path.split(self.path)[1] == "win32com": # Complete and utter hack for win32com. + try: + path = win32api.GetFullPathName(os.path.join(self.path, "..\\win32comext")) + ret = ret + MakePathSubList(path) + except win32ui.error: + pass + return ret + +class HLIProjectRoot(hierlist.HierListItem): + def __init__(self, projectName, displayName = None): + hierlist.HierListItem.__init__(self) + self.projectName = projectName + self.displayName = displayName or projectName + def GetText(self): + return self.displayName + def IsExpandable(self): + return 1 + def GetSubList(self): + paths = regutil.GetRegisteredNamedPath(self.projectName) + pathList = paths.split(";") + if len(pathList)==1: # Single dir - dont bother putting the dir in + ret = MakePathSubList(pathList[0]) + else: + ret = list(map( HLIDirectoryItem, pathList )) + return ret + +class HLIRoot(hierlist.HierListItem): + def __init__(self): + hierlist.HierListItem.__init__(self) + def IsExpandable(self): + return 1 + def GetSubList(self): + keyStr = regutil.BuildDefaultPythonKey() + "\\PythonPath" + hKey = win32api.RegOpenKey(regutil.GetRootKey(), keyStr) + try: + ret = [] + ret.append(HLIProjectRoot("", "Standard Python Library")) # The core path. + index = 0 + while 1: + try: + ret.append(HLIProjectRoot(win32api.RegEnumKey(hKey, index))) + index = index + 1 + except win32api.error: + break + return ret + finally: + win32api.RegCloseKey(hKey) + +class dynamic_browser (dialog.Dialog): + style = win32con.WS_OVERLAPPEDWINDOW | win32con.WS_VISIBLE + cs = ( + win32con.WS_CHILD | + win32con.WS_VISIBLE | + commctrl.TVS_HASLINES | + commctrl.TVS_LINESATROOT | + commctrl.TVS_HASBUTTONS + ) + + dt = [ + ["Python Projects", (0, 0, 200, 200), style, None, (8, "MS Sans Serif")], + ["SysTreeView32", None, win32ui.IDC_LIST1, (0, 0, 200, 200), cs] + ] + + def __init__ (self, hli_root): + dialog.Dialog.__init__ (self, self.dt) + self.hier_list = hierlist.HierListWithItems ( + hli_root, + win32ui.IDB_BROWSER_HIER + ) + self.HookMessage (self.on_size, win32con.WM_SIZE) + + def OnInitDialog (self): + self.hier_list.HierInit (self) + return dialog.Dialog.OnInitDialog (self) + + def on_size (self, params): + lparam = params[3] + w = win32api.LOWORD(lparam) + h = win32api.HIWORD(lparam) + self.GetDlgItem (win32ui.IDC_LIST1).MoveWindow((0,0,w,h)) + +def BrowseDialog(): + root = HLIRoot() + if not root.IsExpandable(): + raise TypeError("Browse() argument must have __dict__ attribute, or be a Browser supported type") + + dlg = dynamic_browser (root) + dlg.CreateWindow() + +def DockableBrowserCreator(parent): + root = HLIRoot() + hl = hierlist.HierListWithItems ( + root, + win32ui.IDB_BROWSER_HIER + ) + + style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_BORDER | commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS + + control = win32ui.CreateTreeCtrl() + control.CreateWindow(style, (0, 0, 150, 300), parent, win32ui.IDC_LIST1) + list = hl.HierInit (parent, control) + return control + +def DockablePathBrowser(): + import pywin.docking.DockingBar + bar = pywin.docking.DockingBar.DockingBar() + bar.CreateWindow(win32ui.GetMainFrame(), DockableBrowserCreator, "Path Browser", 0x8e0a) + bar.SetBarStyle( bar.GetBarStyle()|afxres.CBRS_TOOLTIPS|afxres.CBRS_FLYBY|afxres.CBRS_SIZE_DYNAMIC) + bar.EnableDocking(afxres.CBRS_ALIGN_ANY) + win32ui.GetMainFrame().DockControlBar(bar) + +# The "default" entry point +Browse = DockablePathBrowser diff --git a/Lib/site-packages/pythonwin/pywin/tools/browser.py b/Lib/site-packages/pythonwin/pywin/tools/browser.py new file mode 100644 index 0000000..46fd2f2 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/tools/browser.py @@ -0,0 +1,436 @@ +# basic module browser. + +# usage: +# >>> import browser +# >>> browser.Browse() +# or +# >>> browser.Browse(your_module) +import sys +import types +import __main__ +import win32ui +from pywin.mfc import dialog + +from . import hierlist + +special_names = [ '__doc__', '__name__', '__self__' ] + +# +# HierList items +class HLIPythonObject(hierlist.HierListItem): + def __init__(self, myobject=None, name=None ): + hierlist.HierListItem.__init__(self) + self.myobject = myobject + self.knownExpandable = None + if name: + self.name=name + else: + try: + self.name=myobject.__name__ + except (AttributeError, TypeError): + try: + r = repr(myobject) + if len(r)>20: + r = r[:20] + "..." + self.name=r + except (AttributeError, TypeError): + self.name="???" + def __lt__(self, other): + return self.name < other.name + def __eq__(self, other): + return self.name == other.name + def __repr__(self): + try: + type = self.GetHLIType() + except: + type = "Generic" + return "HLIPythonObject("+type+") - name: "+ self.name + " object: " + repr(self.myobject) + def GetText(self): + try: + return str(self.name) + ' (' + self.GetHLIType() + ')' + except AttributeError: + return str(self.name) + ' = ' + repr(self.myobject) + def InsertDocString(self, lst): + ob = None + try: + ob = self.myobject.__doc__ + except (AttributeError, TypeError): + pass + # I don't quite grok descriptors enough to know how to + # best hook them up. Eg: + # >>> object.__getattribute__.__class__.__doc__ + # + if ob and isinstance(ob, str): + lst.insert(0, HLIDocString( ob, "Doc" )) + + def GetSubList(self): + ret = [] + try: + for (key, ob) in self.myobject.__dict__.items(): + if key not in special_names: + ret.append(MakeHLI( ob, key ) ) + except (AttributeError, TypeError): + pass + try: + for name in self.myobject.__methods__: + ret.append(HLIMethod( name )) # no MakeHLI, as cant auto detect + except (AttributeError, TypeError): + pass + try: + for member in self.myobject.__members__: + if not member in special_names: + ret.append(MakeHLI(getattr(self.myobject, member), member)) + except (AttributeError, TypeError): + pass + ret.sort() + self.InsertDocString(ret) + return ret + # if the has a dict, it is expandable. + def IsExpandable(self): + if self.knownExpandable is None: + self.knownExpandable = self.CalculateIsExpandable() + return self.knownExpandable + + def CalculateIsExpandable(self): + if hasattr(self.myobject, '__doc__'): + return 1 + try: + for key in self.myobject.__dict__.keys(): + if key not in special_names: + return 1 + except (AttributeError, TypeError): + pass + try: + self.myobject.__methods__ + return 1 + except (AttributeError, TypeError): + pass + try: + for item in self.myobject.__members__: + if item not in special_names: + return 1 + except (AttributeError, TypeError): + pass + return 0 + def GetBitmapColumn(self): + if self.IsExpandable(): + return 0 + else: + return 4 + def TakeDefaultAction(self): + ShowObject(self.myobject, self.name) + + +class HLIDocString(HLIPythonObject): + def GetHLIType(self): + return "DocString" + def GetText(self): + return self.myobject.strip() + def IsExpandable(self): + return 0 + def GetBitmapColumn(self): + return 6 + +class HLIModule(HLIPythonObject): + def GetHLIType(self): + return "Module" + +class HLIFrame(HLIPythonObject): + def GetHLIType(self): + return "Stack Frame" + +class HLITraceback(HLIPythonObject): + def GetHLIType(self): + return "Traceback" + +class HLIClass(HLIPythonObject): + def GetHLIType(self): + return "Class" + def GetSubList(self): + ret = [] + for base in self.myobject.__bases__: + ret.append( MakeHLI(base, 'Base class: ' + base.__name__ ) ) + ret = ret + HLIPythonObject.GetSubList(self) + return ret + +class HLIMethod(HLIPythonObject): + # myobject is just a string for methods. + def GetHLIType(self): + return "Method" + def GetText(self): + return "Method: " + self.myobject + '()' + +class HLICode(HLIPythonObject): + def GetHLIType(self): + return "Code" + def IsExpandable(self): + return self.myobject + def GetSubList(self): + ret = [] + ret.append( MakeHLI( self.myobject.co_consts, "Constants (co_consts)" )) + ret.append( MakeHLI( self.myobject.co_names, "Names (co_names)" )) + ret.append( MakeHLI( self.myobject.co_filename, "Filename (co_filename)" )) + ret.append( MakeHLI( self.myobject.co_argcount, "Number of args (co_argcount)")) + ret.append( MakeHLI( self.myobject.co_varnames, "Param names (co_varnames)")) + + return ret + +class HLIInstance(HLIPythonObject): + def GetHLIType(self): + return "Instance" + def GetText(self): + return str(self.name) + ' (Instance of class ' + str(self.myobject.__class__.__name__) + ')' + def IsExpandable(self): + return 1 + def GetSubList(self): + ret = [] + ret.append( MakeHLI( self.myobject.__class__) ) + ret = ret + HLIPythonObject.GetSubList(self) + return ret + + +class HLIBuiltinFunction(HLIPythonObject): + def GetHLIType(self): + return "Builtin Function" + +class HLIFunction(HLIPythonObject): + def GetHLIType(self): + return "Function" + def IsExpandable(self): + return 1 + def GetSubList(self): + ret = [] +# ret.append( MakeHLI( self.myobject.func_argcount, "Arg Count" )) + try: + ret.append( MakeHLI( self.myobject.func_argdefs, "Arg Defs" )) + except AttributeError: + pass + try: + code = self.myobject.__code__ + globs = self.myobject.__globals__ + except AttributeError: + # must be py2.5 or earlier... + code = self.myobject.func_code + globs = self.myobject.func_globals + ret.append(MakeHLI(code, "Code" )) + ret.append(MakeHLI(globs, "Globals" )) + self.InsertDocString(ret) + return ret + +class HLISeq(HLIPythonObject): + def GetHLIType(self): + return "Sequence (abstract!)" + def IsExpandable(self): + return len(self.myobject)>0 + def GetSubList(self): + ret = [] + pos=0 + for item in self.myobject: + ret.append(MakeHLI( item, '['+str(pos)+']' ) ) + pos=pos+1 + self.InsertDocString(ret) + return ret + +class HLIList(HLISeq): + def GetHLIType(self): + return "List" + +class HLITuple(HLISeq): + def GetHLIType(self): + return "Tuple" + +class HLIDict(HLIPythonObject): + def GetHLIType(self): + return "Dict" + def IsExpandable(self): + try: + self.myobject.__doc__ + return 1 + except (AttributeError, TypeError): + return len(self.myobject) > 0 + def GetSubList(self): + ret = [] + keys = list(self.myobject.keys()) + keys.sort() + for key in keys: + ob = self.myobject[key] + ret.append(MakeHLI( ob, str(key) ) ) + self.InsertDocString(ret) + return ret + +# In Python 1.6, strings and Unicode have builtin methods, but we dont really want to see these +class HLIString(HLIPythonObject): + def IsExpandable(self): + return 0 + +TypeMap = { type : HLIClass, + types.FunctionType: HLIFunction, + tuple: HLITuple, + dict: HLIDict, + list: HLIList, + types.ModuleType: HLIModule, + types.CodeType : HLICode, + types.BuiltinFunctionType : HLIBuiltinFunction, + types.FrameType : HLIFrame, + types.TracebackType : HLITraceback, + str : HLIString, + str : HLIString, + int: HLIPythonObject, + int: HLIPythonObject, + bool: HLIPythonObject, + float: HLIPythonObject, + } + +def MakeHLI( ob, name=None ): + try: + cls = TypeMap[type(ob)] + except KeyError: + # hrmph - this check gets more and more bogus as Python + # improves. Its possible we should just *always* use + # HLIInstance? + if hasattr(ob, '__class__'): # 'new style' class + cls = HLIInstance + else: + cls = HLIPythonObject + return cls( ob, name ) + +######################################### +# +# Dialog related. + + +class DialogShowObject(dialog.Dialog): + def __init__(self, object, title): + self.object = object + self.title = title + dialog.Dialog.__init__(self, win32ui.IDD_LARGE_EDIT) + def OnInitDialog(self): + import re + self.SetWindowText(self.title) + self.edit = self.GetDlgItem(win32ui.IDC_EDIT1) + try: + strval = str(self.object) + except: + t, v, tb = sys.exc_info() + strval = "Exception getting object value\n\n%s:%s" % (t, v) + tb = None + strval = re.sub('\n','\r\n', strval) + self.edit.ReplaceSel(strval) + +def ShowObject(object, title): + dlg = DialogShowObject(object, title) + dlg.DoModal() + +# And some mods for a sizable dialog from Sam Rushing! +import win32con +import win32api +import commctrl + +class dynamic_browser (dialog.Dialog): + style = win32con.WS_OVERLAPPEDWINDOW | win32con.WS_VISIBLE + cs = ( + win32con.WS_CHILD | + win32con.WS_VISIBLE | + commctrl.TVS_HASLINES | + commctrl.TVS_LINESATROOT | + commctrl.TVS_HASBUTTONS + ) + + dt = [ + ["Python Object Browser", (0, 0, 200, 200), style, None, (8, "MS Sans Serif")], + ["SysTreeView32", None, win32ui.IDC_LIST1, (0, 0, 200, 200), cs] + ] + + def __init__ (self, hli_root): + dialog.Dialog.__init__ (self, self.dt) + self.hier_list = hierlist.HierListWithItems ( + hli_root, + win32ui.IDB_BROWSER_HIER + ) + self.HookMessage (self.on_size, win32con.WM_SIZE) + + def OnInitDialog (self): + self.hier_list.HierInit (self) + return dialog.Dialog.OnInitDialog (self) + + def OnOK(self): + self.hier_list.HierTerm() + self.hier_list = None + return self._obj_.OnOK() + def OnCancel(self): + self.hier_list.HierTerm() + self.hier_list = None + return self._obj_.OnCancel() + + def on_size (self, params): + lparam = params[3] + w = win32api.LOWORD(lparam) + h = win32api.HIWORD(lparam) + self.GetDlgItem (win32ui.IDC_LIST1).MoveWindow((0,0,w,h)) + +def Browse (ob=__main__): + " Browse the argument, or the main dictionary " + root = MakeHLI (ob, 'root') + if not root.IsExpandable(): + raise TypeError("Browse() argument must have __dict__ attribute, or be a Browser supported type") + + dlg = dynamic_browser (root) + dlg.CreateWindow() + +# +# +# Classes for using the browser in an MDI window, rather than a dialog +# +from pywin.mfc import docview +class BrowserTemplate(docview.DocTemplate): + def __init__(self): + docview.DocTemplate.__init__(self, win32ui.IDR_PYTHONTYPE, BrowserDocument, None, BrowserView) + + def OpenObject(self, root): # Use this instead of OpenDocumentFile. + # Look for existing open document + for doc in self.GetDocumentList(): + if doc.root==root: + doc.GetFirstView().ActivateFrame() + return doc + # not found - new one. + doc = BrowserDocument(self, root) + frame = self.CreateNewFrame(doc) + doc.OnNewDocument() + self.InitialUpdateFrame(frame, doc, 1) + return doc + +class BrowserDocument (docview.Document): + def __init__(self, template, root): + docview.Document.__init__(self, template) + self.root = root + self.SetTitle("Browser: " + root.name) + def OnOpenDocument (self, name): + raise TypeError("This template can not open files") + return 0 + +class BrowserView(docview.TreeView): + def OnInitialUpdate(self): + import commctrl + rc = self._obj_.OnInitialUpdate() + list=hierlist.HierListWithItems( self.GetDocument().root, win32ui.IDB_BROWSER_HIER, win32ui.AFX_IDW_PANE_FIRST) + list.HierInit(self.GetParent()) + list.SetStyle(commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS) + return rc + +template = None +def MakeTemplate(): + global template + if template is None: + template = BrowserTemplate() #win32ui.IDR_PYTHONTYPE, BrowserDocument, None, BrowserView) + +def BrowseMDI(ob=__main__): + """Browse an object using an MDI window. + """ + + MakeTemplate() + root = MakeHLI(ob, repr(ob)) + if not root.IsExpandable(): + raise TypeError("Browse() argument must have __dict__ attribute, or be a Browser supported type") + + template.OpenObject(root) + diff --git a/Lib/site-packages/pythonwin/pywin/tools/hierlist.py b/Lib/site-packages/pythonwin/pywin/tools/hierlist.py new file mode 100644 index 0000000..eaab5a3 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/tools/hierlist.py @@ -0,0 +1,321 @@ +# hierlist +# +# IMPORTANT - Please read before using. + +# This module exposes an API for a Hierarchical Tree Control. +# Previously, a custom tree control was included in Pythonwin which +# has an API very similar to this. + +# The current control used is the common "Tree Control". This module exists now +# to provide an API similar to the old control, but for the new Tree control. + +# If you need to use the Tree Control, you may still find this API a reasonable +# choice. However, you should investigate using the tree control directly +# to provide maximum flexibility (but with extra work). + +import sys +import win32ui +import win32con +import win32api +from win32api import RGB + +from pywin.mfc import object, window, docview, dialog +import commctrl + +# helper to get the text of an arbitary item +def GetItemText(item): + if type(item)==type(()) or type(item)==type([]): + use = item[0] + else: + use = item + if type(use)==type(''): + return use + else: + return repr(item) + + +class HierDialog(dialog.Dialog): + def __init__(self, title, hierList, bitmapID = win32ui.IDB_HIERFOLDERS, dlgID = win32ui.IDD_TREE, dll = None, childListBoxID = win32ui.IDC_LIST1): + dialog.Dialog.__init__(self, dlgID, dll ) # reuse this dialog. + self.hierList=hierList + self.dlgID = dlgID + self.title=title +# self.childListBoxID = childListBoxID + def OnInitDialog(self): + self.SetWindowText(self.title) + self.hierList.HierInit(self) + return dialog.Dialog.OnInitDialog(self) + +class HierList(object.Object): + def __init__(self, root, bitmapID = win32ui.IDB_HIERFOLDERS, listBoxId = None, bitmapMask = None): # used to create object. + self.listControl = None + self.bitmapID = bitmapID + self.root = root + self.listBoxId = listBoxId + self.itemHandleMap = {} + self.filledItemHandlesMap = {} + self.bitmapMask = bitmapMask + def __getattr__(self, attr): + try: + return getattr(self.listControl, attr) + except AttributeError: + return object.Object.__getattr__(self, attr) + + def ItemFromHandle(self, handle): + return self.itemHandleMap[handle] + def SetStyle(self, newStyle): + hwnd = self.listControl.GetSafeHwnd() + style = win32api.GetWindowLong(hwnd, win32con.GWL_STYLE); + win32api.SetWindowLong(hwnd, win32con.GWL_STYLE, (style | newStyle) ) + + def HierInit(self, parent, listControl = None ): # Used when window first exists. + # this also calls "Create" on the listbox. + # params - id of listbbox, ID of bitmap, size of bitmaps + if self.bitmapMask is None: + bitmapMask = RGB(0,0,255) + else: + bitmapMask = self.bitmapMask + self.imageList = win32ui.CreateImageList(self.bitmapID, 16, 0, bitmapMask) + if listControl is None: + if self.listBoxId is None: self.listBoxId = win32ui.IDC_LIST1 + self.listControl = parent.GetDlgItem(self.listBoxId) + else: + self.listControl = listControl + lbid = listControl.GetDlgCtrlID() + assert self.listBoxId is None or self.listBoxId == lbid, "An invalid listbox control ID has been specified (specified as %s, but exists as %s)" % (self.listBoxId, lbid) + self.listBoxId = lbid + self.listControl.SetImageList(self.imageList, commctrl.LVSIL_NORMAL) +# self.list.AttachObject(self) + + ## ??? Need a better way to do this - either some way to detect if it's compiled with UNICODE + ## defined, and/or a way to switch the constants based on UNICODE ??? + if sys.version_info[0] < 3: + parent.HookNotify(self.OnTreeItemExpanding, commctrl.TVN_ITEMEXPANDINGA) + parent.HookNotify(self.OnTreeItemSelChanged, commctrl.TVN_SELCHANGEDA) + else: + parent.HookNotify(self.OnTreeItemExpanding, commctrl.TVN_ITEMEXPANDINGW) + parent.HookNotify(self.OnTreeItemSelChanged, commctrl.TVN_SELCHANGEDW) + parent.HookNotify(self.OnTreeItemDoubleClick, commctrl.NM_DBLCLK) + self.notify_parent = parent + + if self.root: + self.AcceptRoot(self.root) + + def DeleteAllItems(self): + self.listControl.DeleteAllItems() + self.root = None + self.itemHandleMap = {} + self.filledItemHandlesMap = {} + + def HierTerm(self): + # Dont want notifies as we kill the list. + parent = self.notify_parent # GetParentFrame() + if sys.version_info[0] < 3: + parent.HookNotify(None, commctrl.TVN_ITEMEXPANDINGA) + parent.HookNotify(None, commctrl.TVN_SELCHANGEDA) + else: + parent.HookNotify(None, commctrl.TVN_ITEMEXPANDINGW) + parent.HookNotify(None, commctrl.TVN_SELCHANGEDW) + parent.HookNotify(None, commctrl.NM_DBLCLK) + + self.DeleteAllItems() + self.listControl = None + self.notify_parent = None # Break a possible cycle + + def OnTreeItemDoubleClick(self, info, extra): + (hwndFrom, idFrom, code) = info + if idFrom != self.listBoxId: return None + item = self.itemHandleMap[self.listControl.GetSelectedItem()] + self.TakeDefaultAction(item) + return 1 + + def OnTreeItemExpanding(self, info, extra): + (hwndFrom, idFrom, code) = info + if idFrom != self.listBoxId: return None + action, itemOld, itemNew, pt = extra + itemHandle = itemNew[0] + if itemHandle not in self.filledItemHandlesMap: + item = self.itemHandleMap[itemHandle] + self.AddSubList(itemHandle, self.GetSubList(item)) + self.filledItemHandlesMap[itemHandle] = None + return 0 + + def OnTreeItemSelChanged(self, info, extra): + (hwndFrom, idFrom, code) = info + if idFrom != self.listBoxId: return None + action, itemOld, itemNew, pt = extra + itemHandle = itemNew[0] + item = self.itemHandleMap[itemHandle] + self.PerformItemSelected(item) + return 1 + + def AddSubList(self, parentHandle, subItems): + for item in subItems: + self.AddItem(parentHandle, item) + + def AddItem(self, parentHandle, item, hInsertAfter = commctrl.TVI_LAST): + text = self.GetText(item) + if self.IsExpandable(item): + cItems = 1 # Trick it !! + else: + cItems = 0 + bitmapCol = self.GetBitmapColumn(item) + bitmapSel = self.GetSelectedBitmapColumn(item) + if bitmapSel is None: bitmapSel = bitmapCol + ## if type(text) is str: + ## text = text.encode("mbcs") + hitem = self.listControl.InsertItem(parentHandle, hInsertAfter, (None, None, None, text, bitmapCol, bitmapSel, cItems, 0)) + self.itemHandleMap[hitem] = item + return hitem + + def _GetChildHandles(self, handle): + ret = [] + try: + handle = self.listControl.GetChildItem(handle) + while 1: + ret.append(handle) + handle = self.listControl.GetNextItem(handle, commctrl.TVGN_NEXT) + except win32ui.error: + # out of children + pass + return ret + def ItemFromHandle(self, handle): + return self.itemHandleMap[handle] + + def Refresh(self, hparent = None): + # Attempt to refresh the given item's sub-entries, but maintain the tree state + # (ie, the selected item, expanded items, etc) + if hparent is None: hparent = commctrl.TVI_ROOT + if hparent not in self.filledItemHandlesMap: + # This item has never been expanded, so no refresh can possibly be required. + return + root_item = self.itemHandleMap[hparent] + old_handles = self._GetChildHandles(hparent) + old_items = list(map( self.ItemFromHandle, old_handles )) + new_items = self.GetSubList(root_item) + # Now an inefficient technique for synching the items. + inew = 0 + hAfter = commctrl.TVI_FIRST + for iold in range(len(old_items)): + inewlook = inew + matched = 0 + while inewlook < len(new_items): + if old_items[iold] == new_items[inewlook]: + matched = 1 + break + inewlook = inewlook + 1 + if matched: + # Insert the new items. +# print "Inserting after", old_items[iold], old_handles[iold] + for i in range(inew, inewlook): +# print "Inserting index %d (%s)" % (i, new_items[i]) + hAfter = self.AddItem(hparent, new_items[i], hAfter) + + inew = inewlook + 1 + # And recursively refresh iold + hold = old_handles[iold] + if hold in self.filledItemHandlesMap: + self.Refresh(hold) + else: + # Remove the deleted items. +# print "Deleting %d (%s)" % (iold, old_items[iold]) + hdelete = old_handles[iold] + # First recurse and remove the children from the map. + for hchild in self._GetChildHandles(hdelete): + del self.itemHandleMap[hchild] + if hchild in self.filledItemHandlesMap: + del self.filledItemHandlesMap[hchild] + self.listControl.DeleteItem(hdelete) + hAfter = old_handles[iold] + # Fill any remaining new items: + for newItem in new_items[inew:]: +# print "Inserting new item", newItem + self.AddItem(hparent, newItem) + def AcceptRoot(self, root): + self.listControl.DeleteAllItems() + self.itemHandleMap = {commctrl.TVI_ROOT : root} + self.filledItemHandlesMap = {commctrl.TVI_ROOT : root} + subItems = self.GetSubList(root) + self.AddSubList(0, subItems) + + def GetBitmapColumn(self, item): + if self.IsExpandable(item): + return 0 + else: + return 4 + def GetSelectedBitmapColumn(self, item): + return None # Use standard. + + def GetSelectedBitmapColumn(self, item): + return 0 + + def CheckChangedChildren(self): + return self.listControl.CheckChangedChildren() + def GetText(self,item): + return GetItemText(item) + def PerformItemSelected(self, item): + try: + win32ui.SetStatusText('Selected ' + self.GetText(item)) + except win32ui.error: # No status bar! + pass + def TakeDefaultAction(self, item): + win32ui.MessageBox('Got item ' + self.GetText(item)) + +########################################################################## +# +# Classes for use with seperate HierListItems. +# +# +class HierListWithItems(HierList): + def __init__(self, root, bitmapID = win32ui.IDB_HIERFOLDERS, listBoxID = None, bitmapMask = None): # used to create object. + HierList.__init__(self, root, bitmapID, listBoxID, bitmapMask ) + def DelegateCall( self, fn): + return fn() + def GetBitmapColumn(self, item): + rc = self.DelegateCall(item.GetBitmapColumn) + if rc is None: + rc = HierList.GetBitmapColumn(self, item) + return rc + def GetSelectedBitmapColumn(self, item): + return self.DelegateCall(item.GetSelectedBitmapColumn) + def IsExpandable(self, item): + return self.DelegateCall( item.IsExpandable) + def GetText(self, item): + return self.DelegateCall( item.GetText ) + def GetSubList(self, item): + return self.DelegateCall(item.GetSubList) + def PerformItemSelected(self, item): + func = getattr(item, "PerformItemSelected", None) + if func is None: + return HierList.PerformItemSelected( self, item ) + else: + return self.DelegateCall(func) + + def TakeDefaultAction(self, item): + func = getattr(item, "TakeDefaultAction", None) + if func is None: + return HierList.TakeDefaultAction( self, item ) + else: + return self.DelegateCall(func) + +# A hier list item - for use with a HierListWithItems +class HierListItem: + def __init__(self): + pass + def GetText(self): + pass + def GetSubList(self): + pass + def IsExpandable(self): + pass + def GetBitmapColumn(self): + return None # indicate he should do it. + def GetSelectedBitmapColumn(self): + return None # same as other + # for py3k/rich-comp sorting compatibility. + def __lt__(self, other): + # we want unrelated items to be sortable... + return id(self) < id(other) + # for py3k/rich-comp equality compatibility. + def __eq__(self, other): + return False diff --git a/Lib/site-packages/pythonwin/pywin/tools/regedit.py b/Lib/site-packages/pythonwin/pywin/tools/regedit.py new file mode 100644 index 0000000..10ef06e --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/tools/regedit.py @@ -0,0 +1,329 @@ +# Regedit - a Registry Editor for Python +import win32api, win32ui, win32con, commctrl +from pywin.mfc import window, docview, dialog +from . import hierlist +import regutil +import string + +def SafeApply( fn, args, err_desc = "" ): + try: + fn(*args) + return 1 + except win32api.error as exc: + msg = "Error " + err_desc + "\r\n\r\n" + exc.strerror + win32ui.MessageBox(msg) + return 0 + +class SplitterFrame(window.MDIChildWnd): + def __init__(self): + # call base CreateFrame + self.images = None + window.MDIChildWnd.__init__(self) + + def OnCreateClient(self, cp, context): + splitter = win32ui.CreateSplitter() + doc = context.doc + frame_rect = self.GetWindowRect() + size = ((frame_rect[2] - frame_rect[0]), + (frame_rect[3] - frame_rect[1])//2) + sub_size = (size[0]//3, size[1]) + splitter.CreateStatic (self, 1, 2) + # CTreeControl view + self.keysview = RegistryTreeView(doc) + # CListControl view + self.valuesview = RegistryValueView(doc) + + splitter.CreatePane (self.keysview, 0, 0, (sub_size)) + splitter.CreatePane (self.valuesview, 0, 1, (0,0)) # size ignored. + splitter.SetRowInfo(0, size[1] ,0) + # Setup items in the imagelist + + return 1 + + def OnItemDoubleClick(self, info, extra): + (hwndFrom, idFrom, code) = info + if idFrom==win32ui.AFX_IDW_PANE_FIRST: + # Tree control + return None + elif idFrom==win32ui.AFX_IDW_PANE_FIRST + 1: + item = self.keysview.SelectedItem() + self.valuesview.EditValue(item) + return 0 + # List control + else: + return None # Pass it on + + def PerformItemSelected(self,item): + return self.valuesview.UpdateForRegItem(item) + + def OnDestroy(self, msg): + window.MDIChildWnd.OnDestroy(self, msg) + if self.images: + self.images.DeleteImageList() + self.images = None + +class RegistryTreeView(docview.TreeView): + def OnInitialUpdate(self): + rc = self._obj_.OnInitialUpdate() + self.frame = self.GetParent().GetParent() + self.hierList = hierlist.HierListWithItems( self.GetHLIRoot(), win32ui.IDB_HIERFOLDERS, win32ui.AFX_IDW_PANE_FIRST) + self.hierList.HierInit(self.frame, self.GetTreeCtrl()) + self.hierList.SetStyle(commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS) + self.hierList.PerformItemSelected = self.PerformItemSelected + + self.frame.HookNotify(self.frame.OnItemDoubleClick, commctrl.NM_DBLCLK) + self.frame.HookNotify(self.OnItemRightClick, commctrl.NM_RCLICK) +# self.HookMessage(self.OnItemRightClick, win32con.WM_RBUTTONUP) + + def GetHLIRoot(self): + doc = self.GetDocument() + regroot = doc.root + subkey = doc.subkey + return HLIRegistryKey(regroot, subkey, "Root") + + def OnItemRightClick(self, notify_data, extra): + # First select the item we right-clicked on. + pt = self.ScreenToClient(win32api.GetCursorPos()) + flags, hItem = self.HitTest(pt) + if hItem==0 or commctrl.TVHT_ONITEM & flags==0: + return None + self.Select(hItem, commctrl.TVGN_CARET) + + menu = win32ui.CreatePopupMenu() + menu.AppendMenu(win32con.MF_STRING|win32con.MF_ENABLED,1000, "Add Key") + menu.AppendMenu(win32con.MF_STRING|win32con.MF_ENABLED,1001, "Add Value") + menu.AppendMenu(win32con.MF_STRING|win32con.MF_ENABLED,1002, "Delete Key") + self.HookCommand(self.OnAddKey, 1000) + self.HookCommand(self.OnAddValue, 1001) + self.HookCommand(self.OnDeleteKey, 1002) + menu.TrackPopupMenu(win32api.GetCursorPos()) # track at mouse position. + return None + + def OnDeleteKey(self,command, code): + hitem = self.hierList.GetSelectedItem() + item = self.hierList.ItemFromHandle(hitem) + msg = "Are you sure you wish to delete the key '%s'?" % (item.keyName,) + id = win32ui.MessageBox(msg, None, win32con.MB_YESNO) + if id != win32con.IDYES: + return + if SafeApply(win32api.RegDeleteKey, (item.keyRoot, item.keyName), "deleting registry key" ): + # Get the items parent. + try: + hparent = self.GetParentItem(hitem) + except win32ui.error: + hparent = None + self.hierList.Refresh(hparent) + + def OnAddKey(self,command, code): + from pywin.mfc import dialog + val = dialog.GetSimpleInput("New key name", '', "Add new key") + if val is None: return # cancelled. + hitem = self.hierList.GetSelectedItem() + item = self.hierList.ItemFromHandle(hitem) + if SafeApply(win32api.RegCreateKey, (item.keyRoot, item.keyName + "\\" + val)): + self.hierList.Refresh(hitem) + + def OnAddValue(self,command, code): + from pywin.mfc import dialog + val = dialog.GetSimpleInput("New value", "", "Add new value") + if val is None: return # cancelled. + hitem = self.hierList.GetSelectedItem() + item = self.hierList.ItemFromHandle(hitem) + if SafeApply(win32api.RegSetValue, (item.keyRoot, item.keyName, win32con.REG_SZ, val)): + # Simply re-select the current item to refresh the right spitter. + self.PerformItemSelected(item) +# self.Select(hitem, commctrl.TVGN_CARET) + + def PerformItemSelected(self, item): + return self.frame.PerformItemSelected(item) + + def SelectedItem(self): + return self.hierList.ItemFromHandle(self.hierList.GetSelectedItem()) + + def SearchSelectedItem(self): + handle = self.hierList.GetChildItem(0) + while 1: +# print "State is", self.hierList.GetItemState(handle, -1) + if self.hierList.GetItemState(handle, commctrl.TVIS_SELECTED): +# print "Item is ", self.hierList.ItemFromHandle(handle) + return self.hierList.ItemFromHandle(handle) + handle = self.hierList.GetNextSiblingItem(handle) + +class RegistryValueView(docview.ListView): + def OnInitialUpdate(self): + hwnd = self._obj_.GetSafeHwnd() + style = win32api.GetWindowLong(hwnd, win32con.GWL_STYLE); + win32api.SetWindowLong(hwnd, win32con.GWL_STYLE, (style & ~commctrl.LVS_TYPEMASK) | commctrl.LVS_REPORT); + + itemDetails = (commctrl.LVCFMT_LEFT, 100, "Name", 0) + self.InsertColumn(0, itemDetails) + itemDetails = (commctrl.LVCFMT_LEFT, 500, "Data", 0) + self.InsertColumn(1, itemDetails) + + def UpdateForRegItem(self, item): + self.DeleteAllItems() + hkey = win32api.RegOpenKey(item.keyRoot, item.keyName) + try: + valNum = 0 + ret = [] + while 1: + try: + res = win32api.RegEnumValue(hkey, valNum) + except win32api.error: + break + name = res[0] + if not name: name = "(Default)" + self.InsertItem(valNum, name) + self.SetItemText(valNum, 1, str(res[1])) + valNum = valNum + 1 + finally: + win32api.RegCloseKey(hkey) + def EditValue(self, item): + # Edit the current value + class EditDialog(dialog.Dialog): + def __init__(self, item): + self.item = item + dialog.Dialog.__init__(self, win32ui.IDD_LARGE_EDIT) + def OnInitDialog(self): + self.SetWindowText("Enter new value") + self.GetDlgItem(win32con.IDCANCEL).ShowWindow(win32con.SW_SHOW) + self.edit = self.GetDlgItem(win32ui.IDC_EDIT1) + # Modify the edit windows style + style = win32api.GetWindowLong(self.edit.GetSafeHwnd(), win32con.GWL_STYLE) + style = style & (~win32con.ES_WANTRETURN) + win32api.SetWindowLong(self.edit.GetSafeHwnd(), win32con.GWL_STYLE, style) + self.edit.SetWindowText(str(self.item)) + self.edit.SetSel(-1) + return dialog.Dialog.OnInitDialog(self) + def OnDestroy(self,msg): + self.newvalue = self.edit.GetWindowText() + + try: + index = self.GetNextItem(-1, commctrl.LVNI_SELECTED) + except win32ui.error: + return # No item selected. + + if index==0: + keyVal = "" + else: + keyVal = self.GetItemText(index,0) + # Query for a new value. + try: + newVal = self.GetItemsCurrentValue(item, keyVal) + except TypeError as details: + win32ui.MessageBox(details) + return + + d = EditDialog(newVal) + if d.DoModal()==win32con.IDOK: + try: + self.SetItemsCurrentValue(item, keyVal, d.newvalue) + except win32api.error as exc: + win32ui.MessageBox("Error setting value\r\n\n%s" % exc.strerror) + self.UpdateForRegItem(item) + + def GetItemsCurrentValue(self, item, valueName): + hkey = win32api.RegOpenKey(item.keyRoot, item.keyName) + try: + val, type = win32api.RegQueryValueEx(hkey, valueName) + if type != win32con.REG_SZ: + raise TypeError("Only strings can be edited") + return val + finally: + win32api.RegCloseKey(hkey) + + def SetItemsCurrentValue(self, item, valueName, value): + # ** Assumes already checked is a string. + hkey = win32api.RegOpenKey(item.keyRoot, item.keyName , 0, win32con.KEY_SET_VALUE) + try: + win32api.RegSetValueEx(hkey, valueName, 0, win32con.REG_SZ, value) + finally: + win32api.RegCloseKey(hkey) + + +class RegTemplate(docview.DocTemplate): + def __init__(self): + docview.DocTemplate.__init__(self, win32ui.IDR_PYTHONTYPE, None, SplitterFrame, None) + +# def InitialUpdateFrame(self, frame, doc, makeVisible=1): +# self._obj_.InitialUpdateFrame(frame, doc, makeVisible) # call default handler. +# frame.InitialUpdateFrame(doc, makeVisible) + + def OpenRegistryKey(self, root = None, subkey = None): # Use this instead of OpenDocumentFile. + # Look for existing open document + if root is None: root = regutil.GetRootKey() + if subkey is None: subkey = regutil.BuildDefaultPythonKey() + for doc in self.GetDocumentList(): + if doc.root==root and doc.subkey==subkey: + doc.GetFirstView().ActivateFrame() + return doc + # not found - new one. + doc = RegDocument(self, root, subkey) + frame = self.CreateNewFrame(doc) + doc.OnNewDocument() + self.InitialUpdateFrame(frame, doc, 1) + return doc + +class RegDocument (docview.Document): + def __init__(self, template, root, subkey): + docview.Document.__init__(self, template) + self.root = root + self.subkey = subkey + self.SetTitle("Registry Editor: " + subkey) + + def OnOpenDocument (self, name): + raise TypeError("This template can not open files") + return 0 + + +class HLIRegistryKey(hierlist.HierListItem): + def __init__( self, keyRoot, keyName, userName ): + self.keyRoot = keyRoot + self.keyName = keyName + self.userName = userName + hierlist.HierListItem.__init__(self) + def __lt__(self, other): + return self.name < other.name + def __eq__(self, other): + return self.keyRoot==other.keyRoot and \ + self.keyName == other.keyName and \ + self.userName == other.userName + def __repr__(self): + return "<%s with root=%s, key=%s>" % (self.__class__.__name__, self.keyRoot, self.keyName) + def GetText(self): + return self.userName + def IsExpandable(self): + # All keys are expandable, even if they currently have zero children. + return 1 +## hkey = win32api.RegOpenKey(self.keyRoot, self.keyName) +## try: +## keys, vals, dt = win32api.RegQueryInfoKey(hkey) +## return (keys>0) +## finally: +## win32api.RegCloseKey(hkey) + + def GetSubList(self): + hkey = win32api.RegOpenKey(self.keyRoot, self.keyName) + win32ui.DoWaitCursor(1) + try: + keyNum = 0 + ret = [] + while 1: + try: + key = win32api.RegEnumKey(hkey, keyNum) + except win32api.error: + break + ret.append(HLIRegistryKey(self.keyRoot, self.keyName + "\\" + key, key)) + keyNum = keyNum + 1 + finally: + win32api.RegCloseKey(hkey) + win32ui.DoWaitCursor(0) + return ret + +template = RegTemplate() + +def EditRegistry(root = None, key = None): + doc=template.OpenRegistryKey(root, key) + +if __name__=='__main__': + EditRegistry() diff --git a/Lib/site-packages/pythonwin/pywin/tools/regpy.py b/Lib/site-packages/pythonwin/pywin/tools/regpy.py new file mode 100644 index 0000000..22d1755 --- /dev/null +++ b/Lib/site-packages/pythonwin/pywin/tools/regpy.py @@ -0,0 +1,56 @@ +# (sort-of) Registry editor +import win32ui +import dialog +import win32con +import commctrl + +class RegistryControl: + def __init__(self, key): + self.key = key + +class RegEditPropertyPage(dialog.PropertyPage): + IDC_LISTVIEW = 1000 + def GetTemplate(self): + "Return the template used to create this dialog" + + w = 152 # Dialog width + h = 122 # Dialog height + SS_STD = win32con.WS_CHILD | win32con.WS_VISIBLE + FRAMEDLG_STD = win32con.WS_CAPTION | win32con.WS_SYSMENU + style = FRAMEDLG_STD | win32con.WS_VISIBLE | win32con.DS_SETFONT | win32con.WS_MINIMIZEBOX + template = [[self.caption, (0, 0, w, h), style, None, (8, 'Helv')], ] + lvStyle = SS_STD | commctrl.LVS_EDITLABELS | commctrl.LVS_REPORT | commctrl.LVS_AUTOARRANGE | commctrl.LVS_ALIGNLEFT | win32con.WS_BORDER | win32con.WS_TABSTOP + template.append(["SysListView32", "", self.IDC_LISTVIEW, (10, 10, 185, 100), lvStyle]) + return template + +class RegistryPage(RegEditPropertyPage): + def __init__(self): + self.caption="Path" + RegEditPropertyPage.__init__(self, self.GetTemplate()) + def OnInitDialog(self): + self.listview = self.GetDlgItem(self.IDC_LISTVIEW) + RegEditPropertyPage.OnInitDialog(self) + # Setup the listview columns + itemDetails = (commctrl.LVCFMT_LEFT, 100, "App", 0) + self.listview.InsertColumn(0, itemDetails) + itemDetails = (commctrl.LVCFMT_LEFT, 1024, "Paths", 0) + self.listview.InsertColumn(1, itemDetails) + + index = self.listview.InsertItem(0,"App") + self.listview.SetItemText(index, 1, "Path") + + +class RegistrySheet(dialog.PropertySheet): + def __init__(self, title): + dialog.PropertySheet.__init__(self, title) + self.HookMessage(self.OnActivate, win32con.WM_ACTIVATE) + def OnActivate(self, msg): + print("OnAcivate") + +def t(): + ps=RegistrySheet('Registry Settings') + ps.AddPage(RegistryPage()) + ps.DoModal() + +if __name__=='__main__': + t() diff --git a/Lib/site-packages/pythonwin/scintilla.dll b/Lib/site-packages/pythonwin/scintilla.dll new file mode 100644 index 0000000..6976f0d Binary files /dev/null and b/Lib/site-packages/pythonwin/scintilla.dll differ diff --git a/Lib/site-packages/pythonwin/win32ui.pyd b/Lib/site-packages/pythonwin/win32ui.pyd new file mode 100644 index 0000000..76a28a7 Binary files /dev/null and b/Lib/site-packages/pythonwin/win32ui.pyd differ diff --git a/Lib/site-packages/pythonwin/win32uiole.pyd b/Lib/site-packages/pythonwin/win32uiole.pyd new file mode 100644 index 0000000..9ef3aa6 Binary files /dev/null and b/Lib/site-packages/pythonwin/win32uiole.pyd differ diff --git a/Lib/site-packages/pywin32-220-py3.5.egg-info b/Lib/site-packages/pywin32-220-py3.5.egg-info new file mode 100644 index 0000000..40814bc --- /dev/null +++ b/Lib/site-packages/pywin32-220-py3.5.egg-info @@ -0,0 +1,13 @@ +Metadata-Version: 1.0 +Name: pywin32 +Version: 220 +Summary: Python for Window Extensions +Home-page: http://sourceforge.net/projects/pywin32/ +Author: Mark Hammond (et al) +Author-email: mhammond@users.sourceforge.net +License: PSF +Description: Python extensions for Microsoft Windows + Provides access to much of the Win32 API, the + ability to create and use COM objects, and the + Pythonwin environment. +Platform: UNKNOWN diff --git a/Lib/site-packages/pywin32.pth b/Lib/site-packages/pywin32.pth new file mode 100644 index 0000000..49ed1b4 --- /dev/null +++ b/Lib/site-packages/pywin32.pth @@ -0,0 +1,4 @@ +# .pth file for the PyWin32 extensions +win32 +win32\lib +Pythonwin diff --git a/Lib/site-packages/pywin32.version.txt b/Lib/site-packages/pywin32.version.txt new file mode 100644 index 0000000..e8136a7 --- /dev/null +++ b/Lib/site-packages/pywin32.version.txt @@ -0,0 +1 @@ +220 diff --git a/Lib/site-packages/pywin32_system32/pythoncom35.dll b/Lib/site-packages/pywin32_system32/pythoncom35.dll new file mode 100644 index 0000000..60d9b56 Binary files /dev/null and b/Lib/site-packages/pywin32_system32/pythoncom35.dll differ diff --git a/Lib/site-packages/pywin32_system32/pywintypes35.dll b/Lib/site-packages/pywin32_system32/pywintypes35.dll new file mode 100644 index 0000000..ef2910d Binary files /dev/null and b/Lib/site-packages/pywin32_system32/pywintypes35.dll differ diff --git a/Lib/site-packages/win32/Demos/BackupRead_BackupWrite.py b/Lib/site-packages/win32/Demos/BackupRead_BackupWrite.py new file mode 100644 index 0000000..b41c007 --- /dev/null +++ b/Lib/site-packages/win32/Demos/BackupRead_BackupWrite.py @@ -0,0 +1,81 @@ +## demonstrates using BackupRead and BackupWrite to copy all of a file's data streams + +import win32file, win32api, win32con, win32security, ntsecuritycon +from win32com import storagecon +import pythoncom, pywintypes +import struct, traceback +from pywin32_testutil import str2bytes, ob2memory + +all_sd_info=win32security.DACL_SECURITY_INFORMATION|win32security.DACL_SECURITY_INFORMATION| \ + win32security.OWNER_SECURITY_INFORMATION|win32security.GROUP_SECURITY_INFORMATION + +tempdir=win32api.GetTempPath() +tempfile=win32api.GetTempFileName(tempdir,'bkr')[0] +outfile=win32api.GetTempFileName(tempdir,'out')[0] +print('Filename:',tempfile,'Output file:',outfile) + +f=open(tempfile,'w') +f.write('some random junk'+'x'*100) +f.close() + +## add a couple of alternate data streams +f=open(tempfile+':streamdata','w') +f.write('data written to alternate stream'+'y'*100) +f.close() + +f=open(tempfile+':anotherstream','w') +f.write('z'*100) +f.close() + +## add Summary Information, which is stored as a separate stream +m=storagecon.STGM_READWRITE | storagecon.STGM_SHARE_EXCLUSIVE |storagecon.STGM_DIRECT +pss=pythoncom.StgOpenStorageEx(tempfile, m, storagecon.STGFMT_FILE, 0 , pythoncom.IID_IPropertySetStorage,None) +ps=pss.Create(pythoncom.FMTID_SummaryInformation,pythoncom.IID_IPropertyStorage,0,storagecon.STGM_READWRITE|storagecon.STGM_SHARE_EXCLUSIVE) +ps.WriteMultiple((storagecon.PIDSI_KEYWORDS,storagecon.PIDSI_COMMENTS),('keywords','comments')) +ps=None +pss=None + +## add a custom security descriptor to make sure we don't +## get a default that would always be the same for both files in temp dir +new_sd=pywintypes.SECURITY_DESCRIPTOR() +sid=win32security.LookupAccountName('','EveryOne')[0] +acl=pywintypes.ACL() +acl.AddAccessAllowedAce(1, win32con.GENERIC_READ, sid) +acl.AddAccessAllowedAce(1, ntsecuritycon.FILE_APPEND_DATA, sid) +acl.AddAccessAllowedAce(1, win32con.GENERIC_WRITE, sid) +acl.AddAccessAllowedAce(1, ntsecuritycon.FILE_ALL_ACCESS, sid) + +new_sd.SetSecurityDescriptorDacl(True, acl, False) +win32security.SetFileSecurity(tempfile,win32security.DACL_SECURITY_INFORMATION,new_sd) + + +sa=pywintypes.SECURITY_ATTRIBUTES() +sa.bInheritHandle=True +h=win32file.CreateFile(tempfile, win32con.GENERIC_ALL ,win32con.FILE_SHARE_READ, + sa, win32con.OPEN_EXISTING, win32file.FILE_FLAG_BACKUP_SEMANTICS , None) + +outh=win32file.CreateFile(outfile, win32con.GENERIC_ALL ,win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE, + sa, win32con.OPEN_EXISTING, win32file.FILE_FLAG_BACKUP_SEMANTICS , None) + +ctxt=0 +outctxt=0 +buf=None +readsize=100 + +while 1: + bytes_read, buf, ctxt=win32file.BackupRead(h, readsize, buf, False, True, ctxt) + if bytes_read==0: + break + bytes_written, outctxt=win32file.BackupWrite(outh, bytes_read, buf, False, True, outctxt) + print('Written:',bytes_written,'Context:',outctxt) +win32file.BackupRead(h, 0, buf, True, True, ctxt) +win32file.BackupWrite(outh, 0, str2bytes(''), True, True, outctxt) +win32file.CloseHandle(h) +win32file.CloseHandle(outh) + +assert open(tempfile).read()==open(outfile).read(),"File contents differ !" +assert open(tempfile+':streamdata').read()==open(outfile+':streamdata').read(),"streamdata contents differ !" +assert open(tempfile+':anotherstream').read()==open(outfile+':anotherstream').read(),"anotherstream contents differ !" +assert ob2memory(win32security.GetFileSecurity(tempfile,all_sd_info))[:]== \ + ob2memory(win32security.GetFileSecurity(outfile, all_sd_info))[:], "Security descriptors are different !" +## also should check Summary Info programatically diff --git a/Lib/site-packages/win32/Demos/BackupSeek_streamheaders.py b/Lib/site-packages/win32/Demos/BackupSeek_streamheaders.py new file mode 100644 index 0000000..a9b6d78 --- /dev/null +++ b/Lib/site-packages/win32/Demos/BackupSeek_streamheaders.py @@ -0,0 +1,85 @@ +## demonstrates using BackupSeek to enumerate data streams for a file +import win32file, win32api, win32con +from win32com import storagecon +import pythoncom, pywintypes +import struct, traceback + +stream_types={ + win32con.BACKUP_DATA:"Standard data", + win32con.BACKUP_EA_DATA:"Extended attribute data", + win32con.BACKUP_SECURITY_DATA:"Security descriptor data", + win32con.BACKUP_ALTERNATE_DATA:"Alternative data streams", + win32con.BACKUP_LINK:"Hard link information", + win32con.BACKUP_PROPERTY_DATA:"Property data", + win32con.BACKUP_OBJECT_ID:"Objects identifiers", + win32con.BACKUP_REPARSE_DATA:"Reparse points", + win32con.BACKUP_SPARSE_BLOCK:"Sparse file" +} + +tempdir=win32api.GetTempPath() +tempfile=win32api.GetTempFileName(tempdir,'bkr')[0] +print('Filename:',tempfile) + +f=open(tempfile,'w') +f.write('some random junk'+'x'*100) +f.close() + +f=open(tempfile+':streamdata','w') +f.write('data written to alternate stream'+'y'*100) +f.close() + +f=open(tempfile+':anotherstream','w') +f.write('z'*200) +f.close() + +## add Summary Information, which is stored as a separate stream +m=storagecon.STGM_READWRITE | storagecon.STGM_SHARE_EXCLUSIVE |storagecon.STGM_DIRECT +pss=pythoncom.StgOpenStorageEx(tempfile, m, storagecon.STGFMT_FILE, 0 , pythoncom.IID_IPropertySetStorage,None) +ps=pss.Create(pythoncom.FMTID_SummaryInformation,pythoncom.IID_IPropertyStorage,0,storagecon.STGM_READWRITE|storagecon.STGM_SHARE_EXCLUSIVE) +ps.WriteMultiple((storagecon.PIDSI_KEYWORDS,storagecon.PIDSI_COMMENTS),('keywords','comments')) +ps=None +pss=None + +sa=pywintypes.SECURITY_ATTRIBUTES() +sa.bInheritHandle=False +h=win32file.CreateFile(tempfile, win32con.GENERIC_ALL ,win32con.FILE_SHARE_READ, + sa, win32con.OPEN_EXISTING, win32file.FILE_FLAG_BACKUP_SEMANTICS , None) + + +""" stream header: +typedef struct _WIN32_STREAM_ID { + DWORD dwStreamId; DWORD dwStreamAttributes; LARGE_INTEGER Size; + DWORD dwStreamNameSize; WCHAR cStreamName[ANYSIZE_ARRAY]; +} +""" + +win32_stream_id_format="LLQL" +win32_stream_id_size=struct.calcsize(win32_stream_id_format) + +def parse_stream_header(h,ctxt,data): + stream_type, stream_attributes, stream_size, stream_name_size=struct.unpack(win32_stream_id_format,data) + print('\nType:',stream_type,stream_types[stream_type], 'Attributes:', stream_attributes, 'Size:', stream_size, 'Name len:',stream_name_size) + if stream_name_size>0: + ## ??? sdk says this size is in characters, but it appears to be number of bytes ??? + bytes_read, stream_name_buf, ctxt=win32file.BackupRead(h, stream_name_size, None, False, True, ctxt) + stream_name=pywintypes.UnicodeFromRaw(stream_name_buf[:]) + else: + stream_name='Unnamed' + print('Name:'+stream_name) + return ctxt, stream_type, stream_attributes, stream_size, stream_name_size, stream_name + +ctxt=0 +win32_stream_id_buf=None ## gets rebound to a writable buffer on first call and reused +while 1: + bytes_read, win32_stream_id_buf, ctxt=win32file.BackupRead(h, win32_stream_id_size, win32_stream_id_buf, False, True, ctxt) + if bytes_read==0: + break + ctxt, stream_type, stream_attributes, stream_size, stream_name_size, stream_name=\ + parse_stream_header(h, ctxt, win32_stream_id_buf[:]) + if stream_size>0: + bytes_moved=win32file.BackupSeek(h, stream_size, ctxt) + print('Moved: ',bytes_moved) + +win32file.BackupRead(h, win32_stream_id_size, win32_stream_id_buf, True, True, ctxt) +win32file.CloseHandle(h) + diff --git a/Lib/site-packages/win32/Demos/CopyFileEx.py b/Lib/site-packages/win32/Demos/CopyFileEx.py new file mode 100644 index 0000000..2709f41 --- /dev/null +++ b/Lib/site-packages/win32/Demos/CopyFileEx.py @@ -0,0 +1,30 @@ +import win32file, win32api +import os + + +def ProgressRoutine(TotalFileSize, TotalBytesTransferred, StreamSize, StreamBytesTransferred, + StreamNumber, CallbackReason, SourceFile, DestinationFile, Data): + print(Data) + print(TotalFileSize, TotalBytesTransferred, StreamSize, StreamBytesTransferred, StreamNumber, CallbackReason, SourceFile, DestinationFile) + ##if TotalBytesTransferred > 100000: + ## return win32file.PROGRESS_STOP + return win32file.PROGRESS_CONTINUE + +temp_dir=win32api.GetTempPath() +fsrc=win32api.GetTempFileName(temp_dir,'cfe')[0] +fdst=win32api.GetTempFileName(temp_dir,'cfe')[0] +print(fsrc, fdst) + +f=open(fsrc,'w') +f.write('xxxxxxxxxxxxxxxx\n'*32768) +f.close() +## add a couple of extra data streams +f=open(fsrc+':stream_y','w') +f.write('yyyyyyyyyyyyyyyy\n'*32768) +f.close() +f=open(fsrc+':stream_z','w') +f.write('zzzzzzzzzzzzzzzz\n'*32768) +f.close() + +operation_desc='Copying '+fsrc+' to '+fdst +win32file.CopyFileEx(fsrc, fdst, ProgressRoutine, Data=operation_desc, Cancel=False, CopyFlags=win32file.COPY_FILE_RESTARTABLE, Transaction=None) diff --git a/Lib/site-packages/win32/Demos/CreateFileTransacted_MiniVersion.py b/Lib/site-packages/win32/Demos/CreateFileTransacted_MiniVersion.py new file mode 100644 index 0000000..3f09458 --- /dev/null +++ b/Lib/site-packages/win32/Demos/CreateFileTransacted_MiniVersion.py @@ -0,0 +1,68 @@ +""" +This demonstrates the creation of miniversions of a file during a transaction. +The FSCTL_TXFS_CREATE_MINIVERSION control code saves any changes to a new +miniversion (effectively a savepoint within a transaction). +""" + +import win32file, win32api, win32transaction +import win32con, winioctlcon +import struct +import os +from pywin32_testutil import str2bytes # py3k-friendly helper + +""" +Definition of buffer used with FSCTL_TXFS_CREATE_MINIVERSION: +typedef struct _TXFS_CREATE_MINIVERSION_INFO{ + USHORT StructureVersion; + USHORT StructureLength; + ULONG BaseVersion; + USHORT MiniVersion;} +""" +buf_fmt='HHLH0L' ## buffer size must include struct padding +buf_size=struct.calcsize(buf_fmt) + +tempdir=win32api.GetTempPath() +tempfile=win32api.GetTempFileName(tempdir,'cft')[0] +print("Demonstrating transactions on tempfile", tempfile) +f=open(tempfile,'w') +f.write('This is original file.\n') +f.close() + +trans=win32transaction.CreateTransaction(Description='Test creating miniversions of a file') +hfile=win32file.CreateFileW(tempfile, win32con.GENERIC_READ|win32con.GENERIC_WRITE, + win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE, + None, win32con.OPEN_EXISTING, 0 , None, Transaction=trans) + +win32file.WriteFile(hfile, str2bytes('This is first miniversion.\n')) +buf=win32file.DeviceIoControl(hfile, winioctlcon.FSCTL_TXFS_CREATE_MINIVERSION,None,buf_size,None) +struct_ver, struct_len, base_ver, ver_1=struct.unpack(buf_fmt, buf) + +win32file.SetFilePointer(hfile, 0, win32con.FILE_BEGIN) +win32file.WriteFile(hfile, str2bytes('This is second miniversion!\n')) +buf=win32file.DeviceIoControl(hfile, winioctlcon.FSCTL_TXFS_CREATE_MINIVERSION,None,buf_size,None) +struct_ver, struct_len, base_ver, ver_2=struct.unpack(buf_fmt, buf) +hfile.Close() + +## miniversions can't be opened with write access +hfile_0=win32file.CreateFileW(tempfile, win32con.GENERIC_READ, + win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE, + None, win32con.OPEN_EXISTING, 0 , None, Transaction=trans, MiniVersion=base_ver) +print('version:',base_ver,win32file.ReadFile(hfile_0, 100)) +hfile_0.Close() + +hfile_1=win32file.CreateFileW(tempfile, win32con.GENERIC_READ, + win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE, + None, win32con.OPEN_EXISTING, 0 , None, Transaction=trans, MiniVersion=ver_1) +print('version:',ver_1,win32file.ReadFile(hfile_1, 100)) +hfile_1.Close() + +hfile_2=win32file.CreateFileW(tempfile, win32con.GENERIC_READ, + win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE, + None, win32con.OPEN_EXISTING, 0 , None, Transaction=trans, MiniVersion=ver_2) +print('version:',ver_2,win32file.ReadFile(hfile_2, 100)) +hfile_2.Close() + +## MiniVersions are destroyed when transaction is committed or rolled back +win32transaction.CommitTransaction(trans) + +os.unlink(tempfile) diff --git a/Lib/site-packages/win32/Demos/EvtSubscribe_pull.py b/Lib/site-packages/win32/Demos/EvtSubscribe_pull.py new file mode 100644 index 0000000..e8ad7a3 --- /dev/null +++ b/Lib/site-packages/win32/Demos/EvtSubscribe_pull.py @@ -0,0 +1,21 @@ +## Demonstrates how to create a "pull" subscription +import win32evtlog, win32event, win32con +query_text='*[System[Provider[@Name="Microsoft-Windows-Winlogon"]]]' + +h=win32event.CreateEvent(None, 0, 0, None) +s=win32evtlog.EvtSubscribe('System', win32evtlog.EvtSubscribeStartAtOldestRecord, SignalEvent=h, Query=query_text) + +while 1: + while 1: + events=win32evtlog.EvtNext(s, 10) + if len(events)==0: + break + ##for event in events: + ## print (win32evtlog.EvtRender(event, win32evtlog.EvtRenderEventXml)) + print(('retrieved %s events' %len(events))) + while 1: + print ('waiting...') + w=win32event.WaitForSingleObjectEx(h, 2000, True) + if w==win32con.WAIT_OBJECT_0: + break + diff --git a/Lib/site-packages/win32/Demos/EvtSubscribe_push.py b/Lib/site-packages/win32/Demos/EvtSubscribe_push.py new file mode 100644 index 0000000..55635f6 --- /dev/null +++ b/Lib/site-packages/win32/Demos/EvtSubscribe_push.py @@ -0,0 +1,16 @@ +## Demonstrates a "push" subscription with a callback function +import win32evtlog +query_text='*[System[Provider[@Name="Microsoft-Windows-Winlogon"]]]' + +def c(reason, context, evt): + if reason==win32evtlog.EvtSubscribeActionError: + print ('EvtSubscribeActionError') + elif reason==win32evtlog.EvtSubscribeActionDeliver: + print ('EvtSubscribeActionDeliver') + else: + print(('??? Unknown action ???', reason)) + context.append(win32evtlog.EvtRender(evt, win32evtlog.EvtRenderEventXml)) + return 0 + +evttext=[] +s=win32evtlog.EvtSubscribe('System', win32evtlog.EvtSubscribeStartAtOldestRecord, Query='*', Callback=c, Context=evttext) diff --git a/Lib/site-packages/win32/Demos/FileSecurityTest.py b/Lib/site-packages/win32/Demos/FileSecurityTest.py new file mode 100644 index 0000000..8d872c6 --- /dev/null +++ b/Lib/site-packages/win32/Demos/FileSecurityTest.py @@ -0,0 +1,68 @@ +# Contributed by Kelly Kranabetter. +import os, sys +import win32security, ntsecuritycon + +# get security information +#name=r"c:\autoexec.bat" +#name= r"g:\!workgrp\lim" +name=sys.argv[0] + +if not os.path.exists(name): + print(name, "does not exist!") + sys.exit() + +print("On file " , name, "\n") + +# get owner SID +print("OWNER") +sd= win32security.GetFileSecurity(name, win32security.OWNER_SECURITY_INFORMATION) +sid= sd.GetSecurityDescriptorOwner() +print(" ", win32security.LookupAccountSid(None, sid)) + +# get group SID +print("GROUP") +sd= win32security.GetFileSecurity(name, win32security.GROUP_SECURITY_INFORMATION) +sid= sd.GetSecurityDescriptorGroup() +print(" ", win32security.LookupAccountSid(None, sid)) + +# get ACEs +sd= win32security.GetFileSecurity(name, win32security.DACL_SECURITY_INFORMATION) +dacl= sd.GetSecurityDescriptorDacl() +if dacl == None: + print("No Discretionary ACL") +else: + for ace_no in range(0, dacl.GetAceCount()): + ace= dacl.GetAce(ace_no) + print("ACE", ace_no) + + print(" -Type") + for i in ("ACCESS_ALLOWED_ACE_TYPE", "ACCESS_DENIED_ACE_TYPE", "SYSTEM_AUDIT_ACE_TYPE", "SYSTEM_ALARM_ACE_TYPE"): + if getattr(ntsecuritycon, i) == ace[0][0]: + print(" ", i) + + print(" -Flags", hex(ace[0][1])) + for i in ("OBJECT_INHERIT_ACE", "CONTAINER_INHERIT_ACE", "NO_PROPAGATE_INHERIT_ACE", "INHERIT_ONLY_ACE", "SUCCESSFUL_ACCESS_ACE_FLAG", "FAILED_ACCESS_ACE_FLAG"): + if getattr(ntsecuritycon, i) & ace[0][1] == getattr(ntsecuritycon, i): + print(" ", i) + + print(" -mask", hex(ace[1])) + + # files and directories do permissions differently + permissions_file= ("DELETE", "READ_CONTROL", "WRITE_DAC", "WRITE_OWNER", "SYNCHRONIZE", "FILE_GENERIC_READ", "FILE_GENERIC_WRITE", "FILE_GENERIC_EXECUTE", "FILE_DELETE_CHILD") + permissions_dir= ("DELETE", "READ_CONTROL", "WRITE_DAC", "WRITE_OWNER", "SYNCHRONIZE", "FILE_ADD_SUBDIRECTORY", "FILE_ADD_FILE", "FILE_DELETE_CHILD", "FILE_LIST_DIRECTORY", "FILE_TRAVERSE", "FILE_READ_ATTRIBUTES", "FILE_WRITE_ATTRIBUTES", "FILE_READ_EA", "FILE_WRITE_EA") + permissions_dir_inherit= ("DELETE", "READ_CONTROL", "WRITE_DAC", "WRITE_OWNER", "SYNCHRONIZE", "GENERIC_READ", "GENERIC_WRITE", "GENERIC_EXECUTE", "GENERIC_ALL") + if os.path.isfile(name): + permissions= permissions_file + else: + permissions= permissions_dir + # directories also contain an ACE that is inherited by children (files) within them + if ace[0][1] & ntsecuritycon.OBJECT_INHERIT_ACE == ntsecuritycon.OBJECT_INHERIT_ACE and ace[0][1] & ntsecuritycon.INHERIT_ONLY_ACE == ntsecuritycon.INHERIT_ONLY_ACE: + permissions= permissions_dir_inherit + + calc_mask= 0 # calculate the mask so we can see if we are printing all of the permissions + for i in permissions: + if getattr(ntsecuritycon, i) & ace[1] == getattr(ntsecuritycon, i): + calc_mask= calc_mask | getattr(ntsecuritycon, i) + print(" ", i) + print(" ", "Calculated Check Mask=", hex(calc_mask)) + print(" -SID\n ", win32security.LookupAccountSid(None, ace[2])) diff --git a/Lib/site-packages/win32/Demos/GetSaveFileName.py b/Lib/site-packages/win32/Demos/GetSaveFileName.py new file mode 100644 index 0000000..a6308c4 --- /dev/null +++ b/Lib/site-packages/win32/Demos/GetSaveFileName.py @@ -0,0 +1,36 @@ +import win32gui, win32con, os + +filter='Python Scripts\0*.py;*.pyw;*.pys\0Text files\0*.txt\0' +customfilter='Other file types\0*.*\0' + +fname, customfilter, flags=win32gui.GetSaveFileNameW( + InitialDir=os.environ['temp'], + Flags=win32con.OFN_ALLOWMULTISELECT|win32con.OFN_EXPLORER, + File='somefilename', DefExt='py', + Title='GetSaveFileNameW', + Filter=filter, + CustomFilter=customfilter, + FilterIndex=1) + +print('save file names:', repr(fname)) +print('filter used:', repr(customfilter)) +print('Flags:', flags) +for k,v in list(win32con.__dict__.items()): + if k.startswith('OFN_') and flags & v: + print('\t'+k) + +fname, customfilter, flags=win32gui.GetOpenFileNameW( + InitialDir=os.environ['temp'], + Flags=win32con.OFN_ALLOWMULTISELECT|win32con.OFN_EXPLORER, + File='somefilename', DefExt='py', + Title='GetOpenFileNameW', + Filter=filter, + CustomFilter=customfilter, + FilterIndex=0) + +print('open file names:', repr(fname)) +print('filter used:', repr(customfilter)) +print('Flags:', flags) +for k,v in list(win32con.__dict__.items()): + if k.startswith('OFN_') and flags & v: + print('\t'+k) diff --git a/Lib/site-packages/win32/Demos/NetValidatePasswordPolicy.py b/Lib/site-packages/win32/Demos/NetValidatePasswordPolicy.py new file mode 100644 index 0000000..2e52180 --- /dev/null +++ b/Lib/site-packages/win32/Demos/NetValidatePasswordPolicy.py @@ -0,0 +1,101 @@ +"""A demo of using win32net.NetValidatePasswordPolicy. + +Example usage: + +% NetValidatePasswordPolicy.py --password=foo change +which might return: + +> Result of 'change' validation is 0: The operation completed successfully. + +or depending on the policy: + +> Result of 'change' validation is 2245: The password does not meet the +> password policy requirements. Check the minimum password length, +> password complexity and password history requirements. + +Adding --user doesn't seem to change the output (even the PasswordLastSet seen +when '-f' is used doesn't depend on the username), but theoretically it will +also check the password history for the specified user. + +% NetValidatePasswordPolicy.py auth + +which always (with and without '-m') seems to return: + +> Result of 'auth' validation is 2701: Password must change at next logon +""" + +import sys +import win32api +import win32net, win32netcon + +import optparse +from pprint import pprint + +def main(): + parser = optparse.OptionParser("%prog [options] auth|change ...", + description="A win32net.NetValidatePasswordPolicy demo.") + + parser.add_option("-u", "--username", + action="store", + help="The username to pass to the function (only for the " + "change command") + + parser.add_option("-p", "--password", + action="store", + help="The clear-text password to pass to the function " + "(only for the 'change' command)") + + parser.add_option("-m", "--password-matched", + action="store_false", default=True, + help="Used to specify the password does NOT match (ie, " + "uses False for the PasswordMatch/PasswordMatched " + "arg, both 'auth' and 'change' commands)") + + parser.add_option("-s", "--server", + action="store", + help="The name of the server to execute the command on") + + parser.add_option("-f", "--show_fields", + action="store_true", default=False, + help="Print the NET_VALIDATE_PERSISTED_FIELDS returned") + + options, args = parser.parse_args() + + if not args: + args = ["auth"] + + for arg in args: + if arg == "auth": + input = {"PasswordMatched": options.password_matched, + } + val_type = win32netcon.NetValidateAuthentication + elif arg == "change": + input = {"ClearPassword": options.password, + "PasswordMatch": options.password_matched, + "UserAccountName": options.username, + } + val_type = win32netcon.NetValidatePasswordChange + else: + parser.error("Invalid arg - must be 'auth' or 'change'") + + try: + fields, status = win32net.NetValidatePasswordPolicy(options.server, + None, val_type, input) + except NotImplementedError: + print("NetValidatePasswordPolicy not implemented on this platform.") + return 1 + except win32net.error as exc: + print("NetValidatePasswordPolicy failed: ", exc) + return 1 + + if options.show_fields: + print("NET_VALIDATE_PERSISTED_FIELDS fields:") + pprint(fields) + + print("Result of %r validation is %d: %s" % \ + (arg, status, win32api.FormatMessage(status).strip())) + + return 0 + +if __name__=='__main__': + sys.exit(main()) diff --git a/Lib/site-packages/win32/Demos/OpenEncryptedFileRaw.py b/Lib/site-packages/win32/Demos/OpenEncryptedFileRaw.py new file mode 100644 index 0000000..adc4cdf --- /dev/null +++ b/Lib/site-packages/win32/Demos/OpenEncryptedFileRaw.py @@ -0,0 +1,64 @@ +import win32file, win32api, winerror +import os + +def ReadCallback(input_buffer, data, buflen): + fnamein, fnameout, f = data + ## print fnamein, fnameout, buflen + f.write(input_buffer) + ## python 2.3 throws an error if return value is a plain int + return winerror.ERROR_SUCCESS + +def WriteCallback(output_buffer, data, buflen): + fnamebackup, fnameout, f = data + file_data=f.read(buflen) + ## returning 0 as len terminates WriteEncryptedFileRaw + output_len=len(file_data) + output_buffer[:output_len]=file_data + return winerror.ERROR_SUCCESS, output_len + + +tmp_dir=win32api.GetTempPath() +dst_dir=win32api.GetTempFileName(tmp_dir,'oef')[0] +os.remove(dst_dir) +os.mkdir(dst_dir) +print('Destination dir:', dst_dir) + +## create an encrypted file +fname=win32api.GetTempFileName(dst_dir,'ref')[0] +print('orig file:',fname) +f=open(fname,'w') +f.write('xxxxxxxxxxxxxxxx\n'*32768) +f.close() +## add a couple of extra data streams +f=open(fname+':stream_y','w') +f.write('yyyyyyyyyyyyyyyy\n'*32768) +f.close() +f=open(fname+':stream_z','w') +f.write('zzzzzzzzzzzzzzzz\n'*32768) +f.close() +win32file.EncryptFile(fname) + +## backup raw data of encrypted file +bkup_fname=win32api.GetTempFileName(dst_dir,'bef')[0] +print('backup file:', bkup_fname) +f=open(bkup_fname,'wb') +ctxt=win32file.OpenEncryptedFileRaw(fname,0) +try: + win32file.ReadEncryptedFileRaw(ReadCallback, (fname,bkup_fname,f), ctxt) +finally: + ## if context is not closed, file remains locked even if calling process is killed + win32file.CloseEncryptedFileRaw(ctxt) + f.close() + +## restore data from backup to new encrypted file +dst_fname=win32api.GetTempFileName(dst_dir,'wef')[0] +print('restored file:', dst_fname) +f=open(bkup_fname,'rb') +ctxtout=win32file.OpenEncryptedFileRaw(dst_fname, win32file.CREATE_FOR_IMPORT) +try: + win32file.WriteEncryptedFileRaw(WriteCallback, (bkup_fname,dst_fname,f), ctxtout) +finally: + win32file.CloseEncryptedFileRaw(ctxtout) + f.close() + + diff --git a/Lib/site-packages/win32/Demos/RegCreateKeyTransacted.py b/Lib/site-packages/win32/Demos/RegCreateKeyTransacted.py new file mode 100644 index 0000000..b8f300a --- /dev/null +++ b/Lib/site-packages/win32/Demos/RegCreateKeyTransacted.py @@ -0,0 +1,43 @@ +import win32api, win32con, win32transaction + +keyname='Pywin32 test transacted registry functions' +subkeyname='test transacted subkey' +classname='Transacted Class' + +trans=win32transaction.CreateTransaction(Description='test RegCreateKeyTransacted') +key, disp=win32api.RegCreateKeyEx(win32con.HKEY_CURRENT_USER, keyname, + samDesired=win32con.KEY_ALL_ACCESS, Class=classname) +## clean up any existing keys +for subk in win32api.RegEnumKeyExW(key): + win32api.RegDeleteKey(key, subk[0]) + +## reopen key in transacted mode +transacted_key=win32api.RegOpenKeyTransacted(Key=win32con.HKEY_CURRENT_USER, SubKey=keyname, + Transaction=trans, samDesired=win32con.KEY_ALL_ACCESS) +subkey, disp=win32api.RegCreateKeyEx(transacted_key, subkeyname, Transaction=trans, + samDesired=win32con.KEY_ALL_ACCESS, Class=classname) + +## Newly created key should not be visible from non-transacted handle +subkeys=[s[0] for s in win32api.RegEnumKeyExW(key)] +assert subkeyname not in subkeys + +transacted_subkeys=[s[0] for s in win32api.RegEnumKeyExW(transacted_key)] +assert subkeyname in transacted_subkeys + +## Key should be visible to non-transacted handle after commit +win32transaction.CommitTransaction(trans) +subkeys=[s[0] for s in win32api.RegEnumKeyExW(key)] +assert subkeyname in subkeys + +## test transacted delete +del_trans=win32transaction.CreateTransaction(Description='test RegDeleteKeyTransacted') +win32api.RegDeleteKeyEx(key, subkeyname, Transaction=del_trans) +## subkey should still show up for non-transacted handle +subkeys=[s[0] for s in win32api.RegEnumKeyExW(key)] +assert subkeyname in subkeys +## ... and should be gone after commit +win32transaction.CommitTransaction(del_trans) +subkeys=[s[0] for s in win32api.RegEnumKeyExW(key)] +assert subkeyname not in subkeys + +win32api.RegDeleteKey(win32con.HKEY_CURRENT_USER, keyname) diff --git a/Lib/site-packages/win32/Demos/RegRestoreKey.py b/Lib/site-packages/win32/Demos/RegRestoreKey.py new file mode 100644 index 0000000..2480b44 --- /dev/null +++ b/Lib/site-packages/win32/Demos/RegRestoreKey.py @@ -0,0 +1,38 @@ +import win32api, win32security +import win32con, ntsecuritycon, winnt +import os + +temp_dir=win32api.GetTempPath() +fname=win32api.GetTempFileName(temp_dir,'rsk')[0] +print(fname) +## file can't exist +os.remove(fname) + +## enable backup and restore privs +required_privs = ((win32security.LookupPrivilegeValue('',ntsecuritycon.SE_BACKUP_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_RESTORE_NAME),win32con.SE_PRIVILEGE_ENABLED) + ) +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken(ph, win32con.TOKEN_READ|win32con.TOKEN_ADJUST_PRIVILEGES) +adjusted_privs=win32security.AdjustTokenPrivileges(th,0,required_privs) + +try: + sa=win32security.SECURITY_ATTRIBUTES() + my_sid = win32security.GetTokenInformation(th,ntsecuritycon.TokenUser)[0] + sa.SECURITY_DESCRIPTOR.SetSecurityDescriptorOwner(my_sid,0) + + k, disp=win32api.RegCreateKeyEx(win32con.HKEY_CURRENT_USER, 'Python test key', SecurityAttributes=sa, + samDesired=win32con.KEY_ALL_ACCESS, Class='some class', Options=0) + win32api.RegSetValue(k, None, win32con.REG_SZ, 'Default value for python test key') + + subk, disp=win32api.RegCreateKeyEx(k, 'python test subkey', SecurityAttributes=sa, + samDesired=win32con.KEY_ALL_ACCESS, Class='some other class', Options=0) + win32api.RegSetValue(subk, None, win32con.REG_SZ, 'Default value for subkey') + + win32api.RegSaveKeyEx(k, fname, Flags=winnt.REG_STANDARD_FORMAT, SecurityAttributes=sa) + + restored_key, disp=win32api.RegCreateKeyEx(win32con.HKEY_CURRENT_USER, 'Python test key(restored)', SecurityAttributes=sa, + samDesired=win32con.KEY_ALL_ACCESS, Class='restored class', Options=0) + win32api.RegRestoreKey(restored_key, fname) +finally: + win32security.AdjustTokenPrivileges(th, 0, adjusted_privs) \ No newline at end of file diff --git a/Lib/site-packages/win32/Demos/SystemParametersInfo.py b/Lib/site-packages/win32/Demos/SystemParametersInfo.py new file mode 100644 index 0000000..f452e4a --- /dev/null +++ b/Lib/site-packages/win32/Demos/SystemParametersInfo.py @@ -0,0 +1,178 @@ +import win32gui, win32con, win32api, time, os, glob +## some of these tests will fail for systems prior to XP + +for pname in( + ## Set actions all take an unsigned int in pvParam + "SPI_GETMOUSESPEED", "SPI_GETACTIVEWNDTRKTIMEOUT", "SPI_GETCARETWIDTH", + "SPI_GETFOREGROUNDFLASHCOUNT", "SPI_GETFOREGROUNDLOCKTIMEOUT", + ## Set actions all take an unsigned int in uiParam + "SPI_GETWHEELSCROLLLINES", "SPI_GETKEYBOARDDELAY", + "SPI_GETKEYBOARDSPEED", + "SPI_GETMOUSEHOVERHEIGHT", "SPI_GETMOUSEHOVERWIDTH", + "SPI_GETMOUSEHOVERTIME", "SPI_GETSCREENSAVETIMEOUT", "SPI_GETMENUSHOWDELAY", + "SPI_GETLOWPOWERTIMEOUT", "SPI_GETPOWEROFFTIMEOUT", "SPI_GETBORDER", + ## below are winxp only: + "SPI_GETFONTSMOOTHINGCONTRAST", "SPI_GETFONTSMOOTHINGTYPE", "SPI_GETFOCUSBORDERHEIGHT", + "SPI_GETFOCUSBORDERWIDTH", "SPI_GETMOUSECLICKLOCKTIME"): + print(pname) + cget=getattr(win32con,pname) + cset=getattr(win32con,pname.replace('_GET','_SET')) + orig_value=win32gui.SystemParametersInfo(cget) + print('\toriginal setting:',orig_value) + win32gui.SystemParametersInfo(cset, orig_value+1) + new_value=win32gui.SystemParametersInfo(cget) + print('\tnew value:',new_value) + # On Vista, some of these values seem to be ignored. So only "fail" if + # the new value isn't what we set or the original + if new_value!=orig_value+1: + assert new_value == orig_value + print("Strange - setting %s seems to have been ignored" % (pname,)) + win32gui.SystemParametersInfo(cset, orig_value) + assert win32gui.SystemParametersInfo(cget)==orig_value + + + +# these take a boolean value in pvParam +# change to opposite, check that it was changed and change back +for pname in ("SPI_GETFLATMENU","SPI_GETDROPSHADOW","SPI_GETKEYBOARDCUES","SPI_GETMENUFADE", + "SPI_GETCOMBOBOXANIMATION", "SPI_GETCURSORSHADOW", "SPI_GETGRADIENTCAPTIONS", "SPI_GETHOTTRACKING", + "SPI_GETLISTBOXSMOOTHSCROLLING", "SPI_GETMENUANIMATION", "SPI_GETSELECTIONFADE", + "SPI_GETTOOLTIPANIMATION", "SPI_GETTOOLTIPFADE", "SPI_GETUIEFFECTS", "SPI_GETACTIVEWINDOWTRACKING", + "SPI_GETACTIVEWNDTRKZORDER"): + print(pname) + cget=getattr(win32con,pname) + cset=getattr(win32con,pname.replace('_GET','_SET')) + orig_value=win32gui.SystemParametersInfo(cget) + print(orig_value) + win32gui.SystemParametersInfo(cset, not orig_value) + new_value=win32gui.SystemParametersInfo(cget) + print(new_value) + assert orig_value!=new_value + win32gui.SystemParametersInfo(cset, orig_value) + assert win32gui.SystemParametersInfo(cget)==orig_value + + + +# these take a boolean in uiParam +# could combine with above section now that SystemParametersInfo only takes a single parameter +for pname in ("SPI_GETFONTSMOOTHING","SPI_GETICONTITLEWRAP","SPI_GETBEEP","SPI_GETBLOCKSENDINPUTRESETS", + "SPI_GETKEYBOARDPREF","SPI_GETSCREENSAVEACTIVE","SPI_GETMENUDROPALIGNMENT", + "SPI_GETDRAGFULLWINDOWS", "SPI_GETSHOWIMEUI"): + print(pname) + cget=getattr(win32con,pname) + cset=getattr(win32con,pname.replace('_GET','_SET')) + orig_value=win32gui.SystemParametersInfo(cget) + print(orig_value) + win32gui.SystemParametersInfo(cset, not orig_value) + new_value=win32gui.SystemParametersInfo(cget) + print(new_value) + assert orig_value!=new_value + win32gui.SystemParametersInfo(cset, orig_value) + assert win32gui.SystemParametersInfo(cget)==orig_value + + + +print("SPI_GETICONTITLELOGFONT") +lf=win32gui.SystemParametersInfo(win32con.SPI_GETICONTITLELOGFONT) +orig_height=lf.lfHeight +orig_italic=lf.lfItalic +print('Height:', orig_height, 'Italic:',orig_italic) +lf.lfHeight+=2 +lf.lfItalic=not lf.lfItalic +win32gui.SystemParametersInfo(win32con.SPI_SETICONTITLELOGFONT, lf) +new_lf=win32gui.SystemParametersInfo(win32con.SPI_GETICONTITLELOGFONT) +print('New Height:', new_lf.lfHeight, 'New Italic:',new_lf.lfItalic) +assert new_lf.lfHeight==orig_height+2 +assert new_lf.lfItalic!=orig_italic + +lf.lfHeight=orig_height +lf.lfItalic=orig_italic +win32gui.SystemParametersInfo(win32con.SPI_SETICONTITLELOGFONT, lf) +new_lf=win32gui.SystemParametersInfo(win32con.SPI_GETICONTITLELOGFONT) +assert new_lf.lfHeight==orig_height +assert new_lf.lfItalic==orig_italic + + + +print("SPI_GETMOUSEHOVERWIDTH, SPI_GETMOUSEHOVERHEIGHT, SPI_GETMOUSEHOVERTIME") +w=win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERWIDTH) +h=win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERHEIGHT) +t=win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERTIME) +print('w,h,t:', w,h,t) + +win32gui.SystemParametersInfo(win32con.SPI_SETMOUSEHOVERWIDTH,w+1) +win32gui.SystemParametersInfo(win32con.SPI_SETMOUSEHOVERHEIGHT,h+2) +win32gui.SystemParametersInfo(win32con.SPI_SETMOUSEHOVERTIME,t+3) +new_w=win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERWIDTH) +new_h=win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERHEIGHT) +new_t=win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERTIME) +print('new w,h,t:', new_w, new_h, new_t) +assert new_w==w+1 +assert new_h==h+2 +assert new_t==t+3 + +win32gui.SystemParametersInfo(win32con.SPI_SETMOUSEHOVERWIDTH,w) +win32gui.SystemParametersInfo(win32con.SPI_SETMOUSEHOVERHEIGHT,h) +win32gui.SystemParametersInfo(win32con.SPI_SETMOUSEHOVERTIME,t) +new_w=win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERWIDTH) +new_h=win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERHEIGHT) +new_t=win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERTIME) +assert new_w==w +assert new_h==h +assert new_t==t + + + +print("SPI_SETDOUBLECLKWIDTH, SPI_SETDOUBLECLKHEIGHT") +x=win32api.GetSystemMetrics(win32con.SM_CXDOUBLECLK) +y=win32api.GetSystemMetrics(win32con.SM_CYDOUBLECLK) +print('x,y:', x, y) +win32gui.SystemParametersInfo(win32con.SPI_SETDOUBLECLKWIDTH, x+1) +win32gui.SystemParametersInfo(win32con.SPI_SETDOUBLECLKHEIGHT, y+2) +new_x=win32api.GetSystemMetrics(win32con.SM_CXDOUBLECLK) +new_y=win32api.GetSystemMetrics(win32con.SM_CYDOUBLECLK) +print('new x,y:', new_x, new_y) +assert new_x==x+1 +assert new_y==y+2 +win32gui.SystemParametersInfo(win32con.SPI_SETDOUBLECLKWIDTH, x) +win32gui.SystemParametersInfo(win32con.SPI_SETDOUBLECLKHEIGHT, y) +new_x=win32api.GetSystemMetrics(win32con.SM_CXDOUBLECLK) +new_y=win32api.GetSystemMetrics(win32con.SM_CYDOUBLECLK) +assert new_x==x +assert new_y==y + + + +print("SPI_SETDRAGWIDTH, SPI_SETDRAGHEIGHT") +dw=win32api.GetSystemMetrics(win32con.SM_CXDRAG) +dh=win32api.GetSystemMetrics(win32con.SM_CYDRAG) +print('dw,dh:', dw, dh) +win32gui.SystemParametersInfo(win32con.SPI_SETDRAGWIDTH,dw+1) +win32gui.SystemParametersInfo(win32con.SPI_SETDRAGHEIGHT,dh+2) +new_dw=win32api.GetSystemMetrics(win32con.SM_CXDRAG) +new_dh=win32api.GetSystemMetrics(win32con.SM_CYDRAG) +print('new dw,dh:', new_dw, new_dh) +assert new_dw==dw+1 +assert new_dh==dh+2 +win32gui.SystemParametersInfo(win32con.SPI_SETDRAGWIDTH,dw) +win32gui.SystemParametersInfo(win32con.SPI_SETDRAGHEIGHT,dh) +new_dw=win32api.GetSystemMetrics(win32con.SM_CXDRAG) +new_dh=win32api.GetSystemMetrics(win32con.SM_CYDRAG) +assert new_dw==dw +assert new_dh==dh + + + +orig_wallpaper=win32gui.SystemParametersInfo(Action=win32con.SPI_GETDESKWALLPAPER) +print('Original: ',orig_wallpaper) +for bmp in glob.glob(os.path.join(os.environ['windir'],'*.bmp')): + print(bmp) + win32gui.SystemParametersInfo(win32con.SPI_SETDESKWALLPAPER, Param=bmp) + print(win32gui.SystemParametersInfo(Action=win32con.SPI_GETDESKWALLPAPER)) + time.sleep(1) + +win32gui.SystemParametersInfo(win32con.SPI_SETDESKWALLPAPER, Param=orig_wallpaper) + + + + diff --git a/Lib/site-packages/win32/Demos/c_extension/setup.py b/Lib/site-packages/win32/Demos/c_extension/setup.py new file mode 100644 index 0000000..3766f57 --- /dev/null +++ b/Lib/site-packages/win32/Demos/c_extension/setup.py @@ -0,0 +1,23 @@ +# A sample distutils script to show to build your own +# extension module which extends pywintypes or pythoncom. +# +# Use 'python setup.py build' to build this extension. +import os +from distutils.core import setup, Extension +from distutils.sysconfig import get_python_lib + +sources = ["win32_extension.cpp"] + +# Specify the directory where the PyWin32 .h and .lib files are installed. +# If you are doing a win32com extension, you will also need to add +# win32com\Include and win32com\Libs. +ext = Extension("win32_extension", sources, + include_dirs = [os.path.join(get_python_lib(), "win32", "Include")], + library_dirs = [os.path.join(get_python_lib(), "win32", "Libs")], + ) + +setup( + name="win32 extension sample", + version="0.1", + ext_modules=[ext], +) diff --git a/Lib/site-packages/win32/Demos/cerapi.py b/Lib/site-packages/win32/Demos/cerapi.py new file mode 100644 index 0000000..dc905f3 --- /dev/null +++ b/Lib/site-packages/win32/Demos/cerapi.py @@ -0,0 +1,213 @@ +# A demo of the Windows CE Remote API +# +# This connects to a CE device, and interacts with it. + +import wincerapi +import win32event +import win32api +import win32con +import os +import sys +import getopt + + +def DumpPythonRegistry(): + try: + h = wincerapi.CeRegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE, "Software\\Python\\PythonCore\\%s\\PythonPath" % sys.winver) + except win32api.error: + print("The remote device does not appear to have Python installed") + return 0 + path, typ = wincerapi.CeRegQueryValueEx(h, None) + print("The remote PythonPath is '%s'" % (str(path), )) + h.Close() + return 1 + +def DumpRegistry(root, level=0): + # A recursive dump of the remote registry to test most functions. + h = wincerapi.CeRegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE, None) + level_prefix = " " * level + index = 0 + # Enumerate values. + while 1: + try: + name, data, typ = wincerapi.CeRegEnumValue(root, index) + except win32api.error: + break + print("%s%s=%s" % (level_prefix, name, repr(str(data)))) + index = index+1 + # Now enumerate all keys. + index=0 + while 1: + try: + name, klass = wincerapi.CeRegEnumKeyEx(root, index) + except win32api.error: + break + print("%s%s\\" % (level_prefix, name)) + subkey = wincerapi.CeRegOpenKeyEx(root, name) + DumpRegistry(subkey, level+1) + index = index+1 + +def DemoCopyFile(): + # Create a file on the device, and write a string. + cefile = wincerapi.CeCreateFile("TestPython", win32con.GENERIC_WRITE, 0, None, win32con.OPEN_ALWAYS, 0, None) + wincerapi.CeWriteFile(cefile, "Hello from Python") + cefile.Close() + # reopen the file and check the data. + cefile = wincerapi.CeCreateFile("TestPython", win32con.GENERIC_READ, 0, None, win32con.OPEN_EXISTING, 0, None) + if wincerapi.CeReadFile(cefile, 100) != "Hello from Python": + print("Couldnt read the data from the device!") + cefile.Close() + # Delete the test file + wincerapi.CeDeleteFile("TestPython") + print("Created, wrote to, read from and deleted a test file!") + +def DemoCreateProcess(): + try: + hp, ht, pid, tid = wincerapi.CeCreateProcess("Windows\\Python.exe", "", None, None, 0, 0, None, "", None) + + # Not necessary, except to see if handle closing raises an exception + # (if auto-closed, the error is suppressed) + hp.Close() + ht.Close() + print("Python is running on the remote device!") + except win32api.error as xxx_todo_changeme1: + (hr, fn, msg) = xxx_todo_changeme1.args + print("Couldnt execute remote process -", msg) + +def DumpRemoteMachineStatus(): + ACLineStatus, BatteryFlag, BatteryLifePercent, BatteryLifeTime, BatteryFullLifeTime, BackupBatteryFlag, BackupBatteryLifePercent, BackupBatteryLifeTime, BackupBatteryLifeTime = \ + wincerapi.CeGetSystemPowerStatusEx() + if ACLineStatus: + power = "AC" + else: + power = "battery" + if BatteryLifePercent==255: + batPerc = "unknown" + else: + batPerc = BatteryLifePercent + print("The batteries are at %s%%, and is currently being powered by %s" % (batPerc, power)) + + memLoad, totalPhys, availPhys, totalPage, availPage, totalVirt, availVirt = \ + wincerapi.CeGlobalMemoryStatus() + + print("The memory is %d%% utilized." % (memLoad)) + print("%-20s%-10s%-10s" % ("", "Total", "Avail")) + print("%-20s%-10s%-10s" % ("Physical Memory", totalPhys, availPhys)) + print("%-20s%-10s%-10s" % ("Virtual Memory", totalVirt, availVirt)) + print("%-20s%-10s%-10s" % ("Paging file", totalPage, availPage)) + + + storeSize, freeSize = wincerapi.CeGetStoreInformation() + print("%-20s%-10s%-10s" % ("File store", storeSize, freeSize)) + + print("The CE temp path is", wincerapi.CeGetTempPath()) + print("The system info for the device is", wincerapi.CeGetSystemInfo()) + +def DumpRemoteFolders(): + # Dump all special folders possible. + for name, val in list(wincerapi.__dict__.items()): + if name[:6]=="CSIDL_": + try: + loc = str(wincerapi.CeGetSpecialFolderPath(val)) + print("Folder %s is at %s" % (name, loc)) + except win32api.error as details: + pass + + # Get the shortcut targets for the "Start Menu" + print("Dumping start menu shortcuts...") + try: + startMenu = str(wincerapi.CeGetSpecialFolderPath(wincerapi.CSIDL_STARTMENU)) + except win32api.error as details: + print("This device has no start menu!", details) + startMenu = None + + if startMenu: + for fileAttr in wincerapi.CeFindFiles(os.path.join(startMenu, "*")): + fileName = fileAttr[8] + fullPath = os.path.join(startMenu, str(fileName)) + try: + resolved = wincerapi.CeSHGetShortcutTarget(fullPath) + except win32api.error as xxx_todo_changeme: + (rc, fn, msg) = xxx_todo_changeme.args + resolved = "#Error - %s" % msg + print("%s->%s" % (fileName, resolved)) + + # print "The start menu is at", + # print wincerapi.CeSHGetShortcutTarget("\\Windows\\Start Menu\\Shortcut to Python.exe.lnk") + +def usage(): + print("Options:") + print("-a - Execute all demos") + print("-p - Execute Python process on remote device") + print("-r - Dump the remote registry") + print("-f - Dump all remote special folder locations") + print("-s - Dont dump machine status") + print("-y - Perform asynch init of CE connection") + +def main(): + async_init = bStartPython = bDumpRegistry = bDumpFolders = 0 + bDumpStatus = 1 + try: + opts, args = getopt.getopt(sys.argv[1:], "apr") + except getopt.error as why: + print("Invalid usage:", why) + usage() + return + + for o, v in opts: + if o=="-a": + bStartPython = bDumpRegistry = bDumpStatus = bDumpFolders = asynch_init = 1 + if o=="-p": + bStartPython=1 + if o=="-r": + bDumpRegistry=1 + if o=="-s": + bDumpStatus=0 + if o=="-f": + bDumpFolders = 1 + if o=="-y": + print("Doing asynch init of CE connection") + async_init = 1 + + if async_init: + event, rc = wincerapi.CeRapiInitEx() + while 1: + rc = win32event.WaitForSingleObject(event, 500) + if rc==win32event.WAIT_OBJECT_0: + # We connected. + break + else: + print("Waiting for Initialize to complete (picture a Cancel button here :)") + else: + wincerapi.CeRapiInit() + print("Connected to remote CE device.") + try: + verinfo = wincerapi.CeGetVersionEx() + print("The device is running windows CE version %d.%d - %s" % (verinfo[0], verinfo[1], verinfo[4])) + + if bDumpStatus: + print("Dumping remote machine status") + DumpRemoteMachineStatus() + + if bDumpRegistry: + print("Dumping remote registry...") + DumpRegistry(win32con.HKEY_LOCAL_MACHINE) + + if bDumpFolders: + print("Dumping remote folder information") + DumpRemoteFolders() + + DemoCopyFile() + if bStartPython: + print("Starting remote Python process") + if DumpPythonRegistry(): + DemoCreateProcess() + else: + print("Not trying to start Python, as it's not installed") + + finally: + wincerapi.CeRapiUninit() + print("Disconnected") + +if __name__=='__main__': + main() diff --git a/Lib/site-packages/win32/Demos/dde/ddeclient.py b/Lib/site-packages/win32/Demos/dde/ddeclient.py new file mode 100644 index 0000000..fd20bed --- /dev/null +++ b/Lib/site-packages/win32/Demos/dde/ddeclient.py @@ -0,0 +1,19 @@ +# 'Request' example added jjk 11/20/98 + +import win32ui +import dde + +server = dde.CreateServer() +server.Create("TestClient") + +conversation = dde.CreateConversation(server) + +conversation.ConnectTo("RunAny", "RunAnyCommand") +conversation.Exec("DoSomething") +conversation.Exec("DoSomethingElse") + +conversation.ConnectTo("RunAny", "ComputeStringLength") +s = 'abcdefghi' +sl = conversation.Request(s) +print('length of "%s" is %s'%(s,sl)) + diff --git a/Lib/site-packages/win32/Demos/dde/ddeserver.py b/Lib/site-packages/win32/Demos/dde/ddeserver.py new file mode 100644 index 0000000..2637e2a --- /dev/null +++ b/Lib/site-packages/win32/Demos/dde/ddeserver.py @@ -0,0 +1,38 @@ +# 'Request' example added jjk 11/20/98 + +import win32ui +from pywin.mfc import object +import dde + +class MySystemTopic(object.Object): + def __init__(self): + object.Object.__init__(self, dde.CreateServerSystemTopic()) + + def Exec(self, cmd): + print("System Topic asked to exec", cmd) + +class MyOtherTopic(object.Object): + def __init__(self, topicName): + object.Object.__init__(self, dde.CreateTopic(topicName)) + + def Exec(self, cmd): + print("Other Topic asked to exec", cmd) + +class MyRequestTopic(object.Object): + def __init__(self, topicName): + topic = dde.CreateTopic(topicName) + topic.AddItem(dde.CreateStringItem("")) + object.Object.__init__(self, topic) + + def Request(self, aString): + print("Request Topic asked to compute length of:", aString) + return(str(len(aString))) + +server = dde.CreateServer() +server.AddTopic(MySystemTopic()) +server.AddTopic(MyOtherTopic("RunAnyCommand")) +server.AddTopic(MyRequestTopic("ComputeStringLength")) +server.Create('RunAny') + +while 1: + win32ui.PumpWaitingMessages(0, -1) diff --git a/Lib/site-packages/win32/Demos/desktopmanager.py b/Lib/site-packages/win32/Demos/desktopmanager.py new file mode 100644 index 0000000..3cbf928 --- /dev/null +++ b/Lib/site-packages/win32/Demos/desktopmanager.py @@ -0,0 +1,166 @@ +# Demonstrates using a taskbar icon to create and navigate between desktops + +import win32api, win32con, win32gui, win32service, win32process +import pywintypes +import traceback, _thread, time +import io + +## "Shell_TrayWnd" is class of system tray window, broadcasts "TaskbarCreated" when initialized + +def desktop_name_dlgproc(hwnd,msg,wparam,lparam): + """ Handles messages from the desktop name dialog box """ + if msg in (win32con.WM_CLOSE,win32con.WM_DESTROY): + win32gui.DestroyWindow(hwnd) + elif msg == win32con.WM_COMMAND: + if wparam == win32con.IDOK: + desktop_name=win32gui.GetDlgItemText(hwnd, 72) + print('new desktop name: ',desktop_name) + win32gui.DestroyWindow(hwnd) + create_desktop(desktop_name) + + elif wparam == win32con.IDCANCEL: + win32gui.DestroyWindow(hwnd) + +def get_new_desktop_name(parent_hwnd): + """ Create a dialog box to ask the user for name of desktop to be created """ + msgs={win32con.WM_COMMAND:desktop_name_dlgproc, + win32con.WM_CLOSE:desktop_name_dlgproc, + win32con.WM_DESTROY:desktop_name_dlgproc} + # dlg item [type, caption, id, (x,y,cx,cy), style, ex style + style=win32con.WS_BORDER|win32con.WS_VISIBLE|win32con.WS_CAPTION|win32con.WS_SYSMENU ## |win32con.DS_SYSMODAL + h=win32gui.CreateDialogIndirect( + win32api.GetModuleHandle(None), + [['One ugly dialog box !',(100,100,200,100),style,0], + ['Button','Create', win32con.IDOK, (10,10,30,20),win32con.WS_VISIBLE|win32con.WS_TABSTOP|win32con.BS_HOLLOW|win32con.BS_DEFPUSHBUTTON], + ['Button','Never mind', win32con.IDCANCEL, (45,10,50,20),win32con.WS_VISIBLE|win32con.WS_TABSTOP|win32con.BS_HOLLOW], + ['Static','Desktop name:',71,(10,40,70,10),win32con.WS_VISIBLE], + ['Edit','',72,(75,40,90,10),win32con.WS_VISIBLE]], + parent_hwnd, msgs) ## parent_hwnd, msgs) + + win32gui.EnableWindow(h,True) + hcontrol=win32gui.GetDlgItem(h,72) + win32gui.EnableWindow(hcontrol,True) + win32gui.SetFocus(hcontrol) + +def new_icon(hdesk,desktop_name): + """ Runs as a thread on each desktop to create a new tray icon and handle its messages """ + global id + id=id+1 + hdesk.SetThreadDesktop() + ## apparently the threads can't use same hinst, so each needs its own window class + windowclassname='PythonDesktopManager'+desktop_name + wc = win32gui.WNDCLASS() + wc.hInstance = win32api.GetModuleHandle(None) + wc.lpszClassName = windowclassname + wc.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW | win32con.CS_GLOBALCLASS + wc.hCursor = win32gui.LoadCursor( 0, win32con.IDC_ARROW ) + wc.hbrBackground = win32con.COLOR_WINDOW + wc.lpfnWndProc = icon_wndproc + windowclass = win32gui.RegisterClass(wc) + style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU + hwnd = win32gui.CreateWindow(windowclass, 'dm_'+desktop_name, win32con.WS_SYSMENU, + 0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, + 0, 0, wc.hInstance, None) + win32gui.UpdateWindow(hwnd) + flags = win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP + notify_info = (hwnd, id, flags, win32con.WM_USER+20, hicon, 'Desktop Manager (%s)' %desktop_name) + window_info[hwnd]=notify_info + ## wait for explorer to initialize system tray for new desktop + tray_found=0 + while not tray_found: + try: + tray_found=win32gui.FindWindow("Shell_TrayWnd",None) + except win32gui.error: + traceback.print_exc + time.sleep(.5) + win32gui.Shell_NotifyIcon(win32gui.NIM_ADD, notify_info) + win32gui.PumpMessages() + +def create_desktop(desktop_name, start_explorer=1): + """ Creates a new desktop and spawns a thread running on it + Will also start a new icon thread on an existing desktop + """ + sa=pywintypes.SECURITY_ATTRIBUTES() + sa.bInheritHandle=1 + + try: + hdesk=win32service.CreateDesktop(desktop_name, 0, win32con.MAXIMUM_ALLOWED, sa) + except win32service.error: + traceback.print_exc() + errbuf=io.StringIO() + traceback.print_exc(None,errbuf) + win32api.MessageBox(0, errbuf.getvalue(), 'Desktop creation failed') + return + if start_explorer: + s=win32process.STARTUPINFO() + s.lpDesktop=desktop_name + prc_info=win32process.CreateProcess(None, "Explorer.exe",None,None,True,win32con.CREATE_NEW_CONSOLE,None,'c:\\',s) + + th=_thread.start_new_thread(new_icon,(hdesk,desktop_name)) + hdesk.SwitchDesktop() + +def icon_wndproc(hwnd, msg, wp, lp): + """ Window proc for the tray icons """ + if lp==win32con.WM_LBUTTONDOWN: + ## popup menu won't disappear if you don't do this + win32gui.SetForegroundWindow(hwnd) + + curr_desktop=win32service.OpenInputDesktop(0,True,win32con.MAXIMUM_ALLOWED) + curr_desktop_name=win32service.GetUserObjectInformation(curr_desktop,win32con.UOI_NAME) + winsta=win32service.GetProcessWindowStation() + desktops=winsta.EnumDesktops() + m=win32gui.CreatePopupMenu() + desktop_cnt=len(desktops) + ## *don't* create an item 0 + for d in range(1, desktop_cnt+1): + mf_flags=win32con.MF_STRING + ## if you switch to winlogon yourself, there's nothing there and you're stuck + if desktops[d-1].lower() in ('winlogon','disconnect'): + mf_flags=mf_flags|win32con.MF_GRAYED|win32con.MF_DISABLED + if desktops[d-1]==curr_desktop_name: + mf_flags=mf_flags|win32con.MF_CHECKED + win32gui.AppendMenu(m, mf_flags, d, desktops[d-1]) + win32gui.AppendMenu(m, win32con.MF_STRING, desktop_cnt+1, 'Create new ...') + win32gui.AppendMenu(m, win32con.MF_STRING, desktop_cnt+2, 'Exit') + + x,y=win32gui.GetCursorPos() + d=win32gui.TrackPopupMenu(m,win32con.TPM_LEFTBUTTON|win32con.TPM_RETURNCMD|win32con.TPM_NONOTIFY, + x,y, 0, hwnd, None) + win32gui.PumpWaitingMessages() + win32gui.DestroyMenu(m) + if d==desktop_cnt+1: ## Create new + get_new_desktop_name(hwnd) + elif d==desktop_cnt+2: ## Exit + win32gui.PostQuitMessage(0) + win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, window_info[hwnd]) + del window_info[hwnd] + origin_desktop.SwitchDesktop() + elif d>0: + hdesk=win32service.OpenDesktop(desktops[d-1],0,0,win32con.MAXIMUM_ALLOWED) + hdesk.SwitchDesktop() + return 0 + else: + return win32gui.DefWindowProc(hwnd, msg, wp, lp) + +window_info={} +origin_desktop=win32service.OpenInputDesktop(0, True, win32con.MAXIMUM_ALLOWED) +origin_desktop_name=win32service.GetUserObjectInformation(origin_desktop, win32service.UOI_NAME) + +hinst=win32api.GetModuleHandle(None) +try: + hicon=win32gui.LoadIcon(hinst, 1) ## python.exe and pythonw.exe +except win32gui.error: + hicon=win32gui.LoadIcon(hinst, 135) ## pythonwin's icon +id=0 + +create_desktop(str(origin_desktop_name),0) + +## wait for first thread to initialize its icon +while not window_info: + time.sleep(1) + +## exit when last tray icon goes away +while window_info: + win32gui.PumpWaitingMessages() + time.sleep(3) + diff --git a/Lib/site-packages/win32/Demos/eventLogDemo.py b/Lib/site-packages/win32/Demos/eventLogDemo.py new file mode 100644 index 0000000..bb086a8 --- /dev/null +++ b/Lib/site-packages/win32/Demos/eventLogDemo.py @@ -0,0 +1,111 @@ +import win32evtlog +import win32api +import win32con +import win32security # To translate NT Sids to account names. + +import win32evtlogutil + +def ReadLog(computer, logType="Application", dumpEachRecord = 0): + # read the entire log back. + h=win32evtlog.OpenEventLog(computer, logType) + numRecords = win32evtlog.GetNumberOfEventLogRecords(h) +# print "There are %d records" % numRecords + + num=0 + while 1: + objects = win32evtlog.ReadEventLog(h, win32evtlog.EVENTLOG_BACKWARDS_READ|win32evtlog.EVENTLOG_SEQUENTIAL_READ, 0) + if not objects: + break + for object in objects: + # get it for testing purposes, but dont print it. + msg = win32evtlogutil.SafeFormatMessage(object, logType) + if object.Sid is not None: + try: + domain, user, typ = win32security.LookupAccountSid(computer, object.Sid) + sidDesc = "%s/%s" % (domain, user) + except win32security.error: + sidDesc = str(object.Sid) + user_desc = "Event associated with user %s" % (sidDesc,) + else: + user_desc = None + if dumpEachRecord: + print("Event record from %r generated at %s" % (object.SourceName, object.TimeGenerated.Format())) + if user_desc: + print(user_desc) + try: + print(msg) + except UnicodeError: + print("(unicode error printing message: repr() follows...)") + print(repr(msg)) + + num = num + len(objects) + + if numRecords == num: + print("Successfully read all", numRecords, "records") + else: + print("Couldn't get all records - reported %d, but found %d" % (numRecords, num)) + print("(Note that some other app may have written records while we were running!)") + win32evtlog.CloseEventLog(h) + +def usage(): + print("Writes an event to the event log.") + print("-w : Dont write any test records.") + print("-r : Dont read the event log") + print("-c : computerName : Process the log on the specified computer") + print("-v : Verbose") + print("-t : LogType - Use the specified log - default = 'Application'") + + +def test(): + # check if running on Windows NT, if not, display notice and terminate + if win32api.GetVersion() & 0x80000000: + print("This sample only runs on NT") + return + + import sys, getopt + opts, args = getopt.getopt(sys.argv[1:], "rwh?c:t:v") + computer = None + do_read = do_write = 1 + + logType = "Application" + verbose = 0 + + if len(args)>0: + print("Invalid args") + usage() + return 1 + for opt, val in opts: + if opt == '-t': + logType = val + if opt == '-c': + computer = val + if opt in ['-h', '-?']: + usage() + return + if opt=='-r': + do_read = 0 + if opt=='-w': + do_write = 0 + if opt=='-v': + verbose = verbose + 1 + if do_write: + ph=win32api.GetCurrentProcess() + th = win32security.OpenProcessToken(ph,win32con.TOKEN_READ) + my_sid = win32security.GetTokenInformation(th,win32security.TokenUser)[0] + + win32evtlogutil.ReportEvent(logType, 2, + strings=["The message text for event 2","Another insert"], + data = "Raw\0Data".encode("ascii"), sid = my_sid) + win32evtlogutil.ReportEvent(logType, 1, eventType=win32evtlog.EVENTLOG_WARNING_TYPE, + strings=["A warning","An even more dire warning"], + data = "Raw\0Data".encode("ascii"), sid = my_sid) + win32evtlogutil.ReportEvent(logType, 1, eventType=win32evtlog.EVENTLOG_INFORMATION_TYPE, + strings=["An info","Too much info"], + data = "Raw\0Data".encode("ascii"), sid = my_sid) + print("Successfully wrote 3 records to the log") + + if do_read: + ReadLog(computer, logType, verbose > 0) + +if __name__=='__main__': + test() diff --git a/Lib/site-packages/win32/Demos/getfilever.py b/Lib/site-packages/win32/Demos/getfilever.py new file mode 100644 index 0000000..6f6d63f --- /dev/null +++ b/Lib/site-packages/win32/Demos/getfilever.py @@ -0,0 +1,21 @@ +import os, win32api + +ver_strings=('Comments','InternalName','ProductName', + 'CompanyName','LegalCopyright','ProductVersion', + 'FileDescription','LegalTrademarks','PrivateBuild', + 'FileVersion','OriginalFilename','SpecialBuild') +fname = os.environ["comspec"] +d=win32api.GetFileVersionInfo(fname, '\\') +## backslash as parm returns dictionary of numeric info corresponding to VS_FIXEDFILEINFO struc +for n, v in d.items(): + print(n, v) + +pairs=win32api.GetFileVersionInfo(fname, '\\VarFileInfo\\Translation') +## \VarFileInfo\Translation returns list of available (language, codepage) pairs that can be used to retreive string info +## any other must be of the form \StringfileInfo\%04X%04X\parm_name, middle two are language/codepage pair returned from above +for lang, codepage in pairs: + print('lang: ', lang, 'codepage:', codepage) + for ver_string in ver_strings: + str_info='\\StringFileInfo\\%04X%04X\\%s' %(lang,codepage,ver_string) + ## print str_info + print(ver_string, repr(win32api.GetFileVersionInfo(fname, str_info))) diff --git a/Lib/site-packages/win32/Demos/images/frowny.bmp b/Lib/site-packages/win32/Demos/images/frowny.bmp new file mode 100644 index 0000000..43e7621 Binary files /dev/null and b/Lib/site-packages/win32/Demos/images/frowny.bmp differ diff --git a/Lib/site-packages/win32/Demos/images/smiley.bmp b/Lib/site-packages/win32/Demos/images/smiley.bmp new file mode 100644 index 0000000..12ed5de Binary files /dev/null and b/Lib/site-packages/win32/Demos/images/smiley.bmp differ diff --git a/Lib/site-packages/win32/Demos/mmapfile_demo.py b/Lib/site-packages/win32/Demos/mmapfile_demo.py new file mode 100644 index 0000000..42e2af8 --- /dev/null +++ b/Lib/site-packages/win32/Demos/mmapfile_demo.py @@ -0,0 +1,95 @@ +import win32api, mmapfile +import winerror +import tempfile, os +from pywin32_testutil import str2bytes + +system_info=win32api.GetSystemInfo() +page_size=system_info[1] +alloc_size=system_info[7] + +fname=tempfile.mktemp() +mapping_name=os.path.split(fname)[1] +fsize=8*page_size +print(fname, fsize, mapping_name) + +m1=mmapfile.mmapfile(File=fname, Name=mapping_name, MaximumSize=fsize) +m1.seek(100) +m1.write_byte(str2bytes('?')) +m1.seek(-1,1) +assert m1.read_byte()==str2bytes('?') + +## A reopened named mapping should have exact same size as original mapping +m2=mmapfile.mmapfile(Name=mapping_name, File=None, MaximumSize=fsize*2) +assert m2.size()==m1.size() +m1.seek(0,0) +m1.write(fsize*str2bytes('s')) +assert m2.read(fsize)==fsize*str2bytes('s') + +move_src=100 +move_dest=500 +move_size=150 + +m2.seek(move_src,0) +assert m2.tell()==move_src +m2.write(str2bytes('m')*move_size) +m2.move(move_dest, move_src, move_size) +m2.seek(move_dest, 0) +assert m2.read(move_size) == str2bytes('m') * move_size +## m2.write('x'* (fsize+1)) + +m2.close() +m1.resize(fsize*2) +assert m1.size()==fsize * 2 +m1.seek(fsize) +m1.write(str2bytes('w') * fsize) +m1.flush() +m1.close() +os.remove(fname) + + + +## Test a file with size larger than 32 bits +## need 10 GB free on drive where your temp folder lives +fname_large=tempfile.mktemp() +mapping_name='Pywin32_large_mmap' +offsetdata=str2bytes('This is start of offset') + +## Deliberately use odd numbers to test rounding logic +fsize = (1024*1024*1024*10) + 333 +offset = (1024*1024*32) + 42 +view_size = (1024*1024*16) + 111 + +## round mapping size and view size up to multiple of system page size +if fsize%page_size: + fsize += page_size - (fsize%page_size) +if view_size%page_size: + view_size += page_size - (view_size%page_size) +## round offset down to multiple of allocation granularity +offset -= offset%alloc_size + +m1=None +m2=None +try: + try: + m1=mmapfile.mmapfile(fname_large, mapping_name, fsize, 0, offset*2) + except mmapfile.error as exc: + # if we don't have enough disk-space, that's OK. + if exc.winerror!=winerror.ERROR_DISK_FULL: + raise + print("skipping large file test - need", fsize, "available bytes.") + else: + m1.seek(offset) + m1.write(offsetdata) + + ## When reopening an existing mapping without passing a file handle, you have + ## to specify a positive size even though it's ignored + m2=mmapfile.mmapfile(File=None, Name=mapping_name, MaximumSize=1, + FileOffset=offset, NumberOfBytesToMap=view_size) + assert m2.read(len(offsetdata))==offsetdata +finally: + if m1 is not None: + m1.close() + if m2 is not None: + m2.close() + if os.path.exists(fname_large): + os.remove(fname_large) diff --git a/Lib/site-packages/win32/Demos/pipes/cat.py b/Lib/site-packages/win32/Demos/pipes/cat.py new file mode 100644 index 0000000..926201f --- /dev/null +++ b/Lib/site-packages/win32/Demos/pipes/cat.py @@ -0,0 +1,16 @@ +'''cat.py +a version of unix cat, tweaked to show off runproc.py +''' + +import sys +data = sys.stdin.read(1) +sys.stdout.write(data) +sys.stdout.flush() +while data: + data = sys.stdin.read(1) + sys.stdout.write(data) + sys.stdout.flush() +# Just here to have something to read from stderr. +sys.stderr.write("Blah...") + +# end of cat.py diff --git a/Lib/site-packages/win32/Demos/pipes/runproc.py b/Lib/site-packages/win32/Demos/pipes/runproc.py new file mode 100644 index 0000000..b5dd7a4 --- /dev/null +++ b/Lib/site-packages/win32/Demos/pipes/runproc.py @@ -0,0 +1,110 @@ +'''runproc.py + +start a process with three inherited pipes. +Try to write to and read from those. +''' + +import win32api +import win32pipe +import win32file +import win32process +import win32security +import win32con +import msvcrt +import os + +class Process: + def run(self, cmdline): + # security attributes for pipes + sAttrs = win32security.SECURITY_ATTRIBUTES() + sAttrs.bInheritHandle = 1 + + # create pipes + hStdin_r, self.hStdin_w = win32pipe.CreatePipe(sAttrs, 0) + self.hStdout_r, hStdout_w = win32pipe.CreatePipe(sAttrs, 0) + self.hStderr_r, hStderr_w = win32pipe.CreatePipe(sAttrs, 0) + + # set the info structure for the new process. + StartupInfo = win32process.STARTUPINFO() + StartupInfo.hStdInput = hStdin_r + StartupInfo.hStdOutput = hStdout_w + StartupInfo.hStdError = hStderr_w + StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES + # Mark doesn't support wShowWindow yet. + # StartupInfo.dwFlags = StartupInfo.dwFlags | win32process.STARTF_USESHOWWINDOW + # StartupInfo.wShowWindow = win32con.SW_HIDE + + # Create new output read handles and the input write handle. Set + # the inheritance properties to FALSE. Otherwise, the child inherits + # the these handles; resulting in non-closeable handles to the pipes + # being created. + pid = win32api.GetCurrentProcess() + + tmp = win32api.DuplicateHandle( + pid, + self.hStdin_w, + pid, + 0, + 0, # non-inheritable!! + win32con.DUPLICATE_SAME_ACCESS) + # Close the inhertible version of the handle + win32file.CloseHandle(self.hStdin_w) + self.hStdin_w = tmp + tmp = win32api.DuplicateHandle( + pid, + self.hStdout_r, + pid, + 0, + 0, # non-inheritable! + win32con.DUPLICATE_SAME_ACCESS) + # Close the inhertible version of the handle + win32file.CloseHandle(self.hStdout_r) + self.hStdout_r = tmp + + # start the process. + hProcess, hThread, dwPid, dwTid = win32process.CreateProcess( + None, # program + cmdline,# command line + None, # process security attributes + None, # thread attributes + 1, # inherit handles, or USESTDHANDLES won't work. + # creation flags. Don't access the console. + 0, # Don't need anything here. + # If you're in a GUI app, you should use + # CREATE_NEW_CONSOLE here, or any subprocesses + # might fall victim to the problem described in: + # KB article: Q156755, cmd.exe requires + # an NT console in order to perform redirection.. + None, # no new environment + None, # current directory (stay where we are) + StartupInfo) + # normally, we would save the pid etc. here... + + # Child is launched. Close the parents copy of those pipe handles + # that only the child should have open. + # You need to make sure that no handles to the write end of the + # output pipe are maintained in this process or else the pipe will + # not close when the child process exits and the ReadFile will hang. + win32file.CloseHandle(hStderr_w) + win32file.CloseHandle(hStdout_w) + win32file.CloseHandle(hStdin_r) + + self.stdin = os.fdopen(msvcrt.open_osfhandle(self.hStdin_w, 0), "wb") + self.stdin.write('hmmmmm\r\n') + self.stdin.flush() + self.stdin.close() + + self.stdout = os.fdopen(msvcrt.open_osfhandle(self.hStdout_r, 0), "rb") + print("Read on stdout: ", repr(self.stdout.read())) + + self.stderr = os.fdopen(msvcrt.open_osfhandle(self.hStderr_r, 0), "rb") + print("Read on stderr: ", repr(self.stderr.read())) + + +if __name__ == '__main__': + p = Process() + exe = win32api.GetModuleFileName(0) + p.run(exe + ' cat.py') + +# end of runproc.py + diff --git a/Lib/site-packages/win32/Demos/print_desktop.py b/Lib/site-packages/win32/Demos/print_desktop.py new file mode 100644 index 0000000..a2584a9 --- /dev/null +++ b/Lib/site-packages/win32/Demos/print_desktop.py @@ -0,0 +1,67 @@ +import win32print, pywintypes, win32con, win32gui, win32api + +pname=win32print.GetDefaultPrinter() +print(pname) +p=win32print.OpenPrinter(pname) +print('Printer handle: ',p) +print_processor=win32print.GetPrinter(p,2)['pPrintProcessor'] +## call with last parm set to 0 to get total size needed for printer's DEVMODE +dmsize=win32print.DocumentProperties(0, p, pname, None, None, 0) +## dmDriverExtra should be total size - fixed size +driverextra=dmsize - pywintypes.DEVMODEType().Size ## need a better way to get DEVMODE.dmSize +dm=pywintypes.DEVMODEType(driverextra) +dm.Fields=dm.Fields|win32con.DM_ORIENTATION|win32con.DM_COPIES +dm.Orientation=win32con.DMORIENT_LANDSCAPE +dm.Copies=2 +win32print.DocumentProperties(0, p, pname, dm, dm, win32con.DM_IN_BUFFER|win32con.DM_OUT_BUFFER) + +pDC=win32gui.CreateDC(print_processor,pname,dm) +printerwidth=win32print.GetDeviceCaps(pDC, win32con.PHYSICALWIDTH) +printerheight=win32print.GetDeviceCaps(pDC, win32con.PHYSICALHEIGHT) + +hwnd=win32gui.GetDesktopWindow() +l,t,r,b=win32gui.GetWindowRect(hwnd) +desktopheight=b-t +desktopwidth=r-l +dDC = win32gui.GetWindowDC(hwnd) + +dcDC=win32gui.CreateCompatibleDC(dDC) +dcBM = win32gui.CreateCompatibleBitmap(dDC, desktopwidth, desktopheight); +win32gui.SelectObject(dcDC, dcBM) +win32gui.StretchBlt(dcDC, 0, 0, desktopwidth, desktopheight, dDC, 0, 0, desktopwidth, desktopheight, win32con.SRCCOPY) + +pcDC=win32gui.CreateCompatibleDC(pDC) +pcBM=win32gui.CreateCompatibleBitmap(pDC, printerwidth, printerheight) +win32gui.SelectObject(pcDC, pcBM) +win32gui.StretchBlt(pcDC, 0, 0, printerwidth, printerheight, dcDC, 0, 0, desktopwidth, desktopheight, win32con.SRCCOPY) + +win32print.StartDoc(pDC,('desktop.bmp',None,None,0)) +win32print.StartPage(pDC) +win32gui.StretchBlt(pDC, 0, 0, int(printerwidth*.9), int(printerheight*.9), pcDC, 0, 0, printerwidth, printerheight, win32con.SRCCOPY) + +font=win32gui.LOGFONT() +font.lfHeight=int(printerheight/20) +font.lfWidth=font.lfHeight +font.lfWeight=150 +font.lfItalic=1 +font.lfUnderline=1 +hf=win32gui.CreateFontIndirect(font) +win32gui.SelectObject(pDC,hf) +win32gui.SetBkMode(pDC, win32con.TRANSPARENT) +win32gui.SetTextColor(pDC,win32api.RGB(0,255,0)) +win32gui.DrawText(pDC,'Printed by Python!', -1, + (0,0, int(printerwidth*.9), int(printerheight*.9)), + win32con.DT_RIGHT|win32con.DT_BOTTOM|win32con.DT_SINGLELINE) +win32print.EndPage(pDC) +win32print.EndDoc(pDC) + +win32print.ClosePrinter(p) +win32gui.DeleteObject(dcBM) +win32gui.DeleteObject(pcBM) +win32gui.DeleteObject(hf) +win32gui.DeleteDC(dDC) +win32gui.DeleteDC(dcDC) +win32gui.DeleteDC(pDC) +win32gui.DeleteDC(pcDC) + + diff --git a/Lib/site-packages/win32/Demos/rastest.py b/Lib/site-packages/win32/Demos/rastest.py new file mode 100644 index 0000000..00c8d7d --- /dev/null +++ b/Lib/site-packages/win32/Demos/rastest.py @@ -0,0 +1,136 @@ +# rastest.py - test/demonstrate the win32ras module. +# Much of the code here contributed by Jethro Wright. + +import sys +import os +import win32ras + +# Build a little dictionary of RAS states to decent strings. +# eg win32ras.RASCS_OpenPort -> "OpenPort" +stateMap = {} +for name, val in list(win32ras.__dict__.items()): + if name[:6]=="RASCS_": + stateMap[val] = name[6:] + +# Use a lock so the callback can tell the main thread when it is finished. +import win32event +callbackEvent = win32event.CreateEvent(None, 0, 0, None) + +def Callback( hras, msg, state, error, exterror): +# print "Callback called with ", hras, msg, state, error, exterror + stateName = stateMap.get(state, "Unknown state?") + print("Status is %s (%04lx), error code is %d" % (stateName, state, error)) + finished = state in [win32ras.RASCS_Connected] + if finished: + win32event.SetEvent(callbackEvent) + if error != 0 or int( state ) == win32ras.RASCS_Disconnected: + # we know for sure this is a good place to hangup.... + print("Detected call failure: %s" % win32ras.GetErrorString( error )) + HangUp( hras ) + win32event.SetEvent(callbackEvent) + +def ShowConnections(): + print("All phone-book entries:") + for (name,) in win32ras.EnumEntries(): + print(" ", name) + print("Current Connections:") + for con in win32ras.EnumConnections(): + print(" ", con) + +def EditEntry(entryName): + try: + win32ras.EditPhonebookEntry(0,None,entryName) + except win32ras.error as xxx_todo_changeme: + (rc, function, msg) = xxx_todo_changeme.args + print("Can not edit/find the RAS entry -", msg) + +def HangUp( hras ): + # trap potential, irrelevant errors from win32ras.... + try: + win32ras.HangUp( hras ) + except: + print("Tried to hang up gracefully on error, but didn't work....") + return None + +def Connect(entryName, bUseCallback): + if bUseCallback: + theCallback = Callback + win32event.ResetEvent(callbackEvent) + else: + theCallback = None + # in order to *use* the username/password of a particular dun entry, one must + # explicitly get those params under win95.... + try: + dp, b = win32ras.GetEntryDialParams( None, entryName ) + except: + print("Couldn't find DUN entry: %s" % entryName) + else: + hras, rc = win32ras.Dial(None, None, (entryName, "", "", dp[ 3 ], dp[ 4 ], ""),theCallback) + # hras, rc = win32ras.Dial(None, None, (entryName, ),theCallback) + # print hras, rc + if not bUseCallback and rc != 0: + print("Could not dial the RAS connection:", win32ras.GetErrorString(rc)) + hras = HangUp( hras ) + # don't wait here if there's no need to.... + elif bUseCallback and win32event.WaitForSingleObject(callbackEvent, 60000)!=win32event.WAIT_OBJECT_0: + print("Gave up waiting for the process to complete!") + # sdk docs state one must explcitly hangup, even if there's an error.... + try: + cs = win32ras.GetConnectStatus( hras ) + except: + # on error, attempt a hang up anyway.... + hras = HangUp( hras ) + else: + if int( cs[ 0 ] ) == win32ras.RASCS_Disconnected: + hras = HangUp( hras ) + return hras, rc + +def Disconnect( rasEntry ): + # Need to find the entry + name = rasEntry.lower() + for hcon, entryName, devName, devType in win32ras.EnumConnections(): + if entryName.lower() == name: + win32ras.HangUp( hcon ) + print("Disconnected from", rasEntry) + break + else: + print("Could not find an open connection to", entryName) + +usage = """ +Usage: %s [-s] [-l] [-c connection] [-d connection] +-l : List phone-book entries and current connections. +-s : Show status while connecting/disconnecting (uses callbacks) +-c : Connect to the specified phonebook name. +-d : Disconnect from the specified phonebook name. +-e : Edit the specified phonebook entry. +""" + +def main(): + import getopt + try: + opts, args = getopt.getopt(sys.argv[1:], "slc:d:e:") + except getopt.error as why: + print(why) + print(usage % (os.path.basename(sys.argv[0],))) + return + + bCallback = 0 + if args or not opts: + print(usage % (os.path.basename(sys.argv[0],))) + return + for opt, val in opts: + if opt=="-s": + bCallback = 1 + if opt=="-l": + ShowConnections() + if opt=="-c": + hras, rc = Connect(val, bCallback) + if hras != None: + print("hras: 0x%8lx, rc: 0x%04x" % ( hras, rc )) + if opt=="-d": + Disconnect(val) + if opt=="-e": + EditEntry(val) + +if __name__=='__main__': + main() diff --git a/Lib/site-packages/win32/Demos/security/GetTokenInformation.py b/Lib/site-packages/win32/Demos/security/GetTokenInformation.py new file mode 100644 index 0000000..ed1e913 --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/GetTokenInformation.py @@ -0,0 +1,73 @@ +""" Lists various types of information about current user's access token, + including UAC status on Vista +""" + +import pywintypes, win32api, win32security +import win32con, winerror +from security_enums import TOKEN_GROUP_ATTRIBUTES, TOKEN_PRIVILEGE_ATTRIBUTES, \ + SECURITY_IMPERSONATION_LEVEL, TOKEN_TYPE, TOKEN_ELEVATION_TYPE + + +def dump_token(th): + token_type=win32security.GetTokenInformation(th, win32security.TokenType) + print('TokenType:', token_type, TOKEN_TYPE.lookup_name(token_type)) + if token_type==win32security.TokenImpersonation: + imp_lvl=win32security.GetTokenInformation(th, win32security.TokenImpersonationLevel) + print('TokenImpersonationLevel:', imp_lvl, SECURITY_IMPERSONATION_LEVEL.lookup_name(imp_lvl)) + + print('TokenSessionId:', win32security.GetTokenInformation(th, win32security.TokenSessionId)) + + privs=win32security.GetTokenInformation(th,win32security.TokenPrivileges) + print('TokenPrivileges:') + for priv_luid, priv_flags in privs: + flag_names, unk=TOKEN_PRIVILEGE_ATTRIBUTES.lookup_flags(priv_flags) + flag_desc = ' '.join(flag_names) + if (unk): + flag_desc += '(' + str(unk) + ')' + + priv_name=win32security.LookupPrivilegeName('',priv_luid) + priv_desc=win32security.LookupPrivilegeDisplayName('',priv_name) + print('\t', priv_name, priv_desc, priv_flags, flag_desc) + + print('TokenGroups:') + groups=win32security.GetTokenInformation(th,win32security.TokenGroups) + for group_sid, group_attr in groups: + flag_names, unk=TOKEN_GROUP_ATTRIBUTES.lookup_flags(group_attr) + flag_desc = ' '.join(flag_names) + if (unk): + flag_desc += '(' + str(unk) + ')' + if group_attr & TOKEN_GROUP_ATTRIBUTES.SE_GROUP_LOGON_ID: + sid_desc = 'Logon sid' + else: + sid_desc=win32security.LookupAccountSid('',group_sid) + print('\t',group_sid, sid_desc, group_attr, flag_desc) + + ## Vista token information types, will throw (87, 'GetTokenInformation', 'The parameter is incorrect.') on earier OS + try: + is_elevated=win32security.GetTokenInformation(th, win32security.TokenElevation) + print('TokenElevation:', is_elevated) + except pywintypes.error as details: + if details.winerror != winerror.ERROR_INVALID_PARAMETER: + raise + return None + print('TokenHasRestrictions:', win32security.GetTokenInformation(th, win32security.TokenHasRestrictions)) + print('TokenMandatoryPolicy', win32security.GetTokenInformation(th, win32security.TokenMandatoryPolicy)) + print('TokenVirtualizationAllowed:', win32security.GetTokenInformation(th, win32security.TokenVirtualizationAllowed)) + print('TokenVirtualizationEnabled:', win32security.GetTokenInformation(th, win32security.TokenVirtualizationEnabled)) + + elevation_type = win32security.GetTokenInformation(th, win32security.TokenElevationType) + print('TokenElevationType:', elevation_type, TOKEN_ELEVATION_TYPE.lookup_name(elevation_type)) + if elevation_type!=win32security.TokenElevationTypeDefault: + lt=win32security.GetTokenInformation(th, win32security.TokenLinkedToken) + print('TokenLinkedToken:', lt) + else: + lt=None + return lt + + +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken(ph,win32con.MAXIMUM_ALLOWED) +lt = dump_token(th) +if lt: + print('\n\nlinked token info:') + dump_token(lt) diff --git a/Lib/site-packages/win32/Demos/security/account_rights.py b/Lib/site-packages/win32/Demos/security/account_rights.py new file mode 100644 index 0000000..e2f1e44 --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/account_rights.py @@ -0,0 +1,31 @@ +import win32security,win32file,win32api,ntsecuritycon,win32con +from security_enums import TRUSTEE_TYPE,TRUSTEE_FORM,ACE_FLAGS,ACCESS_MODE + +new_privs = ((win32security.LookupPrivilegeValue('',ntsecuritycon.SE_SECURITY_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_CREATE_PERMANENT_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('','SeEnableDelegationPrivilege'),win32con.SE_PRIVILEGE_ENABLED) ##doesn't seem to be in ntsecuritycon.py ? + ) + +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken(ph,win32security.TOKEN_ALL_ACCESS) ##win32con.TOKEN_ADJUST_PRIVILEGES) +win32security.AdjustTokenPrivileges(th,0,new_privs) + +policy_handle = win32security.GetPolicyHandle('',win32security.POLICY_ALL_ACCESS) +tmp_sid = win32security.LookupAccountName('','tmp')[0] + +privs=[ntsecuritycon.SE_DEBUG_NAME,ntsecuritycon.SE_TCB_NAME,ntsecuritycon.SE_RESTORE_NAME,ntsecuritycon.SE_REMOTE_SHUTDOWN_NAME] +win32security.LsaAddAccountRights(policy_handle,tmp_sid,privs) + +privlist=win32security.LsaEnumerateAccountRights(policy_handle,tmp_sid) +for priv in privlist: + print(priv) + +privs=[ntsecuritycon.SE_DEBUG_NAME,ntsecuritycon.SE_TCB_NAME] +win32security.LsaRemoveAccountRights(policy_handle,tmp_sid,0,privs) + +privlist=win32security.LsaEnumerateAccountRights(policy_handle,tmp_sid) +for priv in privlist: + print(priv) + +win32security.LsaClose(policy_handle) + diff --git a/Lib/site-packages/win32/Demos/security/explicit_entries.py b/Lib/site-packages/win32/Demos/security/explicit_entries.py new file mode 100644 index 0000000..f944cbc --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/explicit_entries.py @@ -0,0 +1,144 @@ +import os +import win32security,win32file,win32api,ntsecuritycon,win32con +from security_enums import TRUSTEE_TYPE,TRUSTEE_FORM,ACE_FLAGS,ACCESS_MODE + +fname = os.path.join(win32api.GetTempPath(), "win32security_test.txt") +f=open(fname, "w") +f.write("Hello from Python\n"); +f.close() +print("Testing on file", fname) + +new_privs = ((win32security.LookupPrivilegeValue('',ntsecuritycon.SE_SECURITY_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_SHUTDOWN_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_RESTORE_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_TAKE_OWNERSHIP_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_CREATE_PERMANENT_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('','SeEnableDelegationPrivilege'),win32con.SE_PRIVILEGE_ENABLED) ##doesn't seem to be in ntsecuritycon.py ? + ) + +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken(ph,win32security.TOKEN_ALL_ACCESS) ##win32con.TOKEN_ADJUST_PRIVILEGES) +win32security.AdjustTokenPrivileges(th,0,new_privs) + +all_security_info = \ + win32security.OWNER_SECURITY_INFORMATION|win32security.GROUP_SECURITY_INFORMATION| \ + win32security.DACL_SECURITY_INFORMATION|win32security.SACL_SECURITY_INFORMATION + +sd=win32security.GetFileSecurity(fname,all_security_info) + +old_sacl=sd.GetSecurityDescriptorSacl() +if old_sacl==None: + old_sacl=win32security.ACL() +old_dacl=sd.GetSecurityDescriptorDacl() +if old_dacl==None: + old_dacl=win32security.ACL() + +my_sid = win32security.GetTokenInformation(th,ntsecuritycon.TokenUser)[0] +tmp_sid = win32security.LookupAccountName('','tmp')[0] +pwr_sid = win32security.LookupAccountName('','Power Users')[0] + + +## MultipleTrustee,MultipleTrusteeOperation,TrusteeForm,TrusteeType,Identifier +## first two are ignored +my_trustee = {} +my_trustee['MultipleTrustee']=None +my_trustee['MultipleTrusteeOperation']=0 +my_trustee['TrusteeForm']=TRUSTEE_FORM.TRUSTEE_IS_SID +my_trustee['TrusteeType']=TRUSTEE_TYPE.TRUSTEE_IS_USER +my_trustee['Identifier']=my_sid + +tmp_trustee = {} +tmp_trustee['MultipleTrustee']=None +tmp_trustee['MultipleTrusteeOperation']=0 +tmp_trustee['TrusteeForm']=TRUSTEE_FORM.TRUSTEE_IS_NAME +tmp_trustee['TrusteeType']=TRUSTEE_TYPE.TRUSTEE_IS_USER +tmp_trustee['Identifier']='rupole\\tmp' + +pwr_trustee = {} +pwr_trustee['MultipleTrustee']=None +pwr_trustee['MultipleTrusteeOperation']=0 +pwr_trustee['TrusteeForm']=TRUSTEE_FORM.TRUSTEE_IS_SID +pwr_trustee['TrusteeType']=TRUSTEE_TYPE.TRUSTEE_IS_USER +pwr_trustee['Identifier']=pwr_sid + +expl_list=[] +expl_list.append( + { + 'Trustee':my_trustee, + 'Inheritance':ACE_FLAGS.NO_INHERITANCE, + 'AccessMode':ACCESS_MODE.SET_AUDIT_SUCCESS, ##|ACCESS_MODE.SET_AUDIT_FAILURE, + 'AccessPermissions':win32con.GENERIC_ALL + } + ) + +expl_list.append( + { + 'Trustee':my_trustee, + 'Inheritance':ACE_FLAGS.NO_INHERITANCE, + 'AccessMode':ACCESS_MODE.SET_AUDIT_FAILURE, + 'AccessPermissions':win32con.GENERIC_ALL + } + ) + +expl_list.append( + { + 'Trustee':tmp_trustee, + 'Inheritance':ACE_FLAGS.NO_INHERITANCE, + 'AccessMode':ACCESS_MODE.SET_AUDIT_SUCCESS, + 'AccessPermissions':win32con.GENERIC_ALL + } + ) + +expl_list.append( + { + 'Trustee':tmp_trustee, + 'Inheritance':ACE_FLAGS.NO_INHERITANCE, + 'AccessMode':ACCESS_MODE.SET_AUDIT_FAILURE, + 'AccessPermissions':win32con.GENERIC_ALL + } + ) +old_sacl.SetEntriesInAcl(expl_list) + +expl_list=[] +expl_list.append( + { + 'Trustee':tmp_trustee, + 'Inheritance':ACE_FLAGS.NO_INHERITANCE, + 'AccessMode':ACCESS_MODE.DENY_ACCESS, + 'AccessPermissions':win32con.DELETE + } + ) + +expl_list.append( + { + 'Trustee':tmp_trustee, + 'Inheritance':ACE_FLAGS.NO_INHERITANCE, + 'AccessMode':ACCESS_MODE.GRANT_ACCESS, + 'AccessPermissions':win32con.WRITE_OWNER + } + ) +expl_list.append( + { + 'Trustee':pwr_trustee, + 'Inheritance':ACE_FLAGS.NO_INHERITANCE, + 'AccessMode':ACCESS_MODE.GRANT_ACCESS, + 'AccessPermissions':win32con.GENERIC_READ + } + ) +expl_list.append( + { + 'Trustee':my_trustee, + 'Inheritance':ACE_FLAGS.NO_INHERITANCE, + 'AccessMode':ACCESS_MODE.GRANT_ACCESS, + 'AccessPermissions':win32con.GENERIC_ALL + } + ) + +old_dacl.SetEntriesInAcl(expl_list) +sd.SetSecurityDescriptorSacl(1,old_sacl,1) +sd.SetSecurityDescriptorDacl(1,old_dacl,1) +sd.SetSecurityDescriptorOwner(pwr_sid,1) + +win32security.SetFileSecurity(fname, + all_security_info, + sd) diff --git a/Lib/site-packages/win32/Demos/security/get_policy_info.py b/Lib/site-packages/win32/Demos/security/get_policy_info.py new file mode 100644 index 0000000..b7164dc --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/get_policy_info.py @@ -0,0 +1,23 @@ +import win32security,win32file,win32api,ntsecuritycon,win32con +policy_handle = win32security.GetPolicyHandle('rupole',win32security.POLICY_ALL_ACCESS) + +## mod_nbr, mod_time = win32security.LsaQueryInformationPolicy(policy_handle,win32security.PolicyModificationInformation) +## print mod_nbr, mod_time + +domain_name,dns_domain_name, dns_forest_name, domain_guid, domain_sid = \ + win32security.LsaQueryInformationPolicy(policy_handle,win32security.PolicyDnsDomainInformation) +print(domain_name, dns_domain_name, dns_forest_name, domain_guid, domain_sid) + +event_audit_info=win32security.LsaQueryInformationPolicy(policy_handle,win32security.PolicyAuditEventsInformation) +print(event_audit_info) + +domain_name,sid =win32security.LsaQueryInformationPolicy(policy_handle,win32security.PolicyPrimaryDomainInformation) +print(domain_name, sid) + +domain_name,sid =win32security.LsaQueryInformationPolicy(policy_handle,win32security.PolicyAccountDomainInformation) +print(domain_name, sid) + +server_role = win32security.LsaQueryInformationPolicy(policy_handle,win32security.PolicyLsaServerRoleInformation) +print('server role: ',server_role) + +win32security.LsaClose(policy_handle) diff --git a/Lib/site-packages/win32/Demos/security/list_rights.py b/Lib/site-packages/win32/Demos/security/list_rights.py new file mode 100644 index 0000000..7b99f99 --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/list_rights.py @@ -0,0 +1,20 @@ +import win32security,win32file,win32api,ntsecuritycon,win32con +from security_enums import TRUSTEE_TYPE,TRUSTEE_FORM,ACE_FLAGS,ACCESS_MODE + +new_privs = ((win32security.LookupPrivilegeValue('',ntsecuritycon.SE_SECURITY_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_CREATE_PERMANENT_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('','SeEnableDelegationPrivilege'),win32con.SE_PRIVILEGE_ENABLED) ##doesn't seem to be in ntsecuritycon.py ? + ) + +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken(ph,win32security.TOKEN_ALL_ACCESS) ##win32con.TOKEN_ADJUST_PRIVILEGES) +win32security.AdjustTokenPrivileges(th,0,new_privs) + +policy_handle = win32security.GetPolicyHandle('',win32security.POLICY_ALL_ACCESS) + +sidlist=win32security.LsaEnumerateAccountsWithUserRight(policy_handle,ntsecuritycon.SE_RESTORE_NAME) +for sid in sidlist: + print(win32security.LookupAccountSid('',sid)) + +win32security.LsaClose(policy_handle) + diff --git a/Lib/site-packages/win32/Demos/security/localized_names.py b/Lib/site-packages/win32/Demos/security/localized_names.py new file mode 100644 index 0000000..8bbf68b --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/localized_names.py @@ -0,0 +1,61 @@ +# A Python port of the MS knowledge base article Q157234 +# "How to deal with localized and renamed user and group names" +# http://support.microsoft.com/default.aspx?kbid=157234 + +import sys +from win32net import NetUserModalsGet +from win32security import LookupAccountSid +import pywintypes +from ntsecuritycon import * + +def LookupAliasFromRid(TargetComputer, Rid): + # Sid is the same regardless of machine, since the well-known + # BUILTIN domain is referenced. + sid = pywintypes.SID() + sid.Initialize(SECURITY_NT_AUTHORITY, 2) + + for i, r in enumerate((SECURITY_BUILTIN_DOMAIN_RID, Rid)): + sid.SetSubAuthority(i, r) + + name, domain, typ = LookupAccountSid(TargetComputer, sid) + return name + +def LookupUserGroupFromRid(TargetComputer, Rid): + # get the account domain Sid on the target machine + # note: if you were looking up multiple sids based on the same + # account domain, only need to call this once. + umi2 = NetUserModalsGet(TargetComputer, 2) + domain_sid = umi2['domain_id'] + + SubAuthorityCount = domain_sid.GetSubAuthorityCount() + + # create and init new sid with acct domain Sid + acct Rid + sid = pywintypes.SID() + sid.Initialize(domain_sid.GetSidIdentifierAuthority(), + SubAuthorityCount+1) + + # copy existing subauthorities from account domain Sid into + # new Sid + for i in range(SubAuthorityCount): + sid.SetSubAuthority(i, domain_sid.GetSubAuthority(i)) + + # append Rid to new Sid + sid.SetSubAuthority(SubAuthorityCount, Rid) + + name, domain, typ = LookupAccountSid(TargetComputer, sid) + return name + +def main(): + if len(sys.argv) == 2: + targetComputer = sys.argv[1] + else: + targetComputer = None + + name = LookupUserGroupFromRid(targetComputer, DOMAIN_USER_RID_ADMIN) + print("'Administrator' user name = %s" % (name,)) + + name = LookupAliasFromRid(targetComputer, DOMAIN_ALIAS_RID_ADMINS) + print("'Administrators' local group/alias name = %s" % (name,)) + +if __name__=='__main__': + main() diff --git a/Lib/site-packages/win32/Demos/security/lsaregevent.py b/Lib/site-packages/win32/Demos/security/lsaregevent.py new file mode 100644 index 0000000..c553a5f --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/lsaregevent.py @@ -0,0 +1,8 @@ +import win32security, win32event +evt = win32event.CreateEvent(None,0,0,None) +win32security.LsaRegisterPolicyChangeNotification(win32security.PolicyNotifyAuditEventsInformation, evt) +print("Waiting for you change Audit policy in Management console ...") +ret_code=win32event.WaitForSingleObject(evt,1000000000) +## should come back when you change Audit policy in Management console ... +print(ret_code) +win32security.LsaUnregisterPolicyChangeNotification(win32security.PolicyNotifyAuditEventsInformation, evt) diff --git a/Lib/site-packages/win32/Demos/security/lsastore.py b/Lib/site-packages/win32/Demos/security/lsastore.py new file mode 100644 index 0000000..685e401 --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/lsastore.py @@ -0,0 +1,11 @@ +import win32security +policy_handle = win32security.GetPolicyHandle('',win32security.POLICY_ALL_ACCESS) +privatedata='some sensitive data' +keyname='tmp' +win32security.LsaStorePrivateData(policy_handle,keyname,privatedata) +retrieveddata=win32security.LsaRetrievePrivateData(policy_handle,keyname) +assert retrieveddata==privatedata + +## passing None deletes key +win32security.LsaStorePrivateData(policy_handle,keyname,None) +win32security.LsaClose(policy_handle) diff --git a/Lib/site-packages/win32/Demos/security/query_information.py b/Lib/site-packages/win32/Demos/security/query_information.py new file mode 100644 index 0000000..466b87d --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/query_information.py @@ -0,0 +1,25 @@ +from ntsecuritycon import * +import win32api, win32security, winerror + +# This is a Python implementation of win32api.GetDomainName() +def GetDomainName(): + try: + tok = win32security.OpenThreadToken(win32api.GetCurrentThread(), + TOKEN_QUERY, 1) + except win32api.error as details: + if details[0] != winerror.ERROR_NO_TOKEN: + raise + # attempt to open the process token, since no thread token + # exists + tok = win32security.OpenProcessToken(win32api.GetCurrentProcess(), + TOKEN_QUERY) + sid, attr = win32security.GetTokenInformation(tok, TokenUser) + win32api.CloseHandle(tok) + + name, dom, typ = win32security.LookupAccountSid(None, sid) + return dom + +if __name__=='__main__': + print("Domain name is", GetDomainName()) + + diff --git a/Lib/site-packages/win32/Demos/security/regsave_sa.py b/Lib/site-packages/win32/Demos/security/regsave_sa.py new file mode 100644 index 0000000..1004514 --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/regsave_sa.py @@ -0,0 +1,37 @@ +fname='h:\\tmp.reg' + +import win32api, win32con, win32security, ntsecuritycon, pywintypes,os +## regsave will not overwrite a file +if os.path.isfile(fname): + os.remove(fname) + +new_privs = ((win32security.LookupPrivilegeValue('',ntsecuritycon.SE_SECURITY_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_TCB_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_BACKUP_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_RESTORE_NAME),win32con.SE_PRIVILEGE_ENABLED) + + ) +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken(ph,win32security.TOKEN_ALL_ACCESS|win32con.TOKEN_ADJUST_PRIVILEGES) +win32security.AdjustTokenPrivileges(th,0,new_privs) +my_sid = win32security.GetTokenInformation(th,ntsecuritycon.TokenUser)[0] + +hklm=win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE,None,0,win32con.KEY_ALL_ACCESS) +skey=win32api.RegOpenKey(hklm,'SYSTEM',0,win32con.KEY_ALL_ACCESS) + +sa=pywintypes.SECURITY_ATTRIBUTES() +sd=pywintypes.SECURITY_DESCRIPTOR() +sa.SECURITY_DESCRIPTOR=sd +acl=pywintypes.ACL() + +pwr_sid = win32security.LookupAccountName('','Power Users')[0] +acl.AddAccessAllowedAce(win32con.ACL_REVISION,win32con.GENERIC_READ|win32con.ACCESS_SYSTEM_SECURITY,my_sid) +sd.SetSecurityDescriptorDacl(1,acl,0) +sd.SetSecurityDescriptorOwner(pwr_sid,0) +sa.bInheritHandle=1 +assert sa.SECURITY_DESCRIPTOR is sd + +win32api.RegSaveKey(skey,fname,sa) + + + diff --git a/Lib/site-packages/win32/Demos/security/regsecurity.py b/Lib/site-packages/win32/Demos/security/regsecurity.py new file mode 100644 index 0000000..8320a61 --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/regsecurity.py @@ -0,0 +1,20 @@ +import win32api, win32con, win32security, ntsecuritycon + +new_privs = ((win32security.LookupPrivilegeValue('',ntsecuritycon.SE_SECURITY_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_TCB_NAME),win32con.SE_PRIVILEGE_ENABLED) + ) +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken(ph,win32security.TOKEN_ALL_ACCESS|win32con.TOKEN_ADJUST_PRIVILEGES) + +win32security.AdjustTokenPrivileges(th,0,new_privs) +hkey=win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE,None,0,win32con.KEY_ALL_ACCESS) +win32api.RegCreateKey(hkey,'SYSTEM\\NOTMP') +notmpkey=win32api.RegOpenKey(hkey,'SYSTEM\\notmp',0,win32con.ACCESS_SYSTEM_SECURITY) + +tmp_sid = win32security.LookupAccountName('','tmp')[0] +sacl=win32security.ACL() +sacl.AddAuditAccessAce(win32security.ACL_REVISION,win32con.GENERIC_ALL,tmp_sid,1,1) + +sd=win32security.SECURITY_DESCRIPTOR() +sd.SetSecurityDescriptorSacl(1,sacl,1) +win32api.RegSetKeySecurity(notmpkey,win32con.SACL_SECURITY_INFORMATION,sd) diff --git a/Lib/site-packages/win32/Demos/security/sa_inherit.py b/Lib/site-packages/win32/Demos/security/sa_inherit.py new file mode 100644 index 0000000..97d016a --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/sa_inherit.py @@ -0,0 +1,7 @@ +import pywintypes, win32security +sa=pywintypes.SECURITY_ATTRIBUTES() +tmp_sid=win32security.LookupAccountName('','tmp')[0] +sa.SetSecurityDescriptorOwner(tmp_sid,0) +sid=sa.SECURITY_DESCRIPTOR.GetSecurityDescriptorOwner() +print(win32security.LookupAccountSid('',sid)) + diff --git a/Lib/site-packages/win32/Demos/security/security_enums.py b/Lib/site-packages/win32/Demos/security/security_enums.py new file mode 100644 index 0000000..4a4b980 --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/security_enums.py @@ -0,0 +1,316 @@ +import win32security, ntsecuritycon, winnt + +class Enum: + def __init__(self, *const_names): + """Accepts variable number of constant names that can be found in either + win32security, ntsecuritycon, or winnt.""" + for const_name in const_names: + try: + const_val=getattr(win32security,const_name) + except AttributeError: + try: + const_val=getattr(ntsecuritycon, const_name) + except AttributeError: + try: + const_val=getattr(winnt, const_name) + except AttributeError: + raise AttributeError('Constant "%s" not found in win32security, ntsecuritycon, or winnt.' %const_name) + setattr(self, const_name, const_val) + + def lookup_name(self, const_val): + """Looks up the name of a particular value.""" + for k,v in self.__dict__.items(): + if v==const_val: + return k + raise AttributeError('Value %s not found in enum' %const_val) + + def lookup_flags(self, flags): + """Returns the names of all recognized flags in input, and any flags not found in the enum.""" + flag_names=[] + unknown_flags=flags + for k,v in self.__dict__.items(): + if flags & v == v: + flag_names.append(k) + unknown_flags = unknown_flags & ~v + return flag_names, unknown_flags + +TOKEN_INFORMATION_CLASS = Enum( + 'TokenUser', + 'TokenGroups', + 'TokenPrivileges', + 'TokenOwner', + 'TokenPrimaryGroup', + 'TokenDefaultDacl', + 'TokenSource', + 'TokenType', + 'TokenImpersonationLevel', + 'TokenStatistics', + 'TokenRestrictedSids', + 'TokenSessionId', + 'TokenGroupsAndPrivileges', + 'TokenSessionReference', + 'TokenSandBoxInert', + 'TokenAuditPolicy', + 'TokenOrigin', + 'TokenElevationType', + 'TokenLinkedToken', + 'TokenElevation', + 'TokenHasRestrictions', + 'TokenAccessInformation', + 'TokenVirtualizationAllowed', + 'TokenVirtualizationEnabled', + 'TokenIntegrityLevel', + 'TokenUIAccess', + 'TokenMandatoryPolicy', + 'TokenLogonSid') + +TOKEN_TYPE = Enum( + 'TokenPrimary', + 'TokenImpersonation') + +TOKEN_ELEVATION_TYPE = Enum( + 'TokenElevationTypeDefault', + 'TokenElevationTypeFull', + 'TokenElevationTypeLimited') + +POLICY_AUDIT_EVENT_TYPE = Enum( + 'AuditCategorySystem', + 'AuditCategoryLogon', + 'AuditCategoryObjectAccess', + 'AuditCategoryPrivilegeUse', + 'AuditCategoryDetailedTracking', + 'AuditCategoryPolicyChange', + 'AuditCategoryAccountManagement', + 'AuditCategoryDirectoryServiceAccess', + 'AuditCategoryAccountLogon') + +POLICY_INFORMATION_CLASS = Enum( + 'PolicyAuditLogInformation', + 'PolicyAuditEventsInformation', + 'PolicyPrimaryDomainInformation', + 'PolicyPdAccountInformation', + 'PolicyAccountDomainInformation', + 'PolicyLsaServerRoleInformation', + 'PolicyReplicaSourceInformation', + 'PolicyDefaultQuotaInformation', + 'PolicyModificationInformation', + 'PolicyAuditFullSetInformation', + 'PolicyAuditFullQueryInformation', + 'PolicyDnsDomainInformation') + +POLICY_LSA_SERVER_ROLE = Enum( + 'PolicyServerRoleBackup', + 'PolicyServerRolePrimary') + +## access modes for opening a policy handle - this is not a real enum +POLICY_ACCESS_MODES = Enum( + 'POLICY_VIEW_LOCAL_INFORMATION', + 'POLICY_VIEW_AUDIT_INFORMATION', + 'POLICY_GET_PRIVATE_INFORMATION', + 'POLICY_TRUST_ADMIN', + 'POLICY_CREATE_ACCOUNT', + 'POLICY_CREATE_SECRET', + 'POLICY_CREATE_PRIVILEGE', + 'POLICY_SET_DEFAULT_QUOTA_LIMITS', + 'POLICY_SET_AUDIT_REQUIREMENTS', + 'POLICY_AUDIT_LOG_ADMIN', + 'POLICY_SERVER_ADMIN', + 'POLICY_LOOKUP_NAMES', + 'POLICY_NOTIFICATION', + 'POLICY_ALL_ACCESS', + 'POLICY_READ', + 'POLICY_WRITE', + 'POLICY_EXECUTE') + +## EventAuditingOptions flags - not a real enum +POLICY_AUDIT_EVENT_OPTIONS_FLAGS = Enum( + 'POLICY_AUDIT_EVENT_UNCHANGED', + 'POLICY_AUDIT_EVENT_SUCCESS', + 'POLICY_AUDIT_EVENT_FAILURE', + 'POLICY_AUDIT_EVENT_NONE') + +# AceType in ACE_HEADER - not a real enum +ACE_TYPE = Enum( + 'ACCESS_MIN_MS_ACE_TYPE', + 'ACCESS_ALLOWED_ACE_TYPE', + 'ACCESS_DENIED_ACE_TYPE', + 'SYSTEM_AUDIT_ACE_TYPE', + 'SYSTEM_ALARM_ACE_TYPE', + 'ACCESS_MAX_MS_V2_ACE_TYPE', + 'ACCESS_ALLOWED_COMPOUND_ACE_TYPE', + 'ACCESS_MAX_MS_V3_ACE_TYPE', + 'ACCESS_MIN_MS_OBJECT_ACE_TYPE', + 'ACCESS_ALLOWED_OBJECT_ACE_TYPE', + 'ACCESS_DENIED_OBJECT_ACE_TYPE', + 'SYSTEM_AUDIT_OBJECT_ACE_TYPE', + 'SYSTEM_ALARM_OBJECT_ACE_TYPE', + 'ACCESS_MAX_MS_OBJECT_ACE_TYPE', + 'ACCESS_MAX_MS_V4_ACE_TYPE', + 'ACCESS_MAX_MS_ACE_TYPE', + 'ACCESS_ALLOWED_CALLBACK_ACE_TYPE', + 'ACCESS_DENIED_CALLBACK_ACE_TYPE', + 'ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE', + 'ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE', + 'SYSTEM_AUDIT_CALLBACK_ACE_TYPE', + 'SYSTEM_ALARM_CALLBACK_ACE_TYPE', + 'SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE', + 'SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE', + 'SYSTEM_MANDATORY_LABEL_ACE_TYPE', + 'ACCESS_MAX_MS_V5_ACE_TYPE') + +#bit flags for AceFlags - not a real enum +ACE_FLAGS = Enum( + 'CONTAINER_INHERIT_ACE', + 'FAILED_ACCESS_ACE_FLAG', + 'INHERIT_ONLY_ACE', + 'INHERITED_ACE', + 'NO_PROPAGATE_INHERIT_ACE', + 'OBJECT_INHERIT_ACE', + 'SUCCESSFUL_ACCESS_ACE_FLAG', + 'NO_INHERITANCE', + 'SUB_CONTAINERS_AND_OBJECTS_INHERIT', + 'SUB_CONTAINERS_ONLY_INHERIT', + 'SUB_OBJECTS_ONLY_INHERIT') + +# used in SetEntriesInAcl - very similar to ACE_TYPE +ACCESS_MODE = Enum( + 'NOT_USED_ACCESS', + 'GRANT_ACCESS', + 'SET_ACCESS', + 'DENY_ACCESS', + 'REVOKE_ACCESS', + 'SET_AUDIT_SUCCESS', + 'SET_AUDIT_FAILURE') + +# Bit flags in PSECURITY_DESCRIPTOR->Control - not a real enum +SECURITY_DESCRIPTOR_CONTROL_FLAGS = Enum( + 'SE_DACL_AUTO_INHERITED', ## win2k and up + 'SE_SACL_AUTO_INHERITED', ## win2k and up + 'SE_DACL_PROTECTED', ## win2k and up + 'SE_SACL_PROTECTED', ## win2k and up + 'SE_DACL_DEFAULTED', + 'SE_DACL_PRESENT', + 'SE_GROUP_DEFAULTED', + 'SE_OWNER_DEFAULTED', + 'SE_SACL_PRESENT', + 'SE_SELF_RELATIVE', + 'SE_SACL_DEFAULTED') + +# types of SID +SID_NAME_USE = Enum( + 'SidTypeUser', + 'SidTypeGroup', + 'SidTypeDomain', + 'SidTypeAlias', + 'SidTypeWellKnownGroup', + 'SidTypeDeletedAccount', + 'SidTypeInvalid', + 'SidTypeUnknown', + 'SidTypeComputer', + 'SidTypeLabel') + +## bit flags, not a real enum +TOKEN_ACCESS_PRIVILEGES = Enum( + 'TOKEN_ADJUST_DEFAULT', + 'TOKEN_ADJUST_GROUPS', + 'TOKEN_ADJUST_PRIVILEGES', + 'TOKEN_ALL_ACCESS', + 'TOKEN_ASSIGN_PRIMARY', + 'TOKEN_DUPLICATE', + 'TOKEN_EXECUTE', + 'TOKEN_IMPERSONATE', + 'TOKEN_QUERY', + 'TOKEN_QUERY_SOURCE', + 'TOKEN_READ', + 'TOKEN_WRITE') + +SECURITY_IMPERSONATION_LEVEL = Enum( + 'SecurityAnonymous', + 'SecurityIdentification', + 'SecurityImpersonation', + 'SecurityDelegation') + +POLICY_SERVER_ENABLE_STATE = Enum( + 'PolicyServerEnabled', + 'PolicyServerDisabled') + +POLICY_NOTIFICATION_INFORMATION_CLASS = Enum( + 'PolicyNotifyAuditEventsInformation', + 'PolicyNotifyAccountDomainInformation', + 'PolicyNotifyServerRoleInformation', + 'PolicyNotifyDnsDomainInformation', + 'PolicyNotifyDomainEfsInformation', + 'PolicyNotifyDomainKerberosTicketInformation', + 'PolicyNotifyMachineAccountPasswordInformation') + +TRUSTED_INFORMATION_CLASS = Enum( + 'TrustedDomainNameInformation', + 'TrustedControllersInformation', + 'TrustedPosixOffsetInformation', + 'TrustedPasswordInformation', + 'TrustedDomainInformationBasic', + 'TrustedDomainInformationEx', + 'TrustedDomainAuthInformation', + 'TrustedDomainFullInformation', + 'TrustedDomainAuthInformationInternal', + 'TrustedDomainFullInformationInternal', + 'TrustedDomainInformationEx2Internal', + 'TrustedDomainFullInformation2Internal') + +TRUSTEE_FORM = Enum( + 'TRUSTEE_IS_SID', + 'TRUSTEE_IS_NAME', + 'TRUSTEE_BAD_FORM', + 'TRUSTEE_IS_OBJECTS_AND_SID', + 'TRUSTEE_IS_OBJECTS_AND_NAME') + +TRUSTEE_TYPE = Enum( + 'TRUSTEE_IS_UNKNOWN', + 'TRUSTEE_IS_USER', + 'TRUSTEE_IS_GROUP', + 'TRUSTEE_IS_DOMAIN', + 'TRUSTEE_IS_ALIAS', + 'TRUSTEE_IS_WELL_KNOWN_GROUP', + 'TRUSTEE_IS_DELETED', + 'TRUSTEE_IS_INVALID', + 'TRUSTEE_IS_COMPUTER') + +## SE_OBJECT_TYPE - securable objects +SE_OBJECT_TYPE = Enum( + 'SE_UNKNOWN_OBJECT_TYPE', + 'SE_FILE_OBJECT', + 'SE_SERVICE', + 'SE_PRINTER', + 'SE_REGISTRY_KEY', + 'SE_LMSHARE', + 'SE_KERNEL_OBJECT', + 'SE_WINDOW_OBJECT', + 'SE_DS_OBJECT', + 'SE_DS_OBJECT_ALL', + 'SE_PROVIDER_DEFINED_OBJECT', + 'SE_WMIGUID_OBJECT', + 'SE_REGISTRY_WOW64_32KEY') + +PRIVILEGE_FLAGS = Enum( + 'SE_PRIVILEGE_ENABLED_BY_DEFAULT', + 'SE_PRIVILEGE_ENABLED', + 'SE_PRIVILEGE_USED_FOR_ACCESS') + +# Group flags used with TokenGroups +TOKEN_GROUP_ATTRIBUTES = Enum( + 'SE_GROUP_MANDATORY', + 'SE_GROUP_ENABLED_BY_DEFAULT', + 'SE_GROUP_ENABLED', + 'SE_GROUP_OWNER', + 'SE_GROUP_USE_FOR_DENY_ONLY', + 'SE_GROUP_INTEGRITY', + 'SE_GROUP_INTEGRITY_ENABLED', + 'SE_GROUP_LOGON_ID', + 'SE_GROUP_RESOURCE') + +# Privilege flags returned by TokenPrivileges +TOKEN_PRIVILEGE_ATTRIBUTES = Enum( + 'SE_PRIVILEGE_ENABLED_BY_DEFAULT', + 'SE_PRIVILEGE_ENABLED', + 'SE_PRIVILEGE_REMOVED', + 'SE_PRIVILEGE_USED_FOR_ACCESS') diff --git a/Lib/site-packages/win32/Demos/security/set_file_audit.py b/Lib/site-packages/win32/Demos/security/set_file_audit.py new file mode 100644 index 0000000..736f61d --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/set_file_audit.py @@ -0,0 +1,58 @@ +import win32security,win32file,win32api,ntsecuritycon,win32con, os +from win32security import ACL_REVISION_DS, CONTAINER_INHERIT_ACE, OBJECT_INHERIT_ACE, \ + PROTECTED_DACL_SECURITY_INFORMATION, DACL_SECURITY_INFORMATION, SACL_SECURITY_INFORMATION, \ + OWNER_SECURITY_INFORMATION, GROUP_SECURITY_INFORMATION, SE_FILE_OBJECT + +## SE_SECURITY_NAME needed to access SACL, SE_RESTORE_NAME needed to change owner to someone other than yourself +new_privs = ((win32security.LookupPrivilegeValue('',ntsecuritycon.SE_SECURITY_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_RESTORE_NAME),win32con.SE_PRIVILEGE_ENABLED), + ) +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken(ph,win32security.TOKEN_ALL_ACCESS|win32con.TOKEN_ADJUST_PRIVILEGES) +modified_privs=win32security.AdjustTokenPrivileges(th,0,new_privs) + +## look up a few sids that should be available on most systems +my_sid = win32security.GetTokenInformation(th,ntsecuritycon.TokenUser)[0] +pwr_sid = win32security.LookupAccountName('','Power Users')[0] +admin_sid = win32security.LookupAccountName('','Administrators')[0] +everyone_sid=win32security.LookupAccountName('','EveryOne')[0] + +## create a dir and set security so Everyone has read permissions, and all files and subdirs inherit its ACLs +temp_dir=win32api.GetTempPath() +dir_name=win32api.GetTempFileName(temp_dir,'sfa')[0] +os.remove(dir_name) +os.mkdir(dir_name) +dir_dacl=win32security.ACL() +dir_dacl.AddAccessAllowedAceEx(ACL_REVISION_DS, CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE, win32con.GENERIC_READ, everyone_sid) +## make sure current user has permissions on dir +dir_dacl.AddAccessAllowedAceEx(ACL_REVISION_DS, CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE, win32con.GENERIC_ALL, my_sid) +## keep dir from inheriting any permissions so it only has ACEs explicitely set here +win32security.SetNamedSecurityInfo(dir_name, SE_FILE_OBJECT, + OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|PROTECTED_DACL_SECURITY_INFORMATION, + pwr_sid, pwr_sid, dir_dacl, None) + +## Create a file in the dir and add some specific permissions to it +fname=win32api.GetTempFileName(dir_name,'sfa')[0] +print(fname) +file_sd=win32security.GetNamedSecurityInfo(fname, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION) +file_dacl=file_sd.GetSecurityDescriptorDacl() +file_sacl=file_sd.GetSecurityDescriptorSacl() + +if file_dacl is None: + file_dacl=win32security.ACL() +if file_sacl is None: + file_sacl=win32security.ACL() + +file_dacl.AddAccessDeniedAce(file_dacl.GetAclRevision(),win32con.DELETE,admin_sid) +file_dacl.AddAccessDeniedAce(file_dacl.GetAclRevision(),win32con.DELETE,my_sid) +file_dacl.AddAccessAllowedAce(file_dacl.GetAclRevision(),win32con.GENERIC_ALL,pwr_sid) +file_sacl.AddAuditAccessAce(file_dacl.GetAclRevision(),win32con.GENERIC_ALL,my_sid,True,True) + +win32security.SetNamedSecurityInfo(fname, SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION, + None, None, file_dacl, file_sacl) + +win32security.AdjustTokenPrivileges(th, 0, modified_privs) + + + diff --git a/Lib/site-packages/win32/Demos/security/set_file_owner.py b/Lib/site-packages/win32/Demos/security/set_file_owner.py new file mode 100644 index 0000000..7feb08e --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/set_file_owner.py @@ -0,0 +1,38 @@ +fname=r'h:\tmp.txt' + +import win32security,win32file,win32api,ntsecuritycon,win32con + +new_privs = ((win32security.LookupPrivilegeValue('',ntsecuritycon.SE_SECURITY_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_SHUTDOWN_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_TCB_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_RESTORE_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_TAKE_OWNERSHIP_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',ntsecuritycon.SE_CREATE_PERMANENT_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('','SeEnableDelegationPrivilege'),win32con.SE_PRIVILEGE_ENABLED) ##doesn't seem to be in ntsecuritycon.py ? + ) + +ph = win32api.GetCurrentProcess() +th = win32security.OpenProcessToken(ph,win32security.TOKEN_ALL_ACCESS|win32con.TOKEN_ADJUST_PRIVILEGES) +win32security.AdjustTokenPrivileges(th,0,new_privs) + +all_security_info = \ + win32security.OWNER_SECURITY_INFORMATION|win32security.GROUP_SECURITY_INFORMATION| \ + win32security.DACL_SECURITY_INFORMATION|win32security.SACL_SECURITY_INFORMATION + +sd=win32security.GetFileSecurity(fname,all_security_info) +old_dacl=sd.GetSecurityDescriptorDacl() +old_sacl=sd.GetSecurityDescriptorSacl() +old_group=sd.GetSecurityDescriptorGroup() + +new_sd=win32security.SECURITY_DESCRIPTOR() +print("relative, valid, size: ",new_sd.IsSelfRelative(), new_sd.IsValid(), new_sd.GetLength()) + +my_sid = win32security.GetTokenInformation(th,ntsecuritycon.TokenUser)[0] +tmp_sid = win32security.LookupAccountName('','tmp')[0] + +new_sd.SetSecurityDescriptorSacl(1,old_sacl,1) +new_sd.SetSecurityDescriptorDacl(1,old_dacl,1) +new_sd.SetSecurityDescriptorOwner(tmp_sid,0) +new_sd.SetSecurityDescriptorGroup(old_group,0) + +win32security.SetFileSecurity(fname,all_security_info,new_sd) diff --git a/Lib/site-packages/win32/Demos/security/set_policy_info.py b/Lib/site-packages/win32/Demos/security/set_policy_info.py new file mode 100644 index 0000000..70fe8c7 --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/set_policy_info.py @@ -0,0 +1,17 @@ +import win32security,win32file,win32api,ntsecuritycon,win32con +policy_handle = win32security.GetPolicyHandle('rupole',win32security.POLICY_ALL_ACCESS) + +event_audit_info=win32security.LsaQueryInformationPolicy(policy_handle,win32security.PolicyAuditEventsInformation) +print(event_audit_info) + +new_audit_info=list(event_audit_info[1]) +new_audit_info[win32security.AuditCategoryPolicyChange]= \ + win32security.POLICY_AUDIT_EVENT_SUCCESS|win32security.POLICY_AUDIT_EVENT_FAILURE +new_audit_info[win32security.AuditCategoryAccountLogon]= \ + win32security.POLICY_AUDIT_EVENT_SUCCESS|win32security.POLICY_AUDIT_EVENT_FAILURE +new_audit_info[win32security.AuditCategoryLogon]= \ + win32security.POLICY_AUDIT_EVENT_SUCCESS|win32security.POLICY_AUDIT_EVENT_FAILURE + +win32security.LsaSetInformationPolicy(policy_handle, win32security.PolicyAuditEventsInformation, (1,new_audit_info)) + +win32security.LsaClose(policy_handle) diff --git a/Lib/site-packages/win32/Demos/security/setkernelobjectsecurity.py b/Lib/site-packages/win32/Demos/security/setkernelobjectsecurity.py new file mode 100644 index 0000000..ac910cd --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/setkernelobjectsecurity.py @@ -0,0 +1,67 @@ +import win32security,win32api,win32con, win32process +## You need SE_RESTORE_NAME to be able to set the owner of a security descriptor to anybody +## other than yourself or your primary group. Most admin logins don't have it by default, so +## enabling it may fail +new_privs = ((win32security.LookupPrivilegeValue('',win32security.SE_SECURITY_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_TCB_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_SHUTDOWN_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_RESTORE_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_TAKE_OWNERSHIP_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_CREATE_PERMANENT_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_ENABLE_DELEGATION_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_CHANGE_NOTIFY_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_DEBUG_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_PROF_SINGLE_PROCESS_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_SYSTEM_PROFILE_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_LOCK_MEMORY_NAME),win32con.SE_PRIVILEGE_ENABLED) + ) + +all_info=win32security.OWNER_SECURITY_INFORMATION|win32security.GROUP_SECURITY_INFORMATION| \ + win32security.DACL_SECURITY_INFORMATION|win32security.SACL_SECURITY_INFORMATION + +pid=win32api.GetCurrentProcessId() +ph=win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS,0,pid) +## PROCESS_ALL_ACCESS does not contain ACCESS_SYSTEM_SECURITY (neccessy to do SACLs) +th = win32security.OpenProcessToken(ph,win32security.TOKEN_ALL_ACCESS) ##win32con.TOKEN_ADJUST_PRIVILEGES) +old_privs=win32security.AdjustTokenPrivileges(th,0,new_privs) +my_sid = win32security.GetTokenInformation(th,win32security.TokenUser)[0] +pwr_sid=win32security.LookupAccountName('','Power Users')[0] +## reopen process with ACCESS_SYSTEM_SECURITY now that sufficent privs are enabled +ph=win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS|win32con.ACCESS_SYSTEM_SECURITY,0,pid) + +sd=win32security.GetKernelObjectSecurity(ph,all_info) +dacl=sd.GetSecurityDescriptorDacl() +if dacl is None: + dacl=win32security.ACL() +sacl=sd.GetSecurityDescriptorSacl() +if sacl is None: + sacl=win32security.ACL() + +dacl_ace_cnt=dacl.GetAceCount() +sacl_ace_cnt=sacl.GetAceCount() + +dacl.AddAccessAllowedAce(dacl.GetAclRevision(),win32con.ACCESS_SYSTEM_SECURITY|win32con.WRITE_DAC,my_sid) +sacl.AddAuditAccessAce(sacl.GetAclRevision(),win32con.GENERIC_ALL,my_sid,1,1) +sd.SetSecurityDescriptorDacl(1,dacl,0) +sd.SetSecurityDescriptorSacl(1,sacl,0) +sd.SetSecurityDescriptorGroup(pwr_sid,0) +sd.SetSecurityDescriptorOwner(pwr_sid,0) + +win32security.SetKernelObjectSecurity(ph,all_info,sd) +new_sd=win32security.GetKernelObjectSecurity(ph,all_info) + +if new_sd.GetSecurityDescriptorDacl().GetAceCount()!=dacl_ace_cnt+1: + print('New dacl doesn''t contain extra ace ????') +if new_sd.GetSecurityDescriptorSacl().GetAceCount()!=sacl_ace_cnt+1: + print('New Sacl doesn''t contain extra ace ????') +if win32security.LookupAccountSid('',new_sd.GetSecurityDescriptorOwner())[0]!='Power Users': + print('Owner not successfully set to Power Users !!!!!') +if win32security.LookupAccountSid('',new_sd.GetSecurityDescriptorGroup())[0]!='Power Users': + print('Group not successfully set to Power Users !!!!!') + +sd.SetSecurityDescriptorSacl(0,None,0) +win32security.SetKernelObjectSecurity(ph, win32security.SACL_SECURITY_INFORMATION, sd) +new_sd_1=win32security.GetKernelObjectSecurity(ph,win32security.SACL_SECURITY_INFORMATION) +if new_sd_1.GetSecurityDescriptorSacl() is not None: + print('Unable to set Sacl to NULL !!!!!!!!') + diff --git a/Lib/site-packages/win32/Demos/security/setnamedsecurityinfo.py b/Lib/site-packages/win32/Demos/security/setnamedsecurityinfo.py new file mode 100644 index 0000000..20daa16 --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/setnamedsecurityinfo.py @@ -0,0 +1,60 @@ +import win32security,win32api,win32con, win32process +fname, tmp = win32api.GetTempFileName(win32api.GetTempPath(),'tmp') +print(fname) +## You need SE_RESTORE_NAME to be able to set the owner of a security descriptor to anybody +## other than yourself or your primary group. Most admin logins don't have it by default, so +## enabling it may fail +new_privs = ((win32security.LookupPrivilegeValue('',win32security.SE_SECURITY_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_TCB_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_SHUTDOWN_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_RESTORE_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_TAKE_OWNERSHIP_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_CREATE_PERMANENT_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_ENABLE_DELEGATION_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_CHANGE_NOTIFY_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_DEBUG_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_PROF_SINGLE_PROCESS_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_SYSTEM_PROFILE_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_LOCK_MEMORY_NAME),win32con.SE_PRIVILEGE_ENABLED) + ) + +all_info=win32security.OWNER_SECURITY_INFORMATION|win32security.GROUP_SECURITY_INFORMATION| \ + win32security.DACL_SECURITY_INFORMATION|win32security.SACL_SECURITY_INFORMATION + +ph=win32process.GetCurrentProcess() +th = win32security.OpenProcessToken(ph,win32security.TOKEN_ALL_ACCESS) ##win32con.TOKEN_ADJUST_PRIVILEGES) +win32security.AdjustTokenPrivileges(th,0,new_privs) +my_sid = win32security.GetTokenInformation(th,win32security.TokenUser)[0] +pwr_sid=win32security.LookupAccountName('','Power Users')[0] + +sd=win32security.GetNamedSecurityInfo(fname,win32security.SE_FILE_OBJECT,all_info) +dacl=sd.GetSecurityDescriptorDacl() +if dacl is None: + dacl=win32security.ACL() +sacl=sd.GetSecurityDescriptorSacl() +if sacl is None: + sacl=win32security.ACL() + +dacl_ace_cnt=dacl.GetAceCount() +sacl_ace_cnt=sacl.GetAceCount() + +dacl.AddAccessAllowedAce(dacl.GetAclRevision(),win32con.ACCESS_SYSTEM_SECURITY|win32con.WRITE_DAC,my_sid) +sacl.AddAuditAccessAce(sacl.GetAclRevision(),win32con.GENERIC_ALL,my_sid,1,1) + +win32security.SetNamedSecurityInfo(fname,win32security.SE_FILE_OBJECT,all_info,pwr_sid, pwr_sid, dacl, sacl) +new_sd=win32security.GetNamedSecurityInfo(fname,win32security.SE_FILE_OBJECT,all_info) + +## could do additional checking to make sure added ACE contains expected info +if new_sd.GetSecurityDescriptorDacl().GetAceCount()!=dacl_ace_cnt+1: + print('New dacl doesn''t contain extra ace ????') +if new_sd.GetSecurityDescriptorSacl().GetAceCount()!=sacl_ace_cnt+1: + print('New Sacl doesn''t contain extra ace ????') +if win32security.LookupAccountSid('',new_sd.GetSecurityDescriptorOwner())[0]!='Power Users': + print('Owner not successfully set to Power Users !!!!!') +if win32security.LookupAccountSid('',new_sd.GetSecurityDescriptorGroup())[0]!='Power Users': + print('Group not successfully set to Power Users !!!!!') + +win32security.SetNamedSecurityInfo(fname,win32security.SE_FILE_OBJECT,win32security.SACL_SECURITY_INFORMATION, None, None, None, None) +new_sd_1=win32security.GetNamedSecurityInfo(fname,win32security.SE_FILE_OBJECT,win32security.SACL_SECURITY_INFORMATION) +if new_sd_1.GetSecurityDescriptorSacl() is not None: + print('Unable to set Sacl to NULL !!!!!!!!') diff --git a/Lib/site-packages/win32/Demos/security/setsecurityinfo.py b/Lib/site-packages/win32/Demos/security/setsecurityinfo.py new file mode 100644 index 0000000..71e51c3 --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/setsecurityinfo.py @@ -0,0 +1,61 @@ +import win32security,win32api,win32con, win32process +## You need SE_RESTORE_NAME to be able to set the owner of a security descriptor to anybody +## other than yourself or your primary group. Most admin logins don't have it by default, so +## enabling it may fail +new_privs = ((win32security.LookupPrivilegeValue('',win32security.SE_SECURITY_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_TCB_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_SHUTDOWN_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_RESTORE_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_TAKE_OWNERSHIP_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_CREATE_PERMANENT_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_ENABLE_DELEGATION_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_CHANGE_NOTIFY_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_DEBUG_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_PROF_SINGLE_PROCESS_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_SYSTEM_PROFILE_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_LOCK_MEMORY_NAME),win32con.SE_PRIVILEGE_ENABLED) + ) + +all_info=win32security.OWNER_SECURITY_INFORMATION|win32security.GROUP_SECURITY_INFORMATION| \ + win32security.DACL_SECURITY_INFORMATION|win32security.SACL_SECURITY_INFORMATION + +pid=win32api.GetCurrentProcessId() +ph=win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS,0,pid) +## PROCESS_ALL_ACCESS does not contain ACCESS_SYSTEM_SECURITY (neccessy to do SACLs) +th = win32security.OpenProcessToken(ph,win32security.TOKEN_ALL_ACCESS) ##win32con.TOKEN_ADJUST_PRIVILEGES) +old_privs=win32security.AdjustTokenPrivileges(th,0,new_privs) +my_sid = win32security.GetTokenInformation(th,win32security.TokenUser)[0] +pwr_sid=win32security.LookupAccountName('','Power Users')[0] +## reopen process with ACCESS_SYSTEM_SECURITY now that sufficent privs are enabled +ph=win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS|win32con.ACCESS_SYSTEM_SECURITY,0,pid) + +sd=win32security.GetSecurityInfo(ph,win32security.SE_KERNEL_OBJECT,all_info) +dacl=sd.GetSecurityDescriptorDacl() +if dacl is None: + dacl=win32security.ACL() +sacl=sd.GetSecurityDescriptorSacl() +if sacl is None: + sacl=win32security.ACL() + +dacl_ace_cnt=dacl.GetAceCount() +sacl_ace_cnt=sacl.GetAceCount() + +dacl.AddAccessAllowedAce(dacl.GetAclRevision(),win32con.ACCESS_SYSTEM_SECURITY|win32con.WRITE_DAC,my_sid) +sacl.AddAuditAccessAce(sacl.GetAclRevision(),win32con.GENERIC_ALL,my_sid,1,1) + +win32security.SetSecurityInfo(ph,win32security.SE_KERNEL_OBJECT,all_info,pwr_sid, pwr_sid, dacl, sacl) +new_sd=win32security.GetSecurityInfo(ph,win32security.SE_KERNEL_OBJECT,all_info) + +if new_sd.GetSecurityDescriptorDacl().GetAceCount()!=dacl_ace_cnt+1: + print('New dacl doesn''t contain extra ace ????') +if new_sd.GetSecurityDescriptorSacl().GetAceCount()!=sacl_ace_cnt+1: + print('New Sacl doesn''t contain extra ace ????') +if win32security.LookupAccountSid('',new_sd.GetSecurityDescriptorOwner())[0]!='Power Users': + print('Owner not successfully set to Power Users !!!!!') +if win32security.LookupAccountSid('',new_sd.GetSecurityDescriptorGroup())[0]!='Power Users': + print('Group not successfully set to Power Users !!!!!') + +win32security.SetSecurityInfo(ph,win32security.SE_KERNEL_OBJECT,win32security.SACL_SECURITY_INFORMATION, None, None, None, None) +new_sd_1=win32security.GetSecurityInfo(ph,win32security.SE_KERNEL_OBJECT,win32security.SACL_SECURITY_INFORMATION) +if new_sd_1.GetSecurityDescriptorSacl() is not None: + print('Unable to set Sacl to NULL !!!!!!!!') diff --git a/Lib/site-packages/win32/Demos/security/setuserobjectsecurity.py b/Lib/site-packages/win32/Demos/security/setuserobjectsecurity.py new file mode 100644 index 0000000..96841f2 --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/setuserobjectsecurity.py @@ -0,0 +1,42 @@ +import win32security,win32api,win32con, win32process +new_privs = ((win32security.LookupPrivilegeValue('',win32security.SE_SECURITY_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_TCB_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_SHUTDOWN_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_RESTORE_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_TAKE_OWNERSHIP_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_CREATE_PERMANENT_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_ENABLE_DELEGATION_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_CHANGE_NOTIFY_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_DEBUG_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_PROF_SINGLE_PROCESS_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_SYSTEM_PROFILE_NAME),win32con.SE_PRIVILEGE_ENABLED), + (win32security.LookupPrivilegeValue('',win32security.SE_LOCK_MEMORY_NAME),win32con.SE_PRIVILEGE_ENABLED) + ) + +all_info=win32security.OWNER_SECURITY_INFORMATION|win32security.GROUP_SECURITY_INFORMATION| \ + win32security.DACL_SECURITY_INFORMATION|win32security.SACL_SECURITY_INFORMATION +info=win32security.OWNER_SECURITY_INFORMATION|win32security.GROUP_SECURITY_INFORMATION|win32security.DACL_SECURITY_INFORMATION + +ph=win32process.GetCurrentProcess() +th = win32security.OpenProcessToken(ph,win32security.TOKEN_ALL_ACCESS) ##win32con.TOKEN_ADJUST_PRIVILEGES) +win32security.AdjustTokenPrivileges(th,0,new_privs) +my_sid = win32security.GetTokenInformation(th,win32security.TokenUser)[0] +pwr_sid=win32security.LookupAccountName('','Power Users')[0] + +h=win32process.GetProcessWindowStation() +sd=win32security.GetUserObjectSecurity(h,info) +dacl=sd.GetSecurityDescriptorDacl() +ace_cnt=dacl.GetAceCount() + +dacl.AddAccessAllowedAce(dacl.GetAclRevision(),win32con.ACCESS_SYSTEM_SECURITY|win32con.WRITE_DAC,my_sid) +sd.SetSecurityDescriptorDacl(1,dacl,0) +sd.SetSecurityDescriptorGroup(pwr_sid,0) +sd.SetSecurityDescriptorOwner(pwr_sid,0) + +win32security.SetUserObjectSecurity(h,info,sd) +new_sd=win32security.GetUserObjectSecurity(h,info) +assert new_sd.GetSecurityDescriptorDacl().GetAceCount()==ace_cnt+1,'Did not add an ace to the Dacl !!!!!!' +assert win32security.LookupAccountSid('',new_sd.GetSecurityDescriptorOwner())[0]=='Power Users','Owner not successfully set to Power Users !!!!!' +assert win32security.LookupAccountSid('',new_sd.GetSecurityDescriptorGroup())[0]=='Power Users','Group not successfully set to Power Users !!!!!' + + diff --git a/Lib/site-packages/win32/Demos/security/sspi/fetch_url.py b/Lib/site-packages/win32/Demos/security/sspi/fetch_url.py new file mode 100644 index 0000000..26f4c4d --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/sspi/fetch_url.py @@ -0,0 +1,146 @@ +""" +Fetches a URL from a web-server supporting NTLM authentication +eg, IIS. + +If no arguments are specified, a default of http://localhost/localstart.asp +is used. This script does follow simple 302 redirections, so pointing at the +root of an IIS server is should work. +""" + +import sys +import urllib.request, urllib.parse, urllib.error +import http.client +import urllib.parse +from base64 import encodestring, decodestring + +from sspi import ClientAuth + +import optparse # sorry, this demo needs 2.3+ + +options = None # set to optparse options object + +def open_url(host, url): + h = http.client.HTTPConnection(host) +# h.set_debuglevel(9) + h.putrequest('GET', url) + h.endheaders() + resp = h.getresponse() + print("Initial response is", resp.status, resp.reason) + body = resp.read() + if resp.status == 302: # object moved + url = "/" + resp.msg["location"] + resp.close() + h.putrequest('GET', url) + h.endheaders() + resp = h.getresponse() + print("After redirect response is", resp.status, resp.reason) + if options.show_headers: + print("Initial response headers:") + for name, val in list(resp.msg.items()): + print(" %s: %s" % (name, val)) + if options.show_body: + print(body) + if resp.status == 401: + # 401: Unauthorized - here is where the real work starts + auth_info = None + if options.user or options.domain or options.password: + auth_info = options.user, options.domain, options.password + ca = ClientAuth("NTLM", auth_info=auth_info) + auth_scheme = ca.pkg_info['Name'] + data = None + while 1: + err, out_buf = ca.authorize(data) + data = out_buf[0].Buffer + # Encode it as base64 as required by HTTP + auth = encodestring(data).replace("\012", "") + h.putrequest('GET', url) + h.putheader('Authorization', auth_scheme + ' ' + auth) + h.putheader('Content-Length', '0') + h.endheaders() + resp = h.getresponse() + if options.show_headers: + print("Token dance headers:") + for name, val in list(resp.msg.items()): + print(" %s: %s" % (name, val)) + + if err==0: + break + else: + if resp.status != 401: + print("Eeek - got response", resp.status) + cl = resp.msg.get("content-length") + if cl: + print(repr(resp.read(int(cl)))) + else: + print("no content!") + + assert resp.status == 401, resp.status + + assert not resp.will_close, "NTLM is per-connection - must not close" + schemes = [s.strip() for s in resp.msg.get("WWW-Authenticate", "").split(",")] + for scheme in schemes: + if scheme.startswith(auth_scheme): + data = decodestring(scheme[len(auth_scheme)+1:]) + break + else: + print("Could not find scheme '%s' in schemes %r" % (auth_scheme, schemes)) + break + + resp.read() + print("Final response status is", resp.status, resp.reason) + if resp.status == 200: + # Worked! + # Check we can read it again without re-authenticating. + if resp.will_close: + print("EEEK - response will close, but NTLM is per connection - it must stay open") + body = resp.read() + if options.show_body: + print("Final response body:") + print(body) + h.putrequest('GET', url) + h.endheaders() + resp = h.getresponse() + print("Second fetch response is", resp.status, resp.reason) + if options.show_headers: + print("Second response headers:") + for name, val in list(resp.msg.items()): + print(" %s: %s" % (name, val)) + + resp.read(int(resp.msg.get("content-length", 0))) + elif resp.status == 500: + print("Error text") + print(resp.read()) + else: + if options.show_body: + cl = resp.msg.get("content-length") + print(resp.read(int(cl))) + +if __name__=='__main__': + parser = optparse.OptionParser(description=__doc__) + + parser.add_option("", "--show-body", action="store_true", + help="print the body of each response as it is received") + + parser.add_option("", "--show-headers", action="store_true", + help="print the headers of each response as it is received") + + parser.add_option("", "--user", action="store", + help="The username to login with") + + parser.add_option("", "--password", action="store", + help="The password to login with") + + parser.add_option("", "--domain", action="store", + help="The domain to login to") + + options, args = parser.parse_args() + if not args: + print("Run with --help for usage details") + args = ["http://localhost/localstart.asp"] + for url in args: + scheme, netloc, path, params, query, fragment = urllib.parse.urlparse(url) + if (scheme != "http") or params or query or fragment: + parser.error("Scheme must be http, URL must be simple") + + print("Opening '%s' from '%s'" % (path, netloc)) + r = open_url(netloc, path) diff --git a/Lib/site-packages/win32/Demos/security/sspi/simple_auth.py b/Lib/site-packages/win32/Demos/security/sspi/simple_auth.py new file mode 100644 index 0000000..7e52d5a --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/sspi/simple_auth.py @@ -0,0 +1,71 @@ +# A demo of basic SSPI authentication. +# There is a 'client' context and a 'server' context - typically these will +# be on different machines (here they are in the same process, but the same +# concepts apply) +import sspi +import win32security, sspicon, win32api + +def lookup_ret_code(err): + for k,v in list(sspicon.__dict__.items()): + if k[0:6] in ('SEC_I_','SEC_E_') and v==err: + return k + + +""" +pkg_name='Kerberos' +sspiclient=SSPIClient(pkg_name, win32api.GetUserName(), ## target spn is ourself + None, None, ## use none for client name and authentication information for current context + ## u'username', (u'username',u'domain.com',u'passwd'), + sspicon.ISC_REQ_INTEGRITY|sspicon.ISC_REQ_SEQUENCE_DETECT|sspicon.ISC_REQ_REPLAY_DETECT| \ + sspicon.ISC_REQ_DELEGATE|sspicon.ISC_REQ_CONFIDENTIALITY|sspicon.ISC_REQ_USE_SESSION_KEY) +sspiserver=SSPIServer(pkg_name, None, + sspicon.ASC_REQ_INTEGRITY|sspicon.ASC_REQ_SEQUENCE_DETECT|sspicon.ASC_REQ_REPLAY_DETECT| \ + sspicon.ASC_REQ_DELEGATE|sspicon.ASC_REQ_CONFIDENTIALITY|sspicon.ASC_REQ_STREAM|sspicon.ASC_REQ_USE_SESSION_KEY) +""" + +pkg_name='NTLM' + +# Setup the 2 contexts. +sspiclient=sspi.ClientAuth(pkg_name) +sspiserver=sspi.ServerAuth(pkg_name) + +# Perform the authentication dance, each loop exchanging more information +# on the way to completing authentication. +sec_buffer=None +while 1: + err, sec_buffer = sspiclient.authorize(sec_buffer) + err, sec_buffer = sspiserver.authorize(sec_buffer) + if err==0: + break + +# The server can now impersonate the client. In this demo the 2 users will +# always be the same. +sspiserver.ctxt.ImpersonateSecurityContext() +print('Impersonated user: ',win32api.GetUserNameEx(win32api.NameSamCompatible)) +sspiserver.ctxt.RevertSecurityContext() +print('Reverted to self: ',win32api.GetUserName()) + +pkg_size_info=sspiclient.ctxt.QueryContextAttributes(sspicon.SECPKG_ATTR_SIZES) +# Now sign some data +msg='some data to be encrypted ......' + +sigsize=pkg_size_info['MaxSignature'] +sigbuf=win32security.PySecBufferDescType() +sigbuf.append(win32security.PySecBufferType(len(msg), sspicon.SECBUFFER_DATA)) +sigbuf.append(win32security.PySecBufferType(sigsize, sspicon.SECBUFFER_TOKEN)) +sigbuf[0].Buffer=msg +sspiclient.ctxt.MakeSignature(0,sigbuf,1) +sspiserver.ctxt.VerifySignature(sigbuf,1) + +# And finally encrypt some. +trailersize=pkg_size_info['SecurityTrailer'] +encbuf=win32security.PySecBufferDescType() +encbuf.append(win32security.PySecBufferType(len(msg), sspicon.SECBUFFER_DATA)) +encbuf.append(win32security.PySecBufferType(trailersize, sspicon.SECBUFFER_TOKEN)) +encbuf[0].Buffer=msg +sspiclient.ctxt.EncryptMessage(0,encbuf,1) +print('Encrypted data:',repr(encbuf[0].Buffer)) +sspiserver.ctxt.DecryptMessage(encbuf,1) +print('Unencrypted data:',encbuf[0].Buffer) + + diff --git a/Lib/site-packages/win32/Demos/security/sspi/socket_server.py b/Lib/site-packages/win32/Demos/security/sspi/socket_server.py new file mode 100644 index 0000000..77d4649 --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/sspi/socket_server.py @@ -0,0 +1,178 @@ +"""A sample socket server and client using SSPI authentication and encryption. + +You must run with either 'client' or 'server' as arguments. A server must be +running before a client can connect. + +To use with Kerberos you should include in the client options +--target-spn=username, where 'username' is the user under which the server is +being run. + +Running either the client or server as a different user can be informative. +A command-line such as the following may be useful: +`runas /user:{user} {fqp}\python.exe {fqp}\socket_server.py --wait client|server` + +{fqp} should specify the relevant fully-qualified path names. + +To use 'runas' with Kerberos, the client program will need to +specify --target-spn with the username under which the *server* is running. + +See the SSPI documentation for more details. +""" + + +import sys +import struct +import socketserver +import win32api +import http.client +import traceback + +import win32security +import sspi, sspicon + +import optparse # sorry, this demo needs 2.3+ + +options = None # set to optparse object. + +def GetUserName(): + try: + return win32api.GetUserName() + except win32api.error as details: + # Seeing 'access denied' errors here for non-local users (presumably + # without permission to login locally). Get the fully-qualified + # username, although a side-effect of these permission-denied errors + # is a lack of Python codecs - so printing the Unicode value fails. + # So just return the repr(), and avoid codecs completely. + return repr(win32api.GetUserNameEx(win32api.NameSamCompatible)) + +# Send a simple "message" over a socket - send the number of bytes first, +# then the string. Ditto for receive. +def _send_msg(s, m): + s.send(struct.pack("i", len(m))) + s.send(m) + +def _get_msg(s): + size_data = s.recv(struct.calcsize("i")) + if not size_data: + return None + cb = struct.unpack("i", size_data)[0] + return s.recv(cb) + +class SSPISocketServer(socketserver.TCPServer): + def __init__(self, *args, **kw): + socketserver.TCPServer.__init__(self, *args, **kw) + self.sa = sspi.ServerAuth(options.package) + + def verify_request(self, sock, ca): + # Do the sspi auth dance + self.sa.reset() + while 1: + data = _get_msg(sock) + if data is None: + return False + try: + err, sec_buffer = self.sa.authorize(data) + except sspi.error as details: + print("FAILED to authorize client:", details) + return False + + if err==0: + break + _send_msg(sock, sec_buffer[0].Buffer) + return True + + def process_request(self, request, client_address): + # An example using the connection once it is established. + print("The server is running as user", GetUserName()) + self.sa.ctxt.ImpersonateSecurityContext() + try: + print("Having conversation with client as user", GetUserName()) + while 1: + # we need to grab 2 bits of data - the encrypted data, and the + # 'key' + data = _get_msg(request) + key = _get_msg(request) + if data is None or key is None: + break + data = self.sa.decrypt(data, key) + print("Client sent:", repr(data)) + finally: + self.sa.ctxt.RevertSecurityContext() + self.close_request(request) + print("The server is back to user", GetUserName()) + +def serve(): + s = SSPISocketServer(("localhost", options.port), None) + print("Running test server...") + s.serve_forever() + +def sspi_client(): + c = http.client.HTTPConnection("localhost", options.port) + c.connect() + # Do the auth dance. + ca = sspi.ClientAuth(options.package, targetspn=options.target_spn) + data = None + while 1: + err, out_buf = ca.authorize(data) + _send_msg(c.sock, out_buf[0].Buffer) + if err==0: + break + data = _get_msg(c.sock) + print("Auth dance complete - sending a few encryted messages") + # Assume out data is sensitive - encrypt the message. + for data in "Hello from the client".split(): + blob, key = ca.encrypt(data) + _send_msg(c.sock, blob) + _send_msg(c.sock, key) + c.sock.close() + print("Client completed.") + +if __name__=='__main__': + parser = optparse.OptionParser("%prog [options] client|server", + description=__doc__) + + parser.add_option("", "--package", action="store", default="NTLM", + help="The SSPI package to use (eg, Kerberos) - default is NTLM") + + parser.add_option("", "--target-spn", action="store", + help="""The target security provider name to use. The + string contents are security-package specific. For + example, 'Kerberos' or 'Negotiate' require the server + principal name (SPN) (ie, the username) of the remote + process. For NTLM this must be blank.""") + + parser.add_option("", "--port", action="store", default="8181", + help="The port number to use (default=8181)") + + parser.add_option("", "--wait", action="store_true", + help="""Cause the program to wait for input just before + terminating. Useful when using via runas to see + any error messages before termination. + """) + + options, args = parser.parse_args() + try: + options.port = int(options.port) + except (ValueError, TypeError): + parser.error("--port must be an integer") + + try: + try: + if not args: + args = [''] + if args[0]=="client": + sspi_client() + elif args[0]=="server": + serve() + else: + parser.error("You must supply 'client' or 'server' - " \ + "use --help for details") + except KeyboardInterrupt: + pass + except SystemExit: + pass + except: + traceback.print_exc() + finally: + if options.wait: + input("Press enter to continue") diff --git a/Lib/site-packages/win32/Demos/security/sspi/validate_password.py b/Lib/site-packages/win32/Demos/security/sspi/validate_password.py new file mode 100644 index 0000000..fc21e4c --- /dev/null +++ b/Lib/site-packages/win32/Demos/security/sspi/validate_password.py @@ -0,0 +1,38 @@ +# Demonstrates how to validate a password. +# See also MSKB article Q180548 +# +# To use with Kerberos you need to jump through the 'targetspn' hoops. + +import win32security +import sys +from sspi import ClientAuth, ServerAuth + +def validate(username, password, domain = ""): + auth_info = username, domain, password + ca = ClientAuth("NTLM", auth_info = auth_info) + sa = ServerAuth("NTLM") + + data = err = None + while err != 0: + err, data = ca.authorize(data) + err, data = sa.authorize(data) + # If we get here without exception, we worked! + +if __name__=='__main__': + if len(sys.argv) not in [2,3,4]: + print("Usage: %s username [password [domain]]" % (__file__,)) + sys.exit(1) + + # password and domain are optional! + password = None + if len(sys.argv)>=3: + password = sys.argv[2] + domain = "" + if len(sys.argv)>=4: + domain = sys.argv[3] + try: + validate(sys.argv[1], password, domain) + print("Validated OK") + except win32security.error as details: + hr, func, msg = details + print("Validation failed: %s (%d)" % (msg, hr)) diff --git a/Lib/site-packages/win32/Demos/service/nativePipeTestService.py b/Lib/site-packages/win32/Demos/service/nativePipeTestService.py new file mode 100644 index 0000000..b0a7a0c --- /dev/null +++ b/Lib/site-packages/win32/Demos/service/nativePipeTestService.py @@ -0,0 +1,56 @@ +# This is an example of a service hosted by python.exe rather than +# pythonservice.exe. + +# Note that it is very rare that using python.exe is a better option +# than the default pythonservice.exe - the latter has better error handling +# so that if Python itself can't be initialized or there are very early +# import errors, you will get error details written to the event log. When +# using python.exe instead, you are forced to wait for the interpreter startup +# and imports to succeed before you are able to effectively setup your own +# error handling. + +# So in short, please make sure you *really* want to do this, otherwise just +# stick with the default. + +import sys +import os +import win32serviceutil +import servicemanager + +from pipeTestService import TestPipeService + +class NativeTestPipeService(TestPipeService): + _svc_name_ = "PyNativePipeTestService" + _svc_display_name_ = "Python Native Pipe Test Service" + _svc_description_ = "Tests Python.exe hosted services" + # tell win32serviceutil we have a custom executable and custom args + # so registration does the right thing. + _exe_name_ = sys.executable + _exe_args_ = '"' + os.path.abspath(sys.argv[0]) + '"' + +def main(): + if len(sys.argv)==1: + # service must be starting... + # for the sake of debugging etc, we use win32traceutil to see + # any unhandled exceptions and print statements. + import win32traceutil + print("service is starting...") + print("(execute this script with '--help' if that isn't what you want)") + + servicemanager.Initialize() + servicemanager.PrepareToHostSingle(NativeTestPipeService) + # Now ask the service manager to fire things up for us... + servicemanager.StartServiceCtrlDispatcher() + print("service done!") + else: + win32serviceutil.HandleCommandLine(NativeTestPipeService) + +if __name__=='__main__': + try: + main() + except (SystemExit, KeyboardInterrupt): + raise + except: + print("Something went bad!") + import traceback + traceback.print_exc() diff --git a/Lib/site-packages/win32/Demos/service/pipeTestService.py b/Lib/site-packages/win32/Demos/service/pipeTestService.py new file mode 100644 index 0000000..3c8af2b --- /dev/null +++ b/Lib/site-packages/win32/Demos/service/pipeTestService.py @@ -0,0 +1,163 @@ +# A Demo of services and named pipes. + +# A multi-threaded service that simply echos back its input. + +# * Install as a service using "pipeTestService.py install" +# * Use Control Panel to change the user name of the service +# to a real user name (ie, NOT the SystemAccount) +# * Start the service. +# * Run the "pipeTestServiceClient.py" program as the client pipe side. + +import win32serviceutil, win32service +import pywintypes, win32con, winerror +# Use "import *" to keep this looking as much as a "normal" service +# as possible. Real code shouldn't do this. +from win32event import * +from win32file import * +from win32pipe import * +from win32api import * +from ntsecuritycon import * + +# Old versions of the service framework would not let you import this +# module at the top-level. Now you can, and can check 'Debugging()' and +# 'RunningAsService()' to check your context. +import servicemanager + +import traceback +import _thread + +def ApplyIgnoreError(fn, args): + try: + return fn(*args) + except error: # Ignore win32api errors. + return None + +class TestPipeService(win32serviceutil.ServiceFramework): + _svc_name_ = "PyPipeTestService" + _svc_display_name_ = "Python Pipe Test Service" + _svc_description_ = "Tests Python service framework by receiving and echoing messages over a named pipe" + + def __init__(self, args): + win32serviceutil.ServiceFramework.__init__(self, args) + self.hWaitStop = CreateEvent(None, 0, 0, None) + self.overlapped = pywintypes.OVERLAPPED() + self.overlapped.hEvent = CreateEvent(None,0,0,None) + self.thread_handles = [] + + def CreatePipeSecurityObject(self): + # Create a security object giving World read/write access, + # but only "Owner" modify access. + sa = pywintypes.SECURITY_ATTRIBUTES() + sidEveryone = pywintypes.SID() + sidEveryone.Initialize(SECURITY_WORLD_SID_AUTHORITY,1) + sidEveryone.SetSubAuthority(0, SECURITY_WORLD_RID) + sidCreator = pywintypes.SID() + sidCreator.Initialize(SECURITY_CREATOR_SID_AUTHORITY,1) + sidCreator.SetSubAuthority(0, SECURITY_CREATOR_OWNER_RID) + + acl = pywintypes.ACL() + acl.AddAccessAllowedAce(FILE_GENERIC_READ|FILE_GENERIC_WRITE, sidEveryone) + acl.AddAccessAllowedAce(FILE_ALL_ACCESS, sidCreator) + + sa.SetSecurityDescriptorDacl(1, acl, 0) + return sa + + # The functions executed in their own thread to process a client request. + def DoProcessClient(self, pipeHandle, tid): + try: + try: + # Create a loop, reading large data. If we knew the data stream was + # was small, a simple ReadFile would do. + d = ''.encode('ascii') # ensure bytes on py2k and py3k... + hr = winerror.ERROR_MORE_DATA + while hr==winerror.ERROR_MORE_DATA: + hr, thisd = ReadFile(pipeHandle, 256) + d = d + thisd + print("Read", d) + ok = 1 + except error: + # Client disconnection - do nothing + ok = 0 + + # A secure service would handle (and ignore!) errors writing to the + # pipe, but for the sake of this demo we dont (if only to see what errors + # we can get when our clients break at strange times :-) + if ok: + msg = ("%s (on thread %d) sent me %s" % (GetNamedPipeHandleState(pipeHandle)[4],tid, d)).encode('ascii') + WriteFile(pipeHandle, msg) + finally: + ApplyIgnoreError( DisconnectNamedPipe, (pipeHandle,) ) + ApplyIgnoreError( CloseHandle, (pipeHandle,) ) + + def ProcessClient(self, pipeHandle): + try: + procHandle = GetCurrentProcess() + th = DuplicateHandle(procHandle, GetCurrentThread(), procHandle, 0, 0, win32con.DUPLICATE_SAME_ACCESS) + try: + self.thread_handles.append(th) + try: + return self.DoProcessClient(pipeHandle, th) + except: + traceback.print_exc() + finally: + self.thread_handles.remove(th) + except: + traceback.print_exc() + + def SvcStop(self): + self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) + SetEvent(self.hWaitStop) + + def SvcDoRun(self): + # Write an event log record - in debug mode we will also + # see this message printed. + servicemanager.LogMsg( + servicemanager.EVENTLOG_INFORMATION_TYPE, + servicemanager.PYS_SERVICE_STARTED, + (self._svc_name_, '') + ) + + num_connections = 0 + while 1: + pipeHandle = CreateNamedPipe("\\\\.\\pipe\\PyPipeTest", + PIPE_ACCESS_DUPLEX| FILE_FLAG_OVERLAPPED, + PIPE_TYPE_MESSAGE | PIPE_READMODE_BYTE, + PIPE_UNLIMITED_INSTANCES, # max instances + 0, 0, 6000, + self.CreatePipeSecurityObject()) + try: + hr = ConnectNamedPipe(pipeHandle, self.overlapped) + except error as details: + print("Error connecting pipe!", details) + CloseHandle(pipeHandle) + break + if hr==winerror.ERROR_PIPE_CONNECTED: + # Client is already connected - signal event + SetEvent(self.overlapped.hEvent) + rc = WaitForMultipleObjects((self.hWaitStop, self.overlapped.hEvent), 0, INFINITE) + if rc==WAIT_OBJECT_0: + # Stop event + break + else: + # Pipe event - spawn thread to deal with it. + _thread.start_new_thread(self.ProcessClient, (pipeHandle,)) + num_connections = num_connections + 1 + + # Sleep to ensure that any new threads are in the list, and then + # wait for all current threads to finish. + # What is a better way? + Sleep(500) + while self.thread_handles: + self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING, 5000) + print("Waiting for %d threads to finish..." % (len(self.thread_handles))) + WaitForMultipleObjects(self.thread_handles, 1, 3000) + # Write another event log record. + servicemanager.LogMsg( + servicemanager.EVENTLOG_INFORMATION_TYPE, + servicemanager.PYS_SERVICE_STOPPED, + (self._svc_name_, " after processing %d connections" % (num_connections,)) + ) + + +if __name__=='__main__': + win32serviceutil.HandleCommandLine(TestPipeService) diff --git a/Lib/site-packages/win32/Demos/service/pipeTestServiceClient.py b/Lib/site-packages/win32/Demos/service/pipeTestServiceClient.py new file mode 100644 index 0000000..f86fdd6 --- /dev/null +++ b/Lib/site-packages/win32/Demos/service/pipeTestServiceClient.py @@ -0,0 +1,121 @@ +# A Test Program for pipeTestService.py +# +# Install and start the Pipe Test service, then run this test +# either from the same machine, or from another using the "-s" param. +# +# Eg: pipeTestServiceClient.py -s server_name Hi There +# Should work. + +from win32pipe import * +from win32file import * +from win32event import * +import pywintypes +import win32api +import winerror +import sys, os, traceback + +verbose = 0 + +#def ReadFromPipe(pipeName): + # Could (Should?) use CallNamedPipe, but this technique allows variable size + # messages (whereas you must supply a buffer size for CallNamedPipe! +# hPipe = CreateFile(pipeName, GENERIC_WRITE, 0, None, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) +# more = 1 +# while more: +# hr = ReadFile(hPipe, 256) +# if hr==0: +# more = 0 +# except win32api.error (hr, fn, desc): +# if hr==winerror.ERROR_MORE_DATA: +# data = dat +# + +def CallPipe(fn, args): + ret = None + retryCount = 0 + while retryCount < 8: # Keep looping until user cancels. + retryCount = retryCount + 1 + try: + return fn(*args) + except win32api.error as exc: + if exc.winerror==winerror.ERROR_PIPE_BUSY: + win32api.Sleep(5000) + continue + else: + raise + + raise RuntimeError("Could not make a connection to the server") + +def testClient(server,msg): + if verbose: + print("Sending", msg) + data = CallPipe(CallNamedPipe, ("\\\\%s\\pipe\\PyPipeTest" % server, msg, 256, NMPWAIT_WAIT_FOREVER)) + if verbose: + print("Server sent back '%s'" % data) + print("Sent and received a message!") + +def testLargeMessage(server, size = 4096): + if verbose: + print("Sending message of size %d" % (size)) + msg = "*" * size + data = CallPipe(CallNamedPipe, ("\\\\%s\\pipe\\PyPipeTest" % server, msg, 512, NMPWAIT_WAIT_FOREVER)) + if len(data)-size: + print("Sizes are all wrong - send %d, got back %d" % (size, len(data))) + +def stressThread(server, numMessages, wait): + try: + try: + for i in range(numMessages): + r = CallPipe(CallNamedPipe, ("\\\\%s\\pipe\\PyPipeTest" % server, "#" * 512, 1024, NMPWAIT_WAIT_FOREVER)) + except: + traceback.print_exc() + print("Failed after %d messages" % i) + finally: + SetEvent(wait) + +def stressTestClient(server, numThreads, numMessages): + import _thread + thread_waits = [] + for t_num in range(numThreads): + # Note I could just wait on thread handles (after calling DuplicateHandle) + # See the service itself for an example of waiting for the clients... + wait = CreateEvent(None, 0, 0, None) + thread_waits.append(wait) + _thread.start_new_thread(stressThread, (server,numMessages, wait)) + # Wait for all threads to finish. + WaitForMultipleObjects(thread_waits, 1, INFINITE) + +def main(): + import sys, getopt + server = "." + thread_count = 0 + msg_count = 500 + try: + opts, args = getopt.getopt(sys.argv[1:], 's:t:m:vl') + for o,a in opts: + if o=='-s': + server = a + if o=='-m': + msg_count = int(a) + if o=='-t': + thread_count = int(a) + if o=='-v': + global verbose + verbose = 1 + if o=='-l': + testLargeMessage(server) + msg = " ".join(args).encode("mbcs") + except getopt.error as msg: + print(msg) + my_name = os.path.split(sys.argv[0])[1] + print("Usage: %s [-v] [-s server] [-t thread_count=0] [-m msg_count=500] msg ..." % my_name) + print(" -v = verbose") + print(" Specifying a value for -t will stress test using that many threads.") + return + testClient(server, msg) + if thread_count > 0: + print("Spawning %d threads each sending %d messages..." % (thread_count, msg_count)) + stressTestClient(server, thread_count, msg_count) + +if __name__=='__main__': + main() diff --git a/Lib/site-packages/win32/Demos/service/serviceEvents.py b/Lib/site-packages/win32/Demos/service/serviceEvents.py new file mode 100644 index 0000000..63e7670 --- /dev/null +++ b/Lib/site-packages/win32/Demos/service/serviceEvents.py @@ -0,0 +1,88 @@ +# A Demo of a service that takes advantage of the additional notifications +# available in later Windows versions. + +# Note that all output is written as event log entries - so you must install +# and start the service, then look at the event log for messages as events +# are generated. + +# Events are generated for USB device insertion and removal, power state +# changes and hardware profile events - so try putting your computer to +# sleep and waking it, inserting a memory stick, etc then check the event log + +import win32serviceutil, win32service +import win32event +import servicemanager + +# Most event notification support lives around win32gui +import win32gui, win32gui_struct, win32con +GUID_DEVINTERFACE_USB_DEVICE = "{A5DCBF10-6530-11D2-901F-00C04FB951ED}" + +class EventDemoService(win32serviceutil.ServiceFramework): + _svc_name_ = "PyServiceEventDemo" + _svc_display_name_ = "Python Service Event Demo" + _svc_description_ = "Demonstrates a Python service which takes advantage of the extra notifications" + + def __init__(self, args): + win32serviceutil.ServiceFramework.__init__(self, args) + self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) + # register for a device notification - we pass our service handle + # instead of a window handle. + filter = win32gui_struct.PackDEV_BROADCAST_DEVICEINTERFACE( + GUID_DEVINTERFACE_USB_DEVICE) + self.hdn = win32gui.RegisterDeviceNotification(self.ssh, filter, + win32con.DEVICE_NOTIFY_SERVICE_HANDLE) + + # Override the base class so we can accept additional events. + def GetAcceptedControls(self): + # say we accept them all. + rc = win32serviceutil.ServiceFramework.GetAcceptedControls(self) + rc |= win32service.SERVICE_ACCEPT_PARAMCHANGE \ + | win32service.SERVICE_ACCEPT_NETBINDCHANGE \ + | win32service.SERVICE_CONTROL_DEVICEEVENT \ + | win32service.SERVICE_ACCEPT_HARDWAREPROFILECHANGE \ + | win32service.SERVICE_ACCEPT_POWEREVENT \ + | win32service.SERVICE_ACCEPT_SESSIONCHANGE + return rc + + # All extra events are sent via SvcOtherEx (SvcOther remains as a + # function taking only the first args for backwards compat) + def SvcOtherEx(self, control, event_type, data): + # This is only showing a few of the extra events - see the MSDN + # docs for "HandlerEx callback" for more info. + if control == win32service.SERVICE_CONTROL_DEVICEEVENT: + info = win32gui_struct.UnpackDEV_BROADCAST(data) + msg = "A device event occurred: %x - %s" % (event_type, info) + elif control == win32service.SERVICE_CONTROL_HARDWAREPROFILECHANGE: + msg = "A hardware profile changed: type=%s, data=%s" % (event_type, data) + elif control == win32service.SERVICE_CONTROL_POWEREVENT: + msg = "A power event: setting %s" % data + elif control == win32service.SERVICE_CONTROL_SESSIONCHANGE: + # data is a single elt tuple, but this could potentially grow + # in the future if the win32 struct does + msg = "Session event: type=%s, data=%s" % (event_type, data) + else: + msg = "Other event: code=%d, type=%s, data=%s" \ + % (control, event_type, data) + + servicemanager.LogMsg( + servicemanager.EVENTLOG_INFORMATION_TYPE, + 0xF000, # generic message + (msg, '') + ) + + def SvcStop(self): + self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) + win32event.SetEvent(self.hWaitStop) + + def SvcDoRun(self): + # do nothing at all - just wait to be stopped + win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE) + # Write a stop message. + servicemanager.LogMsg( + servicemanager.EVENTLOG_INFORMATION_TYPE, + servicemanager.PYS_SERVICE_STOPPED, + (self._svc_name_, '') + ) + +if __name__=='__main__': + win32serviceutil.HandleCommandLine(EventDemoService) diff --git a/Lib/site-packages/win32/Demos/timer_demo.py b/Lib/site-packages/win32/Demos/timer_demo.py new file mode 100644 index 0000000..72ebcef --- /dev/null +++ b/Lib/site-packages/win32/Demos/timer_demo.py @@ -0,0 +1,68 @@ +# -*- Mode: Python; tab-width: 4 -*- +# + +# This module, and the timer.pyd core timer support, were written by +# Sam Rushing (rushing@nightmare.com) + +import timer +import time + +# Timers are based on Windows messages. So we need +# to do the event-loop thing! +import win32event, win32gui + +# glork holds a simple counter for us. + +class glork: + + def __init__ (self, delay=1000, max=10): + self.x = 0 + self.max = max + self.id = timer.set_timer (delay, self.increment) + # Could use the threading module, but this is + # a win32 extension test after all! :-) + self.event = win32event.CreateEvent(None, 0, 0, None) + + def increment (self, id, time): + print('x = %d' % self.x) + self.x = self.x + 1 + # if we've reached the max count, + # kill off the timer. + if self.x > self.max: + # we could have used 'self.id' here, too + timer.kill_timer (id) + win32event.SetEvent(self.event) + +# create a counter that will count from '1' thru '10', incrementing +# once a second, and then stop. + +def demo (delay=1000, stop=10): + g = glork(delay, stop) + # Timers are message based - so we need + # To run a message loop while waiting for our timers + # to expire. + start_time = time.time() + while 1: + # We can't simply give a timeout of 30 seconds, as + # we may continouusly be recieving other input messages, + # and therefore never expire. + rc = win32event.MsgWaitForMultipleObjects( + (g.event,), # list of objects + 0, # wait all + 500, # timeout + win32event.QS_ALLEVENTS, # type of input + ) + if rc == win32event.WAIT_OBJECT_0: + # Event signalled. + break + elif rc == win32event.WAIT_OBJECT_0+1: + # Message waiting. + if win32gui.PumpWaitingMessages(): + raise RuntimeError("We got an unexpected WM_QUIT message!") + else: + # This wait timed-out. + if time.time()-start_time > 30: + raise RuntimeError("We timed out waiting for the timers to expire!") + +if __name__=='__main__': + demo() diff --git a/Lib/site-packages/win32/Demos/win32clipboardDemo.py b/Lib/site-packages/win32/Demos/win32clipboardDemo.py new file mode 100644 index 0000000..11fcc63 --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32clipboardDemo.py @@ -0,0 +1,134 @@ +# win32clipboardDemo.py +# +# Demo/test of the win32clipboard module. +from win32clipboard import * +from pywin32_testutil import str2bytes # py3k-friendly helper +import win32con +import types + +if not __debug__: + print("WARNING: The test code in this module uses assert") + print("This instance of Python has asserts disabled, so many tests will be skipped") + +cf_names = {} +# Build map of CF_* constants to names. +for name, val in list(win32con.__dict__.items()): + if name[:3]=="CF_" and name != "CF_SCREENFONTS": # CF_SCREEN_FONTS==CF_TEXT!?!? + cf_names[val] = name + +def TestEmptyClipboard(): + OpenClipboard() + try: + EmptyClipboard() + assert EnumClipboardFormats(0)==0, "Clipboard formats were available after emptying it!" + finally: + CloseClipboard() + +def TestText(): + OpenClipboard() + try: + text = "Hello from Python" + text_bytes = str2bytes(text) + SetClipboardText(text) + got = GetClipboardData(win32con.CF_TEXT) + # CF_TEXT always gives us 'bytes' back . + assert got == text_bytes, "Didnt get the correct result back - '%r'." % (got,) + finally: + CloseClipboard() + + OpenClipboard() + try: + # CF_UNICODE text always gives unicode objects back. + got = GetClipboardData(win32con.CF_UNICODETEXT) + assert got == text, "Didnt get the correct result back - '%r'." % (got,) + assert type(got)==str, "Didnt get the correct result back - '%r'." % (got,) + + # CF_OEMTEXT is a bytes-based format. + got = GetClipboardData(win32con.CF_OEMTEXT) + assert got == text_bytes, "Didnt get the correct result back - '%r'." % (got,) + + # Unicode tests + EmptyClipboard() + text = "Hello from Python unicode" + text_bytes = str2bytes(text) + # Now set the Unicode value + SetClipboardData(win32con.CF_UNICODETEXT, text) + # Get it in Unicode. + got = GetClipboardData(win32con.CF_UNICODETEXT) + assert got == text, "Didnt get the correct result back - '%r'." % (got,) + assert type(got)==str, "Didnt get the correct result back - '%r'." % (got,) + + # Close and open the clipboard to ensure auto-conversions take place. + finally: + CloseClipboard() + + OpenClipboard() + try: + + # Make sure I can still get the text as bytes + got = GetClipboardData(win32con.CF_TEXT) + assert got == text_bytes, "Didnt get the correct result back - '%r'." % (got,) + # Make sure we get back the correct types. + got = GetClipboardData(win32con.CF_UNICODETEXT) + assert type(got)==str, "Didnt get the correct result back - '%r'." % (got,) + got = GetClipboardData(win32con.CF_OEMTEXT) + assert got == text_bytes, "Didnt get the correct result back - '%r'." % (got,) + print("Clipboard text tests worked correctly") + finally: + CloseClipboard() + +def TestClipboardEnum(): + OpenClipboard() + try: + # Enumerate over the clipboard types + enum = 0 + while 1: + enum = EnumClipboardFormats(enum) + if enum==0: + break + assert IsClipboardFormatAvailable(enum), "Have format, but clipboard says it is not available!" + n = cf_names.get(enum,"") + if not n: + try: + n = GetClipboardFormatName(enum) + except error: + n = "unknown (%s)" % (enum,) + + print("Have format", n) + print("Clipboard enumerator tests worked correctly") + finally: + CloseClipboard() + +class Foo: + def __init__(self, **kw): + self.__dict__.update(kw) + def __cmp__(self, other): + return cmp(self.__dict__, other.__dict__) + def __eq__(self, other): + return self.__dict__==other.__dict__ + +def TestCustomFormat(): + OpenClipboard() + try: + # Just for the fun of it pickle Python objects through the clipboard + fmt = RegisterClipboardFormat("Python Pickle Format") + import pickle + pickled_object = Foo(a=1, b=2, Hi=3) + SetClipboardData(fmt, pickle.dumps( pickled_object ) ) + # Now read it back. + data = GetClipboardData(fmt) + loaded_object = pickle.loads(data) + assert pickle.loads(data) == pickled_object, "Didnt get the correct data!" + + print("Clipboard custom format tests worked correctly") + finally: + CloseClipboard() + + +if __name__=='__main__': + TestEmptyClipboard() + TestText() + TestCustomFormat() + TestClipboardEnum() + # And leave it empty at the end! + TestEmptyClipboard() diff --git a/Lib/site-packages/win32/Demos/win32clipboard_bitmapdemo.py b/Lib/site-packages/win32/Demos/win32clipboard_bitmapdemo.py new file mode 100644 index 0000000..9cb621a --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32clipboard_bitmapdemo.py @@ -0,0 +1,85 @@ +import win32gui +import win32api +import win32clipboard +import win32con +import time + +class ViewerWindow: + def __init__(self): + self.hwndNextViewer = None + + def OnPaint(self, hwnd, msg, wp, lp): + dc, ps=win32gui.BeginPaint(hwnd) + wndrect = win32gui.GetClientRect(hwnd) + wndwidth = wndrect[2]-wndrect[0] + wndheight = wndrect[3]-wndrect[1] + win32clipboard.OpenClipboard() + try: + try: + hbitmap = win32clipboard.GetClipboardData(win32clipboard.CF_BITMAP) + except TypeError: + font=win32gui.LOGFONT() + font.lfHeight=15 #int(wndheight/20) + font.lfWidth=15 #font.lfHeight + # font.lfWeight=150 + hf=win32gui.CreateFontIndirect(font) + win32gui.SelectObject(dc,hf) + win32gui.SetBkMode(dc, win32con.TRANSPARENT) + win32gui.SetTextColor(dc,win32api.RGB(0,0,0)) + win32gui.DrawText(dc,'No bitmaps are in the clipboard\n(try pressing the PrtScn button)', -1, + (0,0, wndwidth, wndheight), + win32con.DT_CENTER) + else: + bminfo = win32gui.GetObject(hbitmap) + dcDC = win32gui.CreateCompatibleDC(None) + win32gui.SelectObject(dcDC, hbitmap) + win32gui.StretchBlt(dc, 0, 0, wndwidth, wndheight, dcDC, 0, 0, bminfo.bmWidth, bminfo.bmHeight, win32con.SRCCOPY) + win32gui.DeleteDC(dcDC) + win32gui.EndPaint(hwnd, ps) + finally: + win32clipboard.CloseClipboard() + return 0 + + def OnDrawClipboard(self, hwnd, msg, wp, lp): + win32gui.InvalidateRect(hwnd,None,True) + + def OnChangeCBChain(self, hwnd, msg, wp, lp): + # If the next window is closing, repair the chain. + if wp == self.hwndNextViewer: + self.hwndNextViewer = lp + # Otherwise, pass the message to the next link. + elif self.hwndNextViewer: + win32gui.SendMessage(self.hwndNextViewer, msg, wp, lp) + + def OnCreate(self, hwnd, msg, wp, lp): + self.hwndNextViewer = win32gui.SetClipboardViewer(hwnd); + + def OnClose(self, hwnd, msg, wp, lp): + win32clipboard.ChangeClipboardChain(hwnd, self.hwndNextViewer) + win32gui.DestroyWindow(hwnd) + win32gui.PostQuitMessage(0) + + def go(self): + wndproc={win32con.WM_PAINT: self.OnPaint, + win32con.WM_CLOSE: self.OnClose, + win32con.WM_CREATE: self.OnCreate, + win32con.WM_DRAWCLIPBOARD: self.OnDrawClipboard, + win32con.WM_CHANGECBCHAIN: self.OnChangeCBChain, + } + + wc = win32gui.WNDCLASS() + wc.lpszClassName = 'test_win32clipboard_bmp' + wc.style = win32con.CS_GLOBALCLASS|win32con.CS_VREDRAW | win32con.CS_HREDRAW + wc.hbrBackground = win32con.COLOR_WINDOW+1 + wc.lpfnWndProc=wndproc + class_atom=win32gui.RegisterClass(wc) + hwnd = win32gui.CreateWindowEx(0, class_atom,'ClipboardViewer', + win32con.WS_CAPTION|win32con.WS_VISIBLE|win32con.WS_THICKFRAME|win32con.WS_SYSMENU, + 100,100,900,900, 0, 0, 0, None) + win32clipboard.SetClipboardViewer(hwnd) + win32gui.PumpMessages() + win32gui.UnregisterClass(class_atom,None) + +if __name__=='__main__': + w = ViewerWindow() + w.go() diff --git a/Lib/site-packages/win32/Demos/win32comport_demo.py b/Lib/site-packages/win32/Demos/win32comport_demo.py new file mode 100644 index 0000000..d74d7db --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32comport_demo.py @@ -0,0 +1,133 @@ +# This is a simple serial port terminal demo. +# +# Its primary purpose is to demonstrate the native serial port access offered via +# win32file. + +# It uses 3 threads: +# - The main thread, which cranks up the other 2 threads, then simply waits for them to exit. +# - The user-input thread - blocks waiting for a keyboard character, and when found sends it +# out the COM port. If the character is Ctrl+C, it stops, signalling the COM port thread to stop. +# - The COM port thread is simply listening for input on the COM port, and prints it to the screen. + +# This demo uses userlapped IO, so that none of the read or write operations actually block (however, +# in this sample, the very next thing we do _is_ block - so it shows off the concepts even though it +# doesnt exploit them. + +from win32file import * # The base COM port and file IO functions. +from win32event import * # We use events and the WaitFor[Multiple]Objects functions. +import win32con # constants. +import msvcrt # For the getch() function. + +import threading +import sys + +def FindModem(): + # Snoop over the comports, seeing if it is likely we have a modem. + for i in range(1,5): + port = "COM%d" % (i,) + try: + handle = CreateFile(port, + win32con.GENERIC_READ | win32con.GENERIC_WRITE, + 0, # exclusive access + None, # no security + win32con.OPEN_EXISTING, + win32con.FILE_ATTRIBUTE_NORMAL, + None) + # It appears that an available COM port will always success here, + # just return 0 for the status flags. We only care that it has _any_ status + # flags (and therefore probably a real modem) + if GetCommModemStatus(handle) != 0: + return port + except error: + pass # No port, or modem status failed. + return None + +# A basic synchronous COM port file-like object +class SerialTTY: + def __init__(self, port): + if type(port)==type(0): + port = "COM%d" % (port,) + self.handle = CreateFile(port, + win32con.GENERIC_READ | win32con.GENERIC_WRITE, + 0, # exclusive access + None, # no security + win32con.OPEN_EXISTING, + win32con.FILE_ATTRIBUTE_NORMAL | win32con.FILE_FLAG_OVERLAPPED, + None) + # Tell the port we want a notification on each char. + SetCommMask(self.handle, EV_RXCHAR) + # Setup a 4k buffer + SetupComm(self.handle, 4096, 4096) + # Remove anything that was there + PurgeComm(self.handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) + # Setup for overlapped IO. + timeouts = 0xFFFFFFFF, 0, 1000, 0, 1000 + SetCommTimeouts(self.handle, timeouts) + # Setup the connection info. + dcb = GetCommState( self.handle ) + dcb.BaudRate = CBR_115200 + dcb.ByteSize = 8 + dcb.Parity = NOPARITY + dcb.StopBits = ONESTOPBIT + SetCommState(self.handle, dcb) + print("Connected to %s at %s baud" % (port, dcb.BaudRate)) + + def _UserInputReaderThread(self): + overlapped = OVERLAPPED() + overlapped.hEvent = CreateEvent(None, 1, 0, None) + try: + while 1: + ch = msvcrt.getch() + if ord(ch)==3: + break + WriteFile(self.handle, ch, overlapped) + # Wait for the write to complete. + WaitForSingleObject(overlapped.hEvent, INFINITE) + finally: + SetEvent(self.eventStop) + + def _ComPortThread(self): + overlapped = OVERLAPPED() + overlapped.hEvent = CreateEvent(None, 1, 0, None) + while 1: + # XXX - note we could _probably_ just use overlapped IO on the win32file.ReadFile() statement + # XXX but this tests the COM stuff! + rc, mask = WaitCommEvent(self.handle, overlapped) + if rc == 0: # Character already ready! + SetEvent(overlapped.hEvent) + rc = WaitForMultipleObjects([overlapped.hEvent, self.eventStop], 0, INFINITE) + if rc == WAIT_OBJECT_0: + # Some input - read and print it + flags, comstat = ClearCommError( self.handle ) + rc, data = ReadFile(self.handle, comstat.cbInQue, overlapped) + WaitForSingleObject(overlapped.hEvent, INFINITE) + sys.stdout.write(data) + else: + # Stop the thread! + # Just incase the user input thread uis still going, close it + sys.stdout.close() + break + + def Run(self): + self.eventStop = CreateEvent(None, 0, 0, None) + # Start the reader and writer threads. + user_thread = threading.Thread(target = self._UserInputReaderThread) + user_thread.start() + com_thread = threading.Thread(target = self._ComPortThread) + com_thread.start() + user_thread.join() + com_thread.join() + +if __name__=='__main__': + print("Serial port terminal demo - press Ctrl+C to exit") + if len(sys.argv)<=1: + port = FindModem() + if port is None: + print("No COM port specified, and no modem could be found") + print("Please re-run this script with the name of a COM port (eg COM3)") + sys.exit(1) + else: + port = sys.argv[1] + + tty = SerialTTY(port) + tty.Run() diff --git a/Lib/site-packages/win32/Demos/win32console_demo.py b/Lib/site-packages/win32/Demos/win32console_demo.py new file mode 100644 index 0000000..568a2a0 --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32console_demo.py @@ -0,0 +1,103 @@ +import win32console, win32con +import traceback, time + +virtual_keys={} +for k,v in list(win32con.__dict__.items()): + if k.startswith('VK_'): + virtual_keys[v]=k + +free_console=True +try: + win32console.AllocConsole() +except win32console.error as exc: + if exc.winerror!=5: + raise + ## only free console if one was created successfully + free_console=False + +stdout=win32console.GetStdHandle(win32console.STD_OUTPUT_HANDLE) +stdin=win32console.GetStdHandle(win32console.STD_INPUT_HANDLE) +newbuffer=win32console.CreateConsoleScreenBuffer() +newbuffer.SetConsoleActiveScreenBuffer() +newbuffer.SetConsoleTextAttribute(win32console.FOREGROUND_RED|win32console.FOREGROUND_INTENSITY + |win32console.BACKGROUND_GREEN|win32console.BACKGROUND_INTENSITY) +newbuffer.WriteConsole('This is a new screen buffer\n') + +## test setting screen buffer and window size +## screen buffer size cannot be smaller than window size +window_size=newbuffer.GetConsoleScreenBufferInfo()['Window'] +coord=win32console.PyCOORDType(X=window_size.Right+20, Y=window_size.Bottom+20) +newbuffer.SetConsoleScreenBufferSize(coord) + +window_size.Right+=10 +window_size.Bottom+=10 +newbuffer.SetConsoleWindowInfo(Absolute=True,ConsoleWindow=window_size) + +## write some records to the input queue +x=win32console.PyINPUT_RECORDType(win32console.KEY_EVENT) +x.Char='X' +x.KeyDown=True +x.RepeatCount=1 +x.VirtualKeyCode=0x58 +x.ControlKeyState=win32con.SHIFT_PRESSED + +z=win32console.PyINPUT_RECORDType(win32console.KEY_EVENT) +z.Char='Z' +z.KeyDown=True +z.RepeatCount=1 +z.VirtualKeyCode=0x5a +z.ControlKeyState=win32con.SHIFT_PRESSED + +stdin.WriteConsoleInput([x,z,x]) + +newbuffer.SetConsoleTextAttribute(win32console.FOREGROUND_RED|win32console.FOREGROUND_INTENSITY + |win32console.BACKGROUND_GREEN|win32console.BACKGROUND_INTENSITY) +newbuffer.WriteConsole('Press some keys, click some characters with the mouse\n') + +newbuffer.SetConsoleTextAttribute(win32console.FOREGROUND_BLUE|win32console.FOREGROUND_INTENSITY + |win32console.BACKGROUND_RED|win32console.BACKGROUND_INTENSITY) +newbuffer.WriteConsole('Hit "End" key to quit\n') + +breakout=False +while not breakout: + input_records=stdin.ReadConsoleInput(10) + for input_record in input_records: + if input_record.EventType==win32console.KEY_EVENT: + if input_record.KeyDown: + if input_record.Char=='\0': + newbuffer.WriteConsole(virtual_keys.get(input_record.VirtualKeyCode, 'VirtualKeyCode: %s' %input_record.VirtualKeyCode)) + else: + newbuffer.WriteConsole(input_record.Char) + if input_record.VirtualKeyCode==win32con.VK_END: + breakout=True + break + elif input_record.EventType==win32console.MOUSE_EVENT: + if input_record.EventFlags==0: ## 0 indicates a button event + if input_record.ButtonState!=0: ## exclude button releases + pos=input_record.MousePosition + # switch the foreground and background colors of the character that was clicked + attr=newbuffer.ReadConsoleOutputAttribute(Length=1, ReadCoord=pos)[0] + new_attr=attr + if attr&win32console.FOREGROUND_BLUE: + new_attr=(new_attr&~win32console.FOREGROUND_BLUE)|win32console.BACKGROUND_BLUE + if attr&win32console.FOREGROUND_RED: + new_attr=(new_attr&~win32console.FOREGROUND_RED)|win32console.BACKGROUND_RED + if attr&win32console.FOREGROUND_GREEN: + new_attr=(new_attr&~win32console.FOREGROUND_GREEN)|win32console.BACKGROUND_GREEN + + if attr&win32console.BACKGROUND_BLUE: + new_attr=(new_attr&~win32console.BACKGROUND_BLUE)|win32console.FOREGROUND_BLUE + if attr&win32console.BACKGROUND_RED: + new_attr=(new_attr&~win32console.BACKGROUND_RED)|win32console.FOREGROUND_RED + if attr&win32console.BACKGROUND_GREEN: + new_attr=(new_attr&~win32console.BACKGROUND_GREEN)|win32console.FOREGROUND_GREEN + newbuffer.WriteConsoleOutputAttribute((new_attr,),pos) + else: + newbuffer.WriteConsole(str(input_record)) + time.sleep(0.1) + +stdout.SetConsoleActiveScreenBuffer() +newbuffer.Close() +if free_console: + win32console.FreeConsole() + diff --git a/Lib/site-packages/win32/Demos/win32cred_demo.py b/Lib/site-packages/win32/Demos/win32cred_demo.py new file mode 100644 index 0000000..1f2658c --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32cred_demo.py @@ -0,0 +1,52 @@ +""" +Demonstrates prompting for credentials, saving, and loggging on with marshalled credential. +Also shows how to load user's profile +""" + +import win32net, win32security, win32api, win32con +import win32profile, win32cred + +## Prompt for a username/pwd for local computer +uiinfo={'MessageText':'Enter credentials for local machine','CaptionText':'win32cred_demo.py'} +target, pwd, save=win32cred.CredUIPromptForCredentials(TargetName=win32api.GetComputerName(), AuthError=0, + Flags=win32cred.CREDUI_FLAGS_DO_NOT_PERSIST|win32cred.CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX, + Save=False, UiInfo=uiinfo) + +attrs=[ + {'Keyword':'attr1', 'Flags':0, 'Value':'unicode data'}, + {'Keyword':'attr2', 'Flags':0, 'Value':'character data'} + ] +cred={'Comment':'Created by win32cred_demo.py', 'UserName':target, 'TargetAlias': None, + 'TargetName':target,'CredentialBlob':pwd, 'Flags':win32cred.CRED_FLAGS_USERNAME_TARGET, + 'Persist':win32cred.CRED_PERSIST_ENTERPRISE,'Type':win32cred.CRED_TYPE_DOMAIN_PASSWORD, + 'Attributes':attrs} +win32cred.CredWrite(cred) +pwd=None +print(win32cred.CredRead(target, win32cred.CRED_TYPE_DOMAIN_PASSWORD)) + +## Marshal saved credential and use it to log on +mc=win32cred.CredMarshalCredential(win32cred.UsernameTargetCredential, target) +th=win32security.LogonUser(mc,None,'',win32con.LOGON32_LOGON_INTERACTIVE, win32con.LOGON32_PROVIDER_DEFAULT) +win32security.ImpersonateLoggedOnUser(th) +print('GetUserName:',win32api.GetUserName()) +win32security.RevertToSelf() + +## Load user's profile. (first check if user has a roaming profile) +username, domain=win32cred.CredUIParseUserName(target) +user_info_4=win32net.NetUserGetInfo(None, username, 4) +profilepath=user_info_4['profile'] +## LoadUserProfile apparently doesn't like an empty string +if not profilepath: + profilepath=None + +## leave Flags in since 2.3 still chokes on some types of optional keyword args +hk=win32profile.LoadUserProfile(th, {'UserName':username, 'Flags':0, 'ProfilePath':profilepath}) +## Get user's environment variables in a form that can be passed to win32process.CreateProcessAsUser +env=win32profile.CreateEnvironmentBlock(th,False) + + +## Cleanup should probably be in a finally block +win32profile.UnloadUserProfile(th, hk) +th.Close() + + diff --git a/Lib/site-packages/win32/Demos/win32fileDemo.py b/Lib/site-packages/win32/Demos/win32fileDemo.py new file mode 100644 index 0000000..948b90a --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32fileDemo.py @@ -0,0 +1,37 @@ +# This is a "demo" of win32file - it used to be more a test case than a +# demo, so has been moved to the test directory. + +# Please contribute your favourite simple little demo. +import win32file, win32api, win32con +import os + +# A very simple demo - note that this does no more than you can do with +# builtin Python file objects, so for something as simple as this, you +# generally *should* use builtin Python objects. Only use win32file etc +# when you need win32 specific features not available in Python. +def SimpleFileDemo(): + testName = os.path.join( win32api.GetTempPath(), "win32file_demo_test_file") + if os.path.exists(testName): os.unlink(testName) + # Open the file for writing. + handle = win32file.CreateFile(testName, + win32file.GENERIC_WRITE, + 0, + None, + win32con.CREATE_NEW, + 0, + None) + test_data = "Hello\0there".encode("ascii") + win32file.WriteFile(handle, test_data) + handle.Close() + # Open it for reading. + handle = win32file.CreateFile(testName, win32file.GENERIC_READ, 0, None, win32con.OPEN_EXISTING, 0, None) + rc, data = win32file.ReadFile(handle, 1024) + handle.Close() + if data == test_data: + print("Successfully wrote and read a file") + else: + raise Exception("Got different data back???") + os.unlink(testName) + +if __name__=='__main__': + SimpleFileDemo() diff --git a/Lib/site-packages/win32/Demos/win32gui_demo.py b/Lib/site-packages/win32/Demos/win32gui_demo.py new file mode 100644 index 0000000..de4aac8 --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32gui_demo.py @@ -0,0 +1,106 @@ +# The start of a win32gui generic demo. +# Feel free to contribute more demos back ;-) + +import win32gui, win32con, win32api +import time, math, random + +def _MyCallback( hwnd, extra ): + hwnds, classes = extra + hwnds.append(hwnd) + classes[win32gui.GetClassName(hwnd)] = 1 + +def TestEnumWindows(): + windows = [] + classes = {} + win32gui.EnumWindows(_MyCallback, (windows, classes)) + print("Enumerated a total of %d windows with %d classes" % (len(windows),len(classes))) + if "tooltips_class32" not in classes: + print("Hrmmmm - I'm very surprised to not find a 'tooltips_class32' class.") + + +def OnPaint_1(hwnd, msg, wp, lp): + dc, ps=win32gui.BeginPaint(hwnd) + win32gui.SetGraphicsMode(dc, win32con.GM_ADVANCED) + br=win32gui.CreateSolidBrush(win32api.RGB(255,0,0)) + win32gui.SelectObject(dc, br) + angle=win32gui.GetWindowLong(hwnd, win32con.GWL_USERDATA) + win32gui.SetWindowLong(hwnd, win32con.GWL_USERDATA, angle+2) + r_angle=angle*(math.pi/180) + win32gui.SetWorldTransform(dc, + {'M11':math.cos(r_angle), 'M12':math.sin(r_angle), 'M21':math.sin(r_angle)*-1, 'M22':math.cos(r_angle),'Dx':250,'Dy':250}) + win32gui.MoveToEx(dc,250,250) + win32gui.BeginPath(dc) + win32gui.Pie(dc, 10, 70, 200, 200, 350, 350, 75, 10) + win32gui.Chord(dc, 200, 200, 850, 0, 350, 350, 75, 10) + win32gui.LineTo(dc, 300,300) + win32gui.LineTo(dc, 100, 20) + win32gui.LineTo(dc, 20, 100) + win32gui.LineTo(dc, 400, 0) + win32gui.LineTo(dc, 0, 400) + win32gui.EndPath(dc) + win32gui.StrokeAndFillPath(dc) + win32gui.EndPaint(hwnd, ps) + return 0 +wndproc_1={win32con.WM_PAINT:OnPaint_1} + +def OnPaint_2(hwnd, msg, wp, lp): + dc, ps=win32gui.BeginPaint(hwnd) + win32gui.SetGraphicsMode(dc, win32con.GM_ADVANCED) + l,t,r,b=win32gui.GetClientRect(hwnd) + + for x in range(25): + vertices=( + {'x':int(random.random()*r), 'y':int(random.random()*b), 'Red':int(random.random()*0xff00), 'Green':0, 'Blue':0, 'Alpha':0}, + {'x':int(random.random()*r), 'y':int(random.random()*b), 'Red':0, 'Green':int(random.random()*0xff00), 'Blue':0, 'Alpha':0}, + {'x':int(random.random()*r), 'y':int(random.random()*b), 'Red':0, 'Green':0, 'Blue':int(random.random()*0xff00), 'Alpha':0}, + ) + mesh=((0,1,2),) + win32gui.GradientFill(dc,vertices, mesh, win32con.GRADIENT_FILL_TRIANGLE) + win32gui.EndPaint(hwnd, ps) + return 0 +wndproc_2={win32con.WM_PAINT:OnPaint_2} + +def TestSetWorldTransform(): + wc = win32gui.WNDCLASS() + wc.lpszClassName = 'test_win32gui_1' + wc.style = win32con.CS_GLOBALCLASS|win32con.CS_VREDRAW | win32con.CS_HREDRAW + wc.hbrBackground = win32con.COLOR_WINDOW+1 + wc.lpfnWndProc=wndproc_1 + class_atom=win32gui.RegisterClass(wc) + hwnd = win32gui.CreateWindow(wc.lpszClassName, + 'Spin the Lobster!', + win32con.WS_CAPTION|win32con.WS_VISIBLE, + 100,100,900,900, 0, 0, 0, None) + for x in range(500): + win32gui.InvalidateRect(hwnd,None,True) + win32gui.PumpWaitingMessages() + time.sleep(0.01) + win32gui.DestroyWindow(hwnd) + win32gui.UnregisterClass(wc.lpszClassName, None) + +def TestGradientFill(): + wc = win32gui.WNDCLASS() + wc.lpszClassName = 'test_win32gui_2' + wc.style = win32con.CS_GLOBALCLASS|win32con.CS_VREDRAW | win32con.CS_HREDRAW + wc.hbrBackground = win32con.COLOR_WINDOW+1 + wc.lpfnWndProc=wndproc_2 + class_atom=win32gui.RegisterClass(wc) + hwnd = win32gui.CreateWindowEx(0, class_atom,'Kaleidoscope', + win32con.WS_CAPTION|win32con.WS_VISIBLE|win32con.WS_THICKFRAME|win32con.WS_SYSMENU, + 100,100,900,900, 0, 0, 0, None) + s=win32gui.GetWindowLong(hwnd,win32con.GWL_EXSTYLE) + win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, s|win32con.WS_EX_LAYERED) + win32gui.SetLayeredWindowAttributes(hwnd, 0, 175, win32con.LWA_ALPHA) + for x in range(30): + win32gui.InvalidateRect(hwnd,None,True) + win32gui.PumpWaitingMessages() + time.sleep(0.3) + win32gui.DestroyWindow(hwnd) + win32gui.UnregisterClass(class_atom,None) + +print("Enumerating all windows...") +TestEnumWindows() +print("Testing drawing functions ...") +TestSetWorldTransform() +TestGradientFill() +print("All tests done!") diff --git a/Lib/site-packages/win32/Demos/win32gui_devicenotify.py b/Lib/site-packages/win32/Demos/win32gui_devicenotify.py new file mode 100644 index 0000000..ced68ad --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32gui_devicenotify.py @@ -0,0 +1,82 @@ +# Demo RegisterDeviceNotification etc. Creates a hidden window to receive +# notifications. See serviceEvents.py for an example of a service doing +# that. +import sys, time +import win32gui, win32con, win32api, win32file +import win32gui_struct, winnt + +# These device GUIDs are from Ioevent.h in the Windows SDK. Ideally they +# could be collected somewhere for pywin32... +GUID_DEVINTERFACE_USB_DEVICE = "{A5DCBF10-6530-11D2-901F-00C04FB951ED}" + +# WM_DEVICECHANGE message handler. +def OnDeviceChange(hwnd, msg, wp, lp): + # Unpack the 'lp' into the appropriate DEV_BROADCAST_* structure, + # using the self-identifying data inside the DEV_BROADCAST_HDR. + info = win32gui_struct.UnpackDEV_BROADCAST(lp) + print("Device change notification:", wp, str(info)) + if wp==win32con.DBT_DEVICEQUERYREMOVE and info.devicetype==win32con.DBT_DEVTYP_HANDLE: + # Our handle is stored away in the structure - just close it + print("Device being removed - closing handle") + win32file.CloseHandle(info.handle) + # and cancel our notifications - if it gets plugged back in we get + # the same notification and try and close the same handle... + win32gui.UnregisterDeviceNotification(info.hdevnotify) + return True + + +def TestDeviceNotifications(dir_names): + wc = win32gui.WNDCLASS() + wc.lpszClassName = 'test_devicenotify' + wc.style = win32con.CS_GLOBALCLASS|win32con.CS_VREDRAW | win32con.CS_HREDRAW + wc.hbrBackground = win32con.COLOR_WINDOW+1 + wc.lpfnWndProc={win32con.WM_DEVICECHANGE:OnDeviceChange} + class_atom=win32gui.RegisterClass(wc) + hwnd = win32gui.CreateWindow(wc.lpszClassName, + 'Testing some devices', + # no need for it to be visible. + win32con.WS_CAPTION, + 100,100,900,900, 0, 0, 0, None) + + hdevs = [] + # Watch for all USB device notifications + filter = win32gui_struct.PackDEV_BROADCAST_DEVICEINTERFACE( + GUID_DEVINTERFACE_USB_DEVICE) + hdev = win32gui.RegisterDeviceNotification(hwnd, filter, + win32con.DEVICE_NOTIFY_WINDOW_HANDLE) + hdevs.append(hdev) + # and create handles for all specified directories + for d in dir_names: + hdir = win32file.CreateFile(d, + winnt.FILE_LIST_DIRECTORY, + winnt.FILE_SHARE_READ | winnt.FILE_SHARE_WRITE | winnt.FILE_SHARE_DELETE, + None, # security attributes + win32con.OPEN_EXISTING, + win32con.FILE_FLAG_BACKUP_SEMANTICS | # required privileges: SE_BACKUP_NAME and SE_RESTORE_NAME. + win32con.FILE_FLAG_OVERLAPPED, + None) + + filter = win32gui_struct.PackDEV_BROADCAST_HANDLE(hdir) + hdev = win32gui.RegisterDeviceNotification(hwnd, filter, + win32con.DEVICE_NOTIFY_WINDOW_HANDLE) + hdevs.append(hdev) + + # now start a message pump and wait for messages to be delivered. + print("Watching", len(hdevs), "handles - press Ctrl+C to terminate, or") + print("add and remove some USB devices...") + if not dir_names: + print("(Note you can also pass paths to watch on the command-line - eg,") + print("pass the root of an inserted USB stick to see events specific to") + print("that volume)") + while 1: + win32gui.PumpWaitingMessages() + time.sleep(0.01) + win32gui.DestroyWindow(hwnd) + win32gui.UnregisterClass(wc.lpszClassName, None) + +if __name__=='__main__': + # optionally pass device/directory names to watch for notifications. + # Eg, plug in a USB device - assume it connects as E: - then execute: + # % win32gui_devicenotify.py E: + # Then remove and insert the device. + TestDeviceNotifications(sys.argv[1:]) diff --git a/Lib/site-packages/win32/Demos/win32gui_dialog.py b/Lib/site-packages/win32/Demos/win32gui_dialog.py new file mode 100644 index 0000000..8581284 --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32gui_dialog.py @@ -0,0 +1,373 @@ +# A demo of a fairly complex dialog. +# +# Features: +# * Uses a "dynamic dialog resource" to build the dialog. +# * Uses a ListView control. +# * Dynamically resizes content. +# * Uses a second worker thread to fill the list. +# * Demostrates support for windows XP themes. + +# If you are on Windows XP, and specify a '--noxp' argument, you will see: +# * alpha-blend issues with icons +# * The buttons are "old" style, rather than based on the XP theme. +# Hence, using: +# import winxpgui as win32gui +# is recommened. +# Please report any problems. +import sys +if "--noxp" in sys.argv: + import win32gui +else: + import winxpgui as win32gui +import win32gui_struct +import win32api +import win32con, winerror +import struct, array +import commctrl +import queue +import os + +IDC_SEARCHTEXT = 1024 +IDC_BUTTON_SEARCH = 1025 +IDC_BUTTON_DISPLAY = 1026 +IDC_LISTBOX = 1027 + +WM_SEARCH_RESULT = win32con.WM_USER + 512 +WM_SEARCH_FINISHED = win32con.WM_USER + 513 + +class _WIN32MASKEDSTRUCT: + def __init__(self, **kw): + full_fmt = "" + for name, fmt, default, mask in self._struct_items_: + self.__dict__[name] = None + if fmt == "z": + full_fmt += "pi" + else: + full_fmt += fmt + for name, val in kw.items(): + if name not in self.__dict__: + raise ValueError("LVITEM structures do not have an item '%s'" % (name,)) + self.__dict__[name] = val + + def __setattr__(self, attr, val): + if not attr.startswith("_") and attr not in self.__dict__: + raise AttributeError(attr) + self.__dict__[attr] = val + + def toparam(self): + self._buffs = [] + full_fmt = "" + vals = [] + mask = 0 + # calc the mask + for name, fmt, default, this_mask in self._struct_items_: + if this_mask is not None and self.__dict__.get(name) is not None: + mask |= this_mask + self.mask = mask + for name, fmt, default, this_mask in self._struct_items_: + val = self.__dict__[name] + if fmt == "z": + fmt = "Pi" + if val is None: + vals.append(0) + vals.append(0) + else: + # Note this demo still works with byte strings. An + # alternate strategy would be to use unicode natively + # and use the 'W' version of the messages - eg, + # LVM_SETITEMW etc. + val = val + "\0" + if isinstance(val, str): + val = val.encode("mbcs") + str_buf = array.array("b", val) + vals.append(str_buf.buffer_info()[0]) + vals.append(len(val)) + self._buffs.append(str_buf) # keep alive during the call. + else: + if val is None: + val = default + vals.append(val) + full_fmt += fmt + return struct.pack(*(full_fmt,) + tuple(vals)) + + +# NOTE: See the win32gui_struct module for an alternative way of dealing +# with these structures +class LVITEM(_WIN32MASKEDSTRUCT): + _struct_items_ = [ + ("mask", "I", 0, None), + ("iItem", "i", 0, None), + ("iSubItem", "i", 0, None), + ("state", "I", 0, commctrl.LVIF_STATE), + ("stateMask", "I", 0, None), + ("text", "z", None, commctrl.LVIF_TEXT), + ("iImage", "i", 0, commctrl.LVIF_IMAGE), + ("lParam", "i", 0, commctrl.LVIF_PARAM), + ("iIdent", "i", 0, None), + ] + +class LVCOLUMN(_WIN32MASKEDSTRUCT): + _struct_items_ = [ + ("mask", "I", 0, None), + ("fmt", "i", 0, commctrl.LVCF_FMT), + ("cx", "i", 0, commctrl.LVCF_WIDTH), + ("text", "z", None, commctrl.LVCF_TEXT), + ("iSubItem", "i", 0, commctrl.LVCF_SUBITEM), + ("iImage", "i", 0, commctrl.LVCF_IMAGE), + ("iOrder", "i", 0, commctrl.LVCF_ORDER), + ] + +class DemoWindowBase: + def __init__(self): + win32gui.InitCommonControls() + self.hinst = win32gui.dllhandle + self.list_data = {} + + def _RegisterWndClass(self): + className = "PythonDocSearch" + message_map = {} + wc = win32gui.WNDCLASS() + wc.SetDialogProc() # Make it a dialog class. + wc.hInstance = self.hinst + wc.lpszClassName = className + wc.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW + wc.hCursor = win32gui.LoadCursor( 0, win32con.IDC_ARROW ) + wc.hbrBackground = win32con.COLOR_WINDOW + 1 + wc.lpfnWndProc = message_map # could also specify a wndproc. + # C code: wc.cbWndExtra = DLGWINDOWEXTRA + sizeof(HBRUSH) + (sizeof(COLORREF)); + wc.cbWndExtra = win32con.DLGWINDOWEXTRA + struct.calcsize("Pi") + icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE + + ## py.ico went away in python 2.5, load from executable instead + this_app=win32api.GetModuleHandle(None) + try: + wc.hIcon=win32gui.LoadIcon(this_app, 1) ## python.exe and pythonw.exe + except win32gui.error: + wc.hIcon=win32gui.LoadIcon(this_app, 135) ## pythonwin's icon + try: + classAtom = win32gui.RegisterClass(wc) + except win32gui.error as err_info: + if err_info.winerror!=winerror.ERROR_CLASS_ALREADY_EXISTS: + raise + return className + + def _GetDialogTemplate(self, dlgClassName): + style = win32con.WS_THICKFRAME | win32con.WS_POPUP | win32con.WS_VISIBLE | win32con.WS_CAPTION | win32con.WS_SYSMENU | win32con.DS_SETFONT | win32con.WS_MINIMIZEBOX + cs = win32con.WS_CHILD | win32con.WS_VISIBLE + title = "Dynamic Dialog Demo" + + # Window frame and title + dlg = [ [title, (0, 0, 210, 250), style, None, (8, "MS Sans Serif"), None, dlgClassName], ] + + # ID label and text box + dlg.append([130, "Enter something", -1, (5, 5, 200, 9), cs | win32con.SS_LEFT]) + s = cs | win32con.WS_TABSTOP | win32con.WS_BORDER + dlg.append(['EDIT', None, IDC_SEARCHTEXT, (5, 15, 200, 12), s]) + + # Search/Display Buttons + # (x positions don't matter here) + s = cs | win32con.WS_TABSTOP + dlg.append([128, "Fill List", IDC_BUTTON_SEARCH, (5, 35, 50, 14), s | win32con.BS_DEFPUSHBUTTON]) + s = win32con.BS_PUSHBUTTON | s + dlg.append([128, "Display", IDC_BUTTON_DISPLAY, (100, 35, 50, 14), s]) + + # List control. + # Can't make this work :( +## s = cs | win32con.WS_TABSTOP +## dlg.append(['SysListView32', "Title", IDC_LISTBOX, (5, 505, 200, 200), s]) + + return dlg + + def _DoCreate(self, fn): + message_map = { + win32con.WM_SIZE: self.OnSize, + win32con.WM_COMMAND: self.OnCommand, + win32con.WM_NOTIFY: self.OnNotify, + win32con.WM_INITDIALOG: self.OnInitDialog, + win32con.WM_CLOSE: self.OnClose, + win32con.WM_DESTROY: self.OnDestroy, + WM_SEARCH_RESULT: self.OnSearchResult, + WM_SEARCH_FINISHED: self.OnSearchFinished, + } + dlgClassName = self._RegisterWndClass() + template = self._GetDialogTemplate(dlgClassName) + return fn(self.hinst, template, 0, message_map) + + def _SetupList(self): + child_style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_BORDER | win32con.WS_HSCROLL | win32con.WS_VSCROLL + child_style |= commctrl.LVS_SINGLESEL | commctrl.LVS_SHOWSELALWAYS | commctrl.LVS_REPORT + self.hwndList = win32gui.CreateWindow("SysListView32", None, child_style, 0, 0, 100, 100, self.hwnd, IDC_LISTBOX, self.hinst, None) + + child_ex_style = win32gui.SendMessage(self.hwndList, commctrl.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0) + child_ex_style |= commctrl.LVS_EX_FULLROWSELECT + win32gui.SendMessage(self.hwndList, commctrl.LVM_SETEXTENDEDLISTVIEWSTYLE, 0, child_ex_style) + + # Add an image list - use the builtin shell folder icon - this + # demonstrates the problem with alpha-blending of icons on XP if + # winxpgui is not used in place of win32gui. + il = win32gui.ImageList_Create( + win32api.GetSystemMetrics(win32con.SM_CXSMICON), + win32api.GetSystemMetrics(win32con.SM_CYSMICON), + commctrl.ILC_COLOR32 | commctrl.ILC_MASK, + 1, # initial size + 0) # cGrow + + shell_dll = os.path.join(win32api.GetSystemDirectory(), "shell32.dll") + large, small = win32gui.ExtractIconEx(shell_dll, 4, 1) + win32gui.ImageList_ReplaceIcon(il, -1, small[0]) + win32gui.DestroyIcon(small[0]) + win32gui.DestroyIcon(large[0]) + win32gui.SendMessage(self.hwndList, commctrl.LVM_SETIMAGELIST, + commctrl.LVSIL_SMALL, il) + + # Setup the list control columns. + lvc = LVCOLUMN(mask = commctrl.LVCF_FMT | commctrl.LVCF_WIDTH | commctrl.LVCF_TEXT | commctrl.LVCF_SUBITEM) + lvc.fmt = commctrl.LVCFMT_LEFT + lvc.iSubItem = 1 + lvc.text = "Title" + lvc.cx = 200 + win32gui.SendMessage(self.hwndList, commctrl.LVM_INSERTCOLUMN, 0, lvc.toparam()) + lvc.iSubItem = 0 + lvc.text = "Order" + lvc.cx = 50 + win32gui.SendMessage(self.hwndList, commctrl.LVM_INSERTCOLUMN, 0, lvc.toparam()) + + win32gui.UpdateWindow(self.hwnd) + + def ClearListItems(self): + win32gui.SendMessage(self.hwndList, commctrl.LVM_DELETEALLITEMS) + self.list_data = {} + + def AddListItem(self, data, *columns): + num_items = win32gui.SendMessage(self.hwndList, commctrl.LVM_GETITEMCOUNT) + item = LVITEM(text=columns[0], iItem = num_items) + new_index = win32gui.SendMessage(self.hwndList, commctrl.LVM_INSERTITEM, 0, item.toparam()) + col_no = 1 + for col in columns[1:]: + item = LVITEM(text=col, iItem = new_index, iSubItem = col_no) + win32gui.SendMessage(self.hwndList, commctrl.LVM_SETITEM, 0, item.toparam()) + col_no += 1 + self.list_data[new_index] = data + + def OnInitDialog(self, hwnd, msg, wparam, lparam): + self.hwnd = hwnd + # centre the dialog + desktop = win32gui.GetDesktopWindow() + l,t,r,b = win32gui.GetWindowRect(self.hwnd) + dt_l, dt_t, dt_r, dt_b = win32gui.GetWindowRect(desktop) + centre_x, centre_y = win32gui.ClientToScreen( desktop, ( (dt_r-dt_l)//2, (dt_b-dt_t)//2) ) + win32gui.MoveWindow(hwnd, centre_x-(r//2), centre_y-(b//2), r-l, b-t, 0) + self._SetupList() + l,t,r,b = win32gui.GetClientRect(self.hwnd) + self._DoSize(r-l,b-t, 1) + + def _DoSize(self, cx, cy, repaint = 1): + # right-justify the textbox. + ctrl = win32gui.GetDlgItem(self.hwnd, IDC_SEARCHTEXT) + l, t, r, b = win32gui.GetWindowRect(ctrl) + l, t = win32gui.ScreenToClient(self.hwnd, (l,t) ) + r, b = win32gui.ScreenToClient(self.hwnd, (r,b) ) + win32gui.MoveWindow(ctrl, l, t, cx-l-5, b-t, repaint) + # The button. + ctrl = win32gui.GetDlgItem(self.hwnd, IDC_BUTTON_DISPLAY) + l, t, r, b = win32gui.GetWindowRect(ctrl) + l, t = win32gui.ScreenToClient(self.hwnd, (l,t) ) + r, b = win32gui.ScreenToClient(self.hwnd, (r,b) ) + list_y = b + 10 + w = r - l + win32gui.MoveWindow(ctrl, cx - 5 - w, t, w, b-t, repaint) + + # The list control + win32gui.MoveWindow(self.hwndList, 0, list_y, cx, cy-list_y, repaint) + # The last column of the list control. + new_width = cx - win32gui.SendMessage(self.hwndList, commctrl.LVM_GETCOLUMNWIDTH, 0) + win32gui.SendMessage(self.hwndList, commctrl.LVM_SETCOLUMNWIDTH, 1, new_width) + + def OnSize(self, hwnd, msg, wparam, lparam): + x = win32api.LOWORD(lparam) + y = win32api.HIWORD(lparam) + self._DoSize(x,y) + return 1 + + def OnSearchResult(self, hwnd, msg, wparam, lparam): + try: + while 1: + params = self.result_queue.get(0) + self.AddListItem(*params) + except queue.Empty: + pass + + def OnSearchFinished(self, hwnd, msg, wparam, lparam): + print("OnSearchFinished") + + def OnNotify(self, hwnd, msg, wparam, lparam): + info = win32gui_struct.UnpackNMITEMACTIVATE(lparam) + if info.code == commctrl.NM_DBLCLK: + print("Double click on item", info.iItem+1) + return 1 + + def OnCommand(self, hwnd, msg, wparam, lparam): + id = win32api.LOWORD(wparam) + if id == IDC_BUTTON_SEARCH: + self.ClearListItems() + def fill_slowly(q, hwnd): + import time + for i in range(20): + q.put(("whatever", str(i+1), "Search result " + str(i) )) + win32gui.PostMessage(hwnd, WM_SEARCH_RESULT, 0, 0) + time.sleep(.25) + win32gui.PostMessage(hwnd, WM_SEARCH_FINISHED, 0, 0) + + import threading + self.result_queue = queue.Queue() + thread = threading.Thread(target = fill_slowly, args=(self.result_queue, self.hwnd) ) + thread.start() + elif id == IDC_BUTTON_DISPLAY: + print("Display button selected") + sel = win32gui.SendMessage(self.hwndList, commctrl.LVM_GETNEXTITEM, -1, commctrl.LVNI_SELECTED) + print("The selected item is", sel+1) + + # These function differ based on how the window is used, so may be overridden + def OnClose(self, hwnd, msg, wparam, lparam): + raise NotImplementedError + + def OnDestroy(self, hwnd, msg, wparam, lparam): + pass + +# An implementation suitable for use with the Win32 Window functions (ie, not +# a true dialog) +class DemoWindow(DemoWindowBase): + def CreateWindow(self): + # Create the window via CreateDialogBoxIndirect - it can then + # work as a "normal" window, once a message loop is established. + self._DoCreate(win32gui.CreateDialogIndirect) + + def OnClose(self, hwnd, msg, wparam, lparam): + win32gui.DestroyWindow(hwnd) + + # We need to arrange to a WM_QUIT message to be sent to our + # PumpMessages() loop. + def OnDestroy(self, hwnd, msg, wparam, lparam): + win32gui.PostQuitMessage(0) # Terminate the app. + +# An implementation suitable for use with the Win32 Dialog functions. +class DemoDialog(DemoWindowBase): + def DoModal(self): + return self._DoCreate(win32gui.DialogBoxIndirect) + + def OnClose(self, hwnd, msg, wparam, lparam): + win32gui.EndDialog(hwnd, 0) + +def DemoModal(): + w=DemoDialog() + w.DoModal() + +def DemoCreateWindow(): + w=DemoWindow() + w.CreateWindow() + # PumpMessages runs until PostQuitMessage() is called by someone. + win32gui.PumpMessages() + +if __name__=='__main__': + DemoModal() + DemoCreateWindow() diff --git a/Lib/site-packages/win32/Demos/win32gui_menu.py b/Lib/site-packages/win32/Demos/win32gui_menu.py new file mode 100644 index 0000000..2e44d17 --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32gui_menu.py @@ -0,0 +1,349 @@ +# Demonstrates some advanced menu concepts using win32gui. +# This creates a taskbar icon which has some fancy menus (but note that +# selecting the menu items does nothing useful - see win32gui_taskbar.py +# for examples of this. + +# NOTE: This is a work in progress. Todo: +# * The "Checked" menu items don't work correctly - I'm not sure why. +# * No support for GetMenuItemInfo. + +# Based on Andy McKay's demo code. +from win32api import * +# Try and use XP features, so we get alpha-blending etc. +try: + from winxpgui import * +except ImportError: + from win32gui import * +from win32gui_struct import * +import win32con +import sys, os +import struct +import array + +this_dir = os.path.split(sys.argv[0])[0] + +class MainWindow: + def __init__(self): + message_map = { + win32con.WM_DESTROY: self.OnDestroy, + win32con.WM_COMMAND: self.OnCommand, + win32con.WM_USER+20 : self.OnTaskbarNotify, + # owner-draw related handlers. + win32con.WM_MEASUREITEM: self.OnMeasureItem, + win32con.WM_DRAWITEM: self.OnDrawItem, + } + # Register the Window class. + wc = WNDCLASS() + hinst = wc.hInstance = GetModuleHandle(None) + wc.lpszClassName = "PythonTaskbarDemo" + wc.lpfnWndProc = message_map # could also specify a wndproc. + classAtom = RegisterClass(wc) + # Create the Window. + style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU + self.hwnd = CreateWindow( classAtom, "Taskbar Demo", style, \ + 0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, \ + 0, 0, hinst, None) + UpdateWindow(self.hwnd) + iconPathName = os.path.abspath(os.path.join( sys.prefix, "pyc.ico" )) + # py2.5 includes the .ico files in the DLLs dir for some reason. + if not os.path.isfile(iconPathName): + iconPathName = os.path.abspath(os.path.join( os.path.split(sys.executable)[0], "DLLs", "pyc.ico" )) + if not os.path.isfile(iconPathName): + # Look in the source tree. + iconPathName = os.path.abspath(os.path.join( os.path.split(sys.executable)[0], "..\\PC\\pyc.ico" )) + if os.path.isfile(iconPathName): + icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE + hicon = LoadImage(hinst, iconPathName, win32con.IMAGE_ICON, 0, 0, icon_flags) + else: + iconPathName = None + print("Can't find a Python icon file - using default") + hicon = LoadIcon(0, win32con.IDI_APPLICATION) + self.iconPathName = iconPathName + + # Load up some information about menus needed by our owner-draw code. + # The font to use on the menu. + ncm = SystemParametersInfo(win32con.SPI_GETNONCLIENTMETRICS) + self.font_menu = CreateFontIndirect(ncm['lfMenuFont']) + # spacing for our ownerdraw menus - not sure exactly what constants + # should be used (and if you owner-draw all items on the menu, it + # doesn't matter!) + self.menu_icon_height = GetSystemMetrics(win32con.SM_CYMENU) - 4 + self.menu_icon_width = self.menu_icon_height + self.icon_x_pad = 8 # space from end of icon to start of text. + # A map we use to stash away data we need for ownerdraw. Keyed + # by integer ID - that ID will be set in dwTypeData of the menu item. + self.menu_item_map = {} + + # Finally, create the menu + self.createMenu() + + flags = NIF_ICON | NIF_MESSAGE | NIF_TIP + nid = (self.hwnd, 0, flags, win32con.WM_USER+20, hicon, "Python Demo") + Shell_NotifyIcon(NIM_ADD, nid) + print("Please right-click on the Python icon in the taskbar") + + def createMenu(self): + self.hmenu = menu = CreatePopupMenu() + # Create our 'Exit' item with the standard, ugly 'close' icon. + item, extras = PackMENUITEMINFO(text = "Exit", + hbmpItem=win32con.HBMMENU_MBAR_CLOSE, + wID=1000) + InsertMenuItem(menu, 0, 1, item) + # Create a 'text only' menu via InsertMenuItem rather then + # AppendMenu, just to prove we can! + item, extras = PackMENUITEMINFO(text = "Text only item", + wID=1001) + InsertMenuItem(menu, 0, 1, item) + + load_bmp_flags=win32con.LR_LOADFROMFILE | \ + win32con.LR_LOADTRANSPARENT + # These images are "over sized", so we load them scaled. + hbmp = LoadImage(0, os.path.join(this_dir, "images/smiley.bmp"), + win32con.IMAGE_BITMAP, 20, 20, load_bmp_flags) + + # Create a top-level menu with a bitmap + item, extras = PackMENUITEMINFO(text="Menu with bitmap", + hbmpItem=hbmp, + wID=1002) + InsertMenuItem(menu, 0, 1, item) + + # Owner-draw menus mainly from: + # http://windowssdk.msdn.microsoft.com/en-us/library/ms647558.aspx + # and: + # http://www.codeguru.com/cpp/controls/menu/bitmappedmenus/article.php/c165 + + # Create one with an icon - this is *lots* more work - we do it + # owner-draw! The primary reason is to handle transparency better - + # converting to a bitmap causes the background to be incorrect when + # the menu item is selected. I can't see a simpler way. + # First, load the icon we want to use. + ico_x = GetSystemMetrics(win32con.SM_CXSMICON) + ico_y = GetSystemMetrics(win32con.SM_CYSMICON) + if self.iconPathName: + hicon = LoadImage(0, self.iconPathName, win32con.IMAGE_ICON, ico_x, ico_y, win32con.LR_LOADFROMFILE) + else: + shell_dll = os.path.join(GetSystemDirectory(), "shell32.dll") + large, small = win32gui.ExtractIconEx(shell_dll, 4, 1) + hicon = small[0] + DestroyIcon(large[0]) + + # Stash away the text and hicon in our map, and add the owner-draw + # item to the menu. + index = 0 + self.menu_item_map[index] = (hicon, "Menu with owner-draw icon") + item, extras = PackMENUITEMINFO(fType=win32con.MFT_OWNERDRAW, + dwItemData=index, + wID=1009) + InsertMenuItem(menu, 0, 1, item) + + # Add another icon-based icon - but this time using HBMMENU_CALLBACK + # in the hbmpItem elt, so we only need to draw the icon (ie, not the + # text or checkmark) + index = 1 + self.menu_item_map[index] = (hicon, None) + item, extras = PackMENUITEMINFO(text="Menu with o-d icon 2", + dwItemData=index, + hbmpItem=win32con.HBMMENU_CALLBACK, + wID=1010) + InsertMenuItem(menu, 0, 1, item) + + # Add another icon-based icon - this time by converting + # via bitmap. Note the icon background when selected is ugly :( + hdcBitmap = CreateCompatibleDC(0) + hdcScreen = GetDC(0) + hbm = CreateCompatibleBitmap(hdcScreen, ico_x, ico_y) + hbmOld = SelectObject(hdcBitmap, hbm) + SetBkMode(hdcBitmap, win32con.TRANSPARENT) + # Fill the background. + brush = GetSysColorBrush(win32con.COLOR_MENU) + FillRect(hdcBitmap, (0, 0, 16, 16), brush) + # unclear if brush needs to be freed. Best clue I can find is: + # "GetSysColorBrush returns a cached brush instead of allocating a new + # one." - implies no DeleteObject. + # draw the icon + DrawIconEx(hdcBitmap, 0, 0, hicon, ico_x, ico_y, 0, 0, win32con.DI_NORMAL) + SelectObject(hdcBitmap, hbmOld) + DeleteDC(hdcBitmap) + item, extras = PackMENUITEMINFO(text="Menu with icon", + hbmpItem=hbm.Detach(), + wID=1011) + InsertMenuItem(menu, 0, 1, item) + + # Create a sub-menu, and put a few funky ones there. + self.sub_menu = sub_menu = CreatePopupMenu() + # A 'checkbox' menu. + item, extras = PackMENUITEMINFO(fState=win32con.MFS_CHECKED, + text="Checkbox menu", + hbmpItem=hbmp, + wID=1003) + InsertMenuItem(sub_menu, 0, 1, item) + # A 'radio' menu. + InsertMenu(sub_menu, 0, win32con.MF_BYPOSITION, win32con.MF_SEPARATOR, None) + item, extras = PackMENUITEMINFO(fType=win32con.MFT_RADIOCHECK, + fState=win32con.MFS_CHECKED, + text="Checkbox menu - bullet 1", + hbmpItem=hbmp, + wID=1004) + InsertMenuItem(sub_menu, 0, 1, item) + item, extras = PackMENUITEMINFO(fType=win32con.MFT_RADIOCHECK, + fState=win32con.MFS_UNCHECKED, + text="Checkbox menu - bullet 2", + hbmpItem=hbmp, + wID=1005) + InsertMenuItem(sub_menu, 0, 1, item) + # And add the sub-menu to the top-level menu. + item, extras = PackMENUITEMINFO(text="Sub-Menu", + hSubMenu=sub_menu) + InsertMenuItem(menu, 0, 1, item) + + # Set 'Exit' as the default option. + SetMenuDefaultItem(menu, 1000, 0) + + + def OnDestroy(self, hwnd, msg, wparam, lparam): + nid = (self.hwnd, 0) + Shell_NotifyIcon(NIM_DELETE, nid) + PostQuitMessage(0) # Terminate the app. + + def OnTaskbarNotify(self, hwnd, msg, wparam, lparam): + if lparam==win32con.WM_RBUTTONUP: + print("You right clicked me.") + # display the menu at the cursor pos. + pos = GetCursorPos() + SetForegroundWindow(self.hwnd) + TrackPopupMenu(self.hmenu, win32con.TPM_LEFTALIGN, pos[0], pos[1], 0, self.hwnd, None) + PostMessage(self.hwnd, win32con.WM_NULL, 0, 0) + elif lparam==win32con.WM_LBUTTONDBLCLK: + print("You double-clicked me") + # find the default menu item and fire it. + cmd = GetMenuDefaultItem(self.hmenu, False, 0) + if cmd == -1: + print("Can't find a default!") + # and just pretend it came from the menu + self.OnCommand(hwnd, win32con.WM_COMMAND, cmd, 0) + return 1 + + def OnCommand(self, hwnd, msg, wparam, lparam): + id = LOWORD(wparam) + if id == 1000: + print("Goodbye") + DestroyWindow(self.hwnd) + elif id in (1003, 1004, 1005): + # Our 'checkbox' and 'radio' items + state = GetMenuState(self.sub_menu, id, win32con.MF_BYCOMMAND) + if state==-1: + raise RuntimeError("No item found") + if state & win32con.MF_CHECKED: + check_flags = win32con.MF_UNCHECKED + print("Menu was checked - unchecking") + else: + check_flags = win32con.MF_CHECKED + print("Menu was unchecked - checking") + + if id == 1003: + # simple checkbox + rc = CheckMenuItem(self.sub_menu, id, + win32con.MF_BYCOMMAND | check_flags) + else: + # radio button - must pass the first and last IDs in the + # "group", and the ID in the group that is to be selected. + rc = CheckMenuRadioItem(self.sub_menu, 1004, 1005, id, + win32con.MF_BYCOMMAND) + # Get and check the new state - first the simple way... + new_state = GetMenuState(self.sub_menu, id, win32con.MF_BYCOMMAND) + if new_state & win32con.MF_CHECKED != check_flags: + raise RuntimeError("The new item didn't get the new checked state!") + # Now the long-winded way via GetMenuItemInfo... + buf, extras = EmptyMENUITEMINFO() + win32gui.GetMenuItemInfo(self.sub_menu, id, False, buf) + fType, fState, wID, hSubMenu, hbmpChecked, hbmpUnchecked, \ + dwItemData, text, hbmpItem = UnpackMENUITEMINFO(buf) + + if fState & win32con.MF_CHECKED != check_flags: + raise RuntimeError("The new item didn't get the new checked state!") + else: + print("OnCommand for ID", id) + + # Owner-draw related functions. We only have 1 owner-draw item, but + # we pretend we have more than that :) + def OnMeasureItem(self, hwnd, msg, wparam, lparam): + ## Last item of MEASUREITEMSTRUCT is a ULONG_PTR + fmt = "5iP" + buf = PyMakeBuffer(struct.calcsize(fmt), lparam) + data = struct.unpack(fmt, buf) + ctlType, ctlID, itemID, itemWidth, itemHeight, itemData = data + + hicon, text = self.menu_item_map[itemData] + if text is None: + # Only drawing icon due to HBMMENU_CALLBACK + cx = self.menu_icon_width + cy = self.menu_icon_height + else: + # drawing the lot! + dc = GetDC(hwnd) + oldFont = SelectObject(dc, self.font_menu) + cx, cy = GetTextExtentPoint32(dc, text) + SelectObject(dc, oldFont) + ReleaseDC(hwnd, dc) + + cx += GetSystemMetrics(win32con.SM_CXMENUCHECK) + cx += self.menu_icon_width + self.icon_x_pad + + cy = GetSystemMetrics(win32con.SM_CYMENU) + + new_data = struct.pack(fmt, ctlType, ctlID, itemID, cx, cy, itemData) + PySetMemory(lparam, new_data) + return True + + def OnDrawItem(self, hwnd, msg, wparam, lparam): + ## lparam is a DRAWITEMSTRUCT + fmt = "5i2P4iP" + data = struct.unpack(fmt, PyGetMemory(lparam, struct.calcsize(fmt))) + ctlType, ctlID, itemID, itemAction, itemState, hwndItem, \ + hDC, left, top, right, bot, itemData = data + + rect = left, top, right, bot + hicon, text = self.menu_item_map[itemData] + + if text is None: + # This means the menu-item had HBMMENU_CALLBACK - so all we + # draw is the icon. rect is the entire area we should use. + DrawIconEx(hDC, left, top, hicon, right-left, bot-top, + 0, 0, win32con.DI_NORMAL) + else: + # If the user has selected the item, use the selected + # text and background colors to display the item. + selected = itemState & win32con.ODS_SELECTED + if selected: + crText = SetTextColor(hDC, GetSysColor(win32con.COLOR_HIGHLIGHTTEXT)) + crBkgnd = SetBkColor(hDC, GetSysColor(win32con.COLOR_HIGHLIGHT)) + + each_pad = self.icon_x_pad // 2 + x_icon = left + GetSystemMetrics(win32con.SM_CXMENUCHECK) + each_pad + x_text = x_icon + self.menu_icon_width + each_pad + + # Draw text first, specifying a complete rect to fill - this sets + # up the background (but overwrites anything else already there!) + # Select the font, draw it, and restore the previous font. + hfontOld = SelectObject(hDC, self.font_menu) + ExtTextOut(hDC, x_text, top+2, win32con.ETO_OPAQUE, rect, text) + SelectObject(hDC, hfontOld) + + # Icon image next. Icons are transparent - no need to handle + # selection specially. + DrawIconEx(hDC, x_icon, top+2, hicon, + self.menu_icon_width, self.menu_icon_height, + 0, 0, win32con.DI_NORMAL) + + # Return the text and background colors to their + # normal state (not selected). + if selected: + SetTextColor(hDC, crText) + SetBkColor(hDC, crBkgnd) + +def main(): + w=MainWindow() + PumpMessages() + +if __name__=='__main__': + main() diff --git a/Lib/site-packages/win32/Demos/win32gui_taskbar.py b/Lib/site-packages/win32/Demos/win32gui_taskbar.py new file mode 100644 index 0000000..f091f6c --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32gui_taskbar.py @@ -0,0 +1,112 @@ +# Creates a task-bar icon. Run from Python.exe to see the +# messages printed. +import win32api, win32gui +import win32con, winerror +import sys, os + +class MainWindow: + def __init__(self): + msg_TaskbarRestart = win32gui.RegisterWindowMessage("TaskbarCreated"); + message_map = { + msg_TaskbarRestart: self.OnRestart, + win32con.WM_DESTROY: self.OnDestroy, + win32con.WM_COMMAND: self.OnCommand, + win32con.WM_USER+20 : self.OnTaskbarNotify, + } + # Register the Window class. + wc = win32gui.WNDCLASS() + hinst = wc.hInstance = win32api.GetModuleHandle(None) + wc.lpszClassName = "PythonTaskbarDemo" + wc.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW; + wc.hCursor = win32api.LoadCursor( 0, win32con.IDC_ARROW ) + wc.hbrBackground = win32con.COLOR_WINDOW + wc.lpfnWndProc = message_map # could also specify a wndproc. + + # Don't blow up if class already registered to make testing easier + try: + classAtom = win32gui.RegisterClass(wc) + except win32gui.error as err_info: + if err_info.winerror!=winerror.ERROR_CLASS_ALREADY_EXISTS: + raise + + # Create the Window. + style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU + self.hwnd = win32gui.CreateWindow( wc.lpszClassName, "Taskbar Demo", style, \ + 0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, \ + 0, 0, hinst, None) + win32gui.UpdateWindow(self.hwnd) + self._DoCreateIcons() + def _DoCreateIcons(self): + # Try and find a custom icon + hinst = win32api.GetModuleHandle(None) + iconPathName = os.path.abspath(os.path.join( os.path.split(sys.executable)[0], "pyc.ico" )) + if not os.path.isfile(iconPathName): + # Look in DLLs dir, a-la py 2.5 + iconPathName = os.path.abspath(os.path.join( os.path.split(sys.executable)[0], "DLLs", "pyc.ico" )) + if not os.path.isfile(iconPathName): + # Look in the source tree. + iconPathName = os.path.abspath(os.path.join( os.path.split(sys.executable)[0], "..\\PC\\pyc.ico" )) + if os.path.isfile(iconPathName): + icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE + hicon = win32gui.LoadImage(hinst, iconPathName, win32con.IMAGE_ICON, 0, 0, icon_flags) + else: + print("Can't find a Python icon file - using default") + hicon = win32gui.LoadIcon(0, win32con.IDI_APPLICATION) + + flags = win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP + nid = (self.hwnd, 0, flags, win32con.WM_USER+20, hicon, "Python Demo") + try: + win32gui.Shell_NotifyIcon(win32gui.NIM_ADD, nid) + except win32gui.error: + # This is common when windows is starting, and this code is hit + # before the taskbar has been created. + print("Failed to add the taskbar icon - is explorer running?") + # but keep running anyway - when explorer starts, we get the + # TaskbarCreated message. + + def OnRestart(self, hwnd, msg, wparam, lparam): + self._DoCreateIcons() + + def OnDestroy(self, hwnd, msg, wparam, lparam): + nid = (self.hwnd, 0) + win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, nid) + win32gui.PostQuitMessage(0) # Terminate the app. + + def OnTaskbarNotify(self, hwnd, msg, wparam, lparam): + if lparam==win32con.WM_LBUTTONUP: + print("You clicked me.") + elif lparam==win32con.WM_LBUTTONDBLCLK: + print("You double-clicked me - goodbye") + win32gui.DestroyWindow(self.hwnd) + elif lparam==win32con.WM_RBUTTONUP: + print("You right clicked me.") + menu = win32gui.CreatePopupMenu() + win32gui.AppendMenu( menu, win32con.MF_STRING, 1023, "Display Dialog") + win32gui.AppendMenu( menu, win32con.MF_STRING, 1024, "Say Hello") + win32gui.AppendMenu( menu, win32con.MF_STRING, 1025, "Exit program" ) + pos = win32gui.GetCursorPos() + # See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/menus_0hdi.asp + win32gui.SetForegroundWindow(self.hwnd) + win32gui.TrackPopupMenu(menu, win32con.TPM_LEFTALIGN, pos[0], pos[1], 0, self.hwnd, None) + win32gui.PostMessage(self.hwnd, win32con.WM_NULL, 0, 0) + return 1 + + def OnCommand(self, hwnd, msg, wparam, lparam): + id = win32api.LOWORD(wparam) + if id == 1023: + import win32gui_dialog + win32gui_dialog.DemoModal() + elif id == 1024: + print("Hello") + elif id == 1025: + print("Goodbye") + win32gui.DestroyWindow(self.hwnd) + else: + print("Unknown command -", id) + +def main(): + w=MainWindow() + win32gui.PumpMessages() + +if __name__=='__main__': + main() diff --git a/Lib/site-packages/win32/Demos/win32netdemo.py b/Lib/site-packages/win32/Demos/win32netdemo.py new file mode 100644 index 0000000..5084309 --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32netdemo.py @@ -0,0 +1,237 @@ +import sys +import win32api +import win32net +import win32netcon +import win32security +import getopt +import traceback + +verbose_level = 0 + +server = None # Run on local machine. + +def verbose(msg): + if verbose_level: + print(msg) + +def CreateUser(): + "Creates a new test user, then deletes the user" + testName = "PyNetTestUser" + try: + win32net.NetUserDel(server, testName) + print("Warning - deleted user before creating it!") + except win32net.error: + pass + + d = {} + d['name'] = testName + d['password'] = 'deleteme' + d['priv'] = win32netcon.USER_PRIV_USER + d['comment'] = "Delete me - created by Python test code" + d['flags'] = win32netcon.UF_NORMAL_ACCOUNT | win32netcon.UF_SCRIPT + win32net.NetUserAdd(server, 1, d) + try: + try: + win32net.NetUserChangePassword(server, testName, "wrong", "new") + print("ERROR: NetUserChangePassword worked with a wrong password!") + except win32net.error: + pass + win32net.NetUserChangePassword(server, testName, "deleteme", "new") + finally: + win32net.NetUserDel(server, testName) + print("Created a user, changed their password, and deleted them!") + +def UserEnum(): + "Enumerates all the local users" + resume = 0 + nuser = 0 + while 1: + data, total, resume = win32net.NetUserEnum(server, 3, win32netcon.FILTER_NORMAL_ACCOUNT, resume) + verbose("Call to NetUserEnum obtained %d entries of %d total" % (len(data), total)) + for user in data: + verbose("Found user %s" % user['name']) + nuser = nuser + 1 + if not resume: + break + assert nuser, "Could not find any users!" + print("Enumerated all the local users") + +def GroupEnum(): + "Enumerates all the domain groups" + nmembers = 0 + resume = 0 + while 1: + data, total, resume = win32net.NetGroupEnum(server, 1, resume) +# print "Call to NetGroupEnum obtained %d entries of %d total" % (len(data), total) + for group in data: + verbose("Found group %(name)s:%(comment)s " % group) + memberresume = 0 + while 1: + memberdata, total, memberresume = win32net.NetGroupGetUsers(server, group['name'], 0, resume) + for member in memberdata: + verbose(" Member %(name)s" % member) + nmembers = nmembers + 1 + if memberresume==0: + break + if not resume: + break + assert nmembers, "Couldnt find a single member in a single group!" + print("Enumerated all the groups") + +def LocalGroupEnum(): + "Enumerates all the local groups" + resume = 0 + nmembers = 0 + while 1: + data, total, resume = win32net.NetLocalGroupEnum(server, 1, resume) + for group in data: + verbose("Found group %(name)s:%(comment)s " % group) + memberresume = 0 + while 1: + memberdata, total, memberresume = win32net.NetLocalGroupGetMembers(server, group['name'], 2, resume) + for member in memberdata: + # Just for the sake of it, we convert the SID to a username + username, domain, type = win32security.LookupAccountSid(server, member['sid']) + nmembers = nmembers + 1 + verbose(" Member %s (%s)" % (username, member['domainandname'])) + if memberresume==0: + break + if not resume: + break + assert nmembers, "Couldnt find a single member in a single group!" + print("Enumerated all the local groups") + +def ServerEnum(): + "Enumerates all servers on the network" + resume = 0 + while 1: + data, total, resume = win32net.NetServerEnum(server, 100, win32netcon.SV_TYPE_ALL, None, resume) + for s in data: + verbose("Found server %s" % s['name']) + # Now loop over the shares. + shareresume=0 + while 1: + sharedata, total, shareresume = win32net.NetShareEnum(server, 2, shareresume) + for share in sharedata: + verbose(" %(netname)s (%(path)s):%(remark)s - in use by %(current_uses)d users" % share) + if not shareresume: + break + if not resume: + break + print("Enumerated all the servers on the network") + +def LocalGroup(uname=None): + "Creates a local group, adds some members, deletes them, then removes the group" + level = 3 + if uname is None: uname=win32api.GetUserName() + if uname.find("\\")<0: + uname = win32api.GetDomainName() + "\\" + uname + group = 'python_test_group' + # delete the group if it already exists + try: + win32net.NetLocalGroupDel(server, group) + print("WARNING: existing local group '%s' has been deleted.") + except win32net.error: + pass + group_data = {'name': group} + win32net.NetLocalGroupAdd(server, 1, group_data) + try: + u={'domainandname': uname} + win32net.NetLocalGroupAddMembers(server, group, level, [u]) + mem, tot, res = win32net.NetLocalGroupGetMembers(server, group, level) + print("members are", mem) + if mem[0]['domainandname'] != uname: + print("ERROR: LocalGroup just added %s, but members are %r" % (uname, mem)) + # Convert the list of dicts to a list of strings. + win32net.NetLocalGroupDelMembers(server, group, [m['domainandname'] for m in mem]) + finally: + win32net.NetLocalGroupDel(server, group) + print("Created a local group, added and removed members, then deleted the group") + +def GetInfo(userName=None): + "Dumps level 3 information about the current user" + if userName is None: userName=win32api.GetUserName() + print("Dumping level 3 information about user") + info = win32net.NetUserGetInfo(server, userName, 3) + for key, val in list(info.items()): + verbose("%s=%s" % (key,val)) + +def SetInfo(userName=None): + "Attempts to change the current users comment, then set it back" + if userName is None: userName=win32api.GetUserName() + oldData = win32net.NetUserGetInfo(server, userName, 3) + try: + d = oldData.copy() + d["usr_comment"] = "Test comment" + win32net.NetUserSetInfo(server, userName, 3, d) + new = win32net.NetUserGetInfo(server, userName, 3)['usr_comment'] + if str(new) != "Test comment": + raise RuntimeError("Could not read the same comment back - got %s" % new) + print("Changed the data for the user") + finally: + win32net.NetUserSetInfo(server, userName, 3, oldData) + +def SetComputerInfo(): + "Doesnt actually change anything, just make sure we could ;-)" + info = win32net.NetWkstaGetInfo(None, 502) + # *sob* - but we can't! Why not!!! + # win32net.NetWkstaSetInfo(None, 502, info) + +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(" -c : include the CreateUser test by default") + 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(): + tests = [] + for ob in list(globals().values()): + if type(ob)==type(main) and ob.__doc__: + tests.append(ob) + opts, args = getopt.getopt(sys.argv[1:], "s:hvc") + create_user = False + for opt, val in opts: + if opt=="-s": + global server + server = val + if opt=="-h": + usage(tests) + if opt=="-v": + global verbose_level + verbose_level = verbose_level + 1 + if opt=="-c": + create_user = True + + if len(args)==0: + print("Running all tests - use '-h' to see command-line options...") + dotests = tests + if not create_user: + dotests.remove(CreateUser) + 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() diff --git a/Lib/site-packages/win32/Demos/win32rcparser_demo.py b/Lib/site-packages/win32/Demos/win32rcparser_demo.py new file mode 100644 index 0000000..7175204 --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32rcparser_demo.py @@ -0,0 +1,77 @@ +# A demo of the win32rcparser module and using win32gui + +import win32gui +import win32api +import win32con +import win32rcparser +import commctrl +import sys, os + +this_dir = os.path.abspath(os.path.dirname(__file__)) +g_rcname = os.path.abspath( + os.path.join( this_dir, "..", "test", "win32rcparser", "test.rc")) + +if not os.path.isfile(g_rcname): + raise RuntimeError("Can't locate test.rc (should be at '%s')" % (g_rcname,)) + +class DemoWindow: + def __init__(self, dlg_template): + self.dlg_template = dlg_template + + def CreateWindow(self): + self._DoCreate(win32gui.CreateDialogIndirect) + + def DoModal(self): + return self._DoCreate(win32gui.DialogBoxIndirect) + + def _DoCreate(self, fn): + message_map = { + win32con.WM_INITDIALOG: self.OnInitDialog, + win32con.WM_CLOSE: self.OnClose, + win32con.WM_DESTROY: self.OnDestroy, + win32con.WM_COMMAND: self.OnCommand, + } + return fn(0, self.dlg_template, 0, message_map) + + def OnInitDialog(self, hwnd, msg, wparam, lparam): + self.hwnd = hwnd + # centre the dialog + desktop = win32gui.GetDesktopWindow() + l,t,r,b = win32gui.GetWindowRect(self.hwnd) + dt_l, dt_t, dt_r, dt_b = win32gui.GetWindowRect(desktop) + centre_x, centre_y = win32gui.ClientToScreen( desktop, ( (dt_r-dt_l)//2, (dt_b-dt_t)//2) ) + win32gui.MoveWindow(hwnd, centre_x-(r//2), centre_y-(b//2), r-l, b-t, 0) + + def OnCommand(self, hwnd, msg, wparam, lparam): + # Needed to make OK/Cancel work - no other controls are handled. + id = win32api.LOWORD(wparam) + if id in [win32con.IDOK, win32con.IDCANCEL]: + win32gui.EndDialog(hwnd, id) + + def OnClose(self, hwnd, msg, wparam, lparam): + win32gui.EndDialog(hwnd, 0) + + def OnDestroy(self, hwnd, msg, wparam, lparam): + pass + +def DemoModal(): + # Load the .rc file. + resources = win32rcparser.Parse(g_rcname) + for id, ddef in resources.dialogs.items(): + print("Displaying dialog", id) + w=DemoWindow(ddef) + w.DoModal() + +if __name__=='__main__': + flags = 0 + for flag in """ICC_DATE_CLASSES ICC_ANIMATE_CLASS ICC_ANIMATE_CLASS + ICC_BAR_CLASSES ICC_COOL_CLASSES ICC_DATE_CLASSES + ICC_HOTKEY_CLASS ICC_INTERNET_CLASSES ICC_LISTVIEW_CLASSES + ICC_PAGESCROLLER_CLASS ICC_PROGRESS_CLASS ICC_TAB_CLASSES + ICC_TREEVIEW_CLASSES ICC_UPDOWN_CLASS ICC_USEREX_CLASSES + ICC_WIN95_CLASSES """.split(): + flags |= getattr(commctrl, flag) + win32gui.InitCommonControlsEx(flags) + # Need to do this go get rich-edit working. + win32api.LoadLibrary("riched20.dll") + DemoModal() diff --git a/Lib/site-packages/win32/Demos/win32servicedemo.py b/Lib/site-packages/win32/Demos/win32servicedemo.py new file mode 100644 index 0000000..cd0c3a2 --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32servicedemo.py @@ -0,0 +1,23 @@ +import win32service +import win32con + + +def EnumServices(): + resume = 0 + accessSCM = win32con.GENERIC_READ + accessSrv = win32service.SC_MANAGER_ALL_ACCESS + + #Open Service Control Manager + hscm = win32service.OpenSCManager(None, None, accessSCM) + + #Enumerate Service Control Manager DB + + typeFilter = win32service.SERVICE_WIN32 + stateFilter = win32service.SERVICE_STATE_ALL + + statuses = win32service.EnumServicesStatus(hscm, typeFilter, stateFilter) + for (short_name, desc, status) in statuses: + print(short_name, desc, status) + + +EnumServices() diff --git a/Lib/site-packages/win32/Demos/win32ts_logoff_disconnected.py b/Lib/site-packages/win32/Demos/win32ts_logoff_disconnected.py new file mode 100644 index 0000000..1539386 --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32ts_logoff_disconnected.py @@ -0,0 +1,13 @@ +""" Finds any disconnected terminal service sessions and logs them off""" +import win32ts +sessions=win32ts.WTSEnumerateSessions(win32ts.WTS_CURRENT_SERVER_HANDLE) +for session in sessions: + """ + WTS_CONNECTSTATE_CLASS: WTSActive,WTSConnected,WTSConnectQuery,WTSShadow,WTSDisconnected, + WTSIdle,WTSListen,WTSReset,WTSDown,WTSInit + """ + if session['State']==win32ts.WTSDisconnected: + sessionid=session['SessionId'] + username=win32ts.WTSQuerySessionInformation(win32ts.WTS_CURRENT_SERVER_HANDLE, sessionid, win32ts.WTSUserName) + print('Logging off disconnected user:',username) + win32ts.WTSLogoffSession(win32ts.WTS_CURRENT_SERVER_HANDLE, sessionid, True) diff --git a/Lib/site-packages/win32/Demos/win32wnet/testwnet.py b/Lib/site-packages/win32/Demos/win32wnet/testwnet.py new file mode 100644 index 0000000..9a6ff70 --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32wnet/testwnet.py @@ -0,0 +1,105 @@ +import win32api +import win32wnet +import sys +from winnetwk import * +import os + +possible_shares = [] + +def _doDumpHandle(handle, level = 0): + indent = " " * level + while 1: + items = win32wnet.WNetEnumResource(handle, 0) + if len(items)==0: + break + for item in items: + try: + if item.dwDisplayType == RESOURCEDISPLAYTYPE_SHARE: + print(indent + "Have share with name:", item.lpRemoteName) + possible_shares.append(item) + elif item.dwDisplayType == RESOURCEDISPLAYTYPE_GENERIC: + print(indent + "Have generic resource with name:", item.lpRemoteName) + else: + # Try generic! + print(indent + "Enumerating " + item.lpRemoteName, end=' ') + k = win32wnet.WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY,0,item) + print() + _doDumpHandle(k, level + 1) + win32wnet.WNetCloseEnum(k) # could do k.Close(), but this is a good test! + except win32wnet.error as details: + print(indent + "Couldn't enumerate this resource: " + details.strerror) + +def TestOpenEnum(): + print("Enumerating all resources on the network - this may take some time...") + handle = win32wnet.WNetOpenEnum(RESOURCE_GLOBALNET,RESOURCETYPE_ANY,0,None) + + try: + _doDumpHandle(handle) + finally: + handle.Close() + print("Finished dumping all resources.") + +def findUnusedDriveLetter(): + existing = [x[0].lower() for x in win32api.GetLogicalDriveStrings().split('\0') if x] + handle = win32wnet.WNetOpenEnum(RESOURCE_REMEMBERED,RESOURCETYPE_DISK,0,None) + try: + while 1: + items = win32wnet.WNetEnumResource(handle, 0) + if len(items)==0: + break + xtra = [i.lpLocalName[0].lower() for i in items if i.lpLocalName] + existing.extend(xtra) + finally: + handle.Close() + for maybe in 'defghijklmnopqrstuvwxyz': + if maybe not in existing: + return maybe + raise RuntimeError("All drive mappings are taken?") + +def TestConnection(): + if len(possible_shares)==0: + print("Couldn't find any potential shares to connect to") + return + localName = findUnusedDriveLetter() + ':' + for share in possible_shares: + print("Attempting connection of", localName, "to", share.lpRemoteName) + try: + win32wnet.WNetAddConnection2(share.dwType, localName, share.lpRemoteName) + except win32wnet.error as details: + print("Couldn't connect: " + details.strerror) + continue + # Have a connection. + try: + fname = os.path.join(localName + "\\", os.listdir(localName + "\\")[0]) + try: + print("Universal name of '%s' is '%s'" % (fname, win32wnet.WNetGetUniversalName(fname))) + except win32wnet.error as details: + print("Couldn't get universal name of '%s': %s" % (fname, details.strerror)) + print("User name for this connection is", win32wnet.WNetGetUser(localName)) + finally: + win32wnet.WNetCancelConnection2(localName, 0, 0) + # and do it again, but this time by using the more modern + # NETRESOURCE way. + nr = win32wnet.NETRESOURCE() + nr.dwType = share.dwType + nr.lpLocalName = localName + nr.lpRemoteName = share.lpRemoteName + win32wnet.WNetAddConnection2(nr) + win32wnet.WNetCancelConnection2(localName, 0, 0) + + # and one more time using WNetAddConnection3 + win32wnet.WNetAddConnection3(0, nr) + win32wnet.WNetCancelConnection2(localName, 0, 0) + + # Only do the first share that succeeds. + break + +def TestGetUser(): + u = win32wnet.WNetGetUser() + print("Current global user is", repr(u)) + if u != win32wnet.WNetGetUser(None): + raise RuntimeError("Default value didnt seem to work!") + +TestGetUser() +TestOpenEnum() +TestConnection() diff --git a/Lib/site-packages/win32/Demos/win32wnet/winnetwk.py b/Lib/site-packages/win32/Demos/win32wnet/winnetwk.py new file mode 100644 index 0000000..df3e7ce --- /dev/null +++ b/Lib/site-packages/win32/Demos/win32wnet/winnetwk.py @@ -0,0 +1,98 @@ +# Generated by h2py from d:\mssdk\include\winnetwk.h +WNNC_NET_MSNET = 0x00010000 +WNNC_NET_LANMAN = 0x00020000 +WNNC_NET_NETWARE = 0x00030000 +WNNC_NET_VINES = 0x00040000 +WNNC_NET_10NET = 0x00050000 +WNNC_NET_LOCUS = 0x00060000 +WNNC_NET_SUN_PC_NFS = 0x00070000 +WNNC_NET_LANSTEP = 0x00080000 +WNNC_NET_9TILES = 0x00090000 +WNNC_NET_LANTASTIC = 0x000A0000 +WNNC_NET_AS400 = 0x000B0000 +WNNC_NET_FTP_NFS = 0x000C0000 +WNNC_NET_PATHWORKS = 0x000D0000 +WNNC_NET_LIFENET = 0x000E0000 +WNNC_NET_POWERLAN = 0x000F0000 +WNNC_NET_BWNFS = 0x00100000 +WNNC_NET_COGENT = 0x00110000 +WNNC_NET_FARALLON = 0x00120000 +WNNC_NET_APPLETALK = 0x00130000 +WNNC_NET_INTERGRAPH = 0x00140000 +WNNC_NET_SYMFONET = 0x00150000 +WNNC_NET_CLEARCASE = 0x00160000 +WNNC_NET_FRONTIER = 0x00170000 +WNNC_NET_BMC = 0x00180000 +WNNC_NET_DCE = 0x00190000 +WNNC_NET_DECORB = 0x00200000 +WNNC_NET_PROTSTOR = 0x00210000 +WNNC_NET_FJ_REDIR = 0x00220000 +WNNC_NET_DISTINCT = 0x00230000 +WNNC_NET_TWINS = 0x00240000 +WNNC_NET_RDR2SAMPLE = 0x00250000 +RESOURCE_CONNECTED = 0x00000001 +RESOURCE_GLOBALNET = 0x00000002 +RESOURCE_REMEMBERED = 0x00000003 +RESOURCE_RECENT = 0x00000004 +RESOURCE_CONTEXT = 0x00000005 +RESOURCETYPE_ANY = 0x00000000 +RESOURCETYPE_DISK = 0x00000001 +RESOURCETYPE_PRINT = 0x00000002 +RESOURCETYPE_RESERVED = 0x00000008 +RESOURCETYPE_UNKNOWN = 0xFFFFFFFF +RESOURCEUSAGE_CONNECTABLE = 0x00000001 +RESOURCEUSAGE_CONTAINER = 0x00000002 +RESOURCEUSAGE_NOLOCALDEVICE = 0x00000004 +RESOURCEUSAGE_SIBLING = 0x00000008 +RESOURCEUSAGE_ATTACHED = 0x00000010 +RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED) +RESOURCEUSAGE_RESERVED = 0x80000000 +RESOURCEDISPLAYTYPE_GENERIC = 0x00000000 +RESOURCEDISPLAYTYPE_DOMAIN = 0x00000001 +RESOURCEDISPLAYTYPE_SERVER = 0x00000002 +RESOURCEDISPLAYTYPE_SHARE = 0x00000003 +RESOURCEDISPLAYTYPE_FILE = 0x00000004 +RESOURCEDISPLAYTYPE_GROUP = 0x00000005 +RESOURCEDISPLAYTYPE_NETWORK = 0x00000006 +RESOURCEDISPLAYTYPE_ROOT = 0x00000007 +RESOURCEDISPLAYTYPE_SHAREADMIN = 0x00000008 +RESOURCEDISPLAYTYPE_DIRECTORY = 0x00000009 +RESOURCEDISPLAYTYPE_TREE = 0x0000000A +RESOURCEDISPLAYTYPE_NDSCONTAINER = 0x0000000B +NETPROPERTY_PERSISTENT = 1 +CONNECT_UPDATE_PROFILE = 0x00000001 +CONNECT_UPDATE_RECENT = 0x00000002 +CONNECT_TEMPORARY = 0x00000004 +CONNECT_INTERACTIVE = 0x00000008 +CONNECT_PROMPT = 0x00000010 +CONNECT_NEED_DRIVE = 0x00000020 +CONNECT_REFCOUNT = 0x00000040 +CONNECT_REDIRECT = 0x00000080 +CONNECT_LOCALDRIVE = 0x00000100 +CONNECT_CURRENT_MEDIA = 0x00000200 +CONNECT_DEFERRED = 0x00000400 +CONNECT_RESERVED = 0xFF000000 +CONNDLG_RO_PATH = 0x00000001 +CONNDLG_CONN_POINT = 0x00000002 +CONNDLG_USE_MRU = 0x00000004 +CONNDLG_HIDE_BOX = 0x00000008 +CONNDLG_PERSIST = 0x00000010 +CONNDLG_NOT_PERSIST = 0x00000020 +DISC_UPDATE_PROFILE = 0x00000001 +DISC_NO_FORCE = 0x00000040 +UNIVERSAL_NAME_INFO_LEVEL = 0x00000001 +REMOTE_NAME_INFO_LEVEL = 0x00000002 +WNFMT_MULTILINE = 0x01 +WNFMT_ABBREVIATED = 0x02 +WNFMT_INENUM = 0x10 +WNFMT_CONNECTION = 0x20 +NETINFO_DLL16 = 0x00000001 +NETINFO_DISKRED = 0x00000004 +NETINFO_PRINTERRED = 0x00000008 +RP_LOGON = 0x01 +RP_INIFILE = 0x02 +PP_DISPLAYERRORS = 0x01 +WNCON_FORNETCARD = 0x00000001 +WNCON_NOTROUTED = 0x00000002 +WNCON_SLOWLINK = 0x00000004 +WNCON_DYNAMIC = 0x00000008 diff --git a/Lib/site-packages/win32/Demos/winprocess.py b/Lib/site-packages/win32/Demos/winprocess.py new file mode 100644 index 0000000..b034833 --- /dev/null +++ b/Lib/site-packages/win32/Demos/winprocess.py @@ -0,0 +1,206 @@ +""" +Windows Process Control + +winprocess.run launches a child process and returns the exit code. +Optionally, it can: + redirect stdin, stdout & stderr to files + run the command as another user + limit the process's running time + control the process window (location, size, window state, desktop) +Works on Windows NT, 2000 & XP. Requires Mark Hammond's win32 +extensions. + +This code is free for any purpose, with no warranty of any kind. +-- John B. Dell'Aquila +""" + +import win32api, win32process, win32security +import win32event, win32con, msvcrt, win32gui +import os + + +def logonUser(loginString): + """ + Login as specified user and return handle. + loginString: 'Domain\nUser\nPassword'; for local + login use . or empty string as domain + e.g. '.\nadministrator\nsecret_password' + """ + domain, user, passwd = loginString.split('\n') + return win32security.LogonUser( + user, + domain, + passwd, + win32con.LOGON32_LOGON_INTERACTIVE, + win32con.LOGON32_PROVIDER_DEFAULT + ) + + +class Process: + """ + A Windows process. + """ + + def __init__(self, cmd, login=None, + hStdin=None, hStdout=None, hStderr=None, + show=1, xy=None, xySize=None, + desktop=None): + """ + Create a Windows process. + cmd: command to run + login: run as user 'Domain\nUser\nPassword' + hStdin, hStdout, hStderr: + handles for process I/O; default is caller's stdin, + stdout & stderr + show: wShowWindow (0=SW_HIDE, 1=SW_NORMAL, ...) + xy: window offset (x, y) of upper left corner in pixels + xySize: window size (width, height) in pixels + desktop: lpDesktop - name of desktop e.g. 'winsta0\\default' + None = inherit current desktop + '' = create new desktop if necessary + + User calling login requires additional privileges: + Act as part of the operating system [not needed on Windows XP] + Increase quotas + Replace a process level token + Login string must EITHER be an administrator's account + (ordinary user can't access current desktop - see Microsoft + Q165194) OR use desktop='' to run another desktop invisibly + (may be very slow to startup & finalize). + """ + si = win32process.STARTUPINFO() + si.dwFlags = (win32con.STARTF_USESTDHANDLES ^ + win32con.STARTF_USESHOWWINDOW) + if hStdin is None: + si.hStdInput = win32api.GetStdHandle(win32api.STD_INPUT_HANDLE) + else: + si.hStdInput = hStdin + if hStdout is None: + si.hStdOutput = win32api.GetStdHandle(win32api.STD_OUTPUT_HANDLE) + else: + si.hStdOutput = hStdout + if hStderr is None: + si.hStdError = win32api.GetStdHandle(win32api.STD_ERROR_HANDLE) + else: + si.hStdError = hStderr + si.wShowWindow = show + if xy is not None: + si.dwX, si.dwY = xy + si.dwFlags ^= win32con.STARTF_USEPOSITION + if xySize is not None: + si.dwXSize, si.dwYSize = xySize + si.dwFlags ^= win32con.STARTF_USESIZE + if desktop is not None: + si.lpDesktop = desktop + procArgs = (None, # appName + cmd, # commandLine + None, # processAttributes + None, # threadAttributes + 1, # bInheritHandles + win32process.CREATE_NEW_CONSOLE, # dwCreationFlags + None, # newEnvironment + None, # currentDirectory + si) # startupinfo + if login is not None: + hUser = logonUser(login) + win32security.ImpersonateLoggedOnUser(hUser) + procHandles = win32process.CreateProcessAsUser(hUser, *procArgs) + win32security.RevertToSelf() + else: + procHandles = win32process.CreateProcess(*procArgs) + self.hProcess, self.hThread, self.PId, self.TId = procHandles + + def wait(self, mSec=None): + """ + Wait for process to finish or for specified number of + milliseconds to elapse. + """ + if mSec is None: + mSec = win32event.INFINITE + return win32event.WaitForSingleObject(self.hProcess, mSec) + + def kill(self, gracePeriod=5000): + """ + Kill process. Try for an orderly shutdown via WM_CLOSE. If + still running after gracePeriod (5 sec. default), terminate. + """ + win32gui.EnumWindows(self.__close__, 0) + if self.wait(gracePeriod) != win32event.WAIT_OBJECT_0: + win32process.TerminateProcess(self.hProcess, 0) + win32api.Sleep(100) # wait for resources to be released + + def __close__(self, hwnd, dummy): + """ + EnumWindows callback - sends WM_CLOSE to any window + owned by this process. + """ + TId, PId = win32process.GetWindowThreadProcessId(hwnd) + if PId == self.PId: + win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0) + + def exitCode(self): + """ + Return process exit code. + """ + return win32process.GetExitCodeProcess(self.hProcess) + + +def run(cmd, mSec=None, stdin=None, stdout=None, stderr=None, **kw): + """ + Run cmd as a child process and return exit code. + mSec: terminate cmd after specified number of milliseconds + stdin, stdout, stderr: + file objects for child I/O (use hStdin etc. to attach + handles instead of files); default is caller's stdin, + stdout & stderr; + kw: see Process.__init__ for more keyword options + """ + if stdin is not None: + kw['hStdin'] = msvcrt.get_osfhandle(stdin.fileno()) + if stdout is not None: + kw['hStdout'] = msvcrt.get_osfhandle(stdout.fileno()) + if stderr is not None: + kw['hStderr'] = msvcrt.get_osfhandle(stderr.fileno()) + child = Process(cmd, **kw) + if child.wait(mSec) != win32event.WAIT_OBJECT_0: + child.kill() + raise WindowsError('process timeout exceeded') + return child.exitCode() + + +if __name__ == '__main__': + + # Pipe commands to a shell and display the output in notepad + print('Testing winprocess.py...') + + import tempfile + + timeoutSeconds = 15 + cmdString = """\ +REM Test of winprocess.py piping commands to a shell.\r +REM This 'notepad' process will terminate in %d seconds.\r +vol\r +net user\r +_this_is_a_test_of_stderr_\r +""" % timeoutSeconds + + cmd_name = tempfile.mktemp() + out_name = cmd_name + '.txt' + try: + cmd = open(cmd_name, "w+b") + out = open(out_name, "w+b") + cmd.write(cmdString.encode('mbcs')) + cmd.seek(0) + print('CMD.EXE exit code:', run('cmd.exe', show=0, stdin=cmd, + stdout=out, stderr=out)) + cmd.close() + print('NOTEPAD exit code:', run('notepad.exe %s' % out.name, + show=win32con.SW_MAXIMIZE, + mSec=timeoutSeconds*1000)) + out.close() + finally: + for n in (cmd_name, out_name): + try: + os.unlink(cmd_name) + except os.error: + pass diff --git a/Lib/site-packages/win32/_win32sysloader.pyd b/Lib/site-packages/win32/_win32sysloader.pyd new file mode 100644 index 0000000..abed4b2 Binary files /dev/null and b/Lib/site-packages/win32/_win32sysloader.pyd differ diff --git a/Lib/site-packages/win32/_winxptheme.pyd b/Lib/site-packages/win32/_winxptheme.pyd new file mode 100644 index 0000000..bb8af10 Binary files /dev/null and b/Lib/site-packages/win32/_winxptheme.pyd differ diff --git a/Lib/site-packages/win32/include/PyWinTypes.h b/Lib/site-packages/win32/include/PyWinTypes.h new file mode 100644 index 0000000..8430e22 --- /dev/null +++ b/Lib/site-packages/win32/include/PyWinTypes.h @@ -0,0 +1,833 @@ + +#ifndef __PYWINTYPES_H__ +#define __PYWINTYPES_H__ + +// If building under a GCC, tweak what we need. +#if defined(__GNUC__) && defined(_POSIX_C_SOURCE) + // python.h complains if _POSIX_C_SOURCE is already defined +# undef _POSIX_C_SOURCE +#endif + +// early msvc versions complain about pragma #s it doesn't understand +// C:\mssdk\VC\INCLUDE\string.h(142) : warning C4616: #pragma warning : warning number '6059' out of range, must be between '4001' and '4999' +// and: +// C:\mssdk\include\wingdi.h(4340) : warning C4068: unknown pragma +// I doubt we ever care about that warning, so unconditionally nuke em! +#pragma warning( disable:4616 4068 ) +// Python.h and Windows.h both protect themselves from multiple +// includes - so it is safe to do here (and provides a handy +// choke point for #include vagaries + +// Some other warnings generated by MSVC6 which we don't care about +#if (PY_VERSION_HEX < 0x02060000) +#pragma warning( disable:4035 ) +#endif + +// windows rpc.h defines "small" as "char" which breaks Python's accu.h, +// so we undefine it before including python. +#ifdef small +#undef small +#endif + +#include "Python.h" +// many many files need python's structmember.h, and its possible people +// #included windows.h before including us... +#ifdef WRITE_RESTRICTED +#undef WRITE_RESTRICTED +#endif +#include "structmember.h" +// and python's structmember.h #defines this, conflicting with windows.h +#ifdef WRITE_RESTRICTED +#undef WRITE_RESTRICTED +#endif +#include "windows.h" +#undef WRITE_RESTRICTED // stop anyone using the wrong one accidently... + + +// Helpers for our modules. +// Some macros to help the pywin32 modules co-exist in py2x and py3k. +// Creates and initializes local variables called 'module' and 'dict'. + +#if (PY_VERSION_HEX < 0x03000000) + +// Use to define the function itself (ie, its name, linkage, params) +#define PYWIN_MODULE_INIT_FUNC(module_name) \ + extern "C" __declspec(dllexport) void init##module_name(void) + +// If the module needs to early-exit on an error condition. +#define PYWIN_MODULE_INIT_RETURN_ERROR return; + +// When the module has successfully initialized. +#define PYWIN_MODULE_INIT_RETURN_SUCCESS return; + +// To setup the module object itself and the module's dictionary. +#define PYWIN_MODULE_INIT_PREPARE(module_name, functions, docstring) \ + PyObject *dict, *module; \ + if (PyWinGlobals_Ensure()==-1) \ + return; \ + if (!(module = Py_InitModule(#module_name, functions))) \ + return; \ + if (!(dict = PyModule_GetDict(module))) \ + return; + +#else +// py3k module helpers. +// Use to define the function itself (ie, its name, linkage, params) +#define PYWIN_MODULE_INIT_FUNC(module_name) \ + extern "C" __declspec(dllexport) PyObject *PyInit_##module_name(void) + +// If the module needs to early-exit on an error condition. +#define PYWIN_MODULE_INIT_RETURN_ERROR return NULL; + +// When the module has successfully initialized. +#define PYWIN_MODULE_INIT_RETURN_SUCCESS return module; + +// To setup the module object itself and the module's dictionary. +#define PYWIN_MODULE_INIT_PREPARE(module_name, functions, docstring) \ + PyObject *dict, *module; \ + static PyModuleDef module_name##_def = { \ + PyModuleDef_HEAD_INIT, \ + #module_name, \ + docstring , \ + -1, \ + functions }; \ + if (PyWinGlobals_Ensure()==-1) \ + return NULL; \ + if (!(module = PyModule_Create(&module_name##_def))) \ + return NULL; \ + if (!(dict = PyModule_GetDict(module))) \ + return NULL; +#endif // PY_VERSION_HEX + + +// Helpers for our types. +#if (PY_VERSION_HEX < 0x03000000) +#define PYWIN_OBJECT_HEAD PyObject_HEAD_INIT(&PyType_Type) 0, +#define PYWIN_ATTR_CONVERT PyString_AsString + +#else // Py3k definitions +// Macro to handle PyObject layout changes in Py3k +#define PYWIN_OBJECT_HEAD PyVarObject_HEAD_INIT(NULL, 0) + +/* Attribute names are passed as Unicode in Py3k, so use a macro to + switch between string and unicode conversion. This function is not + documented, but is used extensively in the Python codebase itself, + so it's reasonable to assume it won't disappear anytime soon. +*/ +#define PYWIN_ATTR_CONVERT _PyUnicode_AsString + +/* Some API functions changed/removed in python 3.0 + Definitions for the string functions are in stringobject.h, + but comments indicate that this header is likely to go away in 3.1. +*/ +#define PyString_Check PyBytes_Check +#define PyString_Size PyBytes_Size +#define PyString_AsString PyBytes_AsString +#define PyString_AsStringAndSize PyBytes_AsStringAndSize +#define PyString_FromString PyBytes_FromString +#define PyString_FromStringAndSize PyBytes_FromStringAndSize +#define _PyString_Resize _PyBytes_Resize +#define PyString_AS_STRING PyBytes_AS_STRING +#define PyString_GET_SIZE PyBytes_GET_SIZE +#define PyString_Concat PyBytes_Concat +#define PyInt_Check PyLong_Check +#define PyInt_FromLong PyLong_FromLong +#define PyInt_AsLong PyLong_AsLong +#define PyInt_AS_LONG PyLong_AS_LONG +#define PyInt_FromSsize_t PyLong_FromSsize_t +#define PyInt_AsSsize_t PyLong_AsSsize_t +#define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask +#define PyNumber_Int PyNumber_Long +#endif // (PY_VERSION_HEX < 0x03000000) + +// See PEP-353 - this is the "official" test... +#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) +// 2.3 and before have no Py_ssize_t +typedef int Py_ssize_t; +#define PyInt_FromSsize_t PyInt_FromLong +#define PyInt_AsSsize_t PyInt_AsLong +#define PY_SSIZE_T_MAX INT_MAX +#define PY_SSIZE_T_MIN INT_MIN +#endif + +// Py_hash_t was introduced as the size of a pointer in python 3.2 - it +// was a simple long before that. +#if PY_VERSION_HEX < 0x03020000 +typedef long Py_hash_t; +#else +typedef Py_ssize_t Py_hash_t; +#endif + +// This only enables runtime checks in debug builds - so we use +// our own so we can enable it always should we desire... +#define PyWin_SAFE_DOWNCAST Py_SAFE_DOWNCAST + +// Lars: for WAVEFORMATEX +#include "mmsystem.h" + + +// *** NOTE *** FREEZE_PYWINTYPES is deprecated. It used to be used +// by the 'freeze' tool, but now py2exe etc do a far better job, and +// don't require a custom built pywintypes DLL. +#ifdef FREEZE_PYWINTYPES + /* The pywintypes module is being included in a frozen .EXE/.DLL */ +# define PYWINTYPES_EXPORT +#else +# ifdef BUILD_PYWINTYPES + /* We are building pywintypesxx.dll */ +# define PYWINTYPES_EXPORT __declspec(dllexport) +#else + /* This module uses pywintypesxx.dll */ +# define PYWINTYPES_EXPORT __declspec(dllimport) +# if defined(_MSC_VER) +# if defined(DEBUG) || defined(_DEBUG) +# pragma comment(lib,"pywintypes_d.lib") +# else +# pragma comment(lib,"pywintypes.lib") +# endif // DEBUG/_DEBUG +# endif // _MSC_VER +# endif // BUILD_PYWINTYPES +#endif // FREEZE_PYWINTYPES + +#if (PY_VERSION_HEX >= 0x03000000) +// Py3k uses memoryview object in place of buffer +extern PYWINTYPES_EXPORT PyObject *PyBuffer_New(Py_ssize_t size); +extern PYWINTYPES_EXPORT PyObject *PyBuffer_FromMemory(void *buf, Py_ssize_t size); +#endif + +// Formats a python traceback into a character string - result must be free()ed +PYWINTYPES_EXPORT char *GetPythonTraceback(PyObject *exc_type, PyObject *exc_value, PyObject *exc_tb); + +#include +/* +** Error/Exception handling +*/ +extern PYWINTYPES_EXPORT PyObject *PyWinExc_ApiError; +// Register a Windows DLL that contains the messages in the specified range. +extern PYWINTYPES_EXPORT BOOL PyWin_RegisterErrorMessageModule(DWORD first, DWORD last, HINSTANCE hmod); +// Get the previously registered hmodule for an error code. +extern PYWINTYPES_EXPORT HINSTANCE PyWin_GetErrorMessageModule(DWORD err); + + +/* A global function that sets an API style error (ie, (code, fn, errTest)) */ +PYWINTYPES_EXPORT PyObject *PyWin_SetAPIError(char *fnName, long err = 0); + +/* Basic COM Exception handling. The main COM exception object + is actually defined here. However, the most useful functions + for raising the exception are still in the COM package. Therefore, + you can use the fn below to raise a basic COM exception - no fancy error + messages available, just the HRESULT. It will, however, _be_ a COM + exception, and therefore trappable like any other COM exception +*/ +extern PYWINTYPES_EXPORT PyObject *PyWinExc_COMError; +PYWINTYPES_EXPORT PyObject *PyWin_SetBasicCOMError(HRESULT hr); + +// Given a PyObject (string, Unicode, etc) create a "BSTR" with the value +PYWINTYPES_EXPORT BOOL PyWinObject_AsBstr(PyObject *stringObject, BSTR *pResult, BOOL bNoneOK = FALSE, DWORD *pResultLen = NULL); +// And free it when finished. +PYWINTYPES_EXPORT void PyWinObject_FreeBstr(BSTR pResult); + +PYWINTYPES_EXPORT PyObject *PyWinObject_FromBstr(const BSTR bstr, BOOL takeOwnership=FALSE); + +// Given a string or Unicode object, get WCHAR characters. +PYWINTYPES_EXPORT BOOL PyWinObject_AsWCHAR(PyObject *stringObject, WCHAR **pResult, BOOL bNoneOK = FALSE, DWORD *pResultLen = NULL); +// And free it when finished. +PYWINTYPES_EXPORT void PyWinObject_FreeWCHAR(WCHAR *pResult); + +// As of Python 2.6, Python switched to 'wchar_t' for unicode, so old +// win32 structures that still use 'unsigned short' now fail from C++ with +// VS8 so we provide a couple of helpers. +// XXX - but, when trying to use VC2003 with x64, the SDK x64 compiler +// reports itself as 14.00.40310.41 - so this breaks under that compiler +// Its not clear how to resolve this, but while VS2003 is the default +// compiler, that is what must work. +// py2.5 on x64 also needs it, and that is min x64 we support +// The main difference seems to be whether the compiler has /Zc:wchar_t (Treat wchar_t as a builtin type) +// on by default, and according to MSDN, _NATIVE_WCHAR_T_DEFINED is the way to check for it +#ifdef _NATIVE_WCHAR_T_DEFINED +inline BOOL PyWinObject_AsWCHAR(PyObject *stringObject, unsigned short **pResult, BOOL bNoneOK = FALSE, DWORD *pResultLen = NULL) +{ + return PyWinObject_AsWCHAR(stringObject, (WCHAR **)pResult, bNoneOK, pResultLen); +} +inline void PyWinObject_FreeWCHAR(unsigned short *pResult) +{ + PyWinObject_FreeWCHAR((WCHAR *)pResult); +} +#endif + +// Given a PyObject (string, Unicode, etc) create a "char *" with the value +// if pResultLen != NULL, it will be set to the result size NOT INCLUDING +// TERMINATOR (to be in line with SysStringLen, PyString_*, etc) +PYWINTYPES_EXPORT BOOL PyWinObject_AsString(PyObject *stringObject, char **pResult, BOOL bNoneOK = FALSE, DWORD *pResultLen = NULL); +// And free it when finished. +PYWINTYPES_EXPORT void PyWinObject_FreeString(char *pResult); +PYWINTYPES_EXPORT void PyWinObject_FreeString(WCHAR *pResult); + +// Automatically freed WCHAR that can be used anywhere WCHAR * is required +class TmpWCHAR +{ +public: + WCHAR *tmp; + TmpWCHAR() { tmp=NULL; } + TmpWCHAR(WCHAR *t) { tmp=t; } + WCHAR * operator= (WCHAR *t){ + PyWinObject_FreeWCHAR(tmp); + tmp=t; + return t; + } + WCHAR ** operator& () {return &tmp;} + boolean operator== (WCHAR *t) { return tmp==t; } + operator WCHAR *() { return tmp; } + ~TmpWCHAR() { PyWinObject_FreeWCHAR(tmp); } +}; + + +// Buffer functions that can be used in place of 's#' input format or PyString_AsStringAndSize +// for 64-bit compatibility and API consistency +PYWINTYPES_EXPORT BOOL PyWinObject_AsReadBuffer(PyObject *ob, void **buf, DWORD *buf_len, BOOL bNoneOk=FALSE); +PYWINTYPES_EXPORT BOOL PyWinObject_AsWriteBuffer(PyObject *ob, void **buf, DWORD *buf_len, BOOL bNoneOk=FALSE); + +// For 64-bit python compatibility, convert sequence to tuple and check length fits in a DWORD +PYWINTYPES_EXPORT PyObject *PyWinSequence_Tuple(PyObject *obseq, DWORD *len); + + +// an 'int' version (but aren't 'int' and 'DWORD' the same size? +// Maybe a signed-ness issue? +inline BOOL PyWinObject_AsReadBuffer(PyObject *ob, void **buf, int *buf_len, BOOL bNoneOk=FALSE) +{ + return PyWinObject_AsReadBuffer(ob, buf, (DWORD *)buf_len, bNoneOk); +} + +/* ANSI/Unicode Support */ +/* If UNICODE defined, will be a BSTR - otherwise a char * + Either way - PyWinObject_FreeTCHAR() must be called +*/ + +// Helpers with py3k in mind: the result object is always a "core string" +// object; ie, a string in py2k and unicode in py3k. Mainly to be used for +// objects that *must* be that type - tp_str slots, __dict__ items, etc. If +// Python doesn't *insist* the result be this type, consider using a function +// that always returns a unicode object (ie, most of the "PyWinObject_From*CHAR" +// functions) +PYWINTYPES_EXPORT PyObject *PyWinCoreString_FromString(const char *str, Py_ssize_t len=(Py_ssize_t)-1); +PYWINTYPES_EXPORT PyObject *PyWinCoreString_FromString(const WCHAR *str, Py_ssize_t len=(Py_ssize_t)-1); + +#define PyWinObject_FromWCHAR PyWinObject_FromOLECHAR + +// Converts a series of consecutive null terminated strings into a list +PYWINTYPES_EXPORT PyObject *PyWinObject_FromMultipleString(WCHAR *multistring); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromMultipleString(char *multistring); +// Converts a sequence of str/unicode objects into a series of consecutive null-terminated +// wide character strings with extra terminating null +PYWINTYPES_EXPORT BOOL PyWinObject_AsMultipleString(PyObject *ob, WCHAR **pmultistring, BOOL bNoneOK=TRUE, DWORD *chars_returned=NULL); +PYWINTYPES_EXPORT void PyWinObject_FreeMultipleString(WCHAR *pmultistring); + +// Converts a sequence of str/unicode objects into a series of consecutive character strings +// terminated by double null +PYWINTYPES_EXPORT BOOL PyWinObject_AsMultipleString(PyObject *ob, char **pmultistring, BOOL bNoneOK=TRUE, DWORD *chars_returned=NULL); +PYWINTYPES_EXPORT void PyWinObject_FreeMultipleString(char *pmultistring); + +// Convert a sequence of strings to an array of WCHAR pointers +PYWINTYPES_EXPORT void PyWinObject_FreeWCHARArray(LPWSTR *wchars, DWORD str_cnt); +PYWINTYPES_EXPORT BOOL PyWinObject_AsWCHARArray(PyObject *str_seq, LPWSTR **wchars, DWORD *str_cnt, BOOL bNoneOK = FALSE); + +// Convert a sequence of string or unicode objects to an array of char * +PYWINTYPES_EXPORT void PyWinObject_FreeCharArray(char **pchars, DWORD str_cnt); +PYWINTYPES_EXPORT BOOL PyWinObject_AsCharArray(PyObject *str_seq, char ***pchars, DWORD *str_cnt, BOOL bNoneOK = FALSE); + +PYWINTYPES_EXPORT PyObject *PyWinObject_FromOLECHAR(const OLECHAR * str); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromOLECHAR(const OLECHAR * str, int numChars); + +// String support for buffers allocated via a function of your choice. +PYWINTYPES_EXPORT BOOL PyWinObject_AsPfnAllocatedWCHAR(PyObject *stringObject, + void *(*pfnAllocator)(ULONG), + WCHAR **ppResult, + BOOL bNoneOK = FALSE, + DWORD *pResultLen = NULL); + +#ifdef UNICODE +// XXX - "AsTCHAR" functions should all die - the type of the Python object +// being returned should not depend on UNICODE or not. +#define PyWinObject_AsTCHAR PyWinObject_AsWCHAR +#define PyWinObject_FreeTCHAR PyWinObject_FreeWCHAR +#define PyWinObject_FromTCHAR PyWinObject_FromOLECHAR +#else /* not UNICODE */ +#define PyWinObject_AsTCHAR PyWinObject_AsString +#define PyWinObject_FreeTCHAR PyWinObject_FreeString + +// PyWinObject_FromTCHAR in a non-unicode build still depends on py3k or not: +// py2x a string object is returned (no conversions). py3x a unicode object +// is returned (ie, the string is decoded) +PYWINTYPES_EXPORT PyObject *PyWinObject_FromTCHAR(const char *str, Py_ssize_t len=(Py_ssize_t)-1); + +#endif // UNICODE + +// String support for buffers allocated via CoTaskMemAlloc and CoTaskMemFree +PYWINTYPES_EXPORT BOOL PyWinObject_AsTaskAllocatedWCHAR(PyObject *stringObject, WCHAR **ppResult, BOOL bNoneOK = FALSE, DWORD *pResultLen = NULL); +PYWINTYPES_EXPORT void PyWinObject_FreeTaskAllocatedWCHAR(WCHAR * str); + +PYWINTYPES_EXPORT void PyWinObject_FreeString(char *str); +PYWINTYPES_EXPORT void PyWinObject_FreeString(WCHAR *str); + +// Copy null terminated string with same allocator as PyWinObject_AsWCHAR, etc +PYWINTYPES_EXPORT WCHAR *PyWin_CopyString(const WCHAR *input); +PYWINTYPES_EXPORT char *PyWin_CopyString(const char *input); + + +// Pointers. +// Substitute for Python's inconsistent PyLong_AsVoidPtr +PYWINTYPES_EXPORT BOOL PyWinLong_AsVoidPtr(PyObject *ob, void **pptr); +PYWINTYPES_EXPORT PyObject *PyWinLong_FromVoidPtr(const void *ptr); + +/* +** LARGE_INTEGER objects +*/ +//AsLARGE_INTEGER takes either int or long +PYWINTYPES_EXPORT BOOL PyWinObject_AsLARGE_INTEGER(PyObject *ob, LARGE_INTEGER *pResult); +PYWINTYPES_EXPORT BOOL PyWinObject_AsULARGE_INTEGER(PyObject *ob, ULARGE_INTEGER *pResult); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromLARGE_INTEGER(LARGE_INTEGER &val); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromULARGE_INTEGER(ULARGE_INTEGER &val); +// Helpers that take a Py_LONG_LONG, but (a) have pywin32 consistent signatures +// and (b) handle int *and* long (where Python only starts doing that in the +// PyLong_* APIs post 2.4) +// We also happen to know a LARGE_INTEGER is an __int64, so do it the easy way +#define PyWinObject_AsPY_LONG_LONG(ob, pResult) PyWinObject_AsLARGE_INTEGER((ob), (LARGE_INTEGER *)(pResult)) +#define PyWinObject_AsUPY_LONG_LONG(ob, pResult) PyWinObject_AsULARGE_INTEGER((ob), (ULARGE_INTEGER *)(pResult)) +#define PyWinObject_FromPY_LONG_LONG(val) PyWinObject_FromLARGE_INTEGER((LARGE_INTEGER)val) +#define PyWinObject_FromUPY_LONG_LONG(val) PyWinObject_FromULARGE_INTEGER((ULARGE_INTEGER)val) + +// A DWORD_PTR and ULONG_PTR appear to mean "integer long enough to hold a pointer" +// It is *not* actually a pointer (but is the same size as a pointer) +inline PyObject *PyWinObject_FromULONG_PTR(ULONG_PTR v) { + return PyWinLong_FromVoidPtr((void *)v); +} +inline BOOL PyWinLong_AsULONG_PTR(PyObject *ob, ULONG_PTR *r) { + return PyWinLong_AsVoidPtr(ob, (void **)r); +} + +inline PyObject *PyWinObject_FromDWORD_PTR(DWORD_PTR v) { + return PyLong_FromVoidPtr((void *)v); +} +inline BOOL PyWinLong_AsDWORD_PTR(PyObject *ob, DWORD_PTR *r) { + return PyWinLong_AsVoidPtr(ob, (void **)r); +} + + +/* +** OVERLAPPED Object and API +*/ +class PyOVERLAPPED; // forward declare +extern PYWINTYPES_EXPORT PyTypeObject PyOVERLAPPEDType; // the Type for PyOVERLAPPED +#define PyOVERLAPPED_Check(ob) ((ob)->ob_type == &PyOVERLAPPEDType) +PYWINTYPES_EXPORT BOOL PyWinObject_AsOVERLAPPED(PyObject *ob, OVERLAPPED **ppOverlapped, BOOL bNoneOK = TRUE); +PYWINTYPES_EXPORT BOOL PyWinObject_AsPyOVERLAPPED(PyObject *ob, PyOVERLAPPED **ppOverlapped, BOOL bNoneOK = TRUE); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromOVERLAPPED(const OVERLAPPED *pOverlapped); + +// A global function that can work as a module method for making an OVERLAPPED object. +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewOVERLAPPED(PyObject *self, PyObject *args); + +#ifndef NO_PYWINTYPES_IID +/* +** IID/GUID support +*/ + +extern PYWINTYPES_EXPORT PyTypeObject PyIIDType; // the Type for PyIID +#define PyIID_Check(ob) ((ob)->ob_type == &PyIIDType) + +// Given an object repring a CLSID (either PyIID or string), fill the CLSID. +PYWINTYPES_EXPORT BOOL PyWinObject_AsIID(PyObject *obCLSID, CLSID *clsid); + +// return a native PyIID object representing an IID +PYWINTYPES_EXPORT PyObject *PyWinObject_FromIID(const IID &riid); + +// return a string/Unicode object representing an IID +PYWINTYPES_EXPORT PyObject *PyWinCoreString_FromIID(const IID &riid); + +// A global function that can work as a module method for making an IID object. +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewIID( PyObject *self, PyObject *args); +#endif /*NO_PYWINTYPES_IID */ + +/* +** TIME support +*/ +// The NO_PYWINTYPES_TIME define was initially used for CE builds. We now +// use that symbol to mean "do we include our old, crap, custom time object?" +// If not defined, we exclusively support datetime objects via the C API. +// (Note py2.3 doesn't have a C API, so will not currently build with +// NO_PYWINTYPES_TIME defined.) +// TODO: If both builtin and datetime objects are enabled, we will enable +// some transitional period using something like +// pywintypes.__future_datatime__, but for now this is defined purely at build +// time. +#if (PY_VERSION_HEX >= 0x03000000) +# define NO_PYWINTYPES_TIME +#endif + +// Python 2.3 doesn't have C Api for datetime, so can't have our new funky +// support. +#if (PY_VERSION_HEX >= 0x02040000) +# define PYWIN_HAVE_DATETIME_CAPI +#endif + +// XXX - fixme - ack - we don't yet like *both* defines existing - and for now +// its only enabled in py3k +#if (PY_VERSION_HEX < 0x03000000) +# undef PYWIN_HAVE_DATETIME_CAPI +#endif + +PYWINTYPES_EXPORT PyObject *PyWinObject_FromSYSTEMTIME(const SYSTEMTIME &t); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromFILETIME(const FILETIME &t); + +// Converts a TimeStamp, which is in 100 nanosecond units like a FILETIME +// TimeStamp is actually defined as a LARGE_INTEGER, so this function will also +// accept Windows security "TimeStamp" objects directly - however, we use a +// LARGE_INTEGER prototype to avoid pulling in the windows security headers. +PYWINTYPES_EXPORT PyObject *PyWinObject_FromTimeStamp(const LARGE_INTEGER &t); +PYWINTYPES_EXPORT PyObject *PyWinTimeObject_Fromtime_t(time_t t); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromDATE(DATE t); + +PYWINTYPES_EXPORT BOOL PyWinObject_AsDATE(PyObject *ob, DATE *pDate); +PYWINTYPES_EXPORT BOOL PyWinObject_AsFILETIME(PyObject *ob, FILETIME *pDate); +PYWINTYPES_EXPORT BOOL PyWinObject_AsSYSTEMTIME(PyObject *ob, SYSTEMTIME *pDate); + +// A global function that can work as a module method for making a time object. +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewTime( PyObject *self, PyObject *args); + +PYWINTYPES_EXPORT BOOL PyWinTime_Check(PyObject *ob); + + +#ifndef NO_PYWINTYPES_TIME + +extern PYWINTYPES_EXPORT PyTypeObject PyTimeType; // the Type for PyTime +#define PyWinTime_CHECK(ob) ((ob)->ob_type == &PyTimeType) + +#endif // NO_PYWINTYPES_TIME + +// functions to return WIN32_FIND_DATA tuples, used in shell, win32api, and win32file +PYWINTYPES_EXPORT PyObject *PyObject_FromWIN32_FIND_DATAA(WIN32_FIND_DATAA *pData); +PYWINTYPES_EXPORT PyObject *PyObject_FromWIN32_FIND_DATAW(WIN32_FIND_DATAW *pData); +#ifdef UNICODE +#define PyObject_FromWIN32_FIND_DATA PyObject_FromWIN32_FIND_DATAW +#else +#define PyObject_FromWIN32_FIND_DATA PyObject_FromWIN32_FIND_DATAA +#endif + +// POINT tuple, used in win32api_display.cpp and win32gui.i +PYWINTYPES_EXPORT BOOL PyWinObject_AsPOINT(PyObject *obpoint, LPPOINT ppoint); + +// IO_COUNTERS dict, used in win32process and win32job +PYWINTYPES_EXPORT PyObject *PyWinObject_FromIO_COUNTERS(PIO_COUNTERS pioc); + +// Make an array of DWORD's from a sequence of Python ints +PYWINTYPES_EXPORT BOOL PyWinObject_AsDWORDArray(PyObject *obdwords, DWORD **pdwords, DWORD *item_cnt, BOOL bNoneOk=TRUE); + +// Conversion for resource id/name and class atom +PYWINTYPES_EXPORT BOOL PyWinObject_AsResourceIdA(PyObject *ob, char **presource_id, BOOL bNoneOK = FALSE); +PYWINTYPES_EXPORT BOOL PyWinObject_AsResourceIdW(PyObject *ob, WCHAR **presource_id, BOOL bNoneOK = FALSE); +PYWINTYPES_EXPORT void PyWinObject_FreeResourceId(char *resource_id); +PYWINTYPES_EXPORT void PyWinObject_FreeResourceId(WCHAR *resource_id); +#ifdef UNICODE +#define PyWinObject_AsResourceId PyWinObject_AsResourceIdW +#else +#define PyWinObject_AsResourceId PyWinObject_AsResourceIdA +#endif + +// WPARAM and LPARAM conversion +PYWINTYPES_EXPORT BOOL PyWinObject_AsPARAM(PyObject *ob, WPARAM *pparam); +inline PyObject *PyWinObject_FromPARAM(WPARAM param) { + return PyWinObject_FromULONG_PTR(param); +} +inline BOOL PyWinObject_AsPARAM(PyObject *ob, LPARAM *pparam) { + return PyWinObject_AsPARAM(ob, (WPARAM *)pparam); +} +inline PyObject *PyWinObject_FromPARAM(LPARAM param) { + return PyWinObject_FromULONG_PTR(param); +} + + +// RECT conversions +// @object PyRECT|Tuple of 4 ints defining a rectangle: (left, top, right, bottom) +PYWINTYPES_EXPORT BOOL PyWinObject_AsRECT(PyObject *obrect, LPRECT prect); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromRECT(LPRECT prect); + +/* +** SECURITY_ATTRIBUTES support +*/ +extern PYWINTYPES_EXPORT PyTypeObject PySECURITY_ATTRIBUTESType; +#define PySECURITY_ATTRIBUTES_Check(ob) ((ob)->ob_type == &PySECURITY_ATTRIBUTESType) +extern PYWINTYPES_EXPORT PyTypeObject PyDEVMODEAType; +extern PYWINTYPES_EXPORT PyTypeObject PyDEVMODEWType; + +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewSECURITY_ATTRIBUTES(PyObject *self, PyObject *args); +PYWINTYPES_EXPORT BOOL PyWinObject_AsSECURITY_ATTRIBUTES(PyObject *ob, SECURITY_ATTRIBUTES **ppSECURITY_ATTRIBUTES, BOOL bNoneOK = TRUE); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromSECURITY_ATTRIBUTES(const SECURITY_ATTRIBUTES &sa); +PYWINTYPES_EXPORT BOOL PyWinObject_AsDEVMODE(PyObject *ob, PDEVMODEA * ppDEVMODE, BOOL bNoneOK = TRUE); +PYWINTYPES_EXPORT BOOL PyWinObject_AsDEVMODE(PyObject *ob, PDEVMODEW * ppDEVMODE, BOOL bNoneOK); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromDEVMODE(PDEVMODEA); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromDEVMODE(PDEVMODEW); + +/* +** WAVEFORMATEX support +*/ + +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewWAVEFORMATEX(PyObject *self, PyObject *args); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromWAVEFROMATEX(const WAVEFORMATEX &wfx); +PYWINTYPES_EXPORT BOOL PyWinObject_AsWAVEFORMATEX(PyObject *ob, WAVEFORMATEX **ppWAVEFORMATEX, BOOL bNoneOK = TRUE); +extern PYWINTYPES_EXPORT PyTypeObject PyWAVEFORMATEXType; +#define PyWAVEFORMATEX_Check(ob) ((ob)->ob_type == &PyWAVEFORMATEXType) + + +/* +** SECURITY_DESCRIPTOR support +*/ +extern PYWINTYPES_EXPORT PyTypeObject PySECURITY_DESCRIPTORType; +#define PySECURITY_DESCRIPTOR_Check(ob) ((ob)->ob_type == &PySECURITY_DESCRIPTORType) + +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewSECURITY_DESCRIPTOR(PyObject *self, PyObject *args); +PYWINTYPES_EXPORT BOOL PyWinObject_AsSECURITY_DESCRIPTOR(PyObject *ob, PSECURITY_DESCRIPTOR *ppSECURITY_DESCRIPTOR, BOOL bNoneOK = TRUE); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromSECURITY_DESCRIPTOR(PSECURITY_DESCRIPTOR psd); + +PYWINTYPES_EXPORT BOOL _MakeAbsoluteSD(PSECURITY_DESCRIPTOR psd_relative, PSECURITY_DESCRIPTOR *ppsd_absolute); +PYWINTYPES_EXPORT void FreeAbsoluteSD(PSECURITY_DESCRIPTOR psd); + +/* +** SID support +*/ +extern PYWINTYPES_EXPORT PyTypeObject PySIDType; +#define PySID_Check(ob) ((ob)->ob_type == &PySIDType) + +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewSID(PyObject *self, PyObject *args); +PYWINTYPES_EXPORT BOOL PyWinObject_AsSID(PyObject *ob, PSID *ppSID, BOOL bNoneOK = FALSE); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromSID(PSID pSID); + +/* +** ACL support +*/ +extern PYWINTYPES_EXPORT PyTypeObject PyACLType; +#define PyACL_Check(ob) ((ob)->ob_type == &PyACLType) + +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewACL(PyObject *self, PyObject *args); +PYWINTYPES_EXPORT BOOL PyWinObject_AsACL(PyObject *ob, PACL *ppACL, BOOL bNoneOK = FALSE); + +/* +** Win32 HANDLE wrapper - any handle closable by "CloseHandle()" +*/ +extern PYWINTYPES_EXPORT PyTypeObject PyHANDLEType; // the Type for PyHANDLE +#define PyHANDLE_Check(ob) ((ob)->ob_type == &PyHANDLEType) + +// Convert an object to a HANDLE - None is always OK, as are ints, etc. +PYWINTYPES_EXPORT BOOL PyWinObject_AsHANDLE(PyObject *ob, HANDLE *pRes); +// For handles that use PyHANDLE. +PYWINTYPES_EXPORT PyObject *PyWinObject_FromHANDLE(HANDLE h); +// For handles that aren't returned as PyHANDLE or a subclass thereof (HDC, HWND, etc). +// Return as python ints or longs +PYWINTYPES_EXPORT PyObject *PyWinLong_FromHANDLE(HANDLE h); + +// A global function that can work as a module method for making a HANDLE object. +PYWINTYPES_EXPORT PyObject *PyWinMethod_NewHANDLE( PyObject *self, PyObject *args); + +// A global function that does the right thing wrt closing a "handle". +// The object can be either a PyHANDLE or an integer. +// If result is FALSE, a Python error is all setup (cf PyHANDLE::Close(), which doesnt set the Python error) +PYWINTYPES_EXPORT BOOL PyWinObject_CloseHANDLE(PyObject *obHandle); + +PYWINTYPES_EXPORT BOOL PyWinObject_AsHKEY(PyObject *ob, HKEY *pRes); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromHKEY(HKEY h); +PYWINTYPES_EXPORT BOOL PyWinObject_CloseHKEY(PyObject *obHandle); + +// MSG structure keeps coming up... +PYWINTYPES_EXPORT BOOL PyWinObject_AsMSG(PyObject *ob, MSG *pMsg); +PYWINTYPES_EXPORT PyObject *PyWinObject_FromMSG(const MSG *pMsg); + +#include "winsock.h" +/* +** SOCKET support. +*/ +PYWINTYPES_EXPORT +BOOL PySocket_AsSOCKET +//------------------------------------------------------------------------- +// Helper function for dealing with socket arguments. +( + PyObject *obSocket, + // [in] Python object being converted into a SOCKET handle. + SOCKET *ps + // [out] Returned socket handle +); + + + +/* +** Other Utilities +*/ +// ---------------------------------------------------------------------- +// WARNING - NEVER EVER USE new() ON THIS CLASS +// This class can be used as a local variable, typically in a Python/C +// function, and can be passed whereever a TCHAR/WCHAR is expected. +// Typical Usage: +// PyWin_AutoFreeBstr arg; +// PyArg_ParseTuple("O", &obStr); +// PyWinObject_AsAutoFreeBstr(obStr, &arg); +// CallTheFunction(arg); // Will correctly pass BSTR/OLECHAR +// -- when the function goes out of scope, the string owned by "arg" will +// -- automatically be freed. +// ---------------------------------------------------------------------- +class PYWINTYPES_EXPORT PyWin_AutoFreeBstr { +public: + PyWin_AutoFreeBstr( BSTR bstr = NULL ); + ~PyWin_AutoFreeBstr(); + void SetBstr( BSTR bstr ); + operator BSTR() {return m_bstr;} +private: + BSTR m_bstr; +}; + +inline BOOL PyWinObject_AsAutoFreeBstr(PyObject *stringObject, PyWin_AutoFreeBstr *pResult, BOOL bNoneOK = FALSE) +{ + if (bNoneOK && stringObject == Py_None) { + pResult->SetBstr(NULL); + return TRUE; + } + BSTR bs; + if (!PyWinObject_AsBstr(stringObject, &bs, bNoneOK)) + return FALSE; + pResult->SetBstr(bs); + return TRUE; +} + +// ---------------------------------------------------------------------- +// +// THREAD MANAGEMENT +// + +// ### need to rename the PYCOM_ stuff soon... + +// We have 2 discrete locks in use (when no free-threaded is used, anyway). +// The first type of lock is the global Python lock. This is the standard lock +// in use by Python, and must be used as documented by Python. Specifically, no +// 2 threads may _ever_ call _any_ Python code (including INCREF/DECREF) without +// first having this thread lock. +// +// The second type of lock is a "global framework lock". This lock is simply a +// critical section, and used whenever 2 threads of C code need access to global +// data. This is different than the Python lock - this lock is used when no Python +// code can ever be called by the threads, but the C code still needs thread-safety. + +// We also supply helper classes which make the usage of these locks a one-liner. + +// The "framework" lock, implemented as a critical section. +PYWINTYPES_EXPORT void PyWin_AcquireGlobalLock(void); +PYWINTYPES_EXPORT void PyWin_ReleaseGlobalLock(void); + +// Helper class for the DLL global lock. +// +// This class magically waits for the Win32/COM framework global lock, and releases it +// when finished. +// NEVER new one of these objects - only use on the stack! +class CEnterLeaveFramework { +public: + CEnterLeaveFramework() {PyWin_AcquireGlobalLock();} + ~CEnterLeaveFramework() {PyWin_ReleaseGlobalLock();} +}; + +// Python thread-lock stuff. Free-threading patches use different semantics, but +// these are abstracted away here... +#ifndef FORCE_NO_FREE_THREAD +# ifdef WITH_FREE_THREAD +# define PYCOM_USE_FREE_THREAD +# endif +#endif +#ifdef PYCOM_USE_FREE_THREAD +# include +#else +# include +#endif + + +// Helper class for Enter/Leave Python +// +// This class magically waits for the Python global lock, and releases it +// when finished. + +// Nested invocations will deadlock, so be careful. + +// NEVER new one of these objects - only use on the stack! +#ifndef PYCOM_USE_FREE_THREAD +extern PYWINTYPES_EXPORT PyInterpreterState *PyWin_InterpreterState; +extern PYWINTYPES_EXPORT BOOL PyWinThreadState_Ensure(); +extern PYWINTYPES_EXPORT void PyWinThreadState_Free(); +extern PYWINTYPES_EXPORT void PyWinThreadState_Clear(); +extern PYWINTYPES_EXPORT void PyWinInterpreterLock_Acquire(); +extern PYWINTYPES_EXPORT void PyWinInterpreterLock_Release(); + +extern PYWINTYPES_EXPORT int PyWinGlobals_Ensure(); +extern PYWINTYPES_EXPORT void PyWinGlobals_Free(); +#else +#define PyWinThreadState_Ensure PyThreadState_Ensure +#define PyWinThreadState_Free PyThreadState_Free +#define PyWinThreadState_Clear PyThreadState_ClearExc + +#endif + +extern PYWINTYPES_EXPORT void PyWin_MakePendingCalls(); + +class CEnterLeavePython { +public: + CEnterLeavePython() { + acquire(); + } + void acquire(void) { + state = PyGILState_Ensure(); + released = FALSE; + } + ~CEnterLeavePython() { + release(); + } + void release(void) { + if (!released) { + PyGILState_Release(state); + released = TRUE; + } + } +private: + PyGILState_STATE state; + BOOL released; +}; + + +// A helper for simple exception handling. +// try/__try +#ifdef MAINWIN +#define PYWINTYPES_TRY try +#else +#define PYWINTYPES_TRY __try +#endif /* MAINWIN */ + +// catch/__except +#if defined(__MINGW32__) || defined(MAINWIN) +#define PYWINTYPES_EXCEPT catch(...) +#else +#define PYWINTYPES_EXCEPT __except( EXCEPTION_EXECUTE_HANDLER ) +#endif +// End of exception helper macros. + +// Class to hold a temporary reference that decrements itself +class TmpPyObject +{ +public: + PyObject *tmp; + TmpPyObject() { tmp=NULL; } + TmpPyObject(PyObject *ob) { tmp=ob; } + PyObject * operator= (PyObject *ob){ + Py_XDECREF(tmp); + tmp=ob; + return tmp; + } + + boolean operator== (PyObject *ob) { return tmp==ob; } + operator PyObject *() { return tmp; } + ~TmpPyObject() { Py_XDECREF(tmp); } +}; + +#endif // __PYWINTYPES_H__ + + diff --git a/Lib/site-packages/win32/lib/afxres.py b/Lib/site-packages/win32/lib/afxres.py new file mode 100644 index 0000000..6f39749 --- /dev/null +++ b/Lib/site-packages/win32/lib/afxres.py @@ -0,0 +1,497 @@ +# Generated by h2py from stdin +TCS_MULTILINE = 0x0200 +CBRS_ALIGN_LEFT = 0x1000 +CBRS_ALIGN_TOP = 0x2000 +CBRS_ALIGN_RIGHT = 0x4000 +CBRS_ALIGN_BOTTOM = 0x8000 +CBRS_ALIGN_ANY = 0xF000 +CBRS_BORDER_LEFT = 0x0100 +CBRS_BORDER_TOP = 0x0200 +CBRS_BORDER_RIGHT = 0x0400 +CBRS_BORDER_BOTTOM = 0x0800 +CBRS_BORDER_ANY = 0x0F00 +CBRS_TOOLTIPS = 0x0010 +CBRS_FLYBY = 0x0020 +CBRS_FLOAT_MULTI = 0x0040 +CBRS_BORDER_3D = 0x0080 +CBRS_HIDE_INPLACE = 0x0008 +CBRS_SIZE_DYNAMIC = 0x0004 +CBRS_SIZE_FIXED = 0x0002 +CBRS_FLOATING = 0x0001 +CBRS_GRIPPER = 0x00400000 +CBRS_ORIENT_HORZ = (CBRS_ALIGN_TOP|CBRS_ALIGN_BOTTOM) +CBRS_ORIENT_VERT = (CBRS_ALIGN_LEFT|CBRS_ALIGN_RIGHT) +CBRS_ORIENT_ANY = (CBRS_ORIENT_HORZ|CBRS_ORIENT_VERT) +CBRS_ALL = 0xFFFF +CBRS_NOALIGN = 0x00000000 +CBRS_LEFT = (CBRS_ALIGN_LEFT|CBRS_BORDER_RIGHT) +CBRS_TOP = (CBRS_ALIGN_TOP|CBRS_BORDER_BOTTOM) +CBRS_RIGHT = (CBRS_ALIGN_RIGHT|CBRS_BORDER_LEFT) +CBRS_BOTTOM = (CBRS_ALIGN_BOTTOM|CBRS_BORDER_TOP) +SBPS_NORMAL = 0x0000 +SBPS_NOBORDERS = 0x0100 +SBPS_POPOUT = 0x0200 +SBPS_OWNERDRAW = 0x1000 +SBPS_DISABLED = 0x04000000 +SBPS_STRETCH = 0x08000000 +ID_INDICATOR_EXT = 0xE700 +ID_INDICATOR_CAPS = 0xE701 +ID_INDICATOR_NUM = 0xE702 +ID_INDICATOR_SCRL = 0xE703 +ID_INDICATOR_OVR = 0xE704 +ID_INDICATOR_REC = 0xE705 +ID_INDICATOR_KANA = 0xE706 +ID_SEPARATOR = 0 +AFX_IDW_CONTROLBAR_FIRST = 0xE800 +AFX_IDW_CONTROLBAR_LAST = 0xE8FF +AFX_IDW_TOOLBAR = 0xE800 +AFX_IDW_STATUS_BAR = 0xE801 +AFX_IDW_PREVIEW_BAR = 0xE802 +AFX_IDW_RESIZE_BAR = 0xE803 +AFX_IDW_DOCKBAR_TOP = 0xE81B +AFX_IDW_DOCKBAR_LEFT = 0xE81C +AFX_IDW_DOCKBAR_RIGHT = 0xE81D +AFX_IDW_DOCKBAR_BOTTOM = 0xE81E +AFX_IDW_DOCKBAR_FLOAT = 0xE81F +def AFX_CONTROLBAR_MASK(nIDC): return (1 << (nIDC - AFX_IDW_CONTROLBAR_FIRST)) + +AFX_IDW_PANE_FIRST = 0xE900 +AFX_IDW_PANE_LAST = 0xE9ff +AFX_IDW_HSCROLL_FIRST = 0xEA00 +AFX_IDW_VSCROLL_FIRST = 0xEA10 +AFX_IDW_SIZE_BOX = 0xEA20 +AFX_IDW_PANE_SAVE = 0xEA21 +AFX_IDS_APP_TITLE = 0xE000 +AFX_IDS_IDLEMESSAGE = 0xE001 +AFX_IDS_HELPMODEMESSAGE = 0xE002 +AFX_IDS_APP_TITLE_EMBEDDING = 0xE003 +AFX_IDS_COMPANY_NAME = 0xE004 +AFX_IDS_OBJ_TITLE_INPLACE = 0xE005 +ID_FILE_NEW = 0xE100 +ID_FILE_OPEN = 0xE101 +ID_FILE_CLOSE = 0xE102 +ID_FILE_SAVE = 0xE103 +ID_FILE_SAVE_AS = 0xE104 +ID_FILE_PAGE_SETUP = 0xE105 +ID_FILE_PRINT_SETUP = 0xE106 +ID_FILE_PRINT = 0xE107 +ID_FILE_PRINT_DIRECT = 0xE108 +ID_FILE_PRINT_PREVIEW = 0xE109 +ID_FILE_UPDATE = 0xE10A +ID_FILE_SAVE_COPY_AS = 0xE10B +ID_FILE_SEND_MAIL = 0xE10C +ID_FILE_MRU_FIRST = 0xE110 +ID_FILE_MRU_FILE1 = 0xE110 +ID_FILE_MRU_FILE2 = 0xE111 +ID_FILE_MRU_FILE3 = 0xE112 +ID_FILE_MRU_FILE4 = 0xE113 +ID_FILE_MRU_FILE5 = 0xE114 +ID_FILE_MRU_FILE6 = 0xE115 +ID_FILE_MRU_FILE7 = 0xE116 +ID_FILE_MRU_FILE8 = 0xE117 +ID_FILE_MRU_FILE9 = 0xE118 +ID_FILE_MRU_FILE10 = 0xE119 +ID_FILE_MRU_FILE11 = 0xE11A +ID_FILE_MRU_FILE12 = 0xE11B +ID_FILE_MRU_FILE13 = 0xE11C +ID_FILE_MRU_FILE14 = 0xE11D +ID_FILE_MRU_FILE15 = 0xE11E +ID_FILE_MRU_FILE16 = 0xE11F +ID_FILE_MRU_LAST = 0xE11F +ID_EDIT_CLEAR = 0xE120 +ID_EDIT_CLEAR_ALL = 0xE121 +ID_EDIT_COPY = 0xE122 +ID_EDIT_CUT = 0xE123 +ID_EDIT_FIND = 0xE124 +ID_EDIT_PASTE = 0xE125 +ID_EDIT_PASTE_LINK = 0xE126 +ID_EDIT_PASTE_SPECIAL = 0xE127 +ID_EDIT_REPEAT = 0xE128 +ID_EDIT_REPLACE = 0xE129 +ID_EDIT_SELECT_ALL = 0xE12A +ID_EDIT_UNDO = 0xE12B +ID_EDIT_REDO = 0xE12C +ID_WINDOW_NEW = 0xE130 +ID_WINDOW_ARRANGE = 0xE131 +ID_WINDOW_CASCADE = 0xE132 +ID_WINDOW_TILE_HORZ = 0xE133 +ID_WINDOW_TILE_VERT = 0xE134 +ID_WINDOW_SPLIT = 0xE135 +AFX_IDM_WINDOW_FIRST = 0xE130 +AFX_IDM_WINDOW_LAST = 0xE13F +AFX_IDM_FIRST_MDICHILD = 0xFF00 +ID_APP_ABOUT = 0xE140 +ID_APP_EXIT = 0xE141 +ID_HELP_INDEX = 0xE142 +ID_HELP_FINDER = 0xE143 +ID_HELP_USING = 0xE144 +ID_CONTEXT_HELP = 0xE145 +ID_HELP = 0xE146 +ID_DEFAULT_HELP = 0xE147 +ID_NEXT_PANE = 0xE150 +ID_PREV_PANE = 0xE151 +ID_FORMAT_FONT = 0xE160 +ID_OLE_INSERT_NEW = 0xE200 +ID_OLE_EDIT_LINKS = 0xE201 +ID_OLE_EDIT_CONVERT = 0xE202 +ID_OLE_EDIT_CHANGE_ICON = 0xE203 +ID_OLE_EDIT_PROPERTIES = 0xE204 +ID_OLE_VERB_FIRST = 0xE210 +ID_OLE_VERB_LAST = 0xE21F +AFX_ID_PREVIEW_CLOSE = 0xE300 +AFX_ID_PREVIEW_NUMPAGE = 0xE301 +AFX_ID_PREVIEW_NEXT = 0xE302 +AFX_ID_PREVIEW_PREV = 0xE303 +AFX_ID_PREVIEW_PRINT = 0xE304 +AFX_ID_PREVIEW_ZOOMIN = 0xE305 +AFX_ID_PREVIEW_ZOOMOUT = 0xE306 +ID_VIEW_TOOLBAR = 0xE800 +ID_VIEW_STATUS_BAR = 0xE801 +ID_RECORD_FIRST = 0xE900 +ID_RECORD_LAST = 0xE901 +ID_RECORD_NEXT = 0xE902 +ID_RECORD_PREV = 0xE903 +IDC_STATIC = (-1) +AFX_IDS_SCFIRST = 0xEF00 +AFX_IDS_SCSIZE = 0xEF00 +AFX_IDS_SCMOVE = 0xEF01 +AFX_IDS_SCMINIMIZE = 0xEF02 +AFX_IDS_SCMAXIMIZE = 0xEF03 +AFX_IDS_SCNEXTWINDOW = 0xEF04 +AFX_IDS_SCPREVWINDOW = 0xEF05 +AFX_IDS_SCCLOSE = 0xEF06 +AFX_IDS_SCRESTORE = 0xEF12 +AFX_IDS_SCTASKLIST = 0xEF13 +AFX_IDS_MDICHILD = 0xEF1F +AFX_IDS_DESKACCESSORY = 0xEFDA +AFX_IDS_OPENFILE = 0xF000 +AFX_IDS_SAVEFILE = 0xF001 +AFX_IDS_ALLFILTER = 0xF002 +AFX_IDS_UNTITLED = 0xF003 +AFX_IDS_SAVEFILECOPY = 0xF004 +AFX_IDS_PREVIEW_CLOSE = 0xF005 +AFX_IDS_UNNAMED_FILE = 0xF006 +AFX_IDS_ABOUT = 0xF010 +AFX_IDS_HIDE = 0xF011 +AFX_IDP_NO_ERROR_AVAILABLE = 0xF020 +AFX_IDS_NOT_SUPPORTED_EXCEPTION = 0xF021 +AFX_IDS_RESOURCE_EXCEPTION = 0xF022 +AFX_IDS_MEMORY_EXCEPTION = 0xF023 +AFX_IDS_USER_EXCEPTION = 0xF024 +AFX_IDS_PRINTONPORT = 0xF040 +AFX_IDS_ONEPAGE = 0xF041 +AFX_IDS_TWOPAGE = 0xF042 +AFX_IDS_PRINTPAGENUM = 0xF043 +AFX_IDS_PREVIEWPAGEDESC = 0xF044 +AFX_IDS_PRINTDEFAULTEXT = 0xF045 +AFX_IDS_PRINTDEFAULT = 0xF046 +AFX_IDS_PRINTFILTER = 0xF047 +AFX_IDS_PRINTCAPTION = 0xF048 +AFX_IDS_PRINTTOFILE = 0xF049 +AFX_IDS_OBJECT_MENUITEM = 0xF080 +AFX_IDS_EDIT_VERB = 0xF081 +AFX_IDS_ACTIVATE_VERB = 0xF082 +AFX_IDS_CHANGE_LINK = 0xF083 +AFX_IDS_AUTO = 0xF084 +AFX_IDS_MANUAL = 0xF085 +AFX_IDS_FROZEN = 0xF086 +AFX_IDS_ALL_FILES = 0xF087 +AFX_IDS_SAVE_MENU = 0xF088 +AFX_IDS_UPDATE_MENU = 0xF089 +AFX_IDS_SAVE_AS_MENU = 0xF08A +AFX_IDS_SAVE_COPY_AS_MENU = 0xF08B +AFX_IDS_EXIT_MENU = 0xF08C +AFX_IDS_UPDATING_ITEMS = 0xF08D +AFX_IDS_METAFILE_FORMAT = 0xF08E +AFX_IDS_DIB_FORMAT = 0xF08F +AFX_IDS_BITMAP_FORMAT = 0xF090 +AFX_IDS_LINKSOURCE_FORMAT = 0xF091 +AFX_IDS_EMBED_FORMAT = 0xF092 +AFX_IDS_PASTELINKEDTYPE = 0xF094 +AFX_IDS_UNKNOWNTYPE = 0xF095 +AFX_IDS_RTF_FORMAT = 0xF096 +AFX_IDS_TEXT_FORMAT = 0xF097 +AFX_IDS_INVALID_CURRENCY = 0xF098 +AFX_IDS_INVALID_DATETIME = 0xF099 +AFX_IDS_INVALID_DATETIMESPAN = 0xF09A +AFX_IDP_INVALID_FILENAME = 0xF100 +AFX_IDP_FAILED_TO_OPEN_DOC = 0xF101 +AFX_IDP_FAILED_TO_SAVE_DOC = 0xF102 +AFX_IDP_ASK_TO_SAVE = 0xF103 +AFX_IDP_FAILED_TO_CREATE_DOC = 0xF104 +AFX_IDP_FILE_TOO_LARGE = 0xF105 +AFX_IDP_FAILED_TO_START_PRINT = 0xF106 +AFX_IDP_FAILED_TO_LAUNCH_HELP = 0xF107 +AFX_IDP_INTERNAL_FAILURE = 0xF108 +AFX_IDP_COMMAND_FAILURE = 0xF109 +AFX_IDP_FAILED_MEMORY_ALLOC = 0xF10A +AFX_IDP_PARSE_INT = 0xF110 +AFX_IDP_PARSE_REAL = 0xF111 +AFX_IDP_PARSE_INT_RANGE = 0xF112 +AFX_IDP_PARSE_REAL_RANGE = 0xF113 +AFX_IDP_PARSE_STRING_SIZE = 0xF114 +AFX_IDP_PARSE_RADIO_BUTTON = 0xF115 +AFX_IDP_PARSE_BYTE = 0xF116 +AFX_IDP_PARSE_UINT = 0xF117 +AFX_IDP_PARSE_DATETIME = 0xF118 +AFX_IDP_PARSE_CURRENCY = 0xF119 +AFX_IDP_FAILED_INVALID_FORMAT = 0xF120 +AFX_IDP_FAILED_INVALID_PATH = 0xF121 +AFX_IDP_FAILED_DISK_FULL = 0xF122 +AFX_IDP_FAILED_ACCESS_READ = 0xF123 +AFX_IDP_FAILED_ACCESS_WRITE = 0xF124 +AFX_IDP_FAILED_IO_ERROR_READ = 0xF125 +AFX_IDP_FAILED_IO_ERROR_WRITE = 0xF126 +AFX_IDP_STATIC_OBJECT = 0xF180 +AFX_IDP_FAILED_TO_CONNECT = 0xF181 +AFX_IDP_SERVER_BUSY = 0xF182 +AFX_IDP_BAD_VERB = 0xF183 +AFX_IDP_FAILED_TO_NOTIFY = 0xF185 +AFX_IDP_FAILED_TO_LAUNCH = 0xF186 +AFX_IDP_ASK_TO_UPDATE = 0xF187 +AFX_IDP_FAILED_TO_UPDATE = 0xF188 +AFX_IDP_FAILED_TO_REGISTER = 0xF189 +AFX_IDP_FAILED_TO_AUTO_REGISTER = 0xF18A +AFX_IDP_FAILED_TO_CONVERT = 0xF18B +AFX_IDP_GET_NOT_SUPPORTED = 0xF18C +AFX_IDP_SET_NOT_SUPPORTED = 0xF18D +AFX_IDP_ASK_TO_DISCARD = 0xF18E +AFX_IDP_FAILED_TO_CREATE = 0xF18F +AFX_IDP_FAILED_MAPI_LOAD = 0xF190 +AFX_IDP_INVALID_MAPI_DLL = 0xF191 +AFX_IDP_FAILED_MAPI_SEND = 0xF192 +AFX_IDP_FILE_NONE = 0xF1A0 +AFX_IDP_FILE_GENERIC = 0xF1A1 +AFX_IDP_FILE_NOT_FOUND = 0xF1A2 +AFX_IDP_FILE_BAD_PATH = 0xF1A3 +AFX_IDP_FILE_TOO_MANY_OPEN = 0xF1A4 +AFX_IDP_FILE_ACCESS_DENIED = 0xF1A5 +AFX_IDP_FILE_INVALID_FILE = 0xF1A6 +AFX_IDP_FILE_REMOVE_CURRENT = 0xF1A7 +AFX_IDP_FILE_DIR_FULL = 0xF1A8 +AFX_IDP_FILE_BAD_SEEK = 0xF1A9 +AFX_IDP_FILE_HARD_IO = 0xF1AA +AFX_IDP_FILE_SHARING = 0xF1AB +AFX_IDP_FILE_LOCKING = 0xF1AC +AFX_IDP_FILE_DISKFULL = 0xF1AD +AFX_IDP_FILE_EOF = 0xF1AE +AFX_IDP_ARCH_NONE = 0xF1B0 +AFX_IDP_ARCH_GENERIC = 0xF1B1 +AFX_IDP_ARCH_READONLY = 0xF1B2 +AFX_IDP_ARCH_ENDOFFILE = 0xF1B3 +AFX_IDP_ARCH_WRITEONLY = 0xF1B4 +AFX_IDP_ARCH_BADINDEX = 0xF1B5 +AFX_IDP_ARCH_BADCLASS = 0xF1B6 +AFX_IDP_ARCH_BADSCHEMA = 0xF1B7 +AFX_IDS_OCC_SCALEUNITS_PIXELS = 0xF1C0 +AFX_IDS_STATUS_FONT = 0xF230 +AFX_IDS_TOOLTIP_FONT = 0xF231 +AFX_IDS_UNICODE_FONT = 0xF232 +AFX_IDS_MINI_FONT = 0xF233 +AFX_IDP_SQL_FIRST = 0xF280 +AFX_IDP_SQL_CONNECT_FAIL = 0xF281 +AFX_IDP_SQL_RECORDSET_FORWARD_ONLY = 0xF282 +AFX_IDP_SQL_EMPTY_COLUMN_LIST = 0xF283 +AFX_IDP_SQL_FIELD_SCHEMA_MISMATCH = 0xF284 +AFX_IDP_SQL_ILLEGAL_MODE = 0xF285 +AFX_IDP_SQL_MULTIPLE_ROWS_AFFECTED = 0xF286 +AFX_IDP_SQL_NO_CURRENT_RECORD = 0xF287 +AFX_IDP_SQL_NO_ROWS_AFFECTED = 0xF288 +AFX_IDP_SQL_RECORDSET_READONLY = 0xF289 +AFX_IDP_SQL_SQL_NO_TOTAL = 0xF28A +AFX_IDP_SQL_ODBC_LOAD_FAILED = 0xF28B +AFX_IDP_SQL_DYNASET_NOT_SUPPORTED = 0xF28C +AFX_IDP_SQL_SNAPSHOT_NOT_SUPPORTED = 0xF28D +AFX_IDP_SQL_API_CONFORMANCE = 0xF28E +AFX_IDP_SQL_SQL_CONFORMANCE = 0xF28F +AFX_IDP_SQL_NO_DATA_FOUND = 0xF290 +AFX_IDP_SQL_ROW_UPDATE_NOT_SUPPORTED = 0xF291 +AFX_IDP_SQL_ODBC_V2_REQUIRED = 0xF292 +AFX_IDP_SQL_NO_POSITIONED_UPDATES = 0xF293 +AFX_IDP_SQL_LOCK_MODE_NOT_SUPPORTED = 0xF294 +AFX_IDP_SQL_DATA_TRUNCATED = 0xF295 +AFX_IDP_SQL_ROW_FETCH = 0xF296 +AFX_IDP_SQL_INCORRECT_ODBC = 0xF297 +AFX_IDP_SQL_UPDATE_DELETE_FAILED = 0xF298 +AFX_IDP_SQL_DYNAMIC_CURSOR_NOT_SUPPORTED = 0xF299 +AFX_IDP_DAO_FIRST = 0xF2A0 +AFX_IDP_DAO_ENGINE_INITIALIZATION = 0xF2A0 +AFX_IDP_DAO_DFX_BIND = 0xF2A1 +AFX_IDP_DAO_OBJECT_NOT_OPEN = 0xF2A2 +AFX_IDP_DAO_ROWTOOSHORT = 0xF2A3 +AFX_IDP_DAO_BADBINDINFO = 0xF2A4 +AFX_IDP_DAO_COLUMNUNAVAILABLE = 0xF2A5 +AFX_IDC_LISTBOX = 100 +AFX_IDC_CHANGE = 101 +AFX_IDC_PRINT_DOCNAME = 201 +AFX_IDC_PRINT_PRINTERNAME = 202 +AFX_IDC_PRINT_PORTNAME = 203 +AFX_IDC_PRINT_PAGENUM = 204 +ID_APPLY_NOW = 0x3021 +ID_WIZBACK = 0x3023 +ID_WIZNEXT = 0x3024 +ID_WIZFINISH = 0x3025 +AFX_IDC_TAB_CONTROL = 0x3020 +AFX_IDD_FILEOPEN = 28676 +AFX_IDD_FILESAVE = 28677 +AFX_IDD_FONT = 28678 +AFX_IDD_COLOR = 28679 +AFX_IDD_PRINT = 28680 +AFX_IDD_PRINTSETUP = 28681 +AFX_IDD_FIND = 28682 +AFX_IDD_REPLACE = 28683 +AFX_IDD_NEWTYPEDLG = 30721 +AFX_IDD_PRINTDLG = 30722 +AFX_IDD_PREVIEW_TOOLBAR = 30723 +AFX_IDD_PREVIEW_SHORTTOOLBAR = 30731 +AFX_IDD_INSERTOBJECT = 30724 +AFX_IDD_CHANGEICON = 30725 +AFX_IDD_CONVERT = 30726 +AFX_IDD_PASTESPECIAL = 30727 +AFX_IDD_EDITLINKS = 30728 +AFX_IDD_FILEBROWSE = 30729 +AFX_IDD_BUSY = 30730 +AFX_IDD_OBJECTPROPERTIES = 30732 +AFX_IDD_CHANGESOURCE = 30733 +AFX_IDC_CONTEXTHELP = 30977 +AFX_IDC_MAGNIFY = 30978 +AFX_IDC_SMALLARROWS = 30979 +AFX_IDC_HSPLITBAR = 30980 +AFX_IDC_VSPLITBAR = 30981 +AFX_IDC_NODROPCRSR = 30982 +AFX_IDC_TRACKNWSE = 30983 +AFX_IDC_TRACKNESW = 30984 +AFX_IDC_TRACKNS = 30985 +AFX_IDC_TRACKWE = 30986 +AFX_IDC_TRACK4WAY = 30987 +AFX_IDC_MOVE4WAY = 30988 +AFX_IDB_MINIFRAME_MENU = 30994 +AFX_IDB_CHECKLISTBOX_NT = 30995 +AFX_IDB_CHECKLISTBOX_95 = 30996 +AFX_IDR_PREVIEW_ACCEL = 30997 +AFX_IDI_STD_MDIFRAME = 31233 +AFX_IDI_STD_FRAME = 31234 +AFX_IDC_FONTPROP = 1000 +AFX_IDC_FONTNAMES = 1001 +AFX_IDC_FONTSTYLES = 1002 +AFX_IDC_FONTSIZES = 1003 +AFX_IDC_STRIKEOUT = 1004 +AFX_IDC_UNDERLINE = 1005 +AFX_IDC_SAMPLEBOX = 1006 +AFX_IDC_COLOR_BLACK = 1100 +AFX_IDC_COLOR_WHITE = 1101 +AFX_IDC_COLOR_RED = 1102 +AFX_IDC_COLOR_GREEN = 1103 +AFX_IDC_COLOR_BLUE = 1104 +AFX_IDC_COLOR_YELLOW = 1105 +AFX_IDC_COLOR_MAGENTA = 1106 +AFX_IDC_COLOR_CYAN = 1107 +AFX_IDC_COLOR_GRAY = 1108 +AFX_IDC_COLOR_LIGHTGRAY = 1109 +AFX_IDC_COLOR_DARKRED = 1110 +AFX_IDC_COLOR_DARKGREEN = 1111 +AFX_IDC_COLOR_DARKBLUE = 1112 +AFX_IDC_COLOR_LIGHTBROWN = 1113 +AFX_IDC_COLOR_DARKMAGENTA = 1114 +AFX_IDC_COLOR_DARKCYAN = 1115 +AFX_IDC_COLORPROP = 1116 +AFX_IDC_SYSTEMCOLORS = 1117 +AFX_IDC_PROPNAME = 1201 +AFX_IDC_PICTURE = 1202 +AFX_IDC_BROWSE = 1203 +AFX_IDC_CLEAR = 1204 +AFX_IDD_PROPPAGE_COLOR = 32257 +AFX_IDD_PROPPAGE_FONT = 32258 +AFX_IDD_PROPPAGE_PICTURE = 32259 +AFX_IDB_TRUETYPE = 32384 +AFX_IDS_PROPPAGE_UNKNOWN = 0xFE01 +AFX_IDS_COLOR_DESKTOP = 0xFE04 +AFX_IDS_COLOR_APPWORKSPACE = 0xFE05 +AFX_IDS_COLOR_WNDBACKGND = 0xFE06 +AFX_IDS_COLOR_WNDTEXT = 0xFE07 +AFX_IDS_COLOR_MENUBAR = 0xFE08 +AFX_IDS_COLOR_MENUTEXT = 0xFE09 +AFX_IDS_COLOR_ACTIVEBAR = 0xFE0A +AFX_IDS_COLOR_INACTIVEBAR = 0xFE0B +AFX_IDS_COLOR_ACTIVETEXT = 0xFE0C +AFX_IDS_COLOR_INACTIVETEXT = 0xFE0D +AFX_IDS_COLOR_ACTIVEBORDER = 0xFE0E +AFX_IDS_COLOR_INACTIVEBORDER = 0xFE0F +AFX_IDS_COLOR_WNDFRAME = 0xFE10 +AFX_IDS_COLOR_SCROLLBARS = 0xFE11 +AFX_IDS_COLOR_BTNFACE = 0xFE12 +AFX_IDS_COLOR_BTNSHADOW = 0xFE13 +AFX_IDS_COLOR_BTNTEXT = 0xFE14 +AFX_IDS_COLOR_BTNHIGHLIGHT = 0xFE15 +AFX_IDS_COLOR_DISABLEDTEXT = 0xFE16 +AFX_IDS_COLOR_HIGHLIGHT = 0xFE17 +AFX_IDS_COLOR_HIGHLIGHTTEXT = 0xFE18 +AFX_IDS_REGULAR = 0xFE19 +AFX_IDS_BOLD = 0xFE1A +AFX_IDS_ITALIC = 0xFE1B +AFX_IDS_BOLDITALIC = 0xFE1C +AFX_IDS_SAMPLETEXT = 0xFE1D +AFX_IDS_DISPLAYSTRING_FONT = 0xFE1E +AFX_IDS_DISPLAYSTRING_COLOR = 0xFE1F +AFX_IDS_DISPLAYSTRING_PICTURE = 0xFE20 +AFX_IDS_PICTUREFILTER = 0xFE21 +AFX_IDS_PICTYPE_UNKNOWN = 0xFE22 +AFX_IDS_PICTYPE_NONE = 0xFE23 +AFX_IDS_PICTYPE_BITMAP = 0xFE24 +AFX_IDS_PICTYPE_METAFILE = 0xFE25 +AFX_IDS_PICTYPE_ICON = 0xFE26 +AFX_IDS_COLOR_PPG = 0xFE28 +AFX_IDS_COLOR_PPG_CAPTION = 0xFE29 +AFX_IDS_FONT_PPG = 0xFE2A +AFX_IDS_FONT_PPG_CAPTION = 0xFE2B +AFX_IDS_PICTURE_PPG = 0xFE2C +AFX_IDS_PICTURE_PPG_CAPTION = 0xFE2D +AFX_IDS_PICTUREBROWSETITLE = 0xFE30 +AFX_IDS_BORDERSTYLE_0 = 0xFE31 +AFX_IDS_BORDERSTYLE_1 = 0xFE32 +AFX_IDS_VERB_EDIT = 0xFE40 +AFX_IDS_VERB_PROPERTIES = 0xFE41 +AFX_IDP_PICTURECANTOPEN = 0xFE83 +AFX_IDP_PICTURECANTLOAD = 0xFE84 +AFX_IDP_PICTURETOOLARGE = 0xFE85 +AFX_IDP_PICTUREREADFAILED = 0xFE86 +AFX_IDP_E_ILLEGALFUNCTIONCALL = 0xFEA0 +AFX_IDP_E_OVERFLOW = 0xFEA1 +AFX_IDP_E_OUTOFMEMORY = 0xFEA2 +AFX_IDP_E_DIVISIONBYZERO = 0xFEA3 +AFX_IDP_E_OUTOFSTRINGSPACE = 0xFEA4 +AFX_IDP_E_OUTOFSTACKSPACE = 0xFEA5 +AFX_IDP_E_BADFILENAMEORNUMBER = 0xFEA6 +AFX_IDP_E_FILENOTFOUND = 0xFEA7 +AFX_IDP_E_BADFILEMODE = 0xFEA8 +AFX_IDP_E_FILEALREADYOPEN = 0xFEA9 +AFX_IDP_E_DEVICEIOERROR = 0xFEAA +AFX_IDP_E_FILEALREADYEXISTS = 0xFEAB +AFX_IDP_E_BADRECORDLENGTH = 0xFEAC +AFX_IDP_E_DISKFULL = 0xFEAD +AFX_IDP_E_BADRECORDNUMBER = 0xFEAE +AFX_IDP_E_BADFILENAME = 0xFEAF +AFX_IDP_E_TOOMANYFILES = 0xFEB0 +AFX_IDP_E_DEVICEUNAVAILABLE = 0xFEB1 +AFX_IDP_E_PERMISSIONDENIED = 0xFEB2 +AFX_IDP_E_DISKNOTREADY = 0xFEB3 +AFX_IDP_E_PATHFILEACCESSERROR = 0xFEB4 +AFX_IDP_E_PATHNOTFOUND = 0xFEB5 +AFX_IDP_E_INVALIDPATTERNSTRING = 0xFEB6 +AFX_IDP_E_INVALIDUSEOFNULL = 0xFEB7 +AFX_IDP_E_INVALIDFILEFORMAT = 0xFEB8 +AFX_IDP_E_INVALIDPROPERTYVALUE = 0xFEB9 +AFX_IDP_E_INVALIDPROPERTYARRAYINDEX = 0xFEBA +AFX_IDP_E_SETNOTSUPPORTEDATRUNTIME = 0xFEBB +AFX_IDP_E_SETNOTSUPPORTED = 0xFEBC +AFX_IDP_E_NEEDPROPERTYARRAYINDEX = 0xFEBD +AFX_IDP_E_SETNOTPERMITTED = 0xFEBE +AFX_IDP_E_GETNOTSUPPORTEDATRUNTIME = 0xFEBF +AFX_IDP_E_GETNOTSUPPORTED = 0xFEC0 +AFX_IDP_E_PROPERTYNOTFOUND = 0xFEC1 +AFX_IDP_E_INVALIDCLIPBOARDFORMAT = 0xFEC2 +AFX_IDP_E_INVALIDPICTURE = 0xFEC3 +AFX_IDP_E_PRINTERERROR = 0xFEC4 +AFX_IDP_E_CANTSAVEFILETOTEMP = 0xFEC5 +AFX_IDP_E_SEARCHTEXTNOTFOUND = 0xFEC6 +AFX_IDP_E_REPLACEMENTSTOOLONG = 0xFEC7 diff --git a/Lib/site-packages/win32/lib/commctrl.py b/Lib/site-packages/win32/lib/commctrl.py new file mode 100644 index 0000000..5f37d27 --- /dev/null +++ b/Lib/site-packages/win32/lib/commctrl.py @@ -0,0 +1,1549 @@ +# Generated by h2py from COMMCTRL.H +WM_USER = 1024 +ICC_LISTVIEW_CLASSES = 1 # listview, header +ICC_TREEVIEW_CLASSES = 2 # treeview, tooltips +ICC_BAR_CLASSES = 4 # toolbar, statusbar, trackbar, tooltips +ICC_TAB_CLASSES = 8 # tab, tooltips +ICC_UPDOWN_CLASS = 16 # updown +ICC_PROGRESS_CLASS = 32 # progress +ICC_HOTKEY_CLASS = 64 # hotkey +ICC_ANIMATE_CLASS = 128 # animate +ICC_WIN95_CLASSES = 255 +ICC_DATE_CLASSES = 256 # month picker, date picker, time picker, updown +ICC_USEREX_CLASSES = 512 # comboex +ICC_COOL_CLASSES = 1024 # rebar (coolbar) control +ICC_INTERNET_CLASSES = 2048 +ICC_PAGESCROLLER_CLASS = 4096 # page scroller +ICC_NATIVEFNTCTL_CLASS = 8192 # native font control +ODT_HEADER = 100 +ODT_TAB = 101 +ODT_LISTVIEW = 102 +PY_0U = 0 +NM_FIRST = (PY_0U) # generic to all controls +NM_LAST = (PY_0U- 99) +LVN_FIRST = (PY_0U-100) # listview +LVN_LAST = (PY_0U-199) +HDN_FIRST = (PY_0U-300) # header +HDN_LAST = (PY_0U-399) +TVN_FIRST = (PY_0U-400) # treeview +TVN_LAST = (PY_0U-499) +TTN_FIRST = (PY_0U-520) # tooltips +TTN_LAST = (PY_0U-549) +TCN_FIRST = (PY_0U-550) # tab control +TCN_LAST = (PY_0U-580) +CDN_FIRST = (PY_0U-601) # common dialog (new) +CDN_LAST = (PY_0U-699) +TBN_FIRST = (PY_0U-700) # toolbar +TBN_LAST = (PY_0U-720) +UDN_FIRST = (PY_0U-721) # updown +UDN_LAST = (PY_0U-740) +MCN_FIRST = (PY_0U-750) # monthcal +MCN_LAST = (PY_0U-759) +DTN_FIRST = (PY_0U-760) # datetimepick +DTN_LAST = (PY_0U-799) +CBEN_FIRST = (PY_0U-800) # combo box ex +CBEN_LAST = (PY_0U-830) +RBN_FIRST = (PY_0U-831) # rebar +RBN_LAST = (PY_0U-859) +IPN_FIRST = (PY_0U-860) # internet address +IPN_LAST = (PY_0U-879) # internet address +SBN_FIRST = (PY_0U-880) # status bar +SBN_LAST = (PY_0U-899) +PGN_FIRST = (PY_0U-900) # Pager Control +PGN_LAST = (PY_0U-950) +LVM_FIRST = 4096 # ListView messages +TV_FIRST = 4352 # TreeView messages +HDM_FIRST = 4608 # Header messages +TCM_FIRST = 4864 # Tab control messages +PGM_FIRST = 5120 # Pager control messages +CCM_FIRST = 8192 # Common control shared messages +CCM_SETBKCOLOR = (CCM_FIRST + 1) # lParam is bkColor +CCM_SETCOLORSCHEME = (CCM_FIRST + 2) # lParam is color scheme +CCM_GETCOLORSCHEME = (CCM_FIRST + 3) # fills in COLORSCHEME pointed to by lParam +CCM_GETDROPTARGET = (CCM_FIRST + 4) +CCM_SETUNICODEFORMAT = (CCM_FIRST + 5) +CCM_GETUNICODEFORMAT = (CCM_FIRST + 6) +INFOTIPSIZE = 1024 +NM_OUTOFMEMORY = (NM_FIRST-1) +NM_CLICK = (NM_FIRST-2) # uses NMCLICK struct +NM_DBLCLK = (NM_FIRST-3) +NM_RETURN = (NM_FIRST-4) +NM_RCLICK = (NM_FIRST-5) # uses NMCLICK struct +NM_RDBLCLK = (NM_FIRST-6) +NM_SETFOCUS = (NM_FIRST-7) +NM_KILLFOCUS = (NM_FIRST-8) +NM_CUSTOMDRAW = (NM_FIRST-12) +NM_HOVER = (NM_FIRST-13) +NM_NCHITTEST = (NM_FIRST-14) # uses NMMOUSE struct +NM_KEYDOWN = (NM_FIRST-15) # uses NMKEY struct +NM_RELEASEDCAPTURE = (NM_FIRST-16) +NM_SETCURSOR = (NM_FIRST-17) # uses NMMOUSE struct +NM_CHAR = (NM_FIRST-18) # uses NMCHAR struct +MSGF_COMMCTRL_BEGINDRAG = 16896 +MSGF_COMMCTRL_SIZEHEADER = 16897 +MSGF_COMMCTRL_DRAGSELECT = 16898 +MSGF_COMMCTRL_TOOLBARCUST = 16899 +CDRF_DODEFAULT = 0 +CDRF_NEWFONT = 2 +CDRF_SKIPDEFAULT = 4 +CDRF_NOTIFYPOSTPAINT = 16 +CDRF_NOTIFYITEMDRAW = 32 +CDRF_NOTIFYSUBITEMDRAW = 32 # flags are the same, we can distinguish by context +CDRF_NOTIFYPOSTERASE = 64 +CDDS_PREPAINT = 1 +CDDS_POSTPAINT = 2 +CDDS_PREERASE = 3 +CDDS_POSTERASE = 4 +CDDS_ITEM = 65536 +CDDS_ITEMPREPAINT = (CDDS_ITEM | CDDS_PREPAINT) +CDDS_ITEMPOSTPAINT = (CDDS_ITEM | CDDS_POSTPAINT) +CDDS_ITEMPREERASE = (CDDS_ITEM | CDDS_PREERASE) +CDDS_ITEMPOSTERASE = (CDDS_ITEM | CDDS_POSTERASE) +CDDS_SUBITEM = 131072 +CDIS_SELECTED = 1 +CDIS_GRAYED = 2 +CDIS_DISABLED = 4 +CDIS_CHECKED = 8 +CDIS_FOCUS = 16 +CDIS_DEFAULT = 32 +CDIS_HOT = 64 +CDIS_MARKED = 128 +CDIS_INDETERMINATE = 256 +CLR_NONE = -1 # 0xFFFFFFFFL +CLR_DEFAULT = -16777216 # 0xFF000000L +ILC_MASK = 1 +ILC_COLOR = 0 +ILC_COLORDDB = 254 +ILC_COLOR4 = 4 +ILC_COLOR8 = 8 +ILC_COLOR16 = 16 +ILC_COLOR24 = 24 +ILC_COLOR32 = 32 +ILC_PALETTE = 2048 # (not implemented) +ILD_NORMAL = 0 +ILD_TRANSPARENT = 1 +ILD_MASK = 16 +ILD_IMAGE = 32 +ILD_ROP = 64 +ILD_BLEND25 = 2 +ILD_BLEND50 = 4 +ILD_OVERLAYMASK = 3840 +ILD_SELECTED = ILD_BLEND50 +ILD_FOCUS = ILD_BLEND25 +ILD_BLEND = ILD_BLEND50 +CLR_HILIGHT = CLR_DEFAULT +ILCF_MOVE = (0) +ILCF_SWAP = (1) +WC_HEADERA = "SysHeader32" +WC_HEADER = WC_HEADERA +HDS_HORZ = 0 +HDS_BUTTONS = 2 +HDS_HOTTRACK = 4 +HDS_HIDDEN = 8 +HDS_DRAGDROP = 64 +HDS_FULLDRAG = 128 +HDI_WIDTH = 1 +HDI_HEIGHT = HDI_WIDTH +HDI_TEXT = 2 +HDI_FORMAT = 4 +HDI_LPARAM = 8 +HDI_BITMAP = 16 +HDI_IMAGE = 32 +HDI_DI_SETITEM = 64 +HDI_ORDER = 128 +HDF_LEFT = 0 +HDF_RIGHT = 1 +HDF_CENTER = 2 +HDF_JUSTIFYMASK = 3 +HDF_RTLREADING = 4 +HDF_OWNERDRAW = 32768 +HDF_STRING = 16384 +HDF_BITMAP = 8192 +HDF_BITMAP_ON_RIGHT = 4096 +HDF_IMAGE = 2048 +HDM_GETITEMCOUNT = (HDM_FIRST + 0) +HDM_INSERTITEMA = (HDM_FIRST + 1) +HDM_INSERTITEMW = (HDM_FIRST + 10) +HDM_INSERTITEM = HDM_INSERTITEMA +HDM_DELETEITEM = (HDM_FIRST + 2) +HDM_GETITEMA = (HDM_FIRST + 3) +HDM_GETITEMW = (HDM_FIRST + 11) +HDM_GETITEM = HDM_GETITEMA +HDM_SETITEMA = (HDM_FIRST + 4) +HDM_SETITEMW = (HDM_FIRST + 12) +HDM_SETITEM = HDM_SETITEMA +HDM_LAYOUT = (HDM_FIRST + 5) +HHT_NOWHERE = 1 +HHT_ONHEADER = 2 +HHT_ONDIVIDER = 4 +HHT_ONDIVOPEN = 8 +HHT_ABOVE = 256 +HHT_BELOW = 512 +HHT_TORIGHT = 1024 +HHT_TOLEFT = 2048 +HDM_HITTEST = (HDM_FIRST + 6) +HDM_GETITEMRECT = (HDM_FIRST + 7) +HDM_SETIMAGELIST = (HDM_FIRST + 8) +HDM_GETIMAGELIST = (HDM_FIRST + 9) +HDM_ORDERTOINDEX = (HDM_FIRST + 15) +HDM_CREATEDRAGIMAGE = (HDM_FIRST + 16) # wparam = which item (by index) +HDM_GETORDERARRAY = (HDM_FIRST + 17) +HDM_SETORDERARRAY = (HDM_FIRST + 18) +HDM_SETHOTDIVIDER = (HDM_FIRST + 19) +HDM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +HDM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +HDN_ITEMCHANGINGA = (HDN_FIRST-0) +HDN_ITEMCHANGINGW = (HDN_FIRST-20) +HDN_ITEMCHANGEDA = (HDN_FIRST-1) +HDN_ITEMCHANGEDW = (HDN_FIRST-21) +HDN_ITEMCLICKA = (HDN_FIRST-2) +HDN_ITEMCLICKW = (HDN_FIRST-22) +HDN_ITEMDBLCLICKA = (HDN_FIRST-3) +HDN_ITEMDBLCLICKW = (HDN_FIRST-23) +HDN_DIVIDERDBLCLICKA = (HDN_FIRST-5) +HDN_DIVIDERDBLCLICKW = (HDN_FIRST-25) +HDN_BEGINTRACKA = (HDN_FIRST-6) +HDN_BEGINTRACKW = (HDN_FIRST-26) +HDN_ENDTRACKA = (HDN_FIRST-7) +HDN_ENDTRACKW = (HDN_FIRST-27) +HDN_TRACKA = (HDN_FIRST-8) +HDN_TRACKW = (HDN_FIRST-28) +HDN_GETDISPINFOA = (HDN_FIRST-9) +HDN_GETDISPINFOW = (HDN_FIRST-29) +HDN_BEGINDRAG = (HDN_FIRST-10) +HDN_ENDDRAG = (HDN_FIRST-11) +HDN_ITEMCHANGING = HDN_ITEMCHANGINGA +HDN_ITEMCHANGED = HDN_ITEMCHANGEDA +HDN_ITEMCLICK = HDN_ITEMCLICKA +HDN_ITEMDBLCLICK = HDN_ITEMDBLCLICKA +HDN_DIVIDERDBLCLICK = HDN_DIVIDERDBLCLICKA +HDN_BEGINTRACK = HDN_BEGINTRACKA +HDN_ENDTRACK = HDN_ENDTRACKA +HDN_TRACK = HDN_TRACKA +HDN_GETDISPINFO = HDN_GETDISPINFOA +TOOLBARCLASSNAMEA = "ToolbarWindow32" +TOOLBARCLASSNAME = TOOLBARCLASSNAMEA +CMB_MASKED = 2 +TBSTATE_CHECKED = 1 +TBSTATE_PRESSED = 2 +TBSTATE_ENABLED = 4 +TBSTATE_HIDDEN = 8 +TBSTATE_INDETERMINATE = 16 +TBSTATE_WRAP = 32 +TBSTATE_ELLIPSES = 64 +TBSTATE_MARKED = 128 +TBSTYLE_BUTTON = 0 +TBSTYLE_SEP = 1 +TBSTYLE_CHECK = 2 +TBSTYLE_GROUP = 4 +TBSTYLE_CHECKGROUP = (TBSTYLE_GROUP | TBSTYLE_CHECK) +TBSTYLE_DROPDOWN = 8 +TBSTYLE_AUTOSIZE = 16 # automatically calculate the cx of the button +TBSTYLE_NOPREFIX = 32 # if this button should not have accel prefix +TBSTYLE_TOOLTIPS = 256 +TBSTYLE_WRAPABLE = 512 +TBSTYLE_ALTDRAG = 1024 +TBSTYLE_FLAT = 2048 +TBSTYLE_LIST = 4096 +TBSTYLE_CUSTOMERASE = 8192 +TBSTYLE_REGISTERDROP = 16384 +TBSTYLE_TRANSPARENT = 32768 +TBSTYLE_EX_DRAWDDARROWS = 1 +BTNS_BUTTON = TBSTYLE_BUTTON +BTNS_SEP = TBSTYLE_SEP # 0x0001 +BTNS_CHECK = TBSTYLE_CHECK # 0x0002 +BTNS_GROUP = TBSTYLE_GROUP # 0x0004 +BTNS_CHECKGROUP = TBSTYLE_CHECKGROUP # (TBSTYLE_GROUP | TBSTYLE_CHECK) +BTNS_DROPDOWN = TBSTYLE_DROPDOWN # 0x0008 +BTNS_AUTOSIZE = TBSTYLE_AUTOSIZE # 0x0010; automatically calculate the cx of the button +BTNS_NOPREFIX = TBSTYLE_NOPREFIX # 0x0020; this button should not have accel prefix +BTNS_SHOWTEXT = 64 # 0x0040 // ignored unless TBSTYLE_EX_MIXEDBUTTONS is set +BTNS_WHOLEDROPDOWN = 128 # 0x0080 // draw drop-down arrow, but without split arrow section +TBCDRF_NOEDGES = 65536 # Don't draw button edges +TBCDRF_HILITEHOTTRACK = 131072 # Use color of the button bk when hottracked +TBCDRF_NOOFFSET = 262144 # Don't offset button if pressed +TBCDRF_NOMARK = 524288 # Don't draw default highlight of image/text for TBSTATE_MARKED +TBCDRF_NOETCHEDEFFECT = 1048576 # Don't draw etched effect for disabled items +TB_ENABLEBUTTON = (WM_USER + 1) +TB_CHECKBUTTON = (WM_USER + 2) +TB_PRESSBUTTON = (WM_USER + 3) +TB_HIDEBUTTON = (WM_USER + 4) +TB_INDETERMINATE = (WM_USER + 5) +TB_MARKBUTTON = (WM_USER + 6) +TB_ISBUTTONENABLED = (WM_USER + 9) +TB_ISBUTTONCHECKED = (WM_USER + 10) +TB_ISBUTTONPRESSED = (WM_USER + 11) +TB_ISBUTTONHIDDEN = (WM_USER + 12) +TB_ISBUTTONINDETERMINATE = (WM_USER + 13) +TB_ISBUTTONHIGHLIGHTED = (WM_USER + 14) +TB_SETSTATE = (WM_USER + 17) +TB_GETSTATE = (WM_USER + 18) +TB_ADDBITMAP = (WM_USER + 19) +HINST_COMMCTRL = -1 +IDB_STD_SMALL_COLOR = 0 +IDB_STD_LARGE_COLOR = 1 +IDB_VIEW_SMALL_COLOR = 4 +IDB_VIEW_LARGE_COLOR = 5 +IDB_HIST_SMALL_COLOR = 8 +IDB_HIST_LARGE_COLOR = 9 +STD_CUT = 0 +STD_COPY = 1 +STD_PASTE = 2 +STD_UNDO = 3 +STD_REDOW = 4 +STD_DELETE = 5 +STD_FILENEW = 6 +STD_FILEOPEN = 7 +STD_FILESAVE = 8 +STD_PRINTPRE = 9 +STD_PROPERTIES = 10 +STD_HELP = 11 +STD_FIND = 12 +STD_REPLACE = 13 +STD_PRINT = 14 +VIEW_LARGEICONS = 0 +VIEW_SMALLICONS = 1 +VIEW_LIST = 2 +VIEW_DETAILS = 3 +VIEW_SORTNAME = 4 +VIEW_SORTSIZE = 5 +VIEW_SORTDATE = 6 +VIEW_SORTTYPE = 7 +VIEW_PARENTFOLDER = 8 +VIEW_NETCONNECT = 9 +VIEW_NETDISCONNECT = 10 +VIEW_NEWFOLDER = 11 +VIEW_VIEWMENU = 12 +HIST_BACK = 0 +HIST_FORWARD = 1 +HIST_FAVORITES = 2 +HIST_ADDTOFAVORITES = 3 +HIST_VIEWTREE = 4 +TB_ADDBUTTONSA = (WM_USER + 20) +TB_INSERTBUTTONA = (WM_USER + 21) +TB_ADDBUTTONS = (WM_USER + 20) +TB_INSERTBUTTON = (WM_USER + 21) +TB_DELETEBUTTON = (WM_USER + 22) +TB_GETBUTTON = (WM_USER + 23) +TB_BUTTONCOUNT = (WM_USER + 24) +TB_COMMANDTOINDEX = (WM_USER + 25) +TB_SAVERESTOREA = (WM_USER + 26) +TB_SAVERESTOREW = (WM_USER + 76) +TB_CUSTOMIZE = (WM_USER + 27) +TB_ADDSTRINGA = (WM_USER + 28) +TB_ADDSTRINGW = (WM_USER + 77) +TB_GETITEMRECT = (WM_USER + 29) +TB_BUTTONSTRUCTSIZE = (WM_USER + 30) +TB_SETBUTTONSIZE = (WM_USER + 31) +TB_SETBITMAPSIZE = (WM_USER + 32) +TB_AUTOSIZE = (WM_USER + 33) +TB_GETTOOLTIPS = (WM_USER + 35) +TB_SETTOOLTIPS = (WM_USER + 36) +TB_SETPARENT = (WM_USER + 37) +TB_SETROWS = (WM_USER + 39) +TB_GETROWS = (WM_USER + 40) +TB_SETCMDID = (WM_USER + 42) +TB_CHANGEBITMAP = (WM_USER + 43) +TB_GETBITMAP = (WM_USER + 44) +TB_GETBUTTONTEXTA = (WM_USER + 45) +TB_GETBUTTONTEXTW = (WM_USER + 75) +TB_REPLACEBITMAP = (WM_USER + 46) +TB_SETINDENT = (WM_USER + 47) +TB_SETIMAGELIST = (WM_USER + 48) +TB_GETIMAGELIST = (WM_USER + 49) +TB_LOADIMAGES = (WM_USER + 50) +TB_GETRECT = (WM_USER + 51) # wParam is the Cmd instead of index +TB_SETHOTIMAGELIST = (WM_USER + 52) +TB_GETHOTIMAGELIST = (WM_USER + 53) +TB_SETDISABLEDIMAGELIST = (WM_USER + 54) +TB_GETDISABLEDIMAGELIST = (WM_USER + 55) +TB_SETSTYLE = (WM_USER + 56) +TB_GETSTYLE = (WM_USER + 57) +TB_GETBUTTONSIZE = (WM_USER + 58) +TB_SETBUTTONWIDTH = (WM_USER + 59) +TB_SETMAXTEXTROWS = (WM_USER + 60) +TB_GETTEXTROWS = (WM_USER + 61) +TB_GETBUTTONTEXT = TB_GETBUTTONTEXTW +TB_SAVERESTORE = TB_SAVERESTOREW +TB_ADDSTRING = TB_ADDSTRINGW +TB_GETBUTTONTEXT = TB_GETBUTTONTEXTA +TB_SAVERESTORE = TB_SAVERESTOREA +TB_ADDSTRING = TB_ADDSTRINGA +TB_GETOBJECT = (WM_USER + 62) # wParam == IID, lParam void **ppv +TB_GETHOTITEM = (WM_USER + 71) +TB_SETHOTITEM = (WM_USER + 72) # wParam == iHotItem +TB_SETANCHORHIGHLIGHT = (WM_USER + 73) # wParam == TRUE/FALSE +TB_GETANCHORHIGHLIGHT = (WM_USER + 74) +TB_MAPACCELERATORA = (WM_USER + 78) # wParam == ch, lParam int * pidBtn +TBIMHT_AFTER = 1 # TRUE = insert After iButton, otherwise before +TBIMHT_BACKGROUND = 2 # TRUE iff missed buttons completely +TB_GETINSERTMARK = (WM_USER + 79) # lParam == LPTBINSERTMARK +TB_SETINSERTMARK = (WM_USER + 80) # lParam == LPTBINSERTMARK +TB_INSERTMARKHITTEST = (WM_USER + 81) # wParam == LPPOINT lParam == LPTBINSERTMARK +TB_MOVEBUTTON = (WM_USER + 82) +TB_GETMAXSIZE = (WM_USER + 83) # lParam == LPSIZE +TB_SETEXTENDEDSTYLE = (WM_USER + 84) # For TBSTYLE_EX_* +TB_GETEXTENDEDSTYLE = (WM_USER + 85) # For TBSTYLE_EX_* +TB_GETPADDING = (WM_USER + 86) +TB_SETPADDING = (WM_USER + 87) +TB_SETINSERTMARKCOLOR = (WM_USER + 88) +TB_GETINSERTMARKCOLOR = (WM_USER + 89) +TB_SETCOLORSCHEME = CCM_SETCOLORSCHEME # lParam is color scheme +TB_GETCOLORSCHEME = CCM_GETCOLORSCHEME # fills in COLORSCHEME pointed to by lParam +TB_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +TB_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +TB_MAPACCELERATORW = (WM_USER + 90) # wParam == ch, lParam int * pidBtn +TB_MAPACCELERATOR = TB_MAPACCELERATORW +TB_MAPACCELERATOR = TB_MAPACCELERATORA +TBBF_LARGE = 1 +TB_GETBITMAPFLAGS = (WM_USER + 41) +TBIF_IMAGE = 1 +TBIF_TEXT = 2 +TBIF_STATE = 4 +TBIF_STYLE = 8 +TBIF_LPARAM = 16 +TBIF_COMMAND = 32 +TBIF_SIZE = 64 +TB_GETBUTTONINFOW = (WM_USER + 63) +TB_SETBUTTONINFOW = (WM_USER + 64) +TB_GETBUTTONINFOA = (WM_USER + 65) +TB_SETBUTTONINFOA = (WM_USER + 66) +TB_INSERTBUTTONW = (WM_USER + 67) +TB_ADDBUTTONSW = (WM_USER + 68) +TB_HITTEST = (WM_USER + 69) +TB_SETDRAWTEXTFLAGS = (WM_USER + 70) # wParam == mask lParam == bit values +TBN_GETBUTTONINFOA = (TBN_FIRST-0) +TBN_GETBUTTONINFOW = (TBN_FIRST-20) +TBN_BEGINDRAG = (TBN_FIRST-1) +TBN_ENDDRAG = (TBN_FIRST-2) +TBN_BEGINADJUST = (TBN_FIRST-3) +TBN_ENDADJUST = (TBN_FIRST-4) +TBN_RESET = (TBN_FIRST-5) +TBN_QUERYINSERT = (TBN_FIRST-6) +TBN_QUERYDELETE = (TBN_FIRST-7) +TBN_TOOLBARCHANGE = (TBN_FIRST-8) +TBN_CUSTHELP = (TBN_FIRST-9) +TBN_DROPDOWN = (TBN_FIRST - 10) +TBN_GETOBJECT = (TBN_FIRST - 12) +HICF_OTHER = 0 +HICF_MOUSE = 1 # Triggered by mouse +HICF_ARROWKEYS = 2 # Triggered by arrow keys +HICF_ACCELERATOR = 4 # Triggered by accelerator +HICF_DUPACCEL = 8 # This accelerator is not unique +HICF_ENTERING = 16 # idOld is invalid +HICF_LEAVING = 32 # idNew is invalid +HICF_RESELECT = 64 # hot item reselected +TBN_HOTITEMCHANGE = (TBN_FIRST - 13) +TBN_DRAGOUT = (TBN_FIRST - 14) # this is sent when the user clicks down on a button then drags off the button +TBN_DELETINGBUTTON = (TBN_FIRST - 15) # uses TBNOTIFY +TBN_GETDISPINFOA = (TBN_FIRST - 16) # This is sent when the toolbar needs some display information +TBN_GETDISPINFOW = (TBN_FIRST - 17) # This is sent when the toolbar needs some display information +TBN_GETINFOTIPA = (TBN_FIRST - 18) +TBN_GETINFOTIPW = (TBN_FIRST - 19) +TBN_GETINFOTIP = TBN_GETINFOTIPA +TBNF_IMAGE = 1 +TBNF_TEXT = 2 +TBNF_DI_SETITEM = 268435456 +TBN_GETDISPINFO = TBN_GETDISPINFOA +TBDDRET_DEFAULT = 0 +TBDDRET_NODEFAULT = 1 +TBDDRET_TREATPRESSED = 2 # Treat as a standard press button +TBN_GETBUTTONINFO = TBN_GETBUTTONINFOA +REBARCLASSNAMEA = "ReBarWindow32" +REBARCLASSNAME = REBARCLASSNAMEA +RBIM_IMAGELIST = 1 +RBS_TOOLTIPS = 256 +RBS_VARHEIGHT = 512 +RBS_BANDBORDERS = 1024 +RBS_FIXEDORDER = 2048 +RBS_REGISTERDROP = 4096 +RBS_AUTOSIZE = 8192 +RBS_VERTICALGRIPPER = 16384 # this always has the vertical gripper (default for horizontal mode) +RBS_DBLCLKTOGGLE = 32768 +RBS_TOOLTIPS = 256 +RBS_VARHEIGHT = 512 +RBS_BANDBORDERS = 1024 +RBS_FIXEDORDER = 2048 +RBBS_BREAK = 1 # break to new line +RBBS_FIXEDSIZE = 2 # band can't be sized +RBBS_CHILDEDGE = 4 # edge around top & bottom of child window +RBBS_HIDDEN = 8 # don't show +RBBS_NOVERT = 16 # don't show when vertical +RBBS_FIXEDBMP = 32 # bitmap doesn't move during band resize +RBBS_VARIABLEHEIGHT = 64 # allow autosizing of this child vertically +RBBS_GRIPPERALWAYS = 128 # always show the gripper +RBBS_NOGRIPPER = 256 # never show the gripper +RBBIM_STYLE = 1 +RBBIM_COLORS = 2 +RBBIM_TEXT = 4 +RBBIM_IMAGE = 8 +RBBIM_CHILD = 16 +RBBIM_CHILDSIZE = 32 +RBBIM_SIZE = 64 +RBBIM_BACKGROUND = 128 +RBBIM_ID = 256 +RBBIM_IDEALSIZE = 512 +RBBIM_LPARAM = 1024 +RB_INSERTBANDA = (WM_USER + 1) +RB_DELETEBAND = (WM_USER + 2) +RB_GETBARINFO = (WM_USER + 3) +RB_SETBARINFO = (WM_USER + 4) +RB_GETBANDINFO = (WM_USER + 5) +RB_SETBANDINFOA = (WM_USER + 6) +RB_SETPARENT = (WM_USER + 7) +RB_HITTEST = (WM_USER + 8) +RB_GETRECT = (WM_USER + 9) +RB_INSERTBANDW = (WM_USER + 10) +RB_SETBANDINFOW = (WM_USER + 11) +RB_GETBANDCOUNT = (WM_USER + 12) +RB_GETROWCOUNT = (WM_USER + 13) +RB_GETROWHEIGHT = (WM_USER + 14) +RB_IDTOINDEX = (WM_USER + 16) # wParam == id +RB_GETTOOLTIPS = (WM_USER + 17) +RB_SETTOOLTIPS = (WM_USER + 18) +RB_SETBKCOLOR = (WM_USER + 19) # sets the default BK color +RB_GETBKCOLOR = (WM_USER + 20) # defaults to CLR_NONE +RB_SETTEXTCOLOR = (WM_USER + 21) +RB_GETTEXTCOLOR = (WM_USER + 22) # defaults to 0x00000000 +RB_SIZETORECT = (WM_USER + 23) # resize the rebar/break bands and such to this rect (lparam) +RB_SETCOLORSCHEME = CCM_SETCOLORSCHEME # lParam is color scheme +RB_GETCOLORSCHEME = CCM_GETCOLORSCHEME # fills in COLORSCHEME pointed to by lParam +RB_INSERTBAND = RB_INSERTBANDA +RB_SETBANDINFO = RB_SETBANDINFOA +RB_BEGINDRAG = (WM_USER + 24) +RB_ENDDRAG = (WM_USER + 25) +RB_DRAGMOVE = (WM_USER + 26) +RB_GETBARHEIGHT = (WM_USER + 27) +RB_GETBANDINFOW = (WM_USER + 28) +RB_GETBANDINFOA = (WM_USER + 29) +RB_GETBANDINFO = RB_GETBANDINFOA +RB_MINIMIZEBAND = (WM_USER + 30) +RB_MAXIMIZEBAND = (WM_USER + 31) +RB_GETDROPTARGET = (CCM_GETDROPTARGET) +RB_GETBANDBORDERS = (WM_USER + 34) # returns in lparam = lprc the amount of edges added to band wparam +RB_SHOWBAND = (WM_USER + 35) # show/hide band +RB_SETPALETTE = (WM_USER + 37) +RB_GETPALETTE = (WM_USER + 38) +RB_MOVEBAND = (WM_USER + 39) +RB_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +RB_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +RBN_HEIGHTCHANGE = (RBN_FIRST - 0) +RBN_GETOBJECT = (RBN_FIRST - 1) +RBN_LAYOUTCHANGED = (RBN_FIRST - 2) +RBN_AUTOSIZE = (RBN_FIRST - 3) +RBN_BEGINDRAG = (RBN_FIRST - 4) +RBN_ENDDRAG = (RBN_FIRST - 5) +RBN_DELETINGBAND = (RBN_FIRST - 6) # Uses NMREBAR +RBN_DELETEDBAND = (RBN_FIRST - 7) # Uses NMREBAR +RBN_CHILDSIZE = (RBN_FIRST - 8) +RBNM_ID = 1 +RBNM_STYLE = 2 +RBNM_LPARAM = 4 +RBHT_NOWHERE = 1 +RBHT_CAPTION = 2 +RBHT_CLIENT = 3 +RBHT_GRABBER = 4 +TOOLTIPS_CLASSA = "tooltips_class32" +TOOLTIPS_CLASS = TOOLTIPS_CLASSA +TTS_ALWAYSTIP = 1 +TTS_NOPREFIX = 2 +TTF_IDISHWND = 1 +TTF_CENTERTIP = 2 +TTF_RTLREADING = 4 +TTF_SUBCLASS = 16 +TTF_TRACK = 32 +TTF_ABSOLUTE = 128 +TTF_TRANSPARENT = 256 +TTF_DI_SETITEM = 32768 # valid only on the TTN_NEEDTEXT callback +TTDT_AUTOMATIC = 0 +TTDT_RESHOW = 1 +TTDT_AUTOPOP = 2 +TTDT_INITIAL = 3 +TTM_ACTIVATE = (WM_USER + 1) +TTM_SETDELAYTIME = (WM_USER + 3) +TTM_ADDTOOLA = (WM_USER + 4) +TTM_ADDTOOLW = (WM_USER + 50) +TTM_DELTOOLA = (WM_USER + 5) +TTM_DELTOOLW = (WM_USER + 51) +TTM_NEWTOOLRECTA = (WM_USER + 6) +TTM_NEWTOOLRECTW = (WM_USER + 52) +TTM_RELAYEVENT = (WM_USER + 7) +TTM_GETTOOLINFOA = (WM_USER + 8) +TTM_GETTOOLINFOW = (WM_USER + 53) +TTM_SETTOOLINFOA = (WM_USER + 9) +TTM_SETTOOLINFOW = (WM_USER + 54) +TTM_HITTESTA = (WM_USER +10) +TTM_HITTESTW = (WM_USER +55) +TTM_GETTEXTA = (WM_USER +11) +TTM_GETTEXTW = (WM_USER +56) +TTM_UPDATETIPTEXTA = (WM_USER +12) +TTM_UPDATETIPTEXTW = (WM_USER +57) +TTM_GETTOOLCOUNT = (WM_USER +13) +TTM_ENUMTOOLSA = (WM_USER +14) +TTM_ENUMTOOLSW = (WM_USER +58) +TTM_GETCURRENTTOOLA = (WM_USER + 15) +TTM_GETCURRENTTOOLW = (WM_USER + 59) +TTM_WINDOWFROMPOINT = (WM_USER + 16) +TTM_TRACKACTIVATE = (WM_USER + 17) # wParam = TRUE/FALSE start end lparam = LPTOOLINFO +TTM_TRACKPOSITION = (WM_USER + 18) # lParam = dwPos +TTM_SETTIPBKCOLOR = (WM_USER + 19) +TTM_SETTIPTEXTCOLOR = (WM_USER + 20) +TTM_GETDELAYTIME = (WM_USER + 21) +TTM_GETTIPBKCOLOR = (WM_USER + 22) +TTM_GETTIPTEXTCOLOR = (WM_USER + 23) +TTM_SETMAXTIPWIDTH = (WM_USER + 24) +TTM_GETMAXTIPWIDTH = (WM_USER + 25) +TTM_SETMARGIN = (WM_USER + 26) # lParam = lprc +TTM_GETMARGIN = (WM_USER + 27) # lParam = lprc +TTM_POP = (WM_USER + 28) +TTM_UPDATE = (WM_USER + 29) +TTM_ADDTOOL = TTM_ADDTOOLA +TTM_DELTOOL = TTM_DELTOOLA +TTM_NEWTOOLRECT = TTM_NEWTOOLRECTA +TTM_GETTOOLINFO = TTM_GETTOOLINFOA +TTM_SETTOOLINFO = TTM_SETTOOLINFOA +TTM_HITTEST = TTM_HITTESTA +TTM_GETTEXT = TTM_GETTEXTA +TTM_UPDATETIPTEXT = TTM_UPDATETIPTEXTA +TTM_ENUMTOOLS = TTM_ENUMTOOLSA +TTM_GETCURRENTTOOL = TTM_GETCURRENTTOOLA +TTN_GETDISPINFOA = (TTN_FIRST - 0) +TTN_GETDISPINFOW = (TTN_FIRST - 10) +TTN_SHOW = (TTN_FIRST - 1) +TTN_POP = (TTN_FIRST - 2) +TTN_GETDISPINFO = TTN_GETDISPINFOA +TTN_NEEDTEXT = TTN_GETDISPINFO +TTN_NEEDTEXTA = TTN_GETDISPINFOA +TTN_NEEDTEXTW = TTN_GETDISPINFOW +SBARS_SIZEGRIP = 256 +SBARS_TOOLTIPS = 2048 +STATUSCLASSNAMEA = "msctls_statusbar32" +STATUSCLASSNAME = STATUSCLASSNAMEA +SB_SETTEXTA = (WM_USER+1) +SB_SETTEXTW = (WM_USER+11) +SB_GETTEXTA = (WM_USER+2) +SB_GETTEXTW = (WM_USER+13) +SB_GETTEXTLENGTHA = (WM_USER+3) +SB_GETTEXTLENGTHW = (WM_USER+12) +SB_GETTEXT = SB_GETTEXTA +SB_SETTEXT = SB_SETTEXTA +SB_GETTEXTLENGTH = SB_GETTEXTLENGTHA +SB_SETPARTS = (WM_USER+4) +SB_GETPARTS = (WM_USER+6) +SB_GETBORDERS = (WM_USER+7) +SB_SETMINHEIGHT = (WM_USER+8) +SB_SIMPLE = (WM_USER+9) +SB_GETRECT = (WM_USER+10) +SB_ISSIMPLE = (WM_USER+14) +SB_SETICON = (WM_USER+15) +SB_SETTIPTEXTA = (WM_USER+16) +SB_SETTIPTEXTW = (WM_USER+17) +SB_GETTIPTEXTA = (WM_USER+18) +SB_GETTIPTEXTW = (WM_USER+19) +SB_GETICON = (WM_USER+20) +SB_SETTIPTEXT = SB_SETTIPTEXTA +SB_GETTIPTEXT = SB_GETTIPTEXTA +SB_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +SB_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +SBT_OWNERDRAW = 4096 +SBT_NOBORDERS = 256 +SBT_POPOUT = 512 +SBT_RTLREADING = 1024 +SBT_NOTABPARSING = 2048 +SBT_TOOLTIPS = 2048 +SB_SETBKCOLOR = CCM_SETBKCOLOR # lParam = bkColor +SBN_SIMPLEMODECHANGE = (SBN_FIRST - 0) +TRACKBAR_CLASSA = "msctls_trackbar32" +TRACKBAR_CLASS = TRACKBAR_CLASSA +TBS_AUTOTICKS = 1 +TBS_VERT = 2 +TBS_HORZ = 0 +TBS_TOP = 4 +TBS_BOTTOM = 0 +TBS_LEFT = 4 +TBS_RIGHT = 0 +TBS_BOTH = 8 +TBS_NOTICKS = 16 +TBS_ENABLESELRANGE = 32 +TBS_FIXEDLENGTH = 64 +TBS_NOTHUMB = 128 +TBS_TOOLTIPS = 256 +TBM_GETPOS = (WM_USER) +TBM_GETRANGEMIN = (WM_USER+1) +TBM_GETRANGEMAX = (WM_USER+2) +TBM_GETTIC = (WM_USER+3) +TBM_SETTIC = (WM_USER+4) +TBM_SETPOS = (WM_USER+5) +TBM_SETRANGE = (WM_USER+6) +TBM_SETRANGEMIN = (WM_USER+7) +TBM_SETRANGEMAX = (WM_USER+8) +TBM_CLEARTICS = (WM_USER+9) +TBM_SETSEL = (WM_USER+10) +TBM_SETSELSTART = (WM_USER+11) +TBM_SETSELEND = (WM_USER+12) +TBM_GETPTICS = (WM_USER+14) +TBM_GETTICPOS = (WM_USER+15) +TBM_GETNUMTICS = (WM_USER+16) +TBM_GETSELSTART = (WM_USER+17) +TBM_GETSELEND = (WM_USER+18) +TBM_CLEARSEL = (WM_USER+19) +TBM_SETTICFREQ = (WM_USER+20) +TBM_SETPAGESIZE = (WM_USER+21) +TBM_GETPAGESIZE = (WM_USER+22) +TBM_SETLINESIZE = (WM_USER+23) +TBM_GETLINESIZE = (WM_USER+24) +TBM_GETTHUMBRECT = (WM_USER+25) +TBM_GETCHANNELRECT = (WM_USER+26) +TBM_SETTHUMBLENGTH = (WM_USER+27) +TBM_GETTHUMBLENGTH = (WM_USER+28) +TBM_SETTOOLTIPS = (WM_USER+29) +TBM_GETTOOLTIPS = (WM_USER+30) +TBM_SETTIPSIDE = (WM_USER+31) +TBTS_TOP = 0 +TBTS_LEFT = 1 +TBTS_BOTTOM = 2 +TBTS_RIGHT = 3 +TBM_SETBUDDY = (WM_USER+32) # wparam = BOOL fLeft; (or right) +TBM_GETBUDDY = (WM_USER+33) # wparam = BOOL fLeft; (or right) +TBM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +TBM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +TB_LINEUP = 0 +TB_LINEDOWN = 1 +TB_PAGEUP = 2 +TB_PAGEDOWN = 3 +TB_THUMBPOSITION = 4 +TB_THUMBTRACK = 5 +TB_TOP = 6 +TB_BOTTOM = 7 +TB_ENDTRACK = 8 +TBCD_TICS = 1 +TBCD_THUMB = 2 +TBCD_CHANNEL = 3 +DL_BEGINDRAG = (WM_USER+133) +DL_DRAGGING = (WM_USER+134) +DL_DROPPED = (WM_USER+135) +DL_CANCELDRAG = (WM_USER+136) +DL_CURSORSET = 0 +DL_STOPCURSOR = 1 +DL_COPYCURSOR = 2 +DL_MOVECURSOR = 3 +DRAGLISTMSGSTRING = "commctrl_DragListMsg" +UPDOWN_CLASSA = "msctls_updown32" +UPDOWN_CLASS = UPDOWN_CLASSA +UD_MAXVAL = 32767 +UD_MINVAL = (-UD_MAXVAL) +UDS_WRAP = 1 +UDS_SETBUDDYINT = 2 +UDS_ALIGNRIGHT = 4 +UDS_ALIGNLEFT = 8 +UDS_AUTOBUDDY = 16 +UDS_ARROWKEYS = 32 +UDS_HORZ = 64 +UDS_NOTHOUSANDS = 128 +UDS_HOTTRACK = 256 +UDM_SETRANGE = (WM_USER+101) +UDM_GETRANGE = (WM_USER+102) +UDM_SETPOS = (WM_USER+103) +UDM_GETPOS = (WM_USER+104) +UDM_SETBUDDY = (WM_USER+105) +UDM_GETBUDDY = (WM_USER+106) +UDM_SETACCEL = (WM_USER+107) +UDM_GETACCEL = (WM_USER+108) +UDM_SETBASE = (WM_USER+109) +UDM_GETBASE = (WM_USER+110) +UDM_SETRANGE32 = (WM_USER+111) +UDM_GETRANGE32 = (WM_USER+112) # wParam & lParam are LPINT +UDM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +UDM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +UDN_DELTAPOS = (UDN_FIRST - 1) +PROGRESS_CLASSA = "msctls_progress32" +PROGRESS_CLASS = PROGRESS_CLASSA +PBS_SMOOTH = 1 +PBS_VERTICAL = 4 +PBM_SETRANGE = (WM_USER+1) +PBM_SETPOS = (WM_USER+2) +PBM_DELTAPOS = (WM_USER+3) +PBM_SETSTEP = (WM_USER+4) +PBM_STEPIT = (WM_USER+5) +PBM_SETRANGE32 = (WM_USER+6) # lParam = high, wParam = low +PBM_GETRANGE = (WM_USER+7) # wParam = return (TRUE ? low : high). lParam = PPBRANGE or NULL +PBM_GETPOS = (WM_USER+8) +PBM_SETBARCOLOR = (WM_USER+9) # lParam = bar color +PBM_SETBKCOLOR = CCM_SETBKCOLOR # lParam = bkColor +HOTKEYF_SHIFT = 1 +HOTKEYF_CONTROL = 2 +HOTKEYF_ALT = 4 +HOTKEYF_EXT = 128 +HOTKEYF_EXT = 8 +HKCOMB_NONE = 1 +HKCOMB_S = 2 +HKCOMB_C = 4 +HKCOMB_A = 8 +HKCOMB_SC = 16 +HKCOMB_SA = 32 +HKCOMB_CA = 64 +HKCOMB_SCA = 128 +HKM_SETHOTKEY = (WM_USER+1) +HKM_GETHOTKEY = (WM_USER+2) +HKM_SETRULES = (WM_USER+3) +HOTKEY_CLASSA = "msctls_hotkey32" +HOTKEY_CLASS = HOTKEY_CLASSA +CCS_TOP = 0x00000001 +CCS_NOMOVEY = 0x00000002 +CCS_BOTTOM = 0x00000003 +CCS_NORESIZE = 0x00000004 +CCS_NOPARENTALIGN = 0x00000008 +CCS_ADJUSTABLE = 0x00000020 +CCS_NODIVIDER = 0x00000040 +CCS_VERT = 0x00000080 +CCS_LEFT = (CCS_VERT | CCS_TOP) +CCS_RIGHT = (CCS_VERT | CCS_BOTTOM) +CCS_NOMOVEX = (CCS_VERT | CCS_NOMOVEY) +WC_LISTVIEWA = "SysListView32" +WC_LISTVIEW = WC_LISTVIEWA +LVS_ICON = 0 +LVS_REPORT = 1 +LVS_SMALLICON = 2 +LVS_LIST = 3 +LVS_TYPEMASK = 3 +LVS_SINGLESEL = 4 +LVS_SHOWSELALWAYS = 8 +LVS_SORTASCENDING = 16 +LVS_SORTDESCENDING = 32 +LVS_SHAREIMAGELISTS = 64 +LVS_NOLABELWRAP = 128 +LVS_AUTOARRANGE = 256 +LVS_EDITLABELS = 512 +LVS_OWNERDATA = 4096 +LVS_NOSCROLL = 8192 +LVS_TYPESTYLEMASK = 64512 +LVS_ALIGNTOP = 0 +LVS_ALIGNLEFT = 2048 +LVS_ALIGNMASK = 3072 +LVS_OWNERDRAWFIXED = 1024 +LVS_NOCOLUMNHEADER = 16384 +LVS_NOSORTHEADER = 32768 +LVM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +LVM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +LVM_GETBKCOLOR = (LVM_FIRST + 0) +LVM_SETBKCOLOR = (LVM_FIRST + 1) +LVM_GETIMAGELIST = (LVM_FIRST + 2) +LVSIL_NORMAL = 0 +LVSIL_SMALL = 1 +LVSIL_STATE = 2 +LVM_SETIMAGELIST = (LVM_FIRST + 3) +LVM_GETITEMCOUNT = (LVM_FIRST + 4) +LVIF_TEXT = 1 +LVIF_IMAGE = 2 +LVIF_PARAM = 4 +LVIF_STATE = 8 +LVIF_INDENT = 16 +LVIF_NORECOMPUTE = 2048 +LVIS_FOCUSED = 1 +LVIS_SELECTED = 2 +LVIS_CUT = 4 +LVIS_DROPHILITED = 8 +LVIS_ACTIVATING = 32 +LVIS_OVERLAYMASK = 3840 +LVIS_STATEIMAGEMASK = 61440 +I_INDENTCALLBACK = (-1) +LPSTR_TEXTCALLBACKA = -1 +LPSTR_TEXTCALLBACK = LPSTR_TEXTCALLBACKA +I_IMAGECALLBACK = (-1) +LVM_GETITEMA = (LVM_FIRST + 5) +LVM_GETITEMW = (LVM_FIRST + 75) +LVM_GETITEM = LVM_GETITEMW +LVM_GETITEM = LVM_GETITEMA +LVM_SETITEMA = (LVM_FIRST + 6) +LVM_SETITEMW = (LVM_FIRST + 76) +LVM_SETITEM = LVM_SETITEMW +LVM_SETITEM = LVM_SETITEMA +LVM_INSERTITEMA = (LVM_FIRST + 7) +LVM_INSERTITEMW = (LVM_FIRST + 77) +LVM_INSERTITEM = LVM_INSERTITEMA +LVM_DELETEITEM = (LVM_FIRST + 8) +LVM_DELETEALLITEMS = (LVM_FIRST + 9) +LVM_GETCALLBACKMASK = (LVM_FIRST + 10) +LVM_SETCALLBACKMASK = (LVM_FIRST + 11) +LVNI_ALL = 0 +LVNI_FOCUSED = 1 +LVNI_SELECTED = 2 +LVNI_CUT = 4 +LVNI_DROPHILITED = 8 +LVNI_ABOVE = 256 +LVNI_BELOW = 512 +LVNI_TOLEFT = 1024 +LVNI_TORIGHT = 2048 +LVM_GETNEXTITEM = (LVM_FIRST + 12) +LVFI_PARAM = 1 +LVFI_STRING = 2 +LVFI_PARTIAL = 8 +LVFI_WRAP = 32 +LVFI_NEARESTXY = 64 +LVM_FINDITEMA = (LVM_FIRST + 13) +LVM_FINDITEMW = (LVM_FIRST + 83) +LVM_FINDITEM = LVM_FINDITEMA +LVIR_BOUNDS = 0 +LVIR_ICON = 1 +LVIR_LABEL = 2 +LVIR_SELECTBOUNDS = 3 +LVM_GETITEMRECT = (LVM_FIRST + 14) +LVM_SETITEMPOSITION = (LVM_FIRST + 15) +LVM_GETITEMPOSITION = (LVM_FIRST + 16) +LVM_GETSTRINGWIDTHA = (LVM_FIRST + 17) +LVM_GETSTRINGWIDTHW = (LVM_FIRST + 87) +LVM_GETSTRINGWIDTH = LVM_GETSTRINGWIDTHA +LVHT_NOWHERE = 1 +LVHT_ONITEMICON = 2 +LVHT_ONITEMLABEL = 4 +LVHT_ONITEMSTATEICON = 8 +LVHT_ONITEM = (LVHT_ONITEMICON | LVHT_ONITEMLABEL | LVHT_ONITEMSTATEICON) +LVHT_ABOVE = 8 +LVHT_BELOW = 16 +LVHT_TORIGHT = 32 +LVHT_TOLEFT = 64 +LVM_HITTEST = (LVM_FIRST + 18) +LVM_ENSUREVISIBLE = (LVM_FIRST + 19) +LVM_SCROLL = (LVM_FIRST + 20) +LVM_REDRAWITEMS = (LVM_FIRST + 21) +LVA_DEFAULT = 0 +LVA_ALIGNLEFT = 1 +LVA_ALIGNTOP = 2 +LVA_SNAPTOGRID = 5 +LVM_ARRANGE = (LVM_FIRST + 22) +LVM_EDITLABELA = (LVM_FIRST + 23) +LVM_EDITLABELW = (LVM_FIRST + 118) +LVM_EDITLABEL = LVM_EDITLABELW +LVM_EDITLABEL = LVM_EDITLABELA +LVM_GETEDITCONTROL = (LVM_FIRST + 24) +LVCF_FMT = 1 +LVCF_WIDTH = 2 +LVCF_TEXT = 4 +LVCF_SUBITEM = 8 +LVCF_IMAGE = 16 +LVCF_ORDER = 32 +LVCFMT_LEFT = 0 +LVCFMT_RIGHT = 1 +LVCFMT_CENTER = 2 +LVCFMT_JUSTIFYMASK = 3 +LVCFMT_IMAGE = 2048 +LVCFMT_BITMAP_ON_RIGHT = 4096 +LVCFMT_COL_HAS_IMAGES = 32768 +LVM_GETCOLUMNA = (LVM_FIRST + 25) +LVM_GETCOLUMNW = (LVM_FIRST + 95) +LVM_GETCOLUMN = LVM_GETCOLUMNA +LVM_SETCOLUMNA = (LVM_FIRST + 26) +LVM_SETCOLUMNW = (LVM_FIRST + 96) +LVM_SETCOLUMN = LVM_SETCOLUMNA +LVM_INSERTCOLUMNA = (LVM_FIRST + 27) +LVM_INSERTCOLUMNW = (LVM_FIRST + 97) +LVM_INSERTCOLUMN = LVM_INSERTCOLUMNA +LVM_DELETECOLUMN = (LVM_FIRST + 28) +LVM_GETCOLUMNWIDTH = (LVM_FIRST + 29) +LVSCW_AUTOSIZE = -1 +LVSCW_AUTOSIZE_USEHEADER = -2 +LVM_SETCOLUMNWIDTH = (LVM_FIRST + 30) +LVM_GETHEADER = (LVM_FIRST + 31) +LVM_CREATEDRAGIMAGE = (LVM_FIRST + 33) +LVM_GETVIEWRECT = (LVM_FIRST + 34) +LVM_GETTEXTCOLOR = (LVM_FIRST + 35) +LVM_SETTEXTCOLOR = (LVM_FIRST + 36) +LVM_GETTEXTBKCOLOR = (LVM_FIRST + 37) +LVM_SETTEXTBKCOLOR = (LVM_FIRST + 38) +LVM_GETTOPINDEX = (LVM_FIRST + 39) +LVM_GETCOUNTPERPAGE = (LVM_FIRST + 40) +LVM_GETORIGIN = (LVM_FIRST + 41) +LVM_UPDATE = (LVM_FIRST + 42) +LVM_SETITEMSTATE = (LVM_FIRST + 43) +LVM_GETITEMSTATE = (LVM_FIRST + 44) +LVM_GETITEMTEXTA = (LVM_FIRST + 45) +LVM_GETITEMTEXTW = (LVM_FIRST + 115) +LVM_GETITEMTEXT = LVM_GETITEMTEXTW +LVM_GETITEMTEXT = LVM_GETITEMTEXTA +LVM_SETITEMTEXTA = (LVM_FIRST + 46) +LVM_SETITEMTEXTW = (LVM_FIRST + 116) +LVM_SETITEMTEXT = LVM_SETITEMTEXTW +LVM_SETITEMTEXT = LVM_SETITEMTEXTA +LVSICF_NOINVALIDATEALL = 1 +LVSICF_NOSCROLL = 2 +LVM_SETITEMCOUNT = (LVM_FIRST + 47) +LVM_SORTITEMS = (LVM_FIRST + 48) +LVM_SETITEMPOSITION32 = (LVM_FIRST + 49) +LVM_GETSELECTEDCOUNT = (LVM_FIRST + 50) +LVM_GETITEMSPACING = (LVM_FIRST + 51) +LVM_GETISEARCHSTRINGA = (LVM_FIRST + 52) +LVM_GETISEARCHSTRINGW = (LVM_FIRST + 117) +LVM_GETISEARCHSTRING = LVM_GETISEARCHSTRINGA +LVM_SETICONSPACING = (LVM_FIRST + 53) +LVM_SETEXTENDEDLISTVIEWSTYLE = (LVM_FIRST + 54) # optional wParam == mask +LVM_GETEXTENDEDLISTVIEWSTYLE = (LVM_FIRST + 55) +LVS_EX_GRIDLINES = 1 +LVS_EX_SUBITEMIMAGES = 2 +LVS_EX_CHECKBOXES = 4 +LVS_EX_TRACKSELECT = 8 +LVS_EX_HEADERDRAGDROP = 16 +LVS_EX_FULLROWSELECT = 32 # applies to report mode only +LVS_EX_ONECLICKACTIVATE = 64 +LVS_EX_TWOCLICKACTIVATE = 128 +LVS_EX_FLATSB = 256 +LVS_EX_REGIONAL = 512 +LVS_EX_INFOTIP = 1024 # listview does InfoTips for you +LVS_EX_UNDERLINEHOT = 2048 +LVS_EX_UNDERLINECOLD = 4096 +LVS_EX_MULTIWORKAREAS = 8192 +LVM_GETSUBITEMRECT = (LVM_FIRST + 56) +LVM_SUBITEMHITTEST = (LVM_FIRST + 57) +LVM_SETCOLUMNORDERARRAY = (LVM_FIRST + 58) +LVM_GETCOLUMNORDERARRAY = (LVM_FIRST + 59) +LVM_SETHOTITEM = (LVM_FIRST + 60) +LVM_GETHOTITEM = (LVM_FIRST + 61) +LVM_SETHOTCURSOR = (LVM_FIRST + 62) +LVM_GETHOTCURSOR = (LVM_FIRST + 63) +LVM_APPROXIMATEVIEWRECT = (LVM_FIRST + 64) +LV_MAX_WORKAREAS = 16 +LVM_SETWORKAREAS = (LVM_FIRST + 65) +LVM_GETWORKAREAS = (LVM_FIRST + 70) +LVM_GETNUMBEROFWORKAREAS = (LVM_FIRST + 73) +LVM_GETSELECTIONMARK = (LVM_FIRST + 66) +LVM_SETSELECTIONMARK = (LVM_FIRST + 67) +LVM_SETHOVERTIME = (LVM_FIRST + 71) +LVM_GETHOVERTIME = (LVM_FIRST + 72) +LVM_SETTOOLTIPS = (LVM_FIRST + 74) +LVM_GETTOOLTIPS = (LVM_FIRST + 78) +LVBKIF_SOURCE_NONE = 0 +LVBKIF_SOURCE_HBITMAP = 1 +LVBKIF_SOURCE_URL = 2 +LVBKIF_SOURCE_MASK = 3 +LVBKIF_STYLE_NORMAL = 0 +LVBKIF_STYLE_TILE = 16 +LVBKIF_STYLE_MASK = 16 +LVM_SETBKIMAGEA = (LVM_FIRST + 68) +LVM_SETBKIMAGEW = (LVM_FIRST + 138) +LVM_GETBKIMAGEA = (LVM_FIRST + 69) +LVM_GETBKIMAGEW = (LVM_FIRST + 139) +LVKF_ALT = 1 +LVKF_CONTROL = 2 +LVKF_SHIFT = 4 +LVN_ITEMCHANGING = (LVN_FIRST-0) +LVN_ITEMCHANGED = (LVN_FIRST-1) +LVN_INSERTITEM = (LVN_FIRST-2) +LVN_DELETEITEM = (LVN_FIRST-3) +LVN_DELETEALLITEMS = (LVN_FIRST-4) +LVN_BEGINLABELEDITA = (LVN_FIRST-5) +LVN_BEGINLABELEDITW = (LVN_FIRST-75) +LVN_ENDLABELEDITA = (LVN_FIRST-6) +LVN_ENDLABELEDITW = (LVN_FIRST-76) +LVN_COLUMNCLICK = (LVN_FIRST-8) +LVN_BEGINDRAG = (LVN_FIRST-9) +LVN_BEGINRDRAG = (LVN_FIRST-11) +LVN_ODCACHEHINT = (LVN_FIRST-13) +LVN_ODFINDITEMA = (LVN_FIRST-52) +LVN_ODFINDITEMW = (LVN_FIRST-79) +LVN_ITEMACTIVATE = (LVN_FIRST-14) +LVN_ODSTATECHANGED = (LVN_FIRST-15) +LVN_ODFINDITEM = LVN_ODFINDITEMA +LVN_HOTTRACK = (LVN_FIRST-21) +LVN_GETDISPINFOA = (LVN_FIRST-50) +LVN_GETDISPINFOW = (LVN_FIRST-77) +LVN_SETDISPINFOA = (LVN_FIRST-51) +LVN_SETDISPINFOW = (LVN_FIRST-78) +LVN_BEGINLABELEDIT = LVN_BEGINLABELEDITA +LVN_ENDLABELEDIT = LVN_ENDLABELEDITA +LVN_GETDISPINFO = LVN_GETDISPINFOA +LVN_SETDISPINFO = LVN_SETDISPINFOA +LVIF_DI_SETITEM = 4096 +LVN_KEYDOWN = (LVN_FIRST-55) +LVN_MARQUEEBEGIN = (LVN_FIRST-56) +LVGIT_UNFOLDED = 1 +LVN_GETINFOTIPA = (LVN_FIRST-57) +LVN_GETINFOTIPW = (LVN_FIRST-58) +LVN_GETINFOTIP = LVN_GETINFOTIPA +WC_TREEVIEWA = "SysTreeView32" +WC_TREEVIEW = WC_TREEVIEWA +TVS_HASBUTTONS = 1 +TVS_HASLINES = 2 +TVS_LINESATROOT = 4 +TVS_EDITLABELS = 8 +TVS_DISABLEDRAGDROP = 16 +TVS_SHOWSELALWAYS = 32 +TVS_RTLREADING = 64 +TVS_NOTOOLTIPS = 128 +TVS_CHECKBOXES = 256 +TVS_TRACKSELECT = 512 +TVS_SINGLEEXPAND = 1024 +TVS_INFOTIP = 2048 +TVS_FULLROWSELECT = 4096 +TVS_NOSCROLL = 8192 +TVS_NONEVENHEIGHT = 16384 +TVIF_TEXT = 1 +TVIF_IMAGE = 2 +TVIF_PARAM = 4 +TVIF_STATE = 8 +TVIF_HANDLE = 16 +TVIF_SELECTEDIMAGE = 32 +TVIF_CHILDREN = 64 +TVIF_INTEGRAL = 128 +TVIS_SELECTED = 2 +TVIS_CUT = 4 +TVIS_DROPHILITED = 8 +TVIS_BOLD = 16 +TVIS_EXPANDED = 32 +TVIS_EXPANDEDONCE = 64 +TVIS_EXPANDPARTIAL = 128 +TVIS_OVERLAYMASK = 3840 +TVIS_STATEIMAGEMASK = 61440 +TVIS_USERMASK = 61440 +I_CHILDRENCALLBACK = (-1) +TVI_ROOT = -65536 +TVI_FIRST = -65535 +TVI_LAST = -65534 +TVI_SORT = -65533 +TVM_INSERTITEMA = (TV_FIRST + 0) +TVM_INSERTITEMW = (TV_FIRST + 50) +TVM_INSERTITEM = TVM_INSERTITEMW +TVM_INSERTITEM = TVM_INSERTITEMA +TVM_DELETEITEM = (TV_FIRST + 1) +TVM_EXPAND = (TV_FIRST + 2) +TVE_COLLAPSE = 1 +TVE_EXPAND = 2 +TVE_TOGGLE = 3 +TVE_EXPANDPARTIAL = 16384 +TVE_COLLAPSERESET = 32768 +TVM_GETITEMRECT = (TV_FIRST + 4) +TVM_GETCOUNT = (TV_FIRST + 5) +TVM_GETINDENT = (TV_FIRST + 6) +TVM_SETINDENT = (TV_FIRST + 7) +TVM_GETIMAGELIST = (TV_FIRST + 8) +TVSIL_NORMAL = 0 +TVSIL_STATE = 2 +TVM_SETIMAGELIST = (TV_FIRST + 9) +TVM_GETNEXTITEM = (TV_FIRST + 10) +TVGN_ROOT = 0 +TVGN_NEXT = 1 +TVGN_PREVIOUS = 2 +TVGN_PARENT = 3 +TVGN_CHILD = 4 +TVGN_FIRSTVISIBLE = 5 +TVGN_NEXTVISIBLE = 6 +TVGN_PREVIOUSVISIBLE = 7 +TVGN_DROPHILITE = 8 +TVGN_CARET = 9 +TVGN_LASTVISIBLE = 10 +TVM_SELECTITEM = (TV_FIRST + 11) +TVM_GETITEMA = (TV_FIRST + 12) +TVM_GETITEMW = (TV_FIRST + 62) +TVM_GETITEM = TVM_GETITEMW +TVM_GETITEM = TVM_GETITEMA +TVM_SETITEMA = (TV_FIRST + 13) +TVM_SETITEMW = (TV_FIRST + 63) +TVM_SETITEM = TVM_SETITEMW +TVM_SETITEM = TVM_SETITEMA +TVM_EDITLABELA = (TV_FIRST + 14) +TVM_EDITLABELW = (TV_FIRST + 65) +TVM_EDITLABEL = TVM_EDITLABELW +TVM_EDITLABEL = TVM_EDITLABELA +TVM_GETEDITCONTROL = (TV_FIRST + 15) +TVM_GETVISIBLECOUNT = (TV_FIRST + 16) +TVM_HITTEST = (TV_FIRST + 17) +TVHT_NOWHERE = 1 +TVHT_ONITEMICON = 2 +TVHT_ONITEMLABEL = 4 +TVHT_ONITEMINDENT = 8 +TVHT_ONITEMBUTTON = 16 +TVHT_ONITEMRIGHT = 32 +TVHT_ONITEMSTATEICON = 64 +TVHT_ABOVE = 256 +TVHT_BELOW = 512 +TVHT_TORIGHT = 1024 +TVHT_TOLEFT = 2048 +TVHT_ONITEM = (TVHT_ONITEMICON | TVHT_ONITEMLABEL | TVHT_ONITEMSTATEICON) +TVM_CREATEDRAGIMAGE = (TV_FIRST + 18) +TVM_SORTCHILDREN = (TV_FIRST + 19) +TVM_ENSUREVISIBLE = (TV_FIRST + 20) +TVM_SORTCHILDRENCB = (TV_FIRST + 21) +TVM_ENDEDITLABELNOW = (TV_FIRST + 22) +TVM_GETISEARCHSTRINGA = (TV_FIRST + 23) +TVM_GETISEARCHSTRINGW = (TV_FIRST + 64) +TVM_GETISEARCHSTRING = TVM_GETISEARCHSTRINGA +TVM_SETTOOLTIPS = (TV_FIRST + 24) +TVM_GETTOOLTIPS = (TV_FIRST + 25) +TVM_SETINSERTMARK = (TV_FIRST + 26) +TVM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +TVM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +TVM_SETITEMHEIGHT = (TV_FIRST + 27) +TVM_GETITEMHEIGHT = (TV_FIRST + 28) +TVM_SETBKCOLOR = (TV_FIRST + 29) +TVM_SETTEXTCOLOR = (TV_FIRST + 30) +TVM_GETBKCOLOR = (TV_FIRST + 31) +TVM_GETTEXTCOLOR = (TV_FIRST + 32) +TVM_SETSCROLLTIME = (TV_FIRST + 33) +TVM_GETSCROLLTIME = (TV_FIRST + 34) +TVM_SETINSERTMARKCOLOR = (TV_FIRST + 37) +TVM_GETINSERTMARKCOLOR = (TV_FIRST + 38) +TVN_SELCHANGINGA = (TVN_FIRST-1) +TVN_SELCHANGINGW = (TVN_FIRST-50) +TVN_SELCHANGEDA = (TVN_FIRST-2) +TVN_SELCHANGEDW = (TVN_FIRST-51) +TVC_UNKNOWN = 0 +TVC_BYMOUSE = 1 +TVC_BYKEYBOARD = 2 +TVN_GETDISPINFOA = (TVN_FIRST-3) +TVN_GETDISPINFOW = (TVN_FIRST-52) +TVN_SETDISPINFOA = (TVN_FIRST-4) +TVN_SETDISPINFOW = (TVN_FIRST-53) +TVIF_DI_SETITEM = 4096 +TVN_ITEMEXPANDINGA = (TVN_FIRST-5) +TVN_ITEMEXPANDINGW = (TVN_FIRST-54) +TVN_ITEMEXPANDEDA = (TVN_FIRST-6) +TVN_ITEMEXPANDEDW = (TVN_FIRST-55) +TVN_BEGINDRAGA = (TVN_FIRST-7) +TVN_BEGINDRAGW = (TVN_FIRST-56) +TVN_BEGINRDRAGA = (TVN_FIRST-8) +TVN_BEGINRDRAGW = (TVN_FIRST-57) +TVN_DELETEITEMA = (TVN_FIRST-9) +TVN_DELETEITEMW = (TVN_FIRST-58) +TVN_BEGINLABELEDITA = (TVN_FIRST-10) +TVN_BEGINLABELEDITW = (TVN_FIRST-59) +TVN_ENDLABELEDITA = (TVN_FIRST-11) +TVN_ENDLABELEDITW = (TVN_FIRST-60) +TVN_KEYDOWN = (TVN_FIRST-12) +TVN_GETINFOTIPA = (TVN_FIRST-13) +TVN_GETINFOTIPW = (TVN_FIRST-14) +TVN_SINGLEEXPAND = (TVN_FIRST-15) +TVN_SELCHANGING = TVN_SELCHANGINGA +TVN_SELCHANGED = TVN_SELCHANGEDA +TVN_GETDISPINFO = TVN_GETDISPINFOA +TVN_SETDISPINFO = TVN_SETDISPINFOA +TVN_ITEMEXPANDING = TVN_ITEMEXPANDINGA +TVN_ITEMEXPANDED = TVN_ITEMEXPANDEDA +TVN_BEGINDRAG = TVN_BEGINDRAGA +TVN_BEGINRDRAG = TVN_BEGINRDRAGA +TVN_DELETEITEM = TVN_DELETEITEMA +TVN_BEGINLABELEDIT = TVN_BEGINLABELEDITA +TVN_ENDLABELEDIT = TVN_ENDLABELEDITA +TVN_GETINFOTIP = TVN_GETINFOTIPA +TVCDRF_NOIMAGES = 65536 +WC_COMBOBOXEXA = "ComboBoxEx32" +WC_COMBOBOXEX = WC_COMBOBOXEXA +CBEIF_TEXT = 1 +CBEIF_IMAGE = 2 +CBEIF_SELECTEDIMAGE = 4 +CBEIF_OVERLAY = 8 +CBEIF_INDENT = 16 +CBEIF_LPARAM = 32 +CBEIF_DI_SETITEM = 268435456 +CBEM_INSERTITEMA = (WM_USER + 1) +CBEM_SETIMAGELIST = (WM_USER + 2) +CBEM_GETIMAGELIST = (WM_USER + 3) +CBEM_GETITEMA = (WM_USER + 4) +CBEM_SETITEMA = (WM_USER + 5) +#CBEM_DELETEITEM = CB_DELETESTRING +CBEM_GETCOMBOCONTROL = (WM_USER + 6) +CBEM_GETEDITCONTROL = (WM_USER + 7) +CBEM_SETEXSTYLE = (WM_USER + 8) # use SETEXTENDEDSTYLE instead +CBEM_SETEXTENDEDSTYLE = (WM_USER + 14) # lparam == new style, wParam (optional) == mask +CBEM_GETEXSTYLE = (WM_USER + 9) # use GETEXTENDEDSTYLE instead +CBEM_GETEXTENDEDSTYLE = (WM_USER + 9) +CBEM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +CBEM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +CBEM_SETEXSTYLE = (WM_USER + 8) +CBEM_GETEXSTYLE = (WM_USER + 9) +CBEM_HASEDITCHANGED = (WM_USER + 10) +CBEM_INSERTITEMW = (WM_USER + 11) +CBEM_SETITEMW = (WM_USER + 12) +CBEM_GETITEMW = (WM_USER + 13) +CBEM_INSERTITEM = CBEM_INSERTITEMA +CBEM_SETITEM = CBEM_SETITEMA +CBEM_GETITEM = CBEM_GETITEMA +CBES_EX_NOEDITIMAGE = 1 +CBES_EX_NOEDITIMAGEINDENT = 2 +CBES_EX_PATHWORDBREAKPROC = 4 +CBES_EX_NOSIZELIMIT = 8 +CBES_EX_CASESENSITIVE = 16 +CBEN_GETDISPINFO = (CBEN_FIRST - 0) +CBEN_GETDISPINFOA = (CBEN_FIRST - 0) +CBEN_INSERTITEM = (CBEN_FIRST - 1) +CBEN_DELETEITEM = (CBEN_FIRST - 2) +CBEN_BEGINEDIT = (CBEN_FIRST - 4) +CBEN_ENDEDITA = (CBEN_FIRST - 5) +CBEN_ENDEDITW = (CBEN_FIRST - 6) +CBEN_GETDISPINFOW = (CBEN_FIRST - 7) +CBEN_DRAGBEGINA = (CBEN_FIRST - 8) +CBEN_DRAGBEGINW = (CBEN_FIRST - 9) +CBEN_DRAGBEGIN = CBEN_DRAGBEGINA +CBEN_ENDEDIT = CBEN_ENDEDITA +CBENF_KILLFOCUS = 1 +CBENF_RETURN = 2 +CBENF_ESCAPE = 3 +CBENF_DROPDOWN = 4 +CBEMAXSTRLEN = 260 +WC_TABCONTROLA = "SysTabControl32" +WC_TABCONTROL = WC_TABCONTROLA +TCS_SCROLLOPPOSITE = 1 # assumes multiline tab +TCS_BOTTOM = 2 +TCS_RIGHT = 2 +TCS_MULTISELECT = 4 # allow multi-select in button mode +TCS_FLATBUTTONS = 8 +TCS_FORCEICONLEFT = 16 +TCS_FORCELABELLEFT = 32 +TCS_HOTTRACK = 64 +TCS_VERTICAL = 128 +TCS_TABS = 0 +TCS_BUTTONS = 256 +TCS_SINGLELINE = 0 +TCS_MULTILINE = 512 +TCS_RIGHTJUSTIFY = 0 +TCS_FIXEDWIDTH = 1024 +TCS_RAGGEDRIGHT = 2048 +TCS_FOCUSONBUTTONDOWN = 4096 +TCS_OWNERDRAWFIXED = 8192 +TCS_TOOLTIPS = 16384 +TCS_FOCUSNEVER = 32768 +TCS_EX_FLATSEPARATORS = 1 +TCS_EX_REGISTERDROP = 2 +TCM_GETIMAGELIST = (TCM_FIRST + 2) +TCM_SETIMAGELIST = (TCM_FIRST + 3) +TCM_GETITEMCOUNT = (TCM_FIRST + 4) +TCIF_TEXT = 1 +TCIF_IMAGE = 2 +TCIF_RTLREADING = 4 +TCIF_PARAM = 8 +TCIF_STATE = 16 +TCIS_BUTTONPRESSED = 1 +TCIS_HIGHLIGHTED = 2 +TCM_GETITEMA = (TCM_FIRST + 5) +TCM_GETITEMW = (TCM_FIRST + 60) +TCM_GETITEM = TCM_GETITEMA +TCM_SETITEMA = (TCM_FIRST + 6) +TCM_SETITEMW = (TCM_FIRST + 61) +TCM_SETITEM = TCM_SETITEMA +TCM_INSERTITEMA = (TCM_FIRST + 7) +TCM_INSERTITEMW = (TCM_FIRST + 62) +TCM_INSERTITEM = TCM_INSERTITEMA +TCM_DELETEITEM = (TCM_FIRST + 8) +TCM_DELETEALLITEMS = (TCM_FIRST + 9) +TCM_GETITEMRECT = (TCM_FIRST + 10) +TCM_GETCURSEL = (TCM_FIRST + 11) +TCM_SETCURSEL = (TCM_FIRST + 12) +TCHT_NOWHERE = 1 +TCHT_ONITEMICON = 2 +TCHT_ONITEMLABEL = 4 +TCHT_ONITEM = (TCHT_ONITEMICON | TCHT_ONITEMLABEL) +TCM_HITTEST = (TCM_FIRST + 13) +TCM_SETITEMEXTRA = (TCM_FIRST + 14) +TCM_ADJUSTRECT = (TCM_FIRST + 40) +TCM_SETITEMSIZE = (TCM_FIRST + 41) +TCM_REMOVEIMAGE = (TCM_FIRST + 42) +TCM_SETPADDING = (TCM_FIRST + 43) +TCM_GETROWCOUNT = (TCM_FIRST + 44) +TCM_GETTOOLTIPS = (TCM_FIRST + 45) +TCM_SETTOOLTIPS = (TCM_FIRST + 46) +TCM_GETCURFOCUS = (TCM_FIRST + 47) +TCM_SETCURFOCUS = (TCM_FIRST + 48) +TCM_SETMINTABWIDTH = (TCM_FIRST + 49) +TCM_DESELECTALL = (TCM_FIRST + 50) +TCM_HIGHLIGHTITEM = (TCM_FIRST + 51) +TCM_SETEXTENDEDSTYLE = (TCM_FIRST + 52) # optional wParam == mask +TCM_GETEXTENDEDSTYLE = (TCM_FIRST + 53) +TCM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +TCM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +TCN_KEYDOWN = (TCN_FIRST - 0) +ANIMATE_CLASSA = "SysAnimate32" +ANIMATE_CLASS = ANIMATE_CLASSA +ACS_CENTER = 1 +ACS_TRANSPARENT = 2 +ACS_AUTOPLAY = 4 +ACS_TIMER = 8 # don't use threads... use timers +ACM_OPENA = (WM_USER+100) +ACM_OPENW = (WM_USER+103) +ACM_OPEN = ACM_OPENW +ACM_OPEN = ACM_OPENA +ACM_PLAY = (WM_USER+101) +ACM_STOP = (WM_USER+102) +ACN_START = 1 +ACN_STOP = 2 +MONTHCAL_CLASSA = "SysMonthCal32" +MONTHCAL_CLASS = MONTHCAL_CLASSA +MCM_FIRST = 4096 +MCM_GETCURSEL = (MCM_FIRST + 1) +MCM_SETCURSEL = (MCM_FIRST + 2) +MCM_GETMAXSELCOUNT = (MCM_FIRST + 3) +MCM_SETMAXSELCOUNT = (MCM_FIRST + 4) +MCM_GETSELRANGE = (MCM_FIRST + 5) +MCM_SETSELRANGE = (MCM_FIRST + 6) +MCM_GETMONTHRANGE = (MCM_FIRST + 7) +MCM_SETDAYSTATE = (MCM_FIRST + 8) +MCM_GETMINREQRECT = (MCM_FIRST + 9) +MCM_SETCOLOR = (MCM_FIRST + 10) +MCM_GETCOLOR = (MCM_FIRST + 11) +MCSC_BACKGROUND = 0 # the background color (between months) +MCSC_TEXT = 1 # the dates +MCSC_TITLEBK = 2 # background of the title +MCSC_TITLETEXT = 3 +MCSC_MONTHBK = 4 # background within the month cal +MCSC_TRAILINGTEXT = 5 # the text color of header & trailing days +MCM_SETTODAY = (MCM_FIRST + 12) +MCM_GETTODAY = (MCM_FIRST + 13) +MCM_HITTEST = (MCM_FIRST + 14) +MCHT_TITLE = 65536 +MCHT_CALENDAR = 131072 +MCHT_TODAYLINK = 196608 +MCHT_NEXT = 16777216 # these indicate that hitting +MCHT_PREV = 33554432 # here will go to the next/prev month +MCHT_NOWHERE = 0 +MCHT_TITLEBK = (MCHT_TITLE) +MCHT_TITLEMONTH = (MCHT_TITLE | 1) +MCHT_TITLEYEAR = (MCHT_TITLE | 2) +MCHT_TITLEBTNNEXT = (MCHT_TITLE | MCHT_NEXT | 3) +MCHT_TITLEBTNPREV = (MCHT_TITLE | MCHT_PREV | 3) +MCHT_CALENDARBK = (MCHT_CALENDAR) +MCHT_CALENDARDATE = (MCHT_CALENDAR | 1) +MCHT_CALENDARDATENEXT = (MCHT_CALENDARDATE | MCHT_NEXT) +MCHT_CALENDARDATEPREV = (MCHT_CALENDARDATE | MCHT_PREV) +MCHT_CALENDARDAY = (MCHT_CALENDAR | 2) +MCHT_CALENDARWEEKNUM = (MCHT_CALENDAR | 3) +MCM_SETFIRSTDAYOFWEEK = (MCM_FIRST + 15) +MCM_GETFIRSTDAYOFWEEK = (MCM_FIRST + 16) +MCM_GETRANGE = (MCM_FIRST + 17) +MCM_SETRANGE = (MCM_FIRST + 18) +MCM_GETMONTHDELTA = (MCM_FIRST + 19) +MCM_SETMONTHDELTA = (MCM_FIRST + 20) +MCM_GETMAXTODAYWIDTH = (MCM_FIRST + 21) +MCM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +MCM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +MCN_SELCHANGE = (MCN_FIRST + 1) +MCN_GETDAYSTATE = (MCN_FIRST + 3) +MCN_SELECT = (MCN_FIRST + 4) +MCS_DAYSTATE = 1 +MCS_MULTISELECT = 2 +MCS_WEEKNUMBERS = 4 +MCS_NOTODAYCIRCLE = 8 +MCS_NOTODAY = 16 +MCS_NOTODAY = 8 +GMR_VISIBLE = 0 # visible portion of display +GMR_DAYSTATE = 1 # above plus the grayed out parts of +DATETIMEPICK_CLASSA = "SysDateTimePick32" +DATETIMEPICK_CLASS = DATETIMEPICK_CLASSA +DTM_FIRST = 4096 +DTM_GETSYSTEMTIME = (DTM_FIRST + 1) +DTM_SETSYSTEMTIME = (DTM_FIRST + 2) +DTM_GETRANGE = (DTM_FIRST + 3) +DTM_SETRANGE = (DTM_FIRST + 4) +DTM_SETFORMATA = (DTM_FIRST + 5) +DTM_SETFORMATW = (DTM_FIRST + 50) +DTM_SETFORMAT = DTM_SETFORMATW +DTM_SETFORMAT = DTM_SETFORMATA +DTM_SETMCCOLOR = (DTM_FIRST + 6) +DTM_GETMCCOLOR = (DTM_FIRST + 7) +DTM_GETMONTHCAL = (DTM_FIRST + 8) +DTM_SETMCFONT = (DTM_FIRST + 9) +DTM_GETMCFONT = (DTM_FIRST + 10) +DTS_UPDOWN = 1 # use UPDOWN instead of MONTHCAL +DTS_SHOWNONE = 2 # allow a NONE selection +DTS_SHORTDATEFORMAT = 0 # use the short date format (app must forward WM_WININICHANGE messages) +DTS_LONGDATEFORMAT = 4 # use the long date format (app must forward WM_WININICHANGE messages) +DTS_TIMEFORMAT = 9 # use the time format (app must forward WM_WININICHANGE messages) +DTS_APPCANPARSE = 16 # allow user entered strings (app MUST respond to DTN_USERSTRING) +DTS_RIGHTALIGN = 32 # right-align popup instead of left-align it +DTN_DATETIMECHANGE = (DTN_FIRST + 1) # the systemtime has changed +DTN_USERSTRINGA = (DTN_FIRST + 2) # the user has entered a string +DTN_USERSTRINGW = (DTN_FIRST + 15) +DTN_USERSTRING = DTN_USERSTRINGW +DTN_WMKEYDOWNA = (DTN_FIRST + 3) # modify keydown on app format field (X) +DTN_WMKEYDOWNW = (DTN_FIRST + 16) +DTN_WMKEYDOWN = DTN_WMKEYDOWNA +DTN_FORMATA = (DTN_FIRST + 4) # query display for app format field (X) +DTN_FORMATW = (DTN_FIRST + 17) +DTN_FORMAT = DTN_FORMATA +DTN_FORMATQUERYA = (DTN_FIRST + 5) # query formatting info for app format field (X) +DTN_FORMATQUERYW = (DTN_FIRST + 18) +DTN_FORMATQUERY = DTN_FORMATQUERYA +DTN_DROPDOWN = (DTN_FIRST + 6) # MonthCal has dropped down +DTN_CLOSEUP = (DTN_FIRST + 7) # MonthCal is popping up +GDTR_MIN = 1 +GDTR_MAX = 2 +GDT_ERROR = -1 +GDT_VALID = 0 +GDT_NONE = 1 +IPM_CLEARADDRESS = (WM_USER+100) # no parameters +IPM_SETADDRESS = (WM_USER+101) # lparam = TCP/IP address +IPM_GETADDRESS = (WM_USER+102) # lresult = # of non black fields. lparam = LPDWORD for TCP/IP address +IPM_SETRANGE = (WM_USER+103) # wparam = field, lparam = range +IPM_SETFOCUS = (WM_USER+104) # wparam = field +IPM_ISBLANK = (WM_USER+105) # no parameters +WC_IPADDRESSA = "SysIPAddress32" +WC_IPADDRESS = WC_IPADDRESSA +IPN_FIELDCHANGED = (IPN_FIRST - 0) +WC_PAGESCROLLERA = "SysPager" +WC_PAGESCROLLER = WC_PAGESCROLLERA +PGS_VERT = 0 +PGS_HORZ = 1 +PGS_AUTOSCROLL = 2 +PGS_DRAGNDROP = 4 +PGF_INVISIBLE = 0 # Scroll button is not visible +PGF_NORMAL = 1 # Scroll button is in normal state +PGF_GRAYED = 2 # Scroll button is in grayed state +PGF_DEPRESSED = 4 # Scroll button is in depressed state +PGF_HOT = 8 # Scroll button is in hot state +PGB_TOPORLEFT = 0 +PGB_BOTTOMORRIGHT = 1 +PGM_SETCHILD = (PGM_FIRST + 1) # lParam == hwnd +PGM_RECALCSIZE = (PGM_FIRST + 2) +PGM_FORWARDMOUSE = (PGM_FIRST + 3) +PGM_SETBKCOLOR = (PGM_FIRST + 4) +PGM_GETBKCOLOR = (PGM_FIRST + 5) +PGM_SETBORDER = (PGM_FIRST + 6) +PGM_GETBORDER = (PGM_FIRST + 7) +PGM_SETPOS = (PGM_FIRST + 8) +PGM_GETPOS = (PGM_FIRST + 9) +PGM_SETBUTTONSIZE = (PGM_FIRST + 10) +PGM_GETBUTTONSIZE = (PGM_FIRST + 11) +PGM_GETBUTTONSTATE = (PGM_FIRST + 12) +PGM_GETDROPTARGET = CCM_GETDROPTARGET +PGN_SCROLL = (PGN_FIRST-1) +PGF_SCROLLUP = 1 +PGF_SCROLLDOWN = 2 +PGF_SCROLLLEFT = 4 +PGF_SCROLLRIGHT = 8 +PGK_SHIFT = 1 +PGK_CONTROL = 2 +PGK_MENU = 4 +PGN_CALCSIZE = (PGN_FIRST-2) +PGF_CALCWIDTH = 1 +PGF_CALCHEIGHT = 2 +WC_NATIVEFONTCTLA = "NativeFontCtl" +WC_NATIVEFONTCTL = WC_NATIVEFONTCTLA +NFS_EDIT = 1 +NFS_STATIC = 2 +NFS_LISTCOMBO = 4 +NFS_BUTTON = 8 +NFS_ALL = 16 +WM_MOUSEHOVER = 673 +WM_MOUSELEAVE = 675 +TME_HOVER = 1 +TME_LEAVE = 2 +TME_QUERY = 1073741824 +TME_CANCEL = -2147483648 +HOVER_DEFAULT = -1 +WSB_PROP_CYVSCROLL = 0x00000001 +WSB_PROP_CXHSCROLL = 0x00000002 +WSB_PROP_CYHSCROLL = 0x00000004 +WSB_PROP_CXVSCROLL = 0x00000008 +WSB_PROP_CXHTHUMB = 0x00000010 +WSB_PROP_CYVTHUMB = 0x00000020 +WSB_PROP_VBKGCOLOR = 0x00000040 +WSB_PROP_HBKGCOLOR = 0x00000080 +WSB_PROP_VSTYLE = 0x00000100 +WSB_PROP_HSTYLE = 0x00000200 +WSB_PROP_WINSTYLE = 0x00000400 +WSB_PROP_PALETTE = 0x00000800 +WSB_PROP_MASK = 0x00000FFF +FSB_FLAT_MODE = 2 +FSB_ENCARTA_MODE = 1 +FSB_REGULAR_MODE = 0 + +def INDEXTOOVERLAYMASK(i): + return i << 8 + +def INDEXTOSTATEIMAGEMASK(i): + return i << 12 diff --git a/Lib/site-packages/win32/lib/dbi.py b/Lib/site-packages/win32/lib/dbi.py new file mode 100644 index 0000000..753ae83 --- /dev/null +++ b/Lib/site-packages/win32/lib/dbi.py @@ -0,0 +1,24 @@ +""" +Skeleton replacement for removed dbi module. +Use of objects created by this module should be replaced with native Python objects. +Dates are now returned as datetime.datetime objects, but will still accept PyTime +objects also. +Raw data for binary fields should be passed as buffer objects for Python 2.x, +and memoryview objects in Py3k. +""" + +import warnings +warnings.warn( + "dbi module is obsolete, code should now use native python datetime and buffer/memoryview objects", + DeprecationWarning) + +import datetime +dbDate = dbiDate = datetime.datetime + +try: + dbRaw = dbiRaw = buffer +except NameError: + dbRaw = dbiRaw = memoryview + +# type names are still exported by odbc module +from odbc import * diff --git a/Lib/site-packages/win32/lib/mmsystem.py b/Lib/site-packages/win32/lib/mmsystem.py new file mode 100644 index 0000000..efa1bad --- /dev/null +++ b/Lib/site-packages/win32/lib/mmsystem.py @@ -0,0 +1,867 @@ +# Generated by h2py from d:/msdev/include/mmsystem.h +MAXPNAMELEN = 32 +MAXERRORLENGTH = 256 +MAX_JOYSTICKOEMVXDNAME = 260 +MM_MICROSOFT = 1 +MM_MIDI_MAPPER = 1 +MM_WAVE_MAPPER = 2 +MM_SNDBLST_MIDIOUT = 3 +MM_SNDBLST_MIDIIN = 4 +MM_SNDBLST_SYNTH = 5 +MM_SNDBLST_WAVEOUT = 6 +MM_SNDBLST_WAVEIN = 7 +MM_ADLIB = 9 +MM_MPU401_MIDIOUT = 10 +MM_MPU401_MIDIIN = 11 +MM_PC_JOYSTICK = 12 +TIME_MS = 0x0001 +TIME_SAMPLES = 0x0002 +TIME_BYTES = 0x0004 +TIME_SMPTE = 0x0008 +TIME_MIDI = 0x0010 +TIME_TICKS = 0x0020 +MM_JOY1MOVE = 0x3A0 +MM_JOY2MOVE = 0x3A1 +MM_JOY1ZMOVE = 0x3A2 +MM_JOY2ZMOVE = 0x3A3 +MM_JOY1BUTTONDOWN = 0x3B5 +MM_JOY2BUTTONDOWN = 0x3B6 +MM_JOY1BUTTONUP = 0x3B7 +MM_JOY2BUTTONUP = 0x3B8 +MM_MCINOTIFY = 0x3B9 +MM_WOM_OPEN = 0x3BB +MM_WOM_CLOSE = 0x3BC +MM_WOM_DONE = 0x3BD +MM_WIM_OPEN = 0x3BE +MM_WIM_CLOSE = 0x3BF +MM_WIM_DATA = 0x3C0 +MM_MIM_OPEN = 0x3C1 +MM_MIM_CLOSE = 0x3C2 +MM_MIM_DATA = 0x3C3 +MM_MIM_LONGDATA = 0x3C4 +MM_MIM_ERROR = 0x3C5 +MM_MIM_LONGERROR = 0x3C6 +MM_MOM_OPEN = 0x3C7 +MM_MOM_CLOSE = 0x3C8 +MM_MOM_DONE = 0x3C9 +MM_STREAM_OPEN = 0x3D4 +MM_STREAM_CLOSE = 0x3D5 +MM_STREAM_DONE = 0x3D6 +MM_STREAM_ERROR = 0x3D7 +MM_MOM_POSITIONCB = 0x3CA +MM_MIM_MOREDATA = 0x3CC +MM_MIXM_LINE_CHANGE = 0x3D0 +MM_MIXM_CONTROL_CHANGE = 0x3D1 +MMSYSERR_BASE = 0 +WAVERR_BASE = 32 +MIDIERR_BASE = 64 +TIMERR_BASE = 96 +JOYERR_BASE = 160 +MCIERR_BASE = 256 +MIXERR_BASE = 1024 +MCI_STRING_OFFSET = 512 +MCI_VD_OFFSET = 1024 +MCI_CD_OFFSET = 1088 +MCI_WAVE_OFFSET = 1152 +MCI_SEQ_OFFSET = 1216 +MMSYSERR_NOERROR = 0 +MMSYSERR_ERROR = (MMSYSERR_BASE + 1) +MMSYSERR_BADDEVICEID = (MMSYSERR_BASE + 2) +MMSYSERR_NOTENABLED = (MMSYSERR_BASE + 3) +MMSYSERR_ALLOCATED = (MMSYSERR_BASE + 4) +MMSYSERR_INVALHANDLE = (MMSYSERR_BASE + 5) +MMSYSERR_NODRIVER = (MMSYSERR_BASE + 6) +MMSYSERR_NOMEM = (MMSYSERR_BASE + 7) +MMSYSERR_NOTSUPPORTED = (MMSYSERR_BASE + 8) +MMSYSERR_BADERRNUM = (MMSYSERR_BASE + 9) +MMSYSERR_INVALFLAG = (MMSYSERR_BASE + 10) +MMSYSERR_INVALPARAM = (MMSYSERR_BASE + 11) +MMSYSERR_HANDLEBUSY = (MMSYSERR_BASE + 12) +MMSYSERR_INVALIDALIAS = (MMSYSERR_BASE + 13) +MMSYSERR_BADDB = (MMSYSERR_BASE + 14) +MMSYSERR_KEYNOTFOUND = (MMSYSERR_BASE + 15) +MMSYSERR_READERROR = (MMSYSERR_BASE + 16) +MMSYSERR_WRITEERROR = (MMSYSERR_BASE + 17) +MMSYSERR_DELETEERROR = (MMSYSERR_BASE + 18) +MMSYSERR_VALNOTFOUND = (MMSYSERR_BASE + 19) +MMSYSERR_NODRIVERCB = (MMSYSERR_BASE + 20) +MMSYSERR_LASTERROR = (MMSYSERR_BASE + 20) +DRV_LOAD = 0x0001 +DRV_ENABLE = 0x0002 +DRV_OPEN = 0x0003 +DRV_CLOSE = 0x0004 +DRV_DISABLE = 0x0005 +DRV_FREE = 0x0006 +DRV_CONFIGURE = 0x0007 +DRV_QUERYCONFIGURE = 0x0008 +DRV_INSTALL = 0x0009 +DRV_REMOVE = 0x000A +DRV_EXITSESSION = 0x000B +DRV_POWER = 0x000F +DRV_RESERVED = 0x0800 +DRV_USER = 0x4000 +DRVCNF_CANCEL = 0x0000 +DRVCNF_OK = 0x0001 +DRVCNF_RESTART = 0x0002 +DRV_CANCEL = DRVCNF_CANCEL +DRV_OK = DRVCNF_OK +DRV_RESTART = DRVCNF_RESTART +DRV_MCI_FIRST = DRV_RESERVED +DRV_MCI_LAST = (DRV_RESERVED + 0xFFF) +CALLBACK_TYPEMASK = 0x00070000 +CALLBACK_NULL = 0x00000000 +CALLBACK_WINDOW = 0x00010000 +CALLBACK_TASK = 0x00020000 +CALLBACK_FUNCTION = 0x00030000 +CALLBACK_THREAD = (CALLBACK_TASK) +CALLBACK_EVENT = 0x00050000 +SND_SYNC = 0x0000 +SND_ASYNC = 0x0001 +SND_NODEFAULT = 0x0002 +SND_MEMORY = 0x0004 +SND_LOOP = 0x0008 +SND_NOSTOP = 0x0010 +SND_NOWAIT = 0x00002000 +SND_ALIAS = 0x00010000 +SND_ALIAS_ID = 0x00110000 +SND_FILENAME = 0x00020000 +SND_RESOURCE = 0x00040004 +SND_PURGE = 0x0040 +SND_APPLICATION = 0x0080 +SND_ALIAS_START = 0 +WAVERR_BADFORMAT = (WAVERR_BASE + 0) +WAVERR_STILLPLAYING = (WAVERR_BASE + 1) +WAVERR_UNPREPARED = (WAVERR_BASE + 2) +WAVERR_SYNC = (WAVERR_BASE + 3) +WAVERR_LASTERROR = (WAVERR_BASE + 3) +WOM_OPEN = MM_WOM_OPEN +WOM_CLOSE = MM_WOM_CLOSE +WOM_DONE = MM_WOM_DONE +WIM_OPEN = MM_WIM_OPEN +WIM_CLOSE = MM_WIM_CLOSE +WIM_DATA = MM_WIM_DATA +WAVE_MAPPER = -1 # 0xFFFFFFFF +WAVE_FORMAT_QUERY = 0x0001 +WAVE_ALLOWSYNC = 0x0002 +WAVE_MAPPED = 0x0004 +WAVE_FORMAT_DIRECT = 0x0008 +WAVE_FORMAT_DIRECT_QUERY = (WAVE_FORMAT_QUERY | WAVE_FORMAT_DIRECT) +WHDR_DONE = 0x00000001 +WHDR_PREPARED = 0x00000002 +WHDR_BEGINLOOP = 0x00000004 +WHDR_ENDLOOP = 0x00000008 +WHDR_INQUEUE = 0x00000010 +WAVECAPS_PITCH = 0x0001 +WAVECAPS_PLAYBACKRATE = 0x0002 +WAVECAPS_VOLUME = 0x0004 +WAVECAPS_LRVOLUME = 0x0008 +WAVECAPS_SYNC = 0x0010 +WAVECAPS_SAMPLEACCURATE = 0x0020 +WAVECAPS_DIRECTSOUND = 0x0040 +WAVE_INVALIDFORMAT = 0x00000000 +WAVE_FORMAT_1M08 = 0x00000001 +WAVE_FORMAT_1S08 = 0x00000002 +WAVE_FORMAT_1M16 = 0x00000004 +WAVE_FORMAT_1S16 = 0x00000008 +WAVE_FORMAT_2M08 = 0x00000010 +WAVE_FORMAT_2S08 = 0x00000020 +WAVE_FORMAT_2M16 = 0x00000040 +WAVE_FORMAT_2S16 = 0x00000080 +WAVE_FORMAT_4M08 = 0x00000100 +WAVE_FORMAT_4S08 = 0x00000200 +WAVE_FORMAT_4M16 = 0x00000400 +WAVE_FORMAT_4S16 = 0x00000800 +WAVE_FORMAT_PCM = 1 +WAVE_FORMAT_IEEE_FLOAT = 3 +MIDIERR_UNPREPARED = (MIDIERR_BASE + 0) +MIDIERR_STILLPLAYING = (MIDIERR_BASE + 1) +MIDIERR_NOMAP = (MIDIERR_BASE + 2) +MIDIERR_NOTREADY = (MIDIERR_BASE + 3) +MIDIERR_NODEVICE = (MIDIERR_BASE + 4) +MIDIERR_INVALIDSETUP = (MIDIERR_BASE + 5) +MIDIERR_BADOPENMODE = (MIDIERR_BASE + 6) +MIDIERR_DONT_CONTINUE = (MIDIERR_BASE + 7) +MIDIERR_LASTERROR = (MIDIERR_BASE + 7) +MIDIPATCHSIZE = 128 +MIM_OPEN = MM_MIM_OPEN +MIM_CLOSE = MM_MIM_CLOSE +MIM_DATA = MM_MIM_DATA +MIM_LONGDATA = MM_MIM_LONGDATA +MIM_ERROR = MM_MIM_ERROR +MIM_LONGERROR = MM_MIM_LONGERROR +MOM_OPEN = MM_MOM_OPEN +MOM_CLOSE = MM_MOM_CLOSE +MOM_DONE = MM_MOM_DONE +MIM_MOREDATA = MM_MIM_MOREDATA +MOM_POSITIONCB = MM_MOM_POSITIONCB +MIDI_IO_STATUS = 0x00000020 +MIDI_CACHE_ALL = 1 +MIDI_CACHE_BESTFIT = 2 +MIDI_CACHE_QUERY = 3 +MIDI_UNCACHE = 4 +MOD_MIDIPORT = 1 +MOD_SYNTH = 2 +MOD_SQSYNTH = 3 +MOD_FMSYNTH = 4 +MOD_MAPPER = 5 +MIDICAPS_VOLUME = 0x0001 +MIDICAPS_LRVOLUME = 0x0002 +MIDICAPS_CACHE = 0x0004 +MIDICAPS_STREAM = 0x0008 +MHDR_DONE = 0x00000001 +MHDR_PREPARED = 0x00000002 +MHDR_INQUEUE = 0x00000004 +MHDR_ISSTRM = 0x00000008 +MEVT_F_SHORT = 0x00000000 +MEVT_F_LONG = -2147483648 # 0x80000000 +MEVT_F_CALLBACK = 0x40000000 +def MEVT_EVENTTYPE(x): return ((BYTE)(((x)>>24)&0xFF)) + +def MEVT_EVENTPARM(x): return ((DWORD)((x)&0x00FFFFFF)) + +MIDISTRM_ERROR = (-2) +MIDIPROP_SET = -2147483648 # 0x80000000 +MIDIPROP_GET = 0x40000000 +MIDIPROP_TIMEDIV = 0x00000001 +MIDIPROP_TEMPO = 0x00000002 +AUXCAPS_CDAUDIO = 1 +AUXCAPS_AUXIN = 2 +AUXCAPS_VOLUME = 0x0001 +AUXCAPS_LRVOLUME = 0x0002 +MIXER_SHORT_NAME_CHARS = 16 +MIXER_LONG_NAME_CHARS = 64 +MIXERR_INVALLINE = (MIXERR_BASE + 0) +MIXERR_INVALCONTROL = (MIXERR_BASE + 1) +MIXERR_INVALVALUE = (MIXERR_BASE + 2) +MIXERR_LASTERROR = (MIXERR_BASE + 2) +MIXER_OBJECTF_HANDLE = -2147483648 # 0x80000000 +MIXER_OBJECTF_MIXER = 0x00000000 +MIXER_OBJECTF_HMIXER = (MIXER_OBJECTF_HANDLE|MIXER_OBJECTF_MIXER) +MIXER_OBJECTF_WAVEOUT = 0x10000000 +MIXER_OBJECTF_HWAVEOUT = (MIXER_OBJECTF_HANDLE|MIXER_OBJECTF_WAVEOUT) +MIXER_OBJECTF_WAVEIN = 0x20000000 +MIXER_OBJECTF_HWAVEIN = (MIXER_OBJECTF_HANDLE|MIXER_OBJECTF_WAVEIN) +MIXER_OBJECTF_MIDIOUT = 0x30000000 +MIXER_OBJECTF_HMIDIOUT = (MIXER_OBJECTF_HANDLE|MIXER_OBJECTF_MIDIOUT) +MIXER_OBJECTF_MIDIIN = 0x40000000 +MIXER_OBJECTF_HMIDIIN = (MIXER_OBJECTF_HANDLE|MIXER_OBJECTF_MIDIIN) +MIXER_OBJECTF_AUX = 0x50000000 +MIXERLINE_LINEF_ACTIVE = 0x00000001 +MIXERLINE_LINEF_DISCONNECTED = 0x00008000 +MIXERLINE_LINEF_SOURCE = -2147483648 # 0x80000000 +MIXERLINE_COMPONENTTYPE_DST_FIRST = 0x00000000 +MIXERLINE_COMPONENTTYPE_DST_UNDEFINED = (MIXERLINE_COMPONENTTYPE_DST_FIRST + 0) +MIXERLINE_COMPONENTTYPE_DST_DIGITAL = (MIXERLINE_COMPONENTTYPE_DST_FIRST + 1) +MIXERLINE_COMPONENTTYPE_DST_LINE = (MIXERLINE_COMPONENTTYPE_DST_FIRST + 2) +MIXERLINE_COMPONENTTYPE_DST_MONITOR = (MIXERLINE_COMPONENTTYPE_DST_FIRST + 3) +MIXERLINE_COMPONENTTYPE_DST_SPEAKERS = (MIXERLINE_COMPONENTTYPE_DST_FIRST + 4) +MIXERLINE_COMPONENTTYPE_DST_HEADPHONES = (MIXERLINE_COMPONENTTYPE_DST_FIRST + 5) +MIXERLINE_COMPONENTTYPE_DST_TELEPHONE = (MIXERLINE_COMPONENTTYPE_DST_FIRST + 6) +MIXERLINE_COMPONENTTYPE_DST_WAVEIN = (MIXERLINE_COMPONENTTYPE_DST_FIRST + 7) +MIXERLINE_COMPONENTTYPE_DST_VOICEIN = (MIXERLINE_COMPONENTTYPE_DST_FIRST + 8) +MIXERLINE_COMPONENTTYPE_DST_LAST = (MIXERLINE_COMPONENTTYPE_DST_FIRST + 8) +MIXERLINE_COMPONENTTYPE_SRC_FIRST = 0x00001000 +MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 0) +MIXERLINE_COMPONENTTYPE_SRC_DIGITAL = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 1) +MIXERLINE_COMPONENTTYPE_SRC_LINE = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 2) +MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 3) +MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 4) +MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 5) +MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 6) +MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 7) +MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 8) +MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 9) +MIXERLINE_COMPONENTTYPE_SRC_ANALOG = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 10) +MIXERLINE_COMPONENTTYPE_SRC_LAST = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 10) +MIXERLINE_TARGETTYPE_UNDEFINED = 0 +MIXERLINE_TARGETTYPE_WAVEOUT = 1 +MIXERLINE_TARGETTYPE_WAVEIN = 2 +MIXERLINE_TARGETTYPE_MIDIOUT = 3 +MIXERLINE_TARGETTYPE_MIDIIN = 4 +MIXERLINE_TARGETTYPE_AUX = 5 +MIXER_GETLINEINFOF_DESTINATION = 0x00000000 +MIXER_GETLINEINFOF_SOURCE = 0x00000001 +MIXER_GETLINEINFOF_LINEID = 0x00000002 +MIXER_GETLINEINFOF_COMPONENTTYPE = 0x00000003 +MIXER_GETLINEINFOF_TARGETTYPE = 0x00000004 +MIXER_GETLINEINFOF_QUERYMASK = 0x0000000F +MIXERCONTROL_CONTROLF_UNIFORM = 0x00000001 +MIXERCONTROL_CONTROLF_MULTIPLE = 0x00000002 +MIXERCONTROL_CONTROLF_DISABLED = -2147483648 # 0x80000000 +MIXERCONTROL_CT_CLASS_MASK = -268435456 # 0xF0000000 +MIXERCONTROL_CT_CLASS_CUSTOM = 0x00000000 +MIXERCONTROL_CT_CLASS_METER = 0x10000000 +MIXERCONTROL_CT_CLASS_SWITCH = 0x20000000 +MIXERCONTROL_CT_CLASS_NUMBER = 0x30000000 +MIXERCONTROL_CT_CLASS_SLIDER = 0x40000000 +MIXERCONTROL_CT_CLASS_FADER = 0x50000000 +MIXERCONTROL_CT_CLASS_TIME = 0x60000000 +MIXERCONTROL_CT_CLASS_LIST = 0x70000000 +MIXERCONTROL_CT_SUBCLASS_MASK = 0x0F000000 +MIXERCONTROL_CT_SC_SWITCH_BOOLEAN = 0x00000000 +MIXERCONTROL_CT_SC_SWITCH_BUTTON = 0x01000000 +MIXERCONTROL_CT_SC_METER_POLLED = 0x00000000 +MIXERCONTROL_CT_SC_TIME_MICROSECS = 0x00000000 +MIXERCONTROL_CT_SC_TIME_MILLISECS = 0x01000000 +MIXERCONTROL_CT_SC_LIST_SINGLE = 0x00000000 +MIXERCONTROL_CT_SC_LIST_MULTIPLE = 0x01000000 +MIXERCONTROL_CT_UNITS_MASK = 0x00FF0000 +MIXERCONTROL_CT_UNITS_CUSTOM = 0x00000000 +MIXERCONTROL_CT_UNITS_BOOLEAN = 0x00010000 +MIXERCONTROL_CT_UNITS_SIGNED = 0x00020000 +MIXERCONTROL_CT_UNITS_UNSIGNED = 0x00030000 +MIXERCONTROL_CT_UNITS_DECIBELS = 0x00040000 +MIXERCONTROL_CT_UNITS_PERCENT = 0x00050000 +MIXERCONTROL_CONTROLTYPE_CUSTOM = (MIXERCONTROL_CT_CLASS_CUSTOM | MIXERCONTROL_CT_UNITS_CUSTOM) +MIXERCONTROL_CONTROLTYPE_BOOLEANMETER = (MIXERCONTROL_CT_CLASS_METER | MIXERCONTROL_CT_SC_METER_POLLED | MIXERCONTROL_CT_UNITS_BOOLEAN) +MIXERCONTROL_CONTROLTYPE_SIGNEDMETER = (MIXERCONTROL_CT_CLASS_METER | MIXERCONTROL_CT_SC_METER_POLLED | MIXERCONTROL_CT_UNITS_SIGNED) +MIXERCONTROL_CONTROLTYPE_PEAKMETER = (MIXERCONTROL_CONTROLTYPE_SIGNEDMETER + 1) +MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER = (MIXERCONTROL_CT_CLASS_METER | MIXERCONTROL_CT_SC_METER_POLLED | MIXERCONTROL_CT_UNITS_UNSIGNED) +MIXERCONTROL_CONTROLTYPE_BOOLEAN = (MIXERCONTROL_CT_CLASS_SWITCH | MIXERCONTROL_CT_SC_SWITCH_BOOLEAN | MIXERCONTROL_CT_UNITS_BOOLEAN) +MIXERCONTROL_CONTROLTYPE_ONOFF = (MIXERCONTROL_CONTROLTYPE_BOOLEAN + 1) +MIXERCONTROL_CONTROLTYPE_MUTE = (MIXERCONTROL_CONTROLTYPE_BOOLEAN + 2) +MIXERCONTROL_CONTROLTYPE_MONO = (MIXERCONTROL_CONTROLTYPE_BOOLEAN + 3) +MIXERCONTROL_CONTROLTYPE_LOUDNESS = (MIXERCONTROL_CONTROLTYPE_BOOLEAN + 4) +MIXERCONTROL_CONTROLTYPE_STEREOENH = (MIXERCONTROL_CONTROLTYPE_BOOLEAN + 5) +MIXERCONTROL_CONTROLTYPE_BUTTON = (MIXERCONTROL_CT_CLASS_SWITCH | MIXERCONTROL_CT_SC_SWITCH_BUTTON | MIXERCONTROL_CT_UNITS_BOOLEAN) +MIXERCONTROL_CONTROLTYPE_DECIBELS = (MIXERCONTROL_CT_CLASS_NUMBER | MIXERCONTROL_CT_UNITS_DECIBELS) +MIXERCONTROL_CONTROLTYPE_SIGNED = (MIXERCONTROL_CT_CLASS_NUMBER | MIXERCONTROL_CT_UNITS_SIGNED) +MIXERCONTROL_CONTROLTYPE_UNSIGNED = (MIXERCONTROL_CT_CLASS_NUMBER | MIXERCONTROL_CT_UNITS_UNSIGNED) +MIXERCONTROL_CONTROLTYPE_PERCENT = (MIXERCONTROL_CT_CLASS_NUMBER | MIXERCONTROL_CT_UNITS_PERCENT) +MIXERCONTROL_CONTROLTYPE_SLIDER = (MIXERCONTROL_CT_CLASS_SLIDER | MIXERCONTROL_CT_UNITS_SIGNED) +MIXERCONTROL_CONTROLTYPE_PAN = (MIXERCONTROL_CONTROLTYPE_SLIDER + 1) +MIXERCONTROL_CONTROLTYPE_QSOUNDPAN = (MIXERCONTROL_CONTROLTYPE_SLIDER + 2) +MIXERCONTROL_CONTROLTYPE_FADER = (MIXERCONTROL_CT_CLASS_FADER | MIXERCONTROL_CT_UNITS_UNSIGNED) +MIXERCONTROL_CONTROLTYPE_VOLUME = (MIXERCONTROL_CONTROLTYPE_FADER + 1) +MIXERCONTROL_CONTROLTYPE_BASS = (MIXERCONTROL_CONTROLTYPE_FADER + 2) +MIXERCONTROL_CONTROLTYPE_TREBLE = (MIXERCONTROL_CONTROLTYPE_FADER + 3) +MIXERCONTROL_CONTROLTYPE_EQUALIZER = (MIXERCONTROL_CONTROLTYPE_FADER + 4) +MIXERCONTROL_CONTROLTYPE_SINGLESELECT = (MIXERCONTROL_CT_CLASS_LIST | MIXERCONTROL_CT_SC_LIST_SINGLE | MIXERCONTROL_CT_UNITS_BOOLEAN) +MIXERCONTROL_CONTROLTYPE_MUX = (MIXERCONTROL_CONTROLTYPE_SINGLESELECT + 1) +MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT = (MIXERCONTROL_CT_CLASS_LIST | MIXERCONTROL_CT_SC_LIST_MULTIPLE | MIXERCONTROL_CT_UNITS_BOOLEAN) +MIXERCONTROL_CONTROLTYPE_MIXER = (MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT + 1) +MIXERCONTROL_CONTROLTYPE_MICROTIME = (MIXERCONTROL_CT_CLASS_TIME | MIXERCONTROL_CT_SC_TIME_MICROSECS | MIXERCONTROL_CT_UNITS_UNSIGNED) +MIXERCONTROL_CONTROLTYPE_MILLITIME = (MIXERCONTROL_CT_CLASS_TIME | MIXERCONTROL_CT_SC_TIME_MILLISECS | MIXERCONTROL_CT_UNITS_UNSIGNED) +MIXER_GETLINECONTROLSF_ALL = 0x00000000 +MIXER_GETLINECONTROLSF_ONEBYID = 0x00000001 +MIXER_GETLINECONTROLSF_ONEBYTYPE = 0x00000002 +MIXER_GETLINECONTROLSF_QUERYMASK = 0x0000000F +MIXER_GETCONTROLDETAILSF_VALUE = 0x00000000 +MIXER_GETCONTROLDETAILSF_LISTTEXT = 0x00000001 +MIXER_GETCONTROLDETAILSF_QUERYMASK = 0x0000000F +MIXER_SETCONTROLDETAILSF_VALUE = 0x00000000 +MIXER_SETCONTROLDETAILSF_CUSTOM = 0x00000001 +MIXER_SETCONTROLDETAILSF_QUERYMASK = 0x0000000F +TIMERR_NOERROR = (0) +TIMERR_NOCANDO = (TIMERR_BASE+1) +TIMERR_STRUCT = (TIMERR_BASE+33) +TIME_ONESHOT = 0x0000 +TIME_PERIODIC = 0x0001 +TIME_CALLBACK_FUNCTION = 0x0000 +TIME_CALLBACK_EVENT_SET = 0x0010 +TIME_CALLBACK_EVENT_PULSE = 0x0020 +JOYERR_NOERROR = (0) +JOYERR_PARMS = (JOYERR_BASE+5) +JOYERR_NOCANDO = (JOYERR_BASE+6) +JOYERR_UNPLUGGED = (JOYERR_BASE+7) +JOY_BUTTON1 = 0x0001 +JOY_BUTTON2 = 0x0002 +JOY_BUTTON3 = 0x0004 +JOY_BUTTON4 = 0x0008 +JOY_BUTTON1CHG = 0x0100 +JOY_BUTTON2CHG = 0x0200 +JOY_BUTTON3CHG = 0x0400 +JOY_BUTTON4CHG = 0x0800 +JOY_BUTTON5 = 0x00000010 +JOY_BUTTON6 = 0x00000020 +JOY_BUTTON7 = 0x00000040 +JOY_BUTTON8 = 0x00000080 +JOY_BUTTON9 = 0x00000100 +JOY_BUTTON10 = 0x00000200 +JOY_BUTTON11 = 0x00000400 +JOY_BUTTON12 = 0x00000800 +JOY_BUTTON13 = 0x00001000 +JOY_BUTTON14 = 0x00002000 +JOY_BUTTON15 = 0x00004000 +JOY_BUTTON16 = 0x00008000 +JOY_BUTTON17 = 0x00010000 +JOY_BUTTON18 = 0x00020000 +JOY_BUTTON19 = 0x00040000 +JOY_BUTTON20 = 0x00080000 +JOY_BUTTON21 = 0x00100000 +JOY_BUTTON22 = 0x00200000 +JOY_BUTTON23 = 0x00400000 +JOY_BUTTON24 = 0x00800000 +JOY_BUTTON25 = 0x01000000 +JOY_BUTTON26 = 0x02000000 +JOY_BUTTON27 = 0x04000000 +JOY_BUTTON28 = 0x08000000 +JOY_BUTTON29 = 0x10000000 +JOY_BUTTON30 = 0x20000000 +JOY_BUTTON31 = 0x40000000 +JOY_BUTTON32 = -2147483648 # 0x80000000 +JOY_POVFORWARD = 0 +JOY_POVRIGHT = 9000 +JOY_POVBACKWARD = 18000 +JOY_POVLEFT = 27000 +JOY_RETURNX = 0x00000001 +JOY_RETURNY = 0x00000002 +JOY_RETURNZ = 0x00000004 +JOY_RETURNR = 0x00000008 +JOY_RETURNU = 0x00000010 +JOY_RETURNV = 0x00000020 +JOY_RETURNPOV = 0x00000040 +JOY_RETURNBUTTONS = 0x00000080 +JOY_RETURNRAWDATA = 0x00000100 +JOY_RETURNPOVCTS = 0x00000200 +JOY_RETURNCENTERED = 0x00000400 +JOY_USEDEADZONE = 0x00000800 +JOY_RETURNALL = (JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | \ + JOY_RETURNR | JOY_RETURNU | JOY_RETURNV | \ + JOY_RETURNPOV | JOY_RETURNBUTTONS) +JOY_CAL_READALWAYS = 0x00010000 +JOY_CAL_READXYONLY = 0x00020000 +JOY_CAL_READ3 = 0x00040000 +JOY_CAL_READ4 = 0x00080000 +JOY_CAL_READXONLY = 0x00100000 +JOY_CAL_READYONLY = 0x00200000 +JOY_CAL_READ5 = 0x00400000 +JOY_CAL_READ6 = 0x00800000 +JOY_CAL_READZONLY = 0x01000000 +JOY_CAL_READRONLY = 0x02000000 +JOY_CAL_READUONLY = 0x04000000 +JOY_CAL_READVONLY = 0x08000000 +JOYSTICKID1 = 0 +JOYSTICKID2 = 1 +JOYCAPS_HASZ = 0x0001 +JOYCAPS_HASR = 0x0002 +JOYCAPS_HASU = 0x0004 +JOYCAPS_HASV = 0x0008 +JOYCAPS_HASPOV = 0x0010 +JOYCAPS_POV4DIR = 0x0020 +JOYCAPS_POVCTS = 0x0040 +MMIOERR_BASE = 256 +MMIOERR_FILENOTFOUND = (MMIOERR_BASE + 1) +MMIOERR_OUTOFMEMORY = (MMIOERR_BASE + 2) +MMIOERR_CANNOTOPEN = (MMIOERR_BASE + 3) +MMIOERR_CANNOTCLOSE = (MMIOERR_BASE + 4) +MMIOERR_CANNOTREAD = (MMIOERR_BASE + 5) +MMIOERR_CANNOTWRITE = (MMIOERR_BASE + 6) +MMIOERR_CANNOTSEEK = (MMIOERR_BASE + 7) +MMIOERR_CANNOTEXPAND = (MMIOERR_BASE + 8) +MMIOERR_CHUNKNOTFOUND = (MMIOERR_BASE + 9) +MMIOERR_UNBUFFERED = (MMIOERR_BASE + 10) +MMIOERR_PATHNOTFOUND = (MMIOERR_BASE + 11) +MMIOERR_ACCESSDENIED = (MMIOERR_BASE + 12) +MMIOERR_SHARINGVIOLATION = (MMIOERR_BASE + 13) +MMIOERR_NETWORKERROR = (MMIOERR_BASE + 14) +MMIOERR_TOOMANYOPENFILES = (MMIOERR_BASE + 15) +MMIOERR_INVALIDFILE = (MMIOERR_BASE + 16) +CFSEPCHAR = ord('+') +MMIO_RWMODE = 0x00000003 +MMIO_SHAREMODE = 0x00000070 +MMIO_CREATE = 0x00001000 +MMIO_PARSE = 0x00000100 +MMIO_DELETE = 0x00000200 +MMIO_EXIST = 0x00004000 +MMIO_ALLOCBUF = 0x00010000 +MMIO_GETTEMP = 0x00020000 +MMIO_DIRTY = 0x10000000 +MMIO_READ = 0x00000000 +MMIO_WRITE = 0x00000001 +MMIO_READWRITE = 0x00000002 +MMIO_COMPAT = 0x00000000 +MMIO_EXCLUSIVE = 0x00000010 +MMIO_DENYWRITE = 0x00000020 +MMIO_DENYREAD = 0x00000030 +MMIO_DENYNONE = 0x00000040 +MMIO_FHOPEN = 0x0010 +MMIO_EMPTYBUF = 0x0010 +MMIO_TOUPPER = 0x0010 +MMIO_INSTALLPROC = 0x00010000 +MMIO_GLOBALPROC = 0x10000000 +MMIO_REMOVEPROC = 0x00020000 +MMIO_UNICODEPROC = 0x01000000 +MMIO_FINDPROC = 0x00040000 +MMIO_FINDCHUNK = 0x0010 +MMIO_FINDRIFF = 0x0020 +MMIO_FINDLIST = 0x0040 +MMIO_CREATERIFF = 0x0020 +MMIO_CREATELIST = 0x0040 +MMIOM_READ = MMIO_READ +MMIOM_WRITE = MMIO_WRITE +MMIOM_SEEK = 2 +MMIOM_OPEN = 3 +MMIOM_CLOSE = 4 +MMIOM_WRITEFLUSH = 5 +MMIOM_RENAME = 6 +MMIOM_USER = 0x8000 +SEEK_SET = 0 +SEEK_CUR = 1 +SEEK_END = 2 +MMIO_DEFAULTBUFFER = 8192 +MCIERR_INVALID_DEVICE_ID = (MCIERR_BASE + 1) +MCIERR_UNRECOGNIZED_KEYWORD = (MCIERR_BASE + 3) +MCIERR_UNRECOGNIZED_COMMAND = (MCIERR_BASE + 5) +MCIERR_HARDWARE = (MCIERR_BASE + 6) +MCIERR_INVALID_DEVICE_NAME = (MCIERR_BASE + 7) +MCIERR_OUT_OF_MEMORY = (MCIERR_BASE + 8) +MCIERR_DEVICE_OPEN = (MCIERR_BASE + 9) +MCIERR_CANNOT_LOAD_DRIVER = (MCIERR_BASE + 10) +MCIERR_MISSING_COMMAND_STRING = (MCIERR_BASE + 11) +MCIERR_PARAM_OVERFLOW = (MCIERR_BASE + 12) +MCIERR_MISSING_STRING_ARGUMENT = (MCIERR_BASE + 13) +MCIERR_BAD_INTEGER = (MCIERR_BASE + 14) +MCIERR_PARSER_INTERNAL = (MCIERR_BASE + 15) +MCIERR_DRIVER_INTERNAL = (MCIERR_BASE + 16) +MCIERR_MISSING_PARAMETER = (MCIERR_BASE + 17) +MCIERR_UNSUPPORTED_FUNCTION = (MCIERR_BASE + 18) +MCIERR_FILE_NOT_FOUND = (MCIERR_BASE + 19) +MCIERR_DEVICE_NOT_READY = (MCIERR_BASE + 20) +MCIERR_INTERNAL = (MCIERR_BASE + 21) +MCIERR_DRIVER = (MCIERR_BASE + 22) +MCIERR_CANNOT_USE_ALL = (MCIERR_BASE + 23) +MCIERR_MULTIPLE = (MCIERR_BASE + 24) +MCIERR_EXTENSION_NOT_FOUND = (MCIERR_BASE + 25) +MCIERR_OUTOFRANGE = (MCIERR_BASE + 26) +MCIERR_FLAGS_NOT_COMPATIBLE = (MCIERR_BASE + 28) +MCIERR_FILE_NOT_SAVED = (MCIERR_BASE + 30) +MCIERR_DEVICE_TYPE_REQUIRED = (MCIERR_BASE + 31) +MCIERR_DEVICE_LOCKED = (MCIERR_BASE + 32) +MCIERR_DUPLICATE_ALIAS = (MCIERR_BASE + 33) +MCIERR_BAD_CONSTANT = (MCIERR_BASE + 34) +MCIERR_MUST_USE_SHAREABLE = (MCIERR_BASE + 35) +MCIERR_MISSING_DEVICE_NAME = (MCIERR_BASE + 36) +MCIERR_BAD_TIME_FORMAT = (MCIERR_BASE + 37) +MCIERR_NO_CLOSING_QUOTE = (MCIERR_BASE + 38) +MCIERR_DUPLICATE_FLAGS = (MCIERR_BASE + 39) +MCIERR_INVALID_FILE = (MCIERR_BASE + 40) +MCIERR_NULL_PARAMETER_BLOCK = (MCIERR_BASE + 41) +MCIERR_UNNAMED_RESOURCE = (MCIERR_BASE + 42) +MCIERR_NEW_REQUIRES_ALIAS = (MCIERR_BASE + 43) +MCIERR_NOTIFY_ON_AUTO_OPEN = (MCIERR_BASE + 44) +MCIERR_NO_ELEMENT_ALLOWED = (MCIERR_BASE + 45) +MCIERR_NONAPPLICABLE_FUNCTION = (MCIERR_BASE + 46) +MCIERR_ILLEGAL_FOR_AUTO_OPEN = (MCIERR_BASE + 47) +MCIERR_FILENAME_REQUIRED = (MCIERR_BASE + 48) +MCIERR_EXTRA_CHARACTERS = (MCIERR_BASE + 49) +MCIERR_DEVICE_NOT_INSTALLED = (MCIERR_BASE + 50) +MCIERR_GET_CD = (MCIERR_BASE + 51) +MCIERR_SET_CD = (MCIERR_BASE + 52) +MCIERR_SET_DRIVE = (MCIERR_BASE + 53) +MCIERR_DEVICE_LENGTH = (MCIERR_BASE + 54) +MCIERR_DEVICE_ORD_LENGTH = (MCIERR_BASE + 55) +MCIERR_NO_INTEGER = (MCIERR_BASE + 56) +MCIERR_WAVE_OUTPUTSINUSE = (MCIERR_BASE + 64) +MCIERR_WAVE_SETOUTPUTINUSE = (MCIERR_BASE + 65) +MCIERR_WAVE_INPUTSINUSE = (MCIERR_BASE + 66) +MCIERR_WAVE_SETINPUTINUSE = (MCIERR_BASE + 67) +MCIERR_WAVE_OUTPUTUNSPECIFIED = (MCIERR_BASE + 68) +MCIERR_WAVE_INPUTUNSPECIFIED = (MCIERR_BASE + 69) +MCIERR_WAVE_OUTPUTSUNSUITABLE = (MCIERR_BASE + 70) +MCIERR_WAVE_SETOUTPUTUNSUITABLE = (MCIERR_BASE + 71) +MCIERR_WAVE_INPUTSUNSUITABLE = (MCIERR_BASE + 72) +MCIERR_WAVE_SETINPUTUNSUITABLE = (MCIERR_BASE + 73) +MCIERR_SEQ_DIV_INCOMPATIBLE = (MCIERR_BASE + 80) +MCIERR_SEQ_PORT_INUSE = (MCIERR_BASE + 81) +MCIERR_SEQ_PORT_NONEXISTENT = (MCIERR_BASE + 82) +MCIERR_SEQ_PORT_MAPNODEVICE = (MCIERR_BASE + 83) +MCIERR_SEQ_PORT_MISCERROR = (MCIERR_BASE + 84) +MCIERR_SEQ_TIMER = (MCIERR_BASE + 85) +MCIERR_SEQ_PORTUNSPECIFIED = (MCIERR_BASE + 86) +MCIERR_SEQ_NOMIDIPRESENT = (MCIERR_BASE + 87) +MCIERR_NO_WINDOW = (MCIERR_BASE + 90) +MCIERR_CREATEWINDOW = (MCIERR_BASE + 91) +MCIERR_FILE_READ = (MCIERR_BASE + 92) +MCIERR_FILE_WRITE = (MCIERR_BASE + 93) +MCIERR_NO_IDENTITY = (MCIERR_BASE + 94) +MCIERR_CUSTOM_DRIVER_BASE = (MCIERR_BASE + 256) +MCI_FIRST = DRV_MCI_FIRST +MCI_OPEN = 0x0803 +MCI_CLOSE = 0x0804 +MCI_ESCAPE = 0x0805 +MCI_PLAY = 0x0806 +MCI_SEEK = 0x0807 +MCI_STOP = 0x0808 +MCI_PAUSE = 0x0809 +MCI_INFO = 0x080A +MCI_GETDEVCAPS = 0x080B +MCI_SPIN = 0x080C +MCI_SET = 0x080D +MCI_STEP = 0x080E +MCI_RECORD = 0x080F +MCI_SYSINFO = 0x0810 +MCI_BREAK = 0x0811 +MCI_SAVE = 0x0813 +MCI_STATUS = 0x0814 +MCI_CUE = 0x0830 +MCI_REALIZE = 0x0840 +MCI_WINDOW = 0x0841 +MCI_PUT = 0x0842 +MCI_WHERE = 0x0843 +MCI_FREEZE = 0x0844 +MCI_UNFREEZE = 0x0845 +MCI_LOAD = 0x0850 +MCI_CUT = 0x0851 +MCI_COPY = 0x0852 +MCI_PASTE = 0x0853 +MCI_UPDATE = 0x0854 +MCI_RESUME = 0x0855 +MCI_DELETE = 0x0856 +MCI_USER_MESSAGES = (DRV_MCI_FIRST + 0x400) +MCI_LAST = 0x0FFF +MCI_DEVTYPE_VCR = 513 +MCI_DEVTYPE_VIDEODISC = 514 +MCI_DEVTYPE_OVERLAY = 515 +MCI_DEVTYPE_CD_AUDIO = 516 +MCI_DEVTYPE_DAT = 517 +MCI_DEVTYPE_SCANNER = 518 +MCI_DEVTYPE_ANIMATION = 519 +MCI_DEVTYPE_DIGITAL_VIDEO = 520 +MCI_DEVTYPE_OTHER = 521 +MCI_DEVTYPE_WAVEFORM_AUDIO = 522 +MCI_DEVTYPE_SEQUENCER = 523 +MCI_DEVTYPE_FIRST = MCI_DEVTYPE_VCR +MCI_DEVTYPE_LAST = MCI_DEVTYPE_SEQUENCER +MCI_DEVTYPE_FIRST_USER = 0x1000 +MCI_MODE_NOT_READY = (MCI_STRING_OFFSET + 12) +MCI_MODE_STOP = (MCI_STRING_OFFSET + 13) +MCI_MODE_PLAY = (MCI_STRING_OFFSET + 14) +MCI_MODE_RECORD = (MCI_STRING_OFFSET + 15) +MCI_MODE_SEEK = (MCI_STRING_OFFSET + 16) +MCI_MODE_PAUSE = (MCI_STRING_OFFSET + 17) +MCI_MODE_OPEN = (MCI_STRING_OFFSET + 18) +MCI_FORMAT_MILLISECONDS = 0 +MCI_FORMAT_HMS = 1 +MCI_FORMAT_MSF = 2 +MCI_FORMAT_FRAMES = 3 +MCI_FORMAT_SMPTE_24 = 4 +MCI_FORMAT_SMPTE_25 = 5 +MCI_FORMAT_SMPTE_30 = 6 +MCI_FORMAT_SMPTE_30DROP = 7 +MCI_FORMAT_BYTES = 8 +MCI_FORMAT_SAMPLES = 9 +MCI_FORMAT_TMSF = 10 +def MCI_MSF_MINUTE(msf): return ((BYTE)(msf)) + +def MCI_MSF_SECOND(msf): return ((BYTE)(((WORD)(msf)) >> 8)) + +def MCI_MSF_FRAME(msf): return ((BYTE)((msf)>>16)) + +def MCI_TMSF_TRACK(tmsf): return ((BYTE)(tmsf)) + +def MCI_TMSF_MINUTE(tmsf): return ((BYTE)(((WORD)(tmsf)) >> 8)) + +def MCI_TMSF_SECOND(tmsf): return ((BYTE)((tmsf)>>16)) + +def MCI_TMSF_FRAME(tmsf): return ((BYTE)((tmsf)>>24)) + +def MCI_HMS_HOUR(hms): return ((BYTE)(hms)) + +def MCI_HMS_MINUTE(hms): return ((BYTE)(((WORD)(hms)) >> 8)) + +def MCI_HMS_SECOND(hms): return ((BYTE)((hms)>>16)) + +MCI_NOTIFY_SUCCESSFUL = 0x0001 +MCI_NOTIFY_SUPERSEDED = 0x0002 +MCI_NOTIFY_ABORTED = 0x0004 +MCI_NOTIFY_FAILURE = 0x0008 +MCI_NOTIFY = 0x00000001 +MCI_WAIT = 0x00000002 +MCI_FROM = 0x00000004 +MCI_TO = 0x00000008 +MCI_TRACK = 0x00000010 +MCI_OPEN_SHAREABLE = 0x00000100 +MCI_OPEN_ELEMENT = 0x00000200 +MCI_OPEN_ALIAS = 0x00000400 +MCI_OPEN_ELEMENT_ID = 0x00000800 +MCI_OPEN_TYPE_ID = 0x00001000 +MCI_OPEN_TYPE = 0x00002000 +MCI_SEEK_TO_START = 0x00000100 +MCI_SEEK_TO_END = 0x00000200 +MCI_STATUS_ITEM = 0x00000100 +MCI_STATUS_START = 0x00000200 +MCI_STATUS_LENGTH = 0x00000001 +MCI_STATUS_POSITION = 0x00000002 +MCI_STATUS_NUMBER_OF_TRACKS = 0x00000003 +MCI_STATUS_MODE = 0x00000004 +MCI_STATUS_MEDIA_PRESENT = 0x00000005 +MCI_STATUS_TIME_FORMAT = 0x00000006 +MCI_STATUS_READY = 0x00000007 +MCI_STATUS_CURRENT_TRACK = 0x00000008 +MCI_INFO_PRODUCT = 0x00000100 +MCI_INFO_FILE = 0x00000200 +MCI_INFO_MEDIA_UPC = 0x00000400 +MCI_INFO_MEDIA_IDENTITY = 0x00000800 +MCI_INFO_NAME = 0x00001000 +MCI_INFO_COPYRIGHT = 0x00002000 +MCI_GETDEVCAPS_ITEM = 0x00000100 +MCI_GETDEVCAPS_CAN_RECORD = 0x00000001 +MCI_GETDEVCAPS_HAS_AUDIO = 0x00000002 +MCI_GETDEVCAPS_HAS_VIDEO = 0x00000003 +MCI_GETDEVCAPS_DEVICE_TYPE = 0x00000004 +MCI_GETDEVCAPS_USES_FILES = 0x00000005 +MCI_GETDEVCAPS_COMPOUND_DEVICE = 0x00000006 +MCI_GETDEVCAPS_CAN_EJECT = 0x00000007 +MCI_GETDEVCAPS_CAN_PLAY = 0x00000008 +MCI_GETDEVCAPS_CAN_SAVE = 0x00000009 +MCI_SYSINFO_QUANTITY = 0x00000100 +MCI_SYSINFO_OPEN = 0x00000200 +MCI_SYSINFO_NAME = 0x00000400 +MCI_SYSINFO_INSTALLNAME = 0x00000800 +MCI_SET_DOOR_OPEN = 0x00000100 +MCI_SET_DOOR_CLOSED = 0x00000200 +MCI_SET_TIME_FORMAT = 0x00000400 +MCI_SET_AUDIO = 0x00000800 +MCI_SET_VIDEO = 0x00001000 +MCI_SET_ON = 0x00002000 +MCI_SET_OFF = 0x00004000 +MCI_SET_AUDIO_ALL = 0x00000000 +MCI_SET_AUDIO_LEFT = 0x00000001 +MCI_SET_AUDIO_RIGHT = 0x00000002 +MCI_BREAK_KEY = 0x00000100 +MCI_BREAK_HWND = 0x00000200 +MCI_BREAK_OFF = 0x00000400 +MCI_RECORD_INSERT = 0x00000100 +MCI_RECORD_OVERWRITE = 0x00000200 +MCI_SAVE_FILE = 0x00000100 +MCI_LOAD_FILE = 0x00000100 +MCI_VD_MODE_PARK = (MCI_VD_OFFSET + 1) +MCI_VD_MEDIA_CLV = (MCI_VD_OFFSET + 2) +MCI_VD_MEDIA_CAV = (MCI_VD_OFFSET + 3) +MCI_VD_MEDIA_OTHER = (MCI_VD_OFFSET + 4) +MCI_VD_FORMAT_TRACK = 0x4001 +MCI_VD_PLAY_REVERSE = 0x00010000 +MCI_VD_PLAY_FAST = 0x00020000 +MCI_VD_PLAY_SPEED = 0x00040000 +MCI_VD_PLAY_SCAN = 0x00080000 +MCI_VD_PLAY_SLOW = 0x00100000 +MCI_VD_SEEK_REVERSE = 0x00010000 +MCI_VD_STATUS_SPEED = 0x00004002 +MCI_VD_STATUS_FORWARD = 0x00004003 +MCI_VD_STATUS_MEDIA_TYPE = 0x00004004 +MCI_VD_STATUS_SIDE = 0x00004005 +MCI_VD_STATUS_DISC_SIZE = 0x00004006 +MCI_VD_GETDEVCAPS_CLV = 0x00010000 +MCI_VD_GETDEVCAPS_CAV = 0x00020000 +MCI_VD_SPIN_UP = 0x00010000 +MCI_VD_SPIN_DOWN = 0x00020000 +MCI_VD_GETDEVCAPS_CAN_REVERSE = 0x00004002 +MCI_VD_GETDEVCAPS_FAST_RATE = 0x00004003 +MCI_VD_GETDEVCAPS_SLOW_RATE = 0x00004004 +MCI_VD_GETDEVCAPS_NORMAL_RATE = 0x00004005 +MCI_VD_STEP_FRAMES = 0x00010000 +MCI_VD_STEP_REVERSE = 0x00020000 +MCI_VD_ESCAPE_STRING = 0x00000100 +MCI_CDA_STATUS_TYPE_TRACK = 0x00004001 +MCI_CDA_TRACK_AUDIO = (MCI_CD_OFFSET + 0) +MCI_CDA_TRACK_OTHER = (MCI_CD_OFFSET + 1) +MCI_WAVE_PCM = (MCI_WAVE_OFFSET + 0) +MCI_WAVE_MAPPER = (MCI_WAVE_OFFSET + 1) +MCI_WAVE_OPEN_BUFFER = 0x00010000 +MCI_WAVE_SET_FORMATTAG = 0x00010000 +MCI_WAVE_SET_CHANNELS = 0x00020000 +MCI_WAVE_SET_SAMPLESPERSEC = 0x00040000 +MCI_WAVE_SET_AVGBYTESPERSEC = 0x00080000 +MCI_WAVE_SET_BLOCKALIGN = 0x00100000 +MCI_WAVE_SET_BITSPERSAMPLE = 0x00200000 +MCI_WAVE_INPUT = 0x00400000 +MCI_WAVE_OUTPUT = 0x00800000 +MCI_WAVE_STATUS_FORMATTAG = 0x00004001 +MCI_WAVE_STATUS_CHANNELS = 0x00004002 +MCI_WAVE_STATUS_SAMPLESPERSEC = 0x00004003 +MCI_WAVE_STATUS_AVGBYTESPERSEC = 0x00004004 +MCI_WAVE_STATUS_BLOCKALIGN = 0x00004005 +MCI_WAVE_STATUS_BITSPERSAMPLE = 0x00004006 +MCI_WAVE_STATUS_LEVEL = 0x00004007 +MCI_WAVE_SET_ANYINPUT = 0x04000000 +MCI_WAVE_SET_ANYOUTPUT = 0x08000000 +MCI_WAVE_GETDEVCAPS_INPUTS = 0x00004001 +MCI_WAVE_GETDEVCAPS_OUTPUTS = 0x00004002 +MCI_SEQ_DIV_PPQN = (0 + MCI_SEQ_OFFSET) +MCI_SEQ_DIV_SMPTE_24 = (1 + MCI_SEQ_OFFSET) +MCI_SEQ_DIV_SMPTE_25 = (2 + MCI_SEQ_OFFSET) +MCI_SEQ_DIV_SMPTE_30DROP = (3 + MCI_SEQ_OFFSET) +MCI_SEQ_DIV_SMPTE_30 = (4 + MCI_SEQ_OFFSET) +MCI_SEQ_FORMAT_SONGPTR = 0x4001 +MCI_SEQ_FILE = 0x4002 +MCI_SEQ_MIDI = 0x4003 +MCI_SEQ_SMPTE = 0x4004 +MCI_SEQ_NONE = 65533 +MCI_SEQ_MAPPER = 65535 +MCI_SEQ_STATUS_TEMPO = 0x00004002 +MCI_SEQ_STATUS_PORT = 0x00004003 +MCI_SEQ_STATUS_SLAVE = 0x00004007 +MCI_SEQ_STATUS_MASTER = 0x00004008 +MCI_SEQ_STATUS_OFFSET = 0x00004009 +MCI_SEQ_STATUS_DIVTYPE = 0x0000400A +MCI_SEQ_STATUS_NAME = 0x0000400B +MCI_SEQ_STATUS_COPYRIGHT = 0x0000400C +MCI_SEQ_SET_TEMPO = 0x00010000 +MCI_SEQ_SET_PORT = 0x00020000 +MCI_SEQ_SET_SLAVE = 0x00040000 +MCI_SEQ_SET_MASTER = 0x00080000 +MCI_SEQ_SET_OFFSET = 0x01000000 +MCI_ANIM_OPEN_WS = 0x00010000 +MCI_ANIM_OPEN_PARENT = 0x00020000 +MCI_ANIM_OPEN_NOSTATIC = 0x00040000 +MCI_ANIM_PLAY_SPEED = 0x00010000 +MCI_ANIM_PLAY_REVERSE = 0x00020000 +MCI_ANIM_PLAY_FAST = 0x00040000 +MCI_ANIM_PLAY_SLOW = 0x00080000 +MCI_ANIM_PLAY_SCAN = 0x00100000 +MCI_ANIM_STEP_REVERSE = 0x00010000 +MCI_ANIM_STEP_FRAMES = 0x00020000 +MCI_ANIM_STATUS_SPEED = 0x00004001 +MCI_ANIM_STATUS_FORWARD = 0x00004002 +MCI_ANIM_STATUS_HWND = 0x00004003 +MCI_ANIM_STATUS_HPAL = 0x00004004 +MCI_ANIM_STATUS_STRETCH = 0x00004005 +MCI_ANIM_INFO_TEXT = 0x00010000 +MCI_ANIM_GETDEVCAPS_CAN_REVERSE = 0x00004001 +MCI_ANIM_GETDEVCAPS_FAST_RATE = 0x00004002 +MCI_ANIM_GETDEVCAPS_SLOW_RATE = 0x00004003 +MCI_ANIM_GETDEVCAPS_NORMAL_RATE = 0x00004004 +MCI_ANIM_GETDEVCAPS_PALETTES = 0x00004006 +MCI_ANIM_GETDEVCAPS_CAN_STRETCH = 0x00004007 +MCI_ANIM_GETDEVCAPS_MAX_WINDOWS = 0x00004008 +MCI_ANIM_REALIZE_NORM = 0x00010000 +MCI_ANIM_REALIZE_BKGD = 0x00020000 +MCI_ANIM_WINDOW_HWND = 0x00010000 +MCI_ANIM_WINDOW_STATE = 0x00040000 +MCI_ANIM_WINDOW_TEXT = 0x00080000 +MCI_ANIM_WINDOW_ENABLE_STRETCH = 0x00100000 +MCI_ANIM_WINDOW_DISABLE_STRETCH = 0x00200000 +MCI_ANIM_WINDOW_DEFAULT = 0x00000000 +MCI_ANIM_RECT = 0x00010000 +MCI_ANIM_PUT_SOURCE = 0x00020000 +MCI_ANIM_PUT_DESTINATION = 0x00040000 +MCI_ANIM_WHERE_SOURCE = 0x00020000 +MCI_ANIM_WHERE_DESTINATION = 0x00040000 +MCI_ANIM_UPDATE_HDC = 0x00020000 +MCI_OVLY_OPEN_WS = 0x00010000 +MCI_OVLY_OPEN_PARENT = 0x00020000 +MCI_OVLY_STATUS_HWND = 0x00004001 +MCI_OVLY_STATUS_STRETCH = 0x00004002 +MCI_OVLY_INFO_TEXT = 0x00010000 +MCI_OVLY_GETDEVCAPS_CAN_STRETCH = 0x00004001 +MCI_OVLY_GETDEVCAPS_CAN_FREEZE = 0x00004002 +MCI_OVLY_GETDEVCAPS_MAX_WINDOWS = 0x00004003 +MCI_OVLY_WINDOW_HWND = 0x00010000 +MCI_OVLY_WINDOW_STATE = 0x00040000 +MCI_OVLY_WINDOW_TEXT = 0x00080000 +MCI_OVLY_WINDOW_ENABLE_STRETCH = 0x00100000 +MCI_OVLY_WINDOW_DISABLE_STRETCH = 0x00200000 +MCI_OVLY_WINDOW_DEFAULT = 0x00000000 +MCI_OVLY_RECT = 0x00010000 +MCI_OVLY_PUT_SOURCE = 0x00020000 +MCI_OVLY_PUT_DESTINATION = 0x00040000 +MCI_OVLY_PUT_FRAME = 0x00080000 +MCI_OVLY_PUT_VIDEO = 0x00100000 +MCI_OVLY_WHERE_SOURCE = 0x00020000 +MCI_OVLY_WHERE_DESTINATION = 0x00040000 +MCI_OVLY_WHERE_FRAME = 0x00080000 +MCI_OVLY_WHERE_VIDEO = 0x00100000 +SELECTDIB = 41 +def DIBINDEX(n): return MAKELONG((n),0x10FF) + diff --git a/Lib/site-packages/win32/lib/netbios.py b/Lib/site-packages/win32/lib/netbios.py new file mode 100644 index 0000000..5c4bb14 --- /dev/null +++ b/Lib/site-packages/win32/lib/netbios.py @@ -0,0 +1,292 @@ +import sys +import win32wnet +import struct + +# Constants generated by h2py from nb30.h +NCBNAMSZ = 16 +MAX_LANA = 254 +NAME_FLAGS_MASK = 0x87 +GROUP_NAME = 0x80 +UNIQUE_NAME = 0x00 +REGISTERING = 0x00 +REGISTERED = 0x04 +DEREGISTERED = 0x05 +DUPLICATE = 0x06 +DUPLICATE_DEREG = 0x07 +LISTEN_OUTSTANDING = 0x01 +CALL_PENDING = 0x02 +SESSION_ESTABLISHED = 0x03 +HANGUP_PENDING = 0x04 +HANGUP_COMPLETE = 0x05 +SESSION_ABORTED = 0x06 +ALL_TRANSPORTS = "M\0\0\0" +MS_NBF = "MNBF" +NCBCALL = 0x10 +NCBLISTEN = 0x11 +NCBHANGUP = 0x12 +NCBSEND = 0x14 +NCBRECV = 0x15 +NCBRECVANY = 0x16 +NCBCHAINSEND = 0x17 +NCBDGSEND = 0x20 +NCBDGRECV = 0x21 +NCBDGSENDBC = 0x22 +NCBDGRECVBC = 0x23 +NCBADDNAME = 0x30 +NCBDELNAME = 0x31 +NCBRESET = 0x32 +NCBASTAT = 0x33 +NCBSSTAT = 0x34 +NCBCANCEL = 0x35 +NCBADDGRNAME = 0x36 +NCBENUM = 0x37 +NCBUNLINK = 0x70 +NCBSENDNA = 0x71 +NCBCHAINSENDNA = 0x72 +NCBLANSTALERT = 0x73 +NCBACTION = 0x77 +NCBFINDNAME = 0x78 +NCBTRACE = 0x79 +ASYNCH = 0x80 +NRC_GOODRET = 0x00 +NRC_BUFLEN = 0x01 +NRC_ILLCMD = 0x03 +NRC_CMDTMO = 0x05 +NRC_INCOMP = 0x06 +NRC_BADDR = 0x07 +NRC_SNUMOUT = 0x08 +NRC_NORES = 0x09 +NRC_SCLOSED = 0x0a +NRC_CMDCAN = 0x0b +NRC_DUPNAME = 0x0d +NRC_NAMTFUL = 0x0e +NRC_ACTSES = 0x0f +NRC_LOCTFUL = 0x11 +NRC_REMTFUL = 0x12 +NRC_ILLNN = 0x13 +NRC_NOCALL = 0x14 +NRC_NOWILD = 0x15 +NRC_INUSE = 0x16 +NRC_NAMERR = 0x17 +NRC_SABORT = 0x18 +NRC_NAMCONF = 0x19 +NRC_IFBUSY = 0x21 +NRC_TOOMANY = 0x22 +NRC_BRIDGE = 0x23 +NRC_CANOCCR = 0x24 +NRC_CANCEL = 0x26 +NRC_DUPENV = 0x30 +NRC_ENVNOTDEF = 0x34 +NRC_OSRESNOTAV = 0x35 +NRC_MAXAPPS = 0x36 +NRC_NOSAPS = 0x37 +NRC_NORESOURCES = 0x38 +NRC_INVADDRESS = 0x39 +NRC_INVDDID = 0x3B +NRC_LOCKFAIL = 0x3C +NRC_OPENERR = 0x3f +NRC_SYSTEM = 0x40 +NRC_PENDING = 0xff + + +UCHAR = "B" +WORD = "H" +DWORD = "I" +USHORT = "H" +ULONG = "I" + +ADAPTER_STATUS_ITEMS = [ + ("6s", "adapter_address"), + (UCHAR, "rev_major"), + (UCHAR, "reserved0"), + (UCHAR, "adapter_type"), + (UCHAR, "rev_minor"), + (WORD, "duration"), + (WORD, "frmr_recv"), + (WORD, "frmr_xmit"), + + (WORD, "iframe_recv_err"), + + (WORD, "xmit_aborts"), + (DWORD, "xmit_success"), + (DWORD, "recv_success"), + + (WORD, "iframe_xmit_err"), + + (WORD, "recv_buff_unavail"), + (WORD, "t1_timeouts"), + (WORD, "ti_timeouts"), + (DWORD, "reserved1"), + (WORD, "free_ncbs"), + (WORD, "max_cfg_ncbs"), + (WORD, "max_ncbs"), + (WORD, "xmit_buf_unavail"), + (WORD, "max_dgram_size"), + (WORD, "pending_sess"), + (WORD, "max_cfg_sess"), + (WORD, "max_sess"), + (WORD, "max_sess_pkt_size"), + (WORD, "name_count"), +] + +NAME_BUFFER_ITEMS = [ + (str(NCBNAMSZ) + "s", "name"), + (UCHAR, "name_num"), + (UCHAR, "name_flags"), +] + +SESSION_HEADER_ITEMS = [ + (UCHAR, "sess_name"), + (UCHAR, "num_sess"), + (UCHAR, "rcv_dg_outstanding"), + (UCHAR, "rcv_any_outstanding"), +] + +SESSION_BUFFER_ITEMS = [ + (UCHAR, "lsn"), + (UCHAR, "state"), + (str(NCBNAMSZ)+"s", "local_name"), + (str(NCBNAMSZ)+"s", "remote_name"), + (UCHAR, "rcvs_outstanding"), + (UCHAR, "sends_outstanding"), +] + +LANA_ENUM_ITEMS = [ + ("B", "length"), # Number of valid entries in lana[] + (str(MAX_LANA+1) + "s", "lana"), +] + +FIND_NAME_HEADER_ITEMS = [ + (WORD, "node_count"), + (UCHAR, "reserved"), + (UCHAR, "unique_group"), +] + +FIND_NAME_BUFFER_ITEMS = [ + (UCHAR, "length"), + (UCHAR, "access_control"), + (UCHAR, "frame_control"), + ("6s", "destination_addr"), + ("6s", "source_addr"), + ("18s", "routing_info"), +] + +ACTION_HEADER_ITEMS = [ + (ULONG, "transport_id"), + (USHORT, "action_code"), + (USHORT, "reserved"), +] + +del UCHAR, WORD, DWORD, USHORT, ULONG + +NCB = win32wnet.NCB +def Netbios(ncb): + ob = ncb.Buffer + is_ours = hasattr(ob, "_pack") + if is_ours: + ob._pack() + try: + return win32wnet.Netbios(ncb) + finally: + if is_ours: + ob._unpack() + +class NCBStruct: + def __init__(self, items): + self._format = "".join([item[0] for item in items]) + self._items = items + self._buffer_ = win32wnet.NCBBuffer(struct.calcsize(self._format)) + + for format, name in self._items: + if len(format)==1: + if format == 'c': + val = '\0' + else: + val = 0 + else: + l = int(format[:-1]) + val = '\0' * l + self.__dict__[name] = val + + def _pack(self): + vals = [] + for format, name in self._items: + try: + vals.append(self.__dict__[name]) + except KeyError: + vals.append(None) + + self._buffer_[:] = struct.pack(*(self._format,) + tuple(vals)) + + def _unpack(self): + items = struct.unpack(self._format, self._buffer_) + assert len(items)==len(self._items), "unexpected number of items to unpack!" + for (format, name), val in zip(self._items, items): + self.__dict__[name] = val + + def __setattr__(self, attr, val): + if attr not in self.__dict__ and attr[0]!='_': + for format, attr_name in self._items: + if attr==attr_name: + break + else: + raise AttributeError(attr) + self.__dict__[attr] = val + +def ADAPTER_STATUS(): + return NCBStruct(ADAPTER_STATUS_ITEMS) + +def NAME_BUFFER(): + return NCBStruct(NAME_BUFFER_ITEMS) + +def SESSION_HEADER(): + return NCBStruct(SESSION_HEADER_ITEMS) + +def SESSION_BUFFER(): + return NCBStruct(SESSION_BUFFER_ITEMS) + +def LANA_ENUM(): + return NCBStruct(LANA_ENUM_ITEMS) + +def FIND_NAME_HEADER(): + return NCBStruct(FIND_NAME_HEADER_ITEMS) + +def FIND_NAME_BUFFER(): + return NCBStruct(FIND_NAME_BUFFER_ITEMS) + +def ACTION_HEADER(): + return NCBStruct(ACTION_HEADER_ITEMS) + +def byte_to_int(b): + """Given an element in a binary buffer, return its integer value""" + if sys.version_info >= (3,0): + # a byte is already an int in py3k + return b + return ord(b) # its a char from a string in py2k. + +if __name__=='__main__': + # code ported from "HOWTO: Get the MAC Address for an Ethernet Adapter" + # MS KB ID: Q118623 + ncb = NCB() + ncb.Command = NCBENUM + la_enum = LANA_ENUM() + ncb.Buffer = la_enum + rc = Netbios(ncb) + if rc != 0: raise RuntimeError("Unexpected result %d" % (rc,)) + for i in range(la_enum.length): + ncb.Reset() + ncb.Command = NCBRESET + ncb.Lana_num = byte_to_int(la_enum.lana[i]) + rc = Netbios(ncb) + if rc != 0: raise RuntimeError("Unexpected result %d" % (rc,)) + ncb.Reset() + ncb.Command = NCBASTAT + ncb.Lana_num = byte_to_int(la_enum.lana[i]) + ncb.Callname = "* ".encode("ascii") # ensure bytes on py2x and 3k + adapter = ADAPTER_STATUS() + ncb.Buffer = adapter + Netbios(ncb) + print("Adapter address:", end=' ') + for ch in adapter.adapter_address: + print("%02x" % (byte_to_int(ch),), end=' ') + print() diff --git a/Lib/site-packages/win32/lib/ntsecuritycon.py b/Lib/site-packages/win32/lib/ntsecuritycon.py new file mode 100644 index 0000000..df52a8b --- /dev/null +++ b/Lib/site-packages/win32/lib/ntsecuritycon.py @@ -0,0 +1,689 @@ +# Hacked from winnt.h + +DELETE = (65536) +READ_CONTROL = (131072) +WRITE_DAC = (262144) +WRITE_OWNER = (524288) +SYNCHRONIZE = (1048576) +STANDARD_RIGHTS_REQUIRED = (983040) +STANDARD_RIGHTS_READ = (READ_CONTROL) +STANDARD_RIGHTS_WRITE = (READ_CONTROL) +STANDARD_RIGHTS_EXECUTE = (READ_CONTROL) +STANDARD_RIGHTS_ALL = (2031616) +SPECIFIC_RIGHTS_ALL = (65535) +ACCESS_SYSTEM_SECURITY = (16777216) +MAXIMUM_ALLOWED = (33554432) +GENERIC_READ = (-2147483648) +GENERIC_WRITE = (1073741824) +GENERIC_EXECUTE = (536870912) +GENERIC_ALL = (268435456) + +# file security permissions +FILE_READ_DATA= ( 1 ) +FILE_LIST_DIRECTORY= ( 1 ) +FILE_WRITE_DATA= ( 2 ) +FILE_ADD_FILE= ( 2 ) +FILE_APPEND_DATA= ( 4 ) +FILE_ADD_SUBDIRECTORY= ( 4 ) +FILE_CREATE_PIPE_INSTANCE= ( 4 ) +FILE_READ_EA= ( 8 ) +FILE_WRITE_EA= ( 16 ) +FILE_EXECUTE= ( 32 ) +FILE_TRAVERSE= ( 32 ) +FILE_DELETE_CHILD= ( 64 ) +FILE_READ_ATTRIBUTES= ( 128 ) +FILE_WRITE_ATTRIBUTES= ( 256 ) +FILE_ALL_ACCESS= (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 1023) +FILE_GENERIC_READ= (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE) +FILE_GENERIC_WRITE= (STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE) +FILE_GENERIC_EXECUTE= (STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE) + + +SECURITY_NULL_SID_AUTHORITY = (0,0,0,0,0,0) +SECURITY_WORLD_SID_AUTHORITY = (0,0,0,0,0,1) +SECURITY_LOCAL_SID_AUTHORITY = (0,0,0,0,0,2) +SECURITY_CREATOR_SID_AUTHORITY = (0,0,0,0,0,3) +SECURITY_NON_UNIQUE_AUTHORITY = (0,0,0,0,0,4) +SECURITY_RESOURCE_MANAGER_AUTHORITY = (0,0,0,0,0,9) + +SECURITY_NULL_RID = 0 +SECURITY_WORLD_RID = 0 +SECURITY_LOCAL_RID = 0X00000000 + +SECURITY_CREATOR_OWNER_RID = 0 +SECURITY_CREATOR_GROUP_RID = 1 + +SECURITY_CREATOR_OWNER_SERVER_RID = 2 +SECURITY_CREATOR_GROUP_SERVER_RID = 3 +SECURITY_CREATOR_OWNER_RIGHTS_RID = 4 + +# NT well-known SIDs +SECURITY_NT_AUTHORITY = (0,0,0,0,0,5) + +SECURITY_DIALUP_RID = 1 +SECURITY_NETWORK_RID = 2 +SECURITY_BATCH_RID = 3 +SECURITY_INTERACTIVE_RID = 4 +SECURITY_SERVICE_RID = 6 +SECURITY_ANONYMOUS_LOGON_RID = 7 +SECURITY_PROXY_RID = 8 +SECURITY_SERVER_LOGON_RID = 9 + +SECURITY_LOGON_IDS_RID = 5 +SECURITY_LOGON_IDS_RID_COUNT = 3 + +SECURITY_LOCAL_SYSTEM_RID = 18 + +SECURITY_NT_NON_UNIQUE = 21 + +SECURITY_BUILTIN_DOMAIN_RID = 32 + +# well-known domain relative sub-authority values (RIDs)... +DOMAIN_USER_RID_ADMIN = 500 +DOMAIN_USER_RID_GUEST = 501 +DOMAIN_USER_RID_KRBTGT = 502 +DOMAIN_USER_RID_MAX = 999 + +# well-known groups ... +DOMAIN_GROUP_RID_ADMINS = 512 +DOMAIN_GROUP_RID_USERS = 513 +DOMAIN_GROUP_RID_GUESTS = 514 +DOMAIN_GROUP_RID_COMPUTERS = 515 +DOMAIN_GROUP_RID_CONTROLLERS = 516 +DOMAIN_GROUP_RID_CERT_ADMINS = 517 +DOMAIN_GROUP_RID_SCHEMA_ADMINS = 518 +DOMAIN_GROUP_RID_ENTERPRISE_ADMINS = 519 +DOMAIN_GROUP_RID_POLICY_ADMINS = 520 +DOMAIN_GROUP_RID_READONLY_CONTROLLERS = 521 + +# well-known aliases ... +DOMAIN_ALIAS_RID_ADMINS = 544 +DOMAIN_ALIAS_RID_USERS = 545 +DOMAIN_ALIAS_RID_GUESTS = 546 +DOMAIN_ALIAS_RID_POWER_USERS = 547 +DOMAIN_ALIAS_RID_ACCOUNT_OPS = 548 +DOMAIN_ALIAS_RID_SYSTEM_OPS = 549 +DOMAIN_ALIAS_RID_PRINT_OPS = 550 +DOMAIN_ALIAS_RID_BACKUP_OPS = 551 +DOMAIN_ALIAS_RID_REPLICATOR = 552 +DOMAIN_ALIAS_RID_RAS_SERVERS = 553 +DOMAIN_ALIAS_RID_PREW2KCOMPACCESS = 554 +DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS = 555 +DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS = 556 +DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS = 557 +DOMAIN_ALIAS_RID_MONITORING_USERS = 558 +DOMAIN_ALIAS_RID_LOGGING_USERS = 559 +DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS = 560 +DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS = 561 +DOMAIN_ALIAS_RID_DCOM_USERS = 562 +DOMAIN_ALIAS_RID_IUSERS = 568 +DOMAIN_ALIAS_RID_CRYPTO_OPERATORS = 569 +DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP = 571 +DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP = 572 +DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP = 573 + +SECURITY_MANDATORY_LABEL_AUTHORITY = (0,0,0,0,0,16) +SECURITY_MANDATORY_UNTRUSTED_RID = 0x00000000 +SECURITY_MANDATORY_LOW_RID = 0x00001000 +SECURITY_MANDATORY_MEDIUM_RID = 0x00002000 +SECURITY_MANDATORY_HIGH_RID = 0x00003000 +SECURITY_MANDATORY_SYSTEM_RID = 0x00004000 +SECURITY_MANDATORY_PROTECTED_PROCESS_RID = 0x00005000 +SECURITY_MANDATORY_MAXIMUM_USER_RID = SECURITY_MANDATORY_SYSTEM_RID + +SYSTEM_LUID = (999, 0) +ANONYMOUS_LOGON_LUID = (998, 0) +LOCALSERVICE_LUID = (997, 0) +NETWORKSERVICE_LUID = (996, 0) +IUSER_LUID = (995, 0) + +# Group attributes + +SE_GROUP_MANDATORY = 1 +SE_GROUP_ENABLED_BY_DEFAULT = 2 +SE_GROUP_ENABLED = 4 +SE_GROUP_OWNER = 8 +SE_GROUP_USE_FOR_DENY_ONLY = 16 +SE_GROUP_INTEGRITY = 32 +SE_GROUP_INTEGRITY_ENABLED = 64 +SE_GROUP_RESOURCE = 536870912 +SE_GROUP_LOGON_ID = -1073741824 + + +# User attributes +# (None yet defined.) + +# ACE types +ACCESS_MIN_MS_ACE_TYPE = (0) +ACCESS_ALLOWED_ACE_TYPE = (0) +ACCESS_DENIED_ACE_TYPE = (1) +SYSTEM_AUDIT_ACE_TYPE = (2) +SYSTEM_ALARM_ACE_TYPE = (3) +ACCESS_MAX_MS_V2_ACE_TYPE = (3) +ACCESS_ALLOWED_COMPOUND_ACE_TYPE = (4) +ACCESS_MAX_MS_V3_ACE_TYPE = (4) +ACCESS_MIN_MS_OBJECT_ACE_TYPE = (5) +ACCESS_ALLOWED_OBJECT_ACE_TYPE = (5) +ACCESS_DENIED_OBJECT_ACE_TYPE = (6) +SYSTEM_AUDIT_OBJECT_ACE_TYPE = (7) +SYSTEM_ALARM_OBJECT_ACE_TYPE = (8) +ACCESS_MAX_MS_OBJECT_ACE_TYPE = (8) +ACCESS_MAX_MS_V4_ACE_TYPE = (8) +ACCESS_MAX_MS_ACE_TYPE = (8) +ACCESS_ALLOWED_CALLBACK_ACE_TYPE = 9 +ACCESS_DENIED_CALLBACK_ACE_TYPE = 10 +ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE = 11 +ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE = 12 +SYSTEM_AUDIT_CALLBACK_ACE_TYPE = 13 +SYSTEM_ALARM_CALLBACK_ACE_TYPE = 14 +SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE = 15 +SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE = 16 +SYSTEM_MANDATORY_LABEL_ACE_TYPE = 17 +ACCESS_MAX_MS_V5_ACE_TYPE = 17 + +# The following are the inherit flags that go into the AceFlags field +# of an Ace header. + +OBJECT_INHERIT_ACE = 1 +CONTAINER_INHERIT_ACE = 2 +NO_PROPAGATE_INHERIT_ACE = 4 +INHERIT_ONLY_ACE = 8 +VALID_INHERIT_FLAGS = 15 + + +SUCCESSFUL_ACCESS_ACE_FLAG = 64 +FAILED_ACCESS_ACE_FLAG = 128 + +SE_OWNER_DEFAULTED = 1 +SE_GROUP_DEFAULTED = 2 +SE_DACL_PRESENT = 4 +SE_DACL_DEFAULTED = 8 +SE_SACL_PRESENT = 16 +SE_SACL_DEFAULTED = 32 +SE_SELF_RELATIVE = 32768 + + +SE_PRIVILEGE_ENABLED_BY_DEFAULT = 1 +SE_PRIVILEGE_ENABLED = 2 +SE_PRIVILEGE_USED_FOR_ACCESS = -2147483648 + +PRIVILEGE_SET_ALL_NECESSARY = 1 + +# NT Defined Privileges + +SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege" +SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege" +SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege" +SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege" +SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege" +SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege" +SE_TCB_NAME = "SeTcbPrivilege" +SE_SECURITY_NAME = "SeSecurityPrivilege" +SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege" +SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege" +SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege" +SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege" +SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege" +SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege" +SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege" +SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege" +SE_BACKUP_NAME = "SeBackupPrivilege" +SE_RESTORE_NAME = "SeRestorePrivilege" +SE_SHUTDOWN_NAME = "SeShutdownPrivilege" +SE_DEBUG_NAME = "SeDebugPrivilege" +SE_AUDIT_NAME = "SeAuditPrivilege" +SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege" +SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege" +SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege" + + +# Enum SECURITY_IMPERSONATION_LEVEL: +SecurityAnonymous = 0 +SecurityIdentification = 1 +SecurityImpersonation = 2 +SecurityDelegation = 3 + +SECURITY_MAX_IMPERSONATION_LEVEL = SecurityDelegation + +DEFAULT_IMPERSONATION_LEVEL = SecurityImpersonation + +TOKEN_ASSIGN_PRIMARY = 1 +TOKEN_DUPLICATE = 2 +TOKEN_IMPERSONATE = 4 +TOKEN_QUERY = 8 +TOKEN_QUERY_SOURCE = 16 +TOKEN_ADJUST_PRIVILEGES = 32 +TOKEN_ADJUST_GROUPS = 64 +TOKEN_ADJUST_DEFAULT = 128 + +TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |\ + TOKEN_ASSIGN_PRIMARY |\ + TOKEN_DUPLICATE |\ + TOKEN_IMPERSONATE |\ + TOKEN_QUERY |\ + TOKEN_QUERY_SOURCE |\ + TOKEN_ADJUST_PRIVILEGES |\ + TOKEN_ADJUST_GROUPS |\ + TOKEN_ADJUST_DEFAULT) + + +TOKEN_READ = (STANDARD_RIGHTS_READ |\ + TOKEN_QUERY) + + +TOKEN_WRITE = (STANDARD_RIGHTS_WRITE |\ + TOKEN_ADJUST_PRIVILEGES |\ + TOKEN_ADJUST_GROUPS |\ + TOKEN_ADJUST_DEFAULT) + +TOKEN_EXECUTE = (STANDARD_RIGHTS_EXECUTE) + +SidTypeUser = 1 +SidTypeGroup = 2 +SidTypeDomain =3 +SidTypeAlias = 4 +SidTypeWellKnownGroup = 5 +SidTypeDeletedAccount = 6 +SidTypeInvalid = 7 +SidTypeUnknown = 8 +SidTypeComputer = 9 +SidTypeLabel = 10 + +# Token types +TokenPrimary = 1 +TokenImpersonation = 2 + +# TOKEN_INFORMATION_CLASS, used with Get/SetTokenInformation +TokenUser = 1 +TokenGroups = 2 +TokenPrivileges = 3 +TokenOwner = 4 +TokenPrimaryGroup = 5 +TokenDefaultDacl = 6 +TokenSource = 7 +TokenType = 8 +TokenImpersonationLevel = 9 +TokenStatistics = 10 +TokenRestrictedSids = 11 +TokenSessionId = 12 +TokenGroupsAndPrivileges = 13 +TokenSessionReference = 14 +TokenSandBoxInert = 15 +TokenAuditPolicy = 16 +TokenOrigin = 17 +TokenElevationType = 18 +TokenLinkedToken = 19 +TokenElevation = 20 +TokenHasRestrictions = 21 +TokenAccessInformation = 22 +TokenVirtualizationAllowed = 23 +TokenVirtualizationEnabled = 24 +TokenIntegrityLevel = 25 +TokenUIAccess = 26 +TokenMandatoryPolicy = 27 +TokenLogonSid = 28 + +# DirectoryService related constants. +# Generated by h2py from NtDsAPI.h +DS_BEHAVIOR_WIN2000 = 0 +DS_BEHAVIOR_WIN2003_WITH_MIXED_DOMAINS = 1 +DS_BEHAVIOR_WIN2003 = 2 +DS_SYNCED_EVENT_NAME = "NTDSInitialSyncsCompleted" +ACTRL_DS_OPEN = 0x00000000 +ACTRL_DS_CREATE_CHILD = 0x00000001 +ACTRL_DS_DELETE_CHILD = 0x00000002 +ACTRL_DS_LIST = 0x00000004 +ACTRL_DS_SELF = 0x00000008 +ACTRL_DS_READ_PROP = 0x00000010 +ACTRL_DS_WRITE_PROP = 0x00000020 +ACTRL_DS_DELETE_TREE = 0x00000040 +ACTRL_DS_LIST_OBJECT = 0x00000080 +ACTRL_DS_CONTROL_ACCESS = 0x00000100 +NTDSAPI_BIND_ALLOW_DELEGATION = (0x00000001) +DS_REPSYNC_ASYNCHRONOUS_OPERATION = 0x00000001 +DS_REPSYNC_WRITEABLE = 0x00000002 +DS_REPSYNC_PERIODIC = 0x00000004 +DS_REPSYNC_INTERSITE_MESSAGING = 0x00000008 +DS_REPSYNC_ALL_SOURCES = 0x00000010 +DS_REPSYNC_FULL = 0x00000020 +DS_REPSYNC_URGENT = 0x00000040 +DS_REPSYNC_NO_DISCARD = 0x00000080 +DS_REPSYNC_FORCE = 0x00000100 +DS_REPSYNC_ADD_REFERENCE = 0x00000200 +DS_REPSYNC_NEVER_COMPLETED = 0x00000400 +DS_REPSYNC_TWO_WAY = 0x00000800 +DS_REPSYNC_NEVER_NOTIFY = 0x00001000 +DS_REPSYNC_INITIAL = 0x00002000 +DS_REPSYNC_USE_COMPRESSION = 0x00004000 +DS_REPSYNC_ABANDONED = 0x00008000 +DS_REPSYNC_INITIAL_IN_PROGRESS = 0x00010000 +DS_REPSYNC_PARTIAL_ATTRIBUTE_SET = 0x00020000 +DS_REPSYNC_REQUEUE = 0x00040000 +DS_REPSYNC_NOTIFICATION = 0x00080000 +DS_REPSYNC_ASYNCHRONOUS_REPLICA = 0x00100000 +DS_REPSYNC_CRITICAL = 0x00200000 +DS_REPSYNC_FULL_IN_PROGRESS = 0x00400000 +DS_REPSYNC_PREEMPTED = 0x00800000 +DS_REPADD_ASYNCHRONOUS_OPERATION = 0x00000001 +DS_REPADD_WRITEABLE = 0x00000002 +DS_REPADD_INITIAL = 0x00000004 +DS_REPADD_PERIODIC = 0x00000008 +DS_REPADD_INTERSITE_MESSAGING = 0x00000010 +DS_REPADD_ASYNCHRONOUS_REPLICA = 0x00000020 +DS_REPADD_DISABLE_NOTIFICATION = 0x00000040 +DS_REPADD_DISABLE_PERIODIC = 0x00000080 +DS_REPADD_USE_COMPRESSION = 0x00000100 +DS_REPADD_NEVER_NOTIFY = 0x00000200 +DS_REPADD_TWO_WAY = 0x00000400 +DS_REPADD_CRITICAL = 0x00000800 +DS_REPDEL_ASYNCHRONOUS_OPERATION = 0x00000001 +DS_REPDEL_WRITEABLE = 0x00000002 +DS_REPDEL_INTERSITE_MESSAGING = 0x00000004 +DS_REPDEL_IGNORE_ERRORS = 0x00000008 +DS_REPDEL_LOCAL_ONLY = 0x00000010 +DS_REPDEL_NO_SOURCE = 0x00000020 +DS_REPDEL_REF_OK = 0x00000040 +DS_REPMOD_ASYNCHRONOUS_OPERATION = 0x00000001 +DS_REPMOD_WRITEABLE = 0x00000002 +DS_REPMOD_UPDATE_FLAGS = 0x00000001 +DS_REPMOD_UPDATE_ADDRESS = 0x00000002 +DS_REPMOD_UPDATE_SCHEDULE = 0x00000004 +DS_REPMOD_UPDATE_RESULT = 0x00000008 +DS_REPMOD_UPDATE_TRANSPORT = 0x00000010 +DS_REPUPD_ASYNCHRONOUS_OPERATION = 0x00000001 +DS_REPUPD_WRITEABLE = 0x00000002 +DS_REPUPD_ADD_REFERENCE = 0x00000004 +DS_REPUPD_DELETE_REFERENCE = 0x00000008 +DS_INSTANCETYPE_IS_NC_HEAD = 0x00000001 +DS_INSTANCETYPE_NC_IS_WRITEABLE = 0x00000004 +DS_INSTANCETYPE_NC_COMING = 0x00000010 +DS_INSTANCETYPE_NC_GOING = 0x00000020 +NTDSDSA_OPT_IS_GC = ( 1 << 0 ) +NTDSDSA_OPT_DISABLE_INBOUND_REPL = ( 1 << 1 ) +NTDSDSA_OPT_DISABLE_OUTBOUND_REPL = ( 1 << 2 ) +NTDSDSA_OPT_DISABLE_NTDSCONN_XLATE = ( 1 << 3 ) +NTDSCONN_OPT_IS_GENERATED = ( 1 << 0 ) +NTDSCONN_OPT_TWOWAY_SYNC = ( 1 << 1 ) +NTDSCONN_OPT_OVERRIDE_NOTIFY_DEFAULT = (1 << 2 ) +NTDSCONN_OPT_USE_NOTIFY = (1 << 3) +NTDSCONN_OPT_DISABLE_INTERSITE_COMPRESSION = (1 << 4) +NTDSCONN_OPT_USER_OWNED_SCHEDULE = (1 << 5) +NTDSCONN_KCC_NO_REASON = ( 0 ) +NTDSCONN_KCC_GC_TOPOLOGY = ( 1 << 0 ) +NTDSCONN_KCC_RING_TOPOLOGY = ( 1 << 1 ) +NTDSCONN_KCC_MINIMIZE_HOPS_TOPOLOGY = ( 1 << 2 ) +NTDSCONN_KCC_STALE_SERVERS_TOPOLOGY = ( 1 << 3 ) +NTDSCONN_KCC_OSCILLATING_CONNECTION_TOPOLOGY = ( 1 << 4 ) +NTDSCONN_KCC_INTERSITE_GC_TOPOLOGY = (1 << 5) +NTDSCONN_KCC_INTERSITE_TOPOLOGY = (1 << 6) +NTDSCONN_KCC_SERVER_FAILOVER_TOPOLOGY = (1 << 7) +NTDSCONN_KCC_SITE_FAILOVER_TOPOLOGY = (1 << 8) +NTDSCONN_KCC_REDUNDANT_SERVER_TOPOLOGY = (1 << 9) +FRSCONN_PRIORITY_MASK = 0x70000000 +FRSCONN_MAX_PRIORITY = 0x8 +NTDSCONN_OPT_IGNORE_SCHEDULE_MASK = (-2147483648) + +NTDSSETTINGS_OPT_IS_AUTO_TOPOLOGY_DISABLED = ( 1 << 0 ) +NTDSSETTINGS_OPT_IS_TOPL_CLEANUP_DISABLED = ( 1 << 1 ) +NTDSSETTINGS_OPT_IS_TOPL_MIN_HOPS_DISABLED = ( 1 << 2 ) +NTDSSETTINGS_OPT_IS_TOPL_DETECT_STALE_DISABLED = ( 1 << 3 ) +NTDSSETTINGS_OPT_IS_INTER_SITE_AUTO_TOPOLOGY_DISABLED = ( 1 << 4 ) +NTDSSETTINGS_OPT_IS_GROUP_CACHING_ENABLED = ( 1 << 5 ) +NTDSSETTINGS_OPT_FORCE_KCC_WHISTLER_BEHAVIOR = ( 1 << 6 ) +NTDSSETTINGS_OPT_FORCE_KCC_W2K_ELECTION = ( 1 << 7 ) +NTDSSETTINGS_OPT_IS_RAND_BH_SELECTION_DISABLED = ( 1 << 8 ) +NTDSSETTINGS_OPT_IS_SCHEDULE_HASHING_ENABLED = ( 1 << 9 ) +NTDSSETTINGS_OPT_IS_REDUNDANT_SERVER_TOPOLOGY_ENABLED = ( 1 << 10 ) +NTDSSETTINGS_DEFAULT_SERVER_REDUNDANCY = 2 +NTDSTRANSPORT_OPT_IGNORE_SCHEDULES = ( 1 << 0 ) +NTDSTRANSPORT_OPT_BRIDGES_REQUIRED = (1 << 1 ) +NTDSSITECONN_OPT_USE_NOTIFY = ( 1 << 0 ) +NTDSSITECONN_OPT_TWOWAY_SYNC = ( 1 << 1 ) +NTDSSITECONN_OPT_DISABLE_COMPRESSION = ( 1 << 2 ) +NTDSSITELINK_OPT_USE_NOTIFY = ( 1 << 0 ) +NTDSSITELINK_OPT_TWOWAY_SYNC = ( 1 << 1 ) +NTDSSITELINK_OPT_DISABLE_COMPRESSION = ( 1 << 2 ) +GUID_USERS_CONTAINER_A = "a9d1ca15768811d1aded00c04fd8d5cd" +GUID_COMPUTRS_CONTAINER_A = "aa312825768811d1aded00c04fd8d5cd" +GUID_SYSTEMS_CONTAINER_A = "ab1d30f3768811d1aded00c04fd8d5cd" +GUID_DOMAIN_CONTROLLERS_CONTAINER_A = "a361b2ffffd211d1aa4b00c04fd7d83a" +GUID_INFRASTRUCTURE_CONTAINER_A = "2fbac1870ade11d297c400c04fd8d5cd" +GUID_DELETED_OBJECTS_CONTAINER_A = "18e2ea80684f11d2b9aa00c04f79f805" +GUID_LOSTANDFOUND_CONTAINER_A = "ab8153b7768811d1aded00c04fd8d5cd" +GUID_FOREIGNSECURITYPRINCIPALS_CONTAINER_A = "22b70c67d56e4efb91e9300fca3dc1aa" +GUID_PROGRAM_DATA_CONTAINER_A = "09460c08ae1e4a4ea0f64aee7daa1e5a" +GUID_MICROSOFT_PROGRAM_DATA_CONTAINER_A = "f4be92a4c777485e878e9421d53087db" +GUID_NTDS_QUOTAS_CONTAINER_A = "6227f0af1fc2410d8e3bb10615bb5b0f" +GUID_USERS_CONTAINER_BYTE = "\xa9\xd1\xca\x15\x76\x88\x11\xd1\xad\xed\x00\xc0\x4f\xd8\xd5\xcd" +GUID_COMPUTRS_CONTAINER_BYTE = "\xaa\x31\x28\x25\x76\x88\x11\xd1\xad\xed\x00\xc0\x4f\xd8\xd5\xcd" +GUID_SYSTEMS_CONTAINER_BYTE = "\xab\x1d\x30\xf3\x76\x88\x11\xd1\xad\xed\x00\xc0\x4f\xd8\xd5\xcd" +GUID_DOMAIN_CONTROLLERS_CONTAINER_BYTE = "\xa3\x61\xb2\xff\xff\xd2\x11\xd1\xaa\x4b\x00\xc0\x4f\xd7\xd8\x3a" +GUID_INFRASTRUCTURE_CONTAINER_BYTE = "\x2f\xba\xc1\x87\x0a\xde\x11\xd2\x97\xc4\x00\xc0\x4f\xd8\xd5\xcd" +GUID_DELETED_OBJECTS_CONTAINER_BYTE = "\x18\xe2\xea\x80\x68\x4f\x11\xd2\xb9\xaa\x00\xc0\x4f\x79\xf8\x05" +GUID_LOSTANDFOUND_CONTAINER_BYTE = "\xab\x81\x53\xb7\x76\x88\x11\xd1\xad\xed\x00\xc0\x4f\xd8\xd5\xcd" +GUID_FOREIGNSECURITYPRINCIPALS_CONTAINER_BYTE = "\x22\xb7\x0c\x67\xd5\x6e\x4e\xfb\x91\xe9\x30\x0f\xca\x3d\xc1\xaa" +GUID_PROGRAM_DATA_CONTAINER_BYTE = "\x09\x46\x0c\x08\xae\x1e\x4a\x4e\xa0\xf6\x4a\xee\x7d\xaa\x1e\x5a" +GUID_MICROSOFT_PROGRAM_DATA_CONTAINER_BYTE = "\xf4\xbe\x92\xa4\xc7\x77\x48\x5e\x87\x8e\x94\x21\xd5\x30\x87\xdb" +GUID_NTDS_QUOTAS_CONTAINER_BYTE = "\x62\x27\xf0\xaf\x1f\xc2\x41\x0d\x8e\x3b\xb1\x06\x15\xbb\x5b\x0f" +DS_REPSYNCALL_NO_OPTIONS = 0x00000000 +DS_REPSYNCALL_ABORT_IF_SERVER_UNAVAILABLE = 0x00000001 +DS_REPSYNCALL_SYNC_ADJACENT_SERVERS_ONLY = 0x00000002 +DS_REPSYNCALL_ID_SERVERS_BY_DN = 0x00000004 +DS_REPSYNCALL_DO_NOT_SYNC = 0x00000008 +DS_REPSYNCALL_SKIP_INITIAL_CHECK = 0x00000010 +DS_REPSYNCALL_PUSH_CHANGES_OUTWARD = 0x00000020 +DS_REPSYNCALL_CROSS_SITE_BOUNDARIES = 0x00000040 +DS_LIST_DSA_OBJECT_FOR_SERVER = 0 +DS_LIST_DNS_HOST_NAME_FOR_SERVER = 1 +DS_LIST_ACCOUNT_OBJECT_FOR_SERVER = 2 +DS_ROLE_SCHEMA_OWNER = 0 +DS_ROLE_DOMAIN_OWNER = 1 +DS_ROLE_PDC_OWNER = 2 +DS_ROLE_RID_OWNER = 3 +DS_ROLE_INFRASTRUCTURE_OWNER = 4 +DS_SCHEMA_GUID_NOT_FOUND = 0 +DS_SCHEMA_GUID_ATTR = 1 +DS_SCHEMA_GUID_ATTR_SET = 2 +DS_SCHEMA_GUID_CLASS = 3 +DS_SCHEMA_GUID_CONTROL_RIGHT = 4 +DS_KCC_FLAG_ASYNC_OP = (1 << 0) +DS_KCC_FLAG_DAMPED = (1 << 1) +DS_EXIST_ADVISORY_MODE = (0x1) +DS_REPL_INFO_FLAG_IMPROVE_LINKED_ATTRS = (0x00000001) +DS_REPL_NBR_WRITEABLE = (0x00000010) +DS_REPL_NBR_SYNC_ON_STARTUP = (0x00000020) +DS_REPL_NBR_DO_SCHEDULED_SYNCS = (0x00000040) +DS_REPL_NBR_USE_ASYNC_INTERSITE_TRANSPORT = (0x00000080) +DS_REPL_NBR_TWO_WAY_SYNC = (0x00000200) +DS_REPL_NBR_RETURN_OBJECT_PARENTS = (0x00000800) +DS_REPL_NBR_FULL_SYNC_IN_PROGRESS = (0x00010000) +DS_REPL_NBR_FULL_SYNC_NEXT_PACKET = (0x00020000) +DS_REPL_NBR_NEVER_SYNCED = (0x00200000) +DS_REPL_NBR_PREEMPTED = (0x01000000) +DS_REPL_NBR_IGNORE_CHANGE_NOTIFICATIONS = (0x04000000) +DS_REPL_NBR_DISABLE_SCHEDULED_SYNC = (0x08000000) +DS_REPL_NBR_COMPRESS_CHANGES = (0x10000000) +DS_REPL_NBR_NO_CHANGE_NOTIFICATIONS = (0x20000000) +DS_REPL_NBR_PARTIAL_ATTRIBUTE_SET = (0x40000000) +DS_REPL_NBR_MODIFIABLE_MASK = \ + ( \ + DS_REPL_NBR_SYNC_ON_STARTUP | \ + DS_REPL_NBR_DO_SCHEDULED_SYNCS | \ + DS_REPL_NBR_TWO_WAY_SYNC | \ + DS_REPL_NBR_IGNORE_CHANGE_NOTIFICATIONS | \ + DS_REPL_NBR_DISABLE_SCHEDULED_SYNC | \ + DS_REPL_NBR_COMPRESS_CHANGES | \ + DS_REPL_NBR_NO_CHANGE_NOTIFICATIONS \ + ) + +# from enum DS_NAME_FORMAT +DS_UNKNOWN_NAME = 0 +DS_FQDN_1779_NAME = 1 +DS_NT4_ACCOUNT_NAME = 2 +DS_DISPLAY_NAME = 3 +DS_UNIQUE_ID_NAME = 6 +DS_CANONICAL_NAME = 7 +DS_USER_PRINCIPAL_NAME = 8 +DS_CANONICAL_NAME_EX = 9 +DS_SERVICE_PRINCIPAL_NAME = 10 +DS_SID_OR_SID_HISTORY_NAME = 11 +DS_DNS_DOMAIN_NAME = 12 + +DS_DOMAIN_SIMPLE_NAME = DS_USER_PRINCIPAL_NAME +DS_ENTERPRISE_SIMPLE_NAME = DS_USER_PRINCIPAL_NAME + +# from enum DS_NAME_FLAGS +DS_NAME_NO_FLAGS = 0x0 +DS_NAME_FLAG_SYNTACTICAL_ONLY = 0x1 +DS_NAME_FLAG_EVAL_AT_DC = 0x2 +DS_NAME_FLAG_GCVERIFY = 0x4 +DS_NAME_FLAG_TRUST_REFERRAL = 0x8 + +# from enum DS_NAME_ERROR +DS_NAME_NO_ERROR = 0 +DS_NAME_ERROR_RESOLVING = 1 +DS_NAME_ERROR_NOT_FOUND = 2 +DS_NAME_ERROR_NOT_UNIQUE = 3 +DS_NAME_ERROR_NO_MAPPING = 4 +DS_NAME_ERROR_DOMAIN_ONLY = 5 +DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING = 6 +DS_NAME_ERROR_TRUST_REFERRAL = 7 + + +# from enum DS_SPN_NAME_TYPE +DS_SPN_DNS_HOST = 0 +DS_SPN_DN_HOST = 1 +DS_SPN_NB_HOST = 2 +DS_SPN_DOMAIN = 3 +DS_SPN_NB_DOMAIN = 4 +DS_SPN_SERVICE = 5 + +# from enum DS_SPN_WRITE_OP +DS_SPN_ADD_SPN_OP = 0 +DS_SPN_REPLACE_SPN_OP = 1 +DS_SPN_DELETE_SPN_OP = 2 + +# Generated by h2py from DsGetDC.h +DS_FORCE_REDISCOVERY = 0x00000001 +DS_DIRECTORY_SERVICE_REQUIRED = 0x00000010 +DS_DIRECTORY_SERVICE_PREFERRED = 0x00000020 +DS_GC_SERVER_REQUIRED = 0x00000040 +DS_PDC_REQUIRED = 0x00000080 +DS_BACKGROUND_ONLY = 0x00000100 +DS_IP_REQUIRED = 0x00000200 +DS_KDC_REQUIRED = 0x00000400 +DS_TIMESERV_REQUIRED = 0x00000800 +DS_WRITABLE_REQUIRED = 0x00001000 +DS_GOOD_TIMESERV_PREFERRED = 0x00002000 +DS_AVOID_SELF = 0x00004000 +DS_ONLY_LDAP_NEEDED = 0x00008000 +DS_IS_FLAT_NAME = 0x00010000 +DS_IS_DNS_NAME = 0x00020000 +DS_RETURN_DNS_NAME = 0x40000000 +DS_RETURN_FLAT_NAME = (-2147483648) +DSGETDC_VALID_FLAGS = ( \ + DS_FORCE_REDISCOVERY | \ + DS_DIRECTORY_SERVICE_REQUIRED | \ + DS_DIRECTORY_SERVICE_PREFERRED | \ + DS_GC_SERVER_REQUIRED | \ + DS_PDC_REQUIRED | \ + DS_BACKGROUND_ONLY | \ + DS_IP_REQUIRED | \ + DS_KDC_REQUIRED | \ + DS_TIMESERV_REQUIRED | \ + DS_WRITABLE_REQUIRED | \ + DS_GOOD_TIMESERV_PREFERRED | \ + DS_AVOID_SELF | \ + DS_ONLY_LDAP_NEEDED | \ + DS_IS_FLAT_NAME | \ + DS_IS_DNS_NAME | \ + DS_RETURN_FLAT_NAME | \ + DS_RETURN_DNS_NAME ) +DS_INET_ADDRESS = 1 +DS_NETBIOS_ADDRESS = 2 +DS_PDC_FLAG = 0x00000001 +DS_GC_FLAG = 0x00000004 +DS_LDAP_FLAG = 0x00000008 +DS_DS_FLAG = 0x00000010 +DS_KDC_FLAG = 0x00000020 +DS_TIMESERV_FLAG = 0x00000040 +DS_CLOSEST_FLAG = 0x00000080 +DS_WRITABLE_FLAG = 0x00000100 +DS_GOOD_TIMESERV_FLAG = 0x00000200 +DS_NDNC_FLAG = 0x00000400 +DS_PING_FLAGS = 0x0000FFFF +DS_DNS_CONTROLLER_FLAG = 0x20000000 +DS_DNS_DOMAIN_FLAG = 0x40000000 +DS_DNS_FOREST_FLAG = (-2147483648) +DS_DOMAIN_IN_FOREST = 0x0001 +DS_DOMAIN_DIRECT_OUTBOUND = 0x0002 +DS_DOMAIN_TREE_ROOT = 0x0004 +DS_DOMAIN_PRIMARY = 0x0008 +DS_DOMAIN_NATIVE_MODE = 0x0010 +DS_DOMAIN_DIRECT_INBOUND = 0x0020 +DS_DOMAIN_VALID_FLAGS = ( \ + DS_DOMAIN_IN_FOREST | \ + DS_DOMAIN_DIRECT_OUTBOUND | \ + DS_DOMAIN_TREE_ROOT | \ + DS_DOMAIN_PRIMARY | \ + DS_DOMAIN_NATIVE_MODE | \ + DS_DOMAIN_DIRECT_INBOUND ) +DS_GFTI_UPDATE_TDO = 0x1 +DS_GFTI_VALID_FLAGS = 0x1 +DS_ONLY_DO_SITE_NAME = 0x01 +DS_NOTIFY_AFTER_SITE_RECORDS = 0x02 +DS_OPEN_VALID_OPTION_FLAGS = ( DS_ONLY_DO_SITE_NAME | DS_NOTIFY_AFTER_SITE_RECORDS ) +DS_OPEN_VALID_FLAGS = ( \ + DS_FORCE_REDISCOVERY | \ + DS_ONLY_LDAP_NEEDED | \ + DS_KDC_REQUIRED | \ + DS_PDC_REQUIRED | \ + DS_GC_SERVER_REQUIRED | \ + DS_WRITABLE_REQUIRED ) + +## from aclui.h +# SI_OBJECT_INFO.dwFlags +SI_EDIT_PERMS = 0x00000000 +SI_EDIT_OWNER = 0x00000001 +SI_EDIT_AUDITS = 0x00000002 +SI_CONTAINER = 0x00000004 +SI_READONLY = 0x00000008 +SI_ADVANCED = 0x00000010 +SI_RESET = 0x00000020 +SI_OWNER_READONLY = 0x00000040 +SI_EDIT_PROPERTIES = 0x00000080 +SI_OWNER_RECURSE = 0x00000100 +SI_NO_ACL_PROTECT = 0x00000200 +SI_NO_TREE_APPLY = 0x00000400 +SI_PAGE_TITLE = 0x00000800 +SI_SERVER_IS_DC = 0x00001000 +SI_RESET_DACL_TREE = 0x00004000 +SI_RESET_SACL_TREE = 0x00008000 +SI_OBJECT_GUID = 0x00010000 +SI_EDIT_EFFECTIVE = 0x00020000 +SI_RESET_DACL = 0x00040000 +SI_RESET_SACL = 0x00080000 +SI_RESET_OWNER = 0x00100000 +SI_NO_ADDITIONAL_PERMISSION = 0x00200000 +SI_MAY_WRITE = 0x10000000 +SI_EDIT_ALL = (SI_EDIT_PERMS | SI_EDIT_OWNER | SI_EDIT_AUDITS) +SI_AUDITS_ELEVATION_REQUIRED = 0x02000000 +SI_VIEW_ONLY = 0x00400000 +SI_OWNER_ELEVATION_REQUIRED = 0x04000000 +SI_PERMS_ELEVATION_REQUIRED = 0x01000000 + +# SI_ACCESS.dwFlags +SI_ACCESS_SPECIFIC = 0x00010000 +SI_ACCESS_GENERAL = 0x00020000 +SI_ACCESS_CONTAINER = 0x00040000 +SI_ACCESS_PROPERTY = 0x00080000 + +# SI_PAGE_TYPE enum +SI_PAGE_PERM = 0 +SI_PAGE_ADVPERM = 1 +SI_PAGE_AUDIT = 2 +SI_PAGE_OWNER = 3 +SI_PAGE_EFFECTIVE =4 + +CFSTR_ACLUI_SID_INFO_LIST = "CFSTR_ACLUI_SID_INFO_LIST" +PSPCB_SI_INITDIALOG = 1025 ## WM_USER+1 diff --git a/Lib/site-packages/win32/lib/pywin32_testutil.py b/Lib/site-packages/win32/lib/pywin32_testutil.py new file mode 100644 index 0000000..760781a --- /dev/null +++ b/Lib/site-packages/win32/lib/pywin32_testutil.py @@ -0,0 +1,270 @@ +# Utilities for the pywin32 tests +import sys +import unittest +import gc +import winerror + +## +## General purpose utilities for the test suite. +## + +def int2long(val): + """return a long on py2k""" + return val + 0x100000000 - 0x100000000 + +# The test suite has lots of string constants containing binary data, but +# the strings are used in various "bytes" contexts. +def str2bytes(sval): + if sys.version_info < (3,0) and isinstance(sval, str): + sval = sval.decode("latin1") + return sval.encode("latin1") + + +# Sometimes we want to pass a string that should explicitly be treated as +# a memory blob. +def str2memory(sval): + if sys.version_info < (3,0): + return buffer(sval) + # py3k. + return memoryview(sval.encode("latin1")) + + +# Sometimes we want to pass an object that exposes its memory +def ob2memory(ob): + if sys.version_info < (3,0): + return buffer(ob) + # py3k. + return memoryview(ob) + + +# Note: no str2unicode: we use u'' literals or unicode() function, and 2to3 +# + +## +## unittest related stuff +## + +# This is a specialized TestCase adaptor which wraps a real test. +class LeakTestCase(unittest.TestCase): + """An 'adaptor' which takes another test. In debug builds we execute the + test once to remove one-off side-effects, then capture the total + reference count, then execute the test a few times. If the total + refcount at the end is greater than we first captured, we have a leak! + + In release builds the test is executed just once, as normal. + + Generally used automatically by the test runner - you can safely + ignore this. + """ + def __init__(self, real_test): + unittest.TestCase.__init__(self) + self.real_test = real_test + self.num_test_cases = 1 + self.num_leak_iters = 2 # seems to be enough! + if hasattr(sys, "gettotalrefcount"): + self.num_test_cases = self.num_test_cases + self.num_leak_iters + + def countTestCases(self): + return self.num_test_cases + + def __call__(self, result = None): + # For the COM suite's sake, always ensure we don't leak + # gateways/interfaces + from pythoncom import _GetInterfaceCount, _GetGatewayCount + gc.collect() + ni = _GetInterfaceCount() + ng = _GetGatewayCount() + self.real_test(result) + # Failed - no point checking anything else + if result.shouldStop or not result.wasSuccessful(): + return + self._do_leak_tests(result) + gc.collect() + lost_i = _GetInterfaceCount() - ni + lost_g = _GetGatewayCount() - ng + if lost_i or lost_g: + msg = "%d interface objects and %d gateway objects leaked" \ + % (lost_i, lost_g) + exc = AssertionError(msg) + result.addFailure(self.real_test, (exc.__class__, exc, None)) + + def runTest(self): + assert 0, "not used" + + def _do_leak_tests(self, result = None): + try: + gtrc = sys.gettotalrefcount + except AttributeError: + return # can't do leak tests in this build + # Assume already called once, to prime any caches etc + gc.collect() + trc = gtrc() + for i in range(self.num_leak_iters): + self.real_test(result) + if result.shouldStop: + break + del i # created after we remembered the refcount! + # int division here means one or 2 stray references won't force + # failure, but one per loop + gc.collect() + lost = (gtrc() - trc) // self.num_leak_iters + if lost < 0: + msg = "LeakTest: %s appeared to gain %d references!!" % (self.real_test, -lost) + result.addFailure(self.real_test, (AssertionError, msg, None)) + if lost > 0: + msg = "LeakTest: %s lost %d references" % (self.real_test, lost) + exc = AssertionError(msg) + result.addFailure(self.real_test, (exc.__class__, exc, None)) + + +class TestLoader(unittest.TestLoader): + def loadTestsFromTestCase(self, testCaseClass): + """Return a suite of all tests cases contained in testCaseClass""" + leak_tests = [] + for name in self.getTestCaseNames(testCaseClass): + real_test = testCaseClass(name) + leak_test = self._getTestWrapper(real_test) + leak_tests.append(leak_test) + return self.suiteClass(leak_tests) + + def fixupTestsForLeakTests(self, test): + if isinstance(test, unittest.TestSuite): + test._tests = [self.fixupTestsForLeakTests(t) for t in test._tests] + return test + else: + # just a normal test case. + return self._getTestWrapper(test) + + def _getTestWrapper(self, test): + # one or 2 tests in the COM test suite set this... + no_leak_tests = getattr(test, "no_leak_tests", False) + if no_leak_tests: + print("Test says it doesn't want leak tests!") + return test + return LeakTestCase(test) + + def loadTestsFromModule(self, mod): + if hasattr(mod, "suite"): + tests = mod.suite() + else: + tests = unittest.TestLoader.loadTestsFromModule(self, mod) + return self.fixupTestsForLeakTests(tests) + + def loadTestsFromName(self, name, module=None): + test = unittest.TestLoader.loadTestsFromName(self, name, module) + if isinstance(test, unittest.TestSuite): + pass # hmmm? print "Don't wrap suites yet!", test._tests + elif isinstance(test, unittest.TestCase): + test = self._getTestWrapper(test) + else: + print("XXX - what is", test) + return test + +# Lots of classes necessary to support one simple feature: we want a 3rd +# test result state - "SKIPPED" - to indicate that the test wasn't able +# to be executed for various reasons. Inspired by bzr's tests, but it +# has other concepts, such as "Expected Failure", which we don't bother +# with. + +# win32 error codes that probably mean we need to be elevated (ie, if we +# aren't elevated, we treat these error codes as 'skipped') +non_admin_error_codes = [winerror.ERROR_ACCESS_DENIED, + winerror.ERROR_PRIVILEGE_NOT_HELD] + +_is_admin = None +def check_is_admin(): + global _is_admin + if _is_admin is None: + from win32com.shell.shell import IsUserAnAdmin + import pythoncom + try: + _is_admin = IsUserAnAdmin() + except pythoncom.com_error as exc: + if exc.hresult != winerror.E_NOTIMPL: + raise + # not impl on this platform - must be old - assume is admin + _is_admin = True + return _is_admin + + +# If this exception is raised by a test, the test is reported as a 'skip' +class TestSkipped(Exception): + pass + + +# The 'TestResult' subclass that records the failures and has the special +# handling for the TestSkipped exception. +class TestResult(unittest._TextTestResult): + def __init__(self, *args, **kw): + super(TestResult, self).__init__(*args, **kw) + self.skips = {} # count of skips for each reason. + + def addError(self, test, err): + """Called when an error has occurred. 'err' is a tuple of values as + returned by sys.exc_info(). + """ + # translate a couple of 'well-known' exceptions into 'skipped' + import pywintypes + exc_val = err[1] + # translate ERROR_ACCESS_DENIED for non-admin users to be skipped. + # (access denied errors for an admin user aren't expected.) + if isinstance(exc_val, pywintypes.error) \ + and exc_val.winerror in non_admin_error_codes \ + and not check_is_admin(): + exc_val = TestSkipped(exc_val) + # and COM errors due to objects not being registered (the com test + # suite will attempt to catch this and handle it itself if the user + # is admin) + elif isinstance(exc_val, pywintypes.com_error) and \ + exc_val.hresult in [winerror.CO_E_CLASSSTRING, + winerror.REGDB_E_CLASSNOTREG, + winerror.TYPE_E_LIBNOTREGISTERED]: + exc_val = TestSkipped(exc_val) + # NotImplemented generally means the platform doesn't support the + # functionality. + elif isinstance(exc_val, NotImplementedError): + exc_val = TestSkipped(NotImplementedError) + + if isinstance(exc_val, TestSkipped): + reason = exc_val.args[0] + # if the reason itself is another exception, get its args. + try: + reason = tuple(reason.args) + except (AttributeError, TypeError): + pass + self.skips.setdefault(reason, 0) + self.skips[reason] += 1 + if self.showAll: + self.stream.writeln("SKIP (%s)" % (reason,)) + elif self.dots: + self.stream.write('S') + self.stream.flush() + return + super(TestResult, self).addError(test, err) + + def printErrors(self): + super(TestResult, self).printErrors() + for reason, num_skipped in self.skips.items(): + self.stream.writeln("SKIPPED: %d tests - %s" % (num_skipped, reason)) + +# TestRunner subclass necessary just to get our TestResult hooked up. +class TestRunner(unittest.TextTestRunner): + def _makeResult(self): + return TestResult(self.stream, self.descriptions, self.verbosity) + + +# TestProgream subclass necessary just to get our TestRunner hooked up, +# which is necessary to get our TestResult hooked up *sob* +class TestProgram(unittest.TestProgram): + def runTests(self): + # clobber existing runner - *sob* - it shouldn't be this hard + self.testRunner = TestRunner(verbosity=self.verbosity) + unittest.TestProgram.runTests(self) + +# A convenient entry-point - if used, 'SKIPPED' exceptions will be supressed. +def testmain(*args, **kw): + new_kw = kw.copy() + if 'testLoader' not in new_kw: + new_kw['testLoader'] = TestLoader() + program_class = new_kw.get('testProgram', TestProgram) + program_class(*args, **new_kw) diff --git a/Lib/site-packages/win32/lib/pywintypes.py b/Lib/site-packages/win32/lib/pywintypes.py new file mode 100644 index 0000000..dea149f --- /dev/null +++ b/Lib/site-packages/win32/lib/pywintypes.py @@ -0,0 +1,124 @@ +# Magic utility that "redirects" to pywintypesxx.dll +import imp, sys, os +def __import_pywin32_system_module__(modname, globs): + # This has been through a number of iterations. The problem: how to + # locate pywintypesXX.dll when it may be in a number of places, and how + # to avoid ever loading it twice. This problem is compounded by the + # fact that the "right" way to do this requires win32api, but this + # itself requires pywintypesXX. + # And the killer problem is that someone may have done 'import win32api' + # before this code is called. In that case Windows will have already + # loaded pywintypesXX as part of loading win32api - but by the time + # we get here, we may locate a different one. This appears to work, but + # then starts raising bizarre TypeErrors complaining that something + # is not a pywintypes type when it clearly is! + + # So in what we hope is the last major iteration of this, we now + # rely on a _win32sysloader module, implemented in C but not relying + # on pywintypesXX.dll. It then can check if the DLL we are looking for + # lib is already loaded. + if not sys.platform.startswith("win32"): + # These extensions can be built on Linux via the 'mainwin' toolkit. + # Look for a native 'lib{modname}.so' + # NOTE: The _win32sysloader module will probably build in this + # environment, so it may be better to use that here too. + for ext, mode, ext_type in imp.get_suffixes(): + if ext_type==imp.C_EXTENSION: + for path in sys.path: + look = os.path.join(path, "lib" + modname + ext) + if os.path.isfile(look): + mod = imp.load_module(modname, None, look, + (ext, mode, ext_type)) + # and fill our namespace with it. + # XXX - if this ever moves to py3k, this will probably + # need similar adjustments as below... + globs.update(mod.__dict__) + return + raise ImportError("No dynamic module " + modname) + # See if this is a debug build. + for suffix_item in imp.get_suffixes(): + if suffix_item[0]=='_d.pyd': + suffix = '_d' + break + else: + suffix = "" + filename = "%s%d%d%s.dll" % \ + (modname, sys.version_info[0], sys.version_info[1], suffix) + if hasattr(sys, "frozen"): + # If we are running from a frozen program (py2exe, McMillan, freeze) + # then we try and load the DLL from our sys.path + # XXX - This path may also benefit from _win32sysloader? However, + # MarkH has never seen the DLL load problem with py2exe programs... + for look in sys.path: + # If the sys.path entry is a (presumably) .zip file, use the + # directory + if os.path.isfile(look): + look = os.path.dirname(look) + found = os.path.join(look, filename) + if os.path.isfile(found): + break + else: + raise ImportError("Module '%s' isn't in frozen sys.path %s" % (modname, sys.path)) + else: + # First see if it already in our process - if so, we must use that. + import _win32sysloader + found = _win32sysloader.GetModuleFilename(filename) + if found is None: + # We ask Windows to load it next. This is in an attempt to + # get the exact same module loaded should pywintypes be imported + # first (which is how we are here) or if, eg, win32api was imported + # first thereby implicitly loading the DLL. + + # Sadly though, it doesn't quite work - if pywintypesxx.dll + # is in system32 *and* the executable's directory, on XP SP2, an + # import of win32api will cause Windows to load pywintypes + # from system32, where LoadLibrary for that name will + # load the one in the exe's dir. + # That shouldn't really matter though, so long as we only ever + # get one loaded. + found = _win32sysloader.LoadModule(filename) + if found is None: + # Windows can't find it - which although isn't relevent here, + # means that we *must* be the first win32 import, as an attempt + # to import win32api etc would fail when Windows attempts to + # locate the DLL. + # This is most likely to happen for "non-admin" installs, where + # we can't put the files anywhere else on the global path. + + # If there is a version in our Python directory, use that + if os.path.isfile(os.path.join(sys.prefix, filename)): + found = os.path.join(sys.prefix, filename) + if found is None: + # Not in the Python directory? Maybe we were installed via + # easy_install... + if os.path.isfile(os.path.join(os.path.dirname(__file__), filename)): + found = os.path.join(os.path.dirname(__file__), filename) + if found is None: + # give up in disgust. + raise ImportError("No system module '%s' (%s)" % (modname, filename)) + # py2k and py3k differences: + # On py2k, after doing "imp.load_module('pywintypes')", sys.modules + # is unchanged - ie, sys.modules['pywintypes'] still refers to *this* + # .py module - but the module's __dict__ has *already* need updated + # with the new module's contents. + # However, on py3k, sys.modules *is* changed - sys.modules['pywintypes'] + # will be changed to the new module object. + # SO: * on py2k don't need to update any globals. + # * on py3k we update our module dict with the new module's dict and + # copy its globals to ours. + old_mod = sys.modules[modname] + # Python can load the module + mod = imp.load_dynamic(modname, found) + # Check the sys.modules[] behaviour we describe above is true... + if sys.version_info < (3,0): + assert sys.modules[modname] is old_mod + assert mod is old_mod + else: + assert sys.modules[modname] is not old_mod + assert sys.modules[modname] is mod + # as above - re-reset to the *old* module object then update globs. + sys.modules[modname] = old_mod + globs.update(mod.__dict__) + + +__import_pywin32_system_module__("pywintypes", globals()) diff --git a/Lib/site-packages/win32/lib/rasutil.py b/Lib/site-packages/win32/lib/rasutil.py new file mode 100644 index 0000000..e4b5945 --- /dev/null +++ b/Lib/site-packages/win32/lib/rasutil.py @@ -0,0 +1,38 @@ +import win32ras + +stateStrings = { + win32ras.RASCS_OpenPort : "OpenPort", + win32ras.RASCS_PortOpened : "PortOpened", + win32ras.RASCS_ConnectDevice : "ConnectDevice", + win32ras.RASCS_DeviceConnected : "DeviceConnected", + win32ras.RASCS_AllDevicesConnected : "AllDevicesConnected", + win32ras.RASCS_Authenticate : "Authenticate", + win32ras.RASCS_AuthNotify : "AuthNotify", + win32ras.RASCS_AuthRetry : "AuthRetry", + win32ras.RASCS_AuthCallback : "AuthCallback", + win32ras.RASCS_AuthChangePassword : "AuthChangePassword", + win32ras.RASCS_AuthProject : "AuthProject", + win32ras.RASCS_AuthLinkSpeed : "AuthLinkSpeed", + win32ras.RASCS_AuthAck : "AuthAck", + win32ras.RASCS_ReAuthenticate : "ReAuthenticate", + win32ras.RASCS_Authenticated : "Authenticated", + win32ras.RASCS_PrepareForCallback : "PrepareForCallback", + win32ras.RASCS_WaitForModemReset : "WaitForModemReset", + win32ras.RASCS_WaitForCallback : "WaitForCallback", + win32ras.RASCS_Projected : "Projected", + win32ras.RASCS_StartAuthentication : "StartAuthentication", + win32ras.RASCS_CallbackComplete : "CallbackComplete", + win32ras.RASCS_LogonNetwork : "LogonNetwork", + win32ras.RASCS_Interactive : "Interactive", + win32ras.RASCS_RetryAuthentication : "RetryAuthentication", + win32ras.RASCS_CallbackSetByCaller : "CallbackSetByCaller", + win32ras.RASCS_PasswordExpired : "PasswordExpired", + win32ras.RASCS_Connected : "Connected", + win32ras.RASCS_Disconnected : "Disconnected" +} + +def TestCallback( hras, msg, state, error, exterror): + print("Callback called with ", hras, msg, stateStrings[state], error, exterror) + +def test(rasName = "_ Divert Off"): + return win32ras.Dial(None, None, (rasName,),TestCallback) \ No newline at end of file diff --git a/Lib/site-packages/win32/lib/regcheck.py b/Lib/site-packages/win32/lib/regcheck.py new file mode 100644 index 0000000..e3879cd --- /dev/null +++ b/Lib/site-packages/win32/lib/regcheck.py @@ -0,0 +1,124 @@ +# This module is very old and useless in this day and age! It will be +# removed in a few years (ie, 2009 or so...) + +import warnings +warnings.warn("The regcheck module has been pending deprecation since build 210", + category=PendingDeprecationWarning) + +import win32con +import regutil +import win32api +import os +import sys + + +def CheckRegisteredExe(exename): + try: + os.stat(win32api.RegQueryValue(regutil.GetRootKey() , regutil.GetAppPathsKey() + "\\" + exename)) +# except SystemError: + except (os.error,win32api.error): + print("Registration of %s - Not registered correctly" % exename) + +def CheckPathString(pathString): + for path in pathString.split(";"): + if not os.path.isdir(path): + return "'%s' is not a valid directory!" % path + return None + +def CheckPythonPaths(verbose): + if verbose: print("Python Paths:") + # Check the core path + if verbose: print("\tCore Path:", end=' ') + try: + appPath = win32api.RegQueryValue(regutil.GetRootKey(), regutil.BuildDefaultPythonKey() + "\\PythonPath") + except win32api.error as exc: + print("** does not exist - ", exc.strerror) + problem = CheckPathString(appPath) + if problem: + print(problem) + else: + if verbose: print(appPath) + + key = win32api.RegOpenKey(regutil.GetRootKey(), regutil.BuildDefaultPythonKey() + "\\PythonPath", 0, win32con.KEY_READ) + try: + keyNo = 0 + while 1: + try: + appName = win32api.RegEnumKey(key, keyNo) + appPath = win32api.RegQueryValue(key, appName) + if verbose: print("\t"+appName+":", end=' ') + if appPath: + problem = CheckPathString(appPath) + if problem: + print(problem) + else: + if verbose: print(appPath) + else: + if verbose: print("(empty)") + keyNo = keyNo + 1 + except win32api.error: + break + finally: + win32api.RegCloseKey(key) + +def CheckHelpFiles(verbose): + if verbose: print("Help Files:") + try: + key = win32api.RegOpenKey(regutil.GetRootKey(), regutil.BuildDefaultPythonKey() + "\\Help", 0, win32con.KEY_READ) + except win32api.error as exc: + import winerror + if exc.winerror!=winerror.ERROR_FILE_NOT_FOUND: + raise + return + + try: + keyNo = 0 + while 1: + try: + helpDesc = win32api.RegEnumKey(key, keyNo) + helpFile = win32api.RegQueryValue(key, helpDesc) + if verbose: print("\t"+helpDesc+":", end=' ') + # query the os section. + try: + os.stat(helpFile ) + if verbose: print(helpFile) + except os.error: + print("** Help file %s does not exist" % helpFile) + keyNo = keyNo + 1 + except win32api.error as exc: + import winerror + if exc.winerror!=winerror.ERROR_NO_MORE_ITEMS: + raise + break + finally: + win32api.RegCloseKey(key) + +def CheckRegisteredModules(verbose): + # Check out all registered modules. + k=regutil.BuildDefaultPythonKey() + "\\Modules" + try: + keyhandle = win32api.RegOpenKey(regutil.GetRootKey(), k) + print("WARNING: 'Modules' registry entry is deprectated and evil!") + except win32api.error as exc: + import winerror + if exc.winerror!=winerror.ERROR_FILE_NOT_FOUND: + raise + return + +def CheckRegistry(verbose=0): + # check the registered modules + if verbose and 'pythonpath' in os.environ: + print("Warning - PythonPath in environment - please check it!") + # Check out all paths on sys.path + + CheckPythonPaths(verbose) + CheckHelpFiles(verbose) + CheckRegisteredModules(verbose) + CheckRegisteredExe("Python.exe") + +if __name__=='__main__': + if len(sys.argv)>1 and sys.argv[1]=='-q': + verbose = 0 + else: + verbose = 1 + CheckRegistry(verbose) diff --git a/Lib/site-packages/win32/lib/regutil.py b/Lib/site-packages/win32/lib/regutil.py new file mode 100644 index 0000000..1dd2039 --- /dev/null +++ b/Lib/site-packages/win32/lib/regutil.py @@ -0,0 +1,284 @@ +# Some registry helpers. +import win32api +import win32con +import sys +import os + +error = "Registry utility error" + +# A .py file has a CLSID associated with it (why? - dunno!) +CLSIDPyFile = "{b51df050-06ae-11cf-ad3b-524153480001}" + +RegistryIDPyFile = "Python.File" # The registry "file type" of a .py file +RegistryIDPycFile = "Python.CompiledFile" # The registry "file type" of a .pyc file + +def BuildDefaultPythonKey(): + """Builds a string containing the path to the current registry key. + + The Python registry key contains the Python version. This function + uses the version of the DLL used by the current process to get the + registry key currently in use. + """ + return "Software\\Python\\PythonCore\\" + sys.winver + +def GetRootKey(): + """Retrieves the Registry root in use by Python. + """ + keyname = BuildDefaultPythonKey() + try: + k = win32api.RegOpenKey(win32con.HKEY_CURRENT_USER, keyname) + k.close() + return win32con.HKEY_CURRENT_USER + except win32api.error: + return win32con.HKEY_LOCAL_MACHINE + +def GetRegistryDefaultValue(subkey, rootkey = None): + """A helper to return the default value for a key in the registry. + """ + if rootkey is None: rootkey = GetRootKey() + return win32api.RegQueryValue(rootkey, subkey) + +def SetRegistryDefaultValue(subKey, value, rootkey = None): + """A helper to set the default value for a key in the registry + """ + if rootkey is None: rootkey = GetRootKey() + if type(value)==str: + typeId = win32con.REG_SZ + elif type(value)==int: + typeId = win32con.REG_DWORD + else: + raise TypeError("Value must be string or integer - was passed " + repr(value)) + + win32api.RegSetValue(rootkey, subKey, typeId ,value) + +def GetAppPathsKey(): + return "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths" + +def RegisterPythonExe(exeFullPath, exeAlias = None, exeAppPath = None): + """Register a .exe file that uses Python. + + Registers the .exe with the OS. This allows the specified .exe to + be run from the command-line or start button without using the full path, + and also to setup application specific path (ie, os.environ['PATH']). + + Currently the exeAppPath is not supported, so this function is general + purpose, and not specific to Python at all. Later, exeAppPath may provide + a reasonable default that is used. + + exeFullPath -- The full path to the .exe + exeAlias = None -- An alias for the exe - if none, the base portion + of the filename is used. + exeAppPath -- Not supported. + """ + # Note - Dont work on win32s (but we dont care anymore!) + if exeAppPath: + raise error("Do not support exeAppPath argument currently") + if exeAlias is None: + exeAlias = os.path.basename(exeFullPath) + win32api.RegSetValue(GetRootKey(), GetAppPathsKey() + "\\" + exeAlias, win32con.REG_SZ, exeFullPath) + +def GetRegisteredExe(exeAlias): + """Get a registered .exe + """ + return win32api.RegQueryValue(GetRootKey(), GetAppPathsKey() + "\\" + exeAlias) + +def UnregisterPythonExe(exeAlias): + """Unregister a .exe file that uses Python. + """ + try: + win32api.RegDeleteKey(GetRootKey(), GetAppPathsKey() + "\\" + exeAlias) + except win32api.error as exc: + import winerror + if exc.winerror!=winerror.ERROR_FILE_NOT_FOUND: + raise + return + +def RegisterNamedPath(name, path): + """Register a named path - ie, a named PythonPath entry. + """ + keyStr = BuildDefaultPythonKey() + "\\PythonPath" + if name: keyStr = keyStr + "\\" + name + win32api.RegSetValue(GetRootKey(), keyStr, win32con.REG_SZ, path) + +def UnregisterNamedPath(name): + """Unregister a named path - ie, a named PythonPath entry. + """ + keyStr = BuildDefaultPythonKey() + "\\PythonPath\\" + name + try: + win32api.RegDeleteKey(GetRootKey(), keyStr) + except win32api.error as exc: + import winerror + if exc.winerror!=winerror.ERROR_FILE_NOT_FOUND: + raise + return + +def GetRegisteredNamedPath(name): + """Get a registered named path, or None if it doesnt exist. + """ + keyStr = BuildDefaultPythonKey() + "\\PythonPath" + if name: keyStr = keyStr + "\\" + name + try: + return win32api.RegQueryValue(GetRootKey(), keyStr) + except win32api.error as exc: + import winerror + if exc.winerror!=winerror.ERROR_FILE_NOT_FOUND: + raise + return None + + +def RegisterModule(modName, modPath): + """Register an explicit module in the registry. This forces the Python import + mechanism to locate this module directly, without a sys.path search. Thus + a registered module need not appear in sys.path at all. + + modName -- The name of the module, as used by import. + modPath -- The full path and file name of the module. + """ + try: + import os + os.stat(modPath) + except os.error: + print("Warning: Registering non-existant module %s" % modPath) + win32api.RegSetValue(GetRootKey(), + BuildDefaultPythonKey() + "\\Modules\\%s" % modName, + win32con.REG_SZ, modPath) + +def UnregisterModule(modName): + """Unregister an explicit module in the registry. + + modName -- The name of the module, as used by import. + """ + try: + win32api.RegDeleteKey(GetRootKey(), + BuildDefaultPythonKey() + "\\Modules\\%s" % modName) + except win32api.error as exc: + import winerror + if exc.winerror!=winerror.ERROR_FILE_NOT_FOUND: + raise + +def GetRegisteredHelpFile(helpDesc): + """Given a description, return the registered entry. + """ + try: + return GetRegistryDefaultValue(BuildDefaultPythonKey() + "\\Help\\" + helpDesc) + except win32api.error: + try: + return GetRegistryDefaultValue(BuildDefaultPythonKey() + "\\Help\\" + helpDesc, win32con.HKEY_CURRENT_USER) + except win32api.error: + pass + return None + +def RegisterHelpFile(helpFile, helpPath, helpDesc = None, bCheckFile = 1): + """Register a help file in the registry. + + Note that this used to support writing to the Windows Help + key, however this is no longer done, as it seems to be incompatible. + + helpFile -- the base name of the help file. + helpPath -- the path to the help file + helpDesc -- A description for the help file. If None, the helpFile param is used. + bCheckFile -- A flag indicating if the file existence should be checked. + """ + if helpDesc is None: helpDesc = helpFile + fullHelpFile = os.path.join(helpPath, helpFile) + try: + if bCheckFile: os.stat(fullHelpFile) + except os.error: + raise ValueError("Help file does not exist") + # Now register with Python itself. + win32api.RegSetValue(GetRootKey(), + BuildDefaultPythonKey() + "\\Help\\%s" % helpDesc, win32con.REG_SZ, fullHelpFile) + +def UnregisterHelpFile(helpFile, helpDesc = None): + """Unregister a help file in the registry. + + helpFile -- the base name of the help file. + helpDesc -- A description for the help file. If None, the helpFile param is used. + """ + key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Help", 0, win32con.KEY_ALL_ACCESS) + try: + try: + win32api.RegDeleteValue(key, helpFile) + except win32api.error as exc: + import winerror + if exc.winerror!=winerror.ERROR_FILE_NOT_FOUND: + raise + finally: + win32api.RegCloseKey(key) + + # Now de-register with Python itself. + if helpDesc is None: helpDesc = helpFile + try: + win32api.RegDeleteKey(GetRootKey(), + BuildDefaultPythonKey() + "\\Help\\%s" % helpDesc) + except win32api.error as exc: + import winerror + if exc.winerror!=winerror.ERROR_FILE_NOT_FOUND: + raise + +def RegisterCoreDLL(coredllName = None): + """Registers the core DLL in the registry. + + If no params are passed, the name of the Python DLL used in + the current process is used and registered. + """ + if coredllName is None: + coredllName = win32api.GetModuleFileName(sys.dllhandle) + # must exist! + else: + try: + os.stat(coredllName) + except os.error: + print("Warning: Registering non-existant core DLL %s" % coredllName) + + hKey = win32api.RegCreateKey(GetRootKey() , BuildDefaultPythonKey()) + try: + win32api.RegSetValue(hKey, "Dll", win32con.REG_SZ, coredllName) + finally: + win32api.RegCloseKey(hKey) + # Lastly, setup the current version to point to me. + win32api.RegSetValue(GetRootKey(), "Software\\Python\\PythonCore\\CurrentVersion", win32con.REG_SZ, sys.winver) + +def RegisterFileExtensions(defPyIcon, defPycIcon, runCommand): + """Register the core Python file extensions. + + defPyIcon -- The default icon to use for .py files, in 'fname,offset' format. + defPycIcon -- The default icon to use for .pyc files, in 'fname,offset' format. + runCommand -- The command line to use for running .py files + """ + # Register the file extensions. + pythonFileId = RegistryIDPyFile + win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , ".py", win32con.REG_SZ, pythonFileId) + win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , pythonFileId , win32con.REG_SZ, "Python File") + win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , "%s\\CLSID" % pythonFileId , win32con.REG_SZ, CLSIDPyFile) + win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , "%s\\DefaultIcon" % pythonFileId, win32con.REG_SZ, defPyIcon) + base = "%s\\Shell" % RegistryIDPyFile + win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\Open", win32con.REG_SZ, "Run") + win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\Open\\Command", win32con.REG_SZ, runCommand) + + # Register the .PYC. + pythonFileId = RegistryIDPycFile + win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , ".pyc", win32con.REG_SZ, pythonFileId) + win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , pythonFileId , win32con.REG_SZ, "Compiled Python File") + win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , "%s\\DefaultIcon" % pythonFileId, win32con.REG_SZ, defPycIcon) + base = "%s\\Shell" % pythonFileId + win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\Open", win32con.REG_SZ, "Run") + win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\Open\\Command", win32con.REG_SZ, runCommand) + +def RegisterShellCommand(shellCommand, exeCommand, shellUserCommand = None): + # Last param for "Open" - for a .py file to be executed by the command line + # or shell execute (eg, just entering "foo.py"), the Command must be "Open", + # but you may associate a different name for the right-click menu. + # In our case, normally we have "Open=Run" + base = "%s\\Shell" % RegistryIDPyFile + if shellUserCommand: + win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\%s" % (shellCommand), win32con.REG_SZ, shellUserCommand) + + win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\%s\\Command" % (shellCommand), win32con.REG_SZ, exeCommand) + +def RegisterDDECommand(shellCommand, ddeApp, ddeTopic, ddeCommand): + base = "%s\\Shell" % RegistryIDPyFile + win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\%s\\ddeexec" % (shellCommand), win32con.REG_SZ, ddeCommand) + win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\%s\\ddeexec\\Application" % (shellCommand), win32con.REG_SZ, ddeApp) + win32api.RegSetValue(win32con.HKEY_CLASSES_ROOT , base + "\\%s\\ddeexec\\Topic" % (shellCommand), win32con.REG_SZ, ddeTopic) + diff --git a/Lib/site-packages/win32/lib/sspi.py b/Lib/site-packages/win32/lib/sspi.py new file mode 100644 index 0000000..91832a9 --- /dev/null +++ b/Lib/site-packages/win32/lib/sspi.py @@ -0,0 +1,226 @@ +""" +Helper classes for SSPI authentication via the win32security module. + +SSPI authentication involves a token-exchange "dance", the exact details +of which depends on the authentication provider used. There are also +a number of complex flags and constants that need to be used - in most +cases, there are reasonable defaults. + +These classes attempt to hide these details from you until you really need +to know. They are not designed to handle all cases, just the common ones. +If you need finer control than offered here, just use the win32security +functions directly. +""" +# Based on Roger Upole's sspi demos. +# $Id$ +import win32security, sspicon + +error = win32security.error + +class _BaseAuth(object): + def __init__(self): + self.reset() + + def reset(self): + """Reset everything to an unauthorized state""" + self.ctxt = None + self.authenticated = False + # The next seq_num for an encrypt/sign operation + self.next_seq_num = 0 + + def _get_next_seq_num(self): + """Get the next sequence number for a transmission. Default + implementation is to increment a counter + """ + ret = self.next_seq_num + self.next_seq_num = self.next_seq_num + 1 + return ret + + def encrypt(self, data): + """Encrypt a string, returning a tuple of (encrypted_data, encryption_data). + These can be passed to decrypt to get back the original string. + """ + pkg_size_info=self.ctxt.QueryContextAttributes(sspicon.SECPKG_ATTR_SIZES) + trailersize=pkg_size_info['SecurityTrailer'] + + encbuf=win32security.PySecBufferDescType() + encbuf.append(win32security.PySecBufferType(len(data), sspicon.SECBUFFER_DATA)) + encbuf.append(win32security.PySecBufferType(trailersize, sspicon.SECBUFFER_TOKEN)) + encbuf[0].Buffer=data + self.ctxt.EncryptMessage(0,encbuf,self._get_next_seq_num()) + return encbuf[0].Buffer, encbuf[1].Buffer + + def decrypt(self, data, trailer): + """Decrypt a previously encrypted string, returning the orignal data""" + encbuf=win32security.PySecBufferDescType() + encbuf.append(win32security.PySecBufferType(len(data), sspicon.SECBUFFER_DATA)) + encbuf.append(win32security.PySecBufferType(len(trailer), sspicon.SECBUFFER_TOKEN)) + encbuf[0].Buffer=data + encbuf[1].Buffer=trailer + self.ctxt.DecryptMessage(encbuf,self._get_next_seq_num()) + return encbuf[0].Buffer + + def sign(self, data): + """sign a string suitable for transmission, returning the signature. + Passing the data and signature to verify will determine if the data + is unchanged. + """ + pkg_size_info=self.ctxt.QueryContextAttributes(sspicon.SECPKG_ATTR_SIZES) + sigsize=pkg_size_info['MaxSignature'] + sigbuf=win32security.PySecBufferDescType() + sigbuf.append(win32security.PySecBufferType(len(data), sspicon.SECBUFFER_DATA)) + sigbuf.append(win32security.PySecBufferType(sigsize, sspicon.SECBUFFER_TOKEN)) + sigbuf[0].Buffer=data + + self.ctxt.MakeSignature(0,sigbuf,self._get_next_seq_num()) + return sigbuf[1].Buffer + + def verify(self, data, sig): + """Verifies data and its signature. If verification fails, an sspi.error + will be raised. + """ + sigbuf=win32security.PySecBufferDescType() + sigbuf.append(win32security.PySecBufferType(len(data), sspicon.SECBUFFER_DATA)) + sigbuf.append(win32security.PySecBufferType(len(sig), sspicon.SECBUFFER_TOKEN)) + + sigbuf[0].Buffer=data + sigbuf[1].Buffer=sig + self.ctxt.VerifySignature(sigbuf,self._get_next_seq_num()) + +class ClientAuth(_BaseAuth): + """Manages the client side of an SSPI authentication handshake + """ + def __init__(self, + pkg_name, # Name of the package to used. + client_name = None, # User for whom credentials are used. + auth_info = None, # or a tuple of (username, domain, password) + targetspn = None, # Target security context provider name. + scflags=None, # security context flags + datarep=sspicon.SECURITY_NETWORK_DREP): + if scflags is None: + scflags = sspicon.ISC_REQ_INTEGRITY|sspicon.ISC_REQ_SEQUENCE_DETECT|\ + sspicon.ISC_REQ_REPLAY_DETECT|sspicon.ISC_REQ_CONFIDENTIALITY + self.scflags=scflags + self.datarep=datarep + self.targetspn=targetspn + self.pkg_info=win32security.QuerySecurityPackageInfo(pkg_name) + self.credentials, \ + self.credentials_expiry=win32security.AcquireCredentialsHandle( + client_name, self.pkg_info['Name'], + sspicon.SECPKG_CRED_OUTBOUND, + None, auth_info) + _BaseAuth.__init__(self) + + # Perform *one* step of the client authentication process. + def authorize(self, sec_buffer_in): + if sec_buffer_in is not None and type(sec_buffer_in) != win32security.PySecBufferDescType: + # User passed us the raw data - wrap it into a SecBufferDesc + sec_buffer_new=win32security.PySecBufferDescType() + tokenbuf=win32security.PySecBufferType(self.pkg_info['MaxToken'], + sspicon.SECBUFFER_TOKEN) + tokenbuf.Buffer=sec_buffer_in + sec_buffer_new.append(tokenbuf) + sec_buffer_in = sec_buffer_new + sec_buffer_out=win32security.PySecBufferDescType() + tokenbuf=win32security.PySecBufferType(self.pkg_info['MaxToken'], sspicon.SECBUFFER_TOKEN) + sec_buffer_out.append(tokenbuf) + ## input context handle should be NULL on first call + ctxtin=self.ctxt + if self.ctxt is None: + self.ctxt=win32security.PyCtxtHandleType() + err, attr, exp=win32security.InitializeSecurityContext( + self.credentials, + ctxtin, + self.targetspn, + self.scflags, + self.datarep, + sec_buffer_in, + self.ctxt, + sec_buffer_out) + # Stash these away incase someone needs to know the state from the + # final call. + self.ctxt_attr = attr + self.ctxt_expiry = exp + + if err in (sspicon.SEC_I_COMPLETE_NEEDED,sspicon.SEC_I_COMPLETE_AND_CONTINUE): + self.ctxt.CompleteAuthToken(sec_buffer_out) + self.authenticated = err == 0 + return err, sec_buffer_out + +class ServerAuth(_BaseAuth): + """Manages the server side of an SSPI authentication handshake + """ + def __init__(self, + pkg_name, + spn = None, + scflags=None, + datarep=sspicon.SECURITY_NETWORK_DREP): + self.spn=spn + self.datarep=datarep + + if scflags is None: + scflags = sspicon.ASC_REQ_INTEGRITY|sspicon.ASC_REQ_SEQUENCE_DETECT|\ + sspicon.ASC_REQ_REPLAY_DETECT|sspicon.ASC_REQ_CONFIDENTIALITY + # Should we default to sspicon.KerbAddExtraCredentialsMessage + # if pkg_name=='Kerberos'? + self.scflags=scflags + + self.pkg_info=win32security.QuerySecurityPackageInfo(pkg_name) + + self.credentials, \ + self.credentials_expiry=win32security.AcquireCredentialsHandle(spn, + self.pkg_info['Name'], sspicon.SECPKG_CRED_INBOUND, None, None) + _BaseAuth.__init__(self) + + # Perform *one* step of the server authentication process. + def authorize(self, sec_buffer_in): + if sec_buffer_in is not None and type(sec_buffer_in) != win32security.PySecBufferDescType: + # User passed us the raw data - wrap it into a SecBufferDesc + sec_buffer_new=win32security.PySecBufferDescType() + tokenbuf=win32security.PySecBufferType(self.pkg_info['MaxToken'], + sspicon.SECBUFFER_TOKEN) + tokenbuf.Buffer=sec_buffer_in + sec_buffer_new.append(tokenbuf) + sec_buffer_in = sec_buffer_new + + sec_buffer_out=win32security.PySecBufferDescType() + tokenbuf=win32security.PySecBufferType(self.pkg_info['MaxToken'], sspicon.SECBUFFER_TOKEN) + sec_buffer_out.append(tokenbuf) + ## input context handle is None initially, then handle returned from last call thereafter + ctxtin=self.ctxt + if self.ctxt is None: + self.ctxt=win32security.PyCtxtHandleType() + err, attr, exp = win32security.AcceptSecurityContext(self.credentials, ctxtin, + sec_buffer_in, self.scflags, + self.datarep, self.ctxt, sec_buffer_out) + + # Stash these away incase someone needs to know the state from the + # final call. + self.ctxt_attr = attr + self.ctxt_expiry = exp + + if err in (sspicon.SEC_I_COMPLETE_NEEDED,sspicon.SEC_I_COMPLETE_AND_CONTINUE): + self.ctxt.CompleteAuthToken(sec_buffer_out) + self.authenticated = err == 0 + return err, sec_buffer_out + +if __name__=='__main__': + # Setup the 2 contexts. + sspiclient=ClientAuth("NTLM") + sspiserver=ServerAuth("NTLM") + + # Perform the authentication dance, each loop exchanging more information + # on the way to completing authentication. + sec_buffer=None + while 1: + err, sec_buffer = sspiclient.authorize(sec_buffer) + err, sec_buffer = sspiserver.authorize(sec_buffer) + if err==0: + break + data = "hello".encode("ascii") # py3k-friendly + sig = sspiclient.sign(data) + sspiserver.verify(data, sig) + + data, key = sspiclient.encrypt(data) + assert sspiserver.decrypt(data, key) == data + print("cool!") diff --git a/Lib/site-packages/win32/lib/sspicon.py b/Lib/site-packages/win32/lib/sspicon.py new file mode 100644 index 0000000..aff57eb --- /dev/null +++ b/Lib/site-packages/win32/lib/sspicon.py @@ -0,0 +1,479 @@ +# Generated by h2py from c:\microsoft sdk\include\sspi.h +ISSP_LEVEL = 32 +ISSP_MODE = 1 +ISSP_LEVEL = 32 +ISSP_MODE = 0 +ISSP_LEVEL = 32 +ISSP_MODE = 1 +def SEC_SUCCESS(Status): return ((Status) >= 0) + +SECPKG_FLAG_INTEGRITY = 1 +SECPKG_FLAG_PRIVACY = 2 +SECPKG_FLAG_TOKEN_ONLY = 4 +SECPKG_FLAG_DATAGRAM = 8 +SECPKG_FLAG_CONNECTION = 16 +SECPKG_FLAG_MULTI_REQUIRED = 32 +SECPKG_FLAG_CLIENT_ONLY = 64 +SECPKG_FLAG_EXTENDED_ERROR = 128 +SECPKG_FLAG_IMPERSONATION = 256 +SECPKG_FLAG_ACCEPT_WIN32_NAME = 512 +SECPKG_FLAG_STREAM = 1024 +SECPKG_FLAG_NEGOTIABLE = 2048 +SECPKG_FLAG_GSS_COMPATIBLE = 4096 +SECPKG_FLAG_LOGON = 8192 +SECPKG_FLAG_ASCII_BUFFERS = 16384 +SECPKG_FLAG_FRAGMENT = 32768 +SECPKG_FLAG_MUTUAL_AUTH = 65536 +SECPKG_FLAG_DELEGATION = 131072 +SECPKG_FLAG_READONLY_WITH_CHECKSUM = 262144 +SECPKG_ID_NONE = 65535 + +SECBUFFER_VERSION = 0 +SECBUFFER_EMPTY = 0 +SECBUFFER_DATA = 1 +SECBUFFER_TOKEN = 2 +SECBUFFER_PKG_PARAMS = 3 +SECBUFFER_MISSING = 4 +SECBUFFER_EXTRA = 5 +SECBUFFER_STREAM_TRAILER = 6 +SECBUFFER_STREAM_HEADER = 7 +SECBUFFER_NEGOTIATION_INFO = 8 +SECBUFFER_PADDING = 9 +SECBUFFER_STREAM = 10 +SECBUFFER_MECHLIST = 11 +SECBUFFER_MECHLIST_SIGNATURE = 12 +SECBUFFER_TARGET = 13 +SECBUFFER_CHANNEL_BINDINGS = 14 +SECBUFFER_ATTRMASK = (-268435456) +SECBUFFER_READONLY = (-2147483648) +SECBUFFER_READONLY_WITH_CHECKSUM = 268435456 +SECBUFFER_RESERVED = 1610612736 + +SECURITY_NATIVE_DREP = 16 +SECURITY_NETWORK_DREP = 0 + +SECPKG_CRED_INBOUND = 1 +SECPKG_CRED_OUTBOUND = 2 +SECPKG_CRED_BOTH = 3 +SECPKG_CRED_DEFAULT = 4 +SECPKG_CRED_RESERVED = -268435456 + +ISC_REQ_DELEGATE = 1 +ISC_REQ_MUTUAL_AUTH = 2 +ISC_REQ_REPLAY_DETECT = 4 +ISC_REQ_SEQUENCE_DETECT = 8 +ISC_REQ_CONFIDENTIALITY = 16 +ISC_REQ_USE_SESSION_KEY = 32 +ISC_REQ_PROMPT_FOR_CREDS = 64 +ISC_REQ_USE_SUPPLIED_CREDS = 128 +ISC_REQ_ALLOCATE_MEMORY = 256 +ISC_REQ_USE_DCE_STYLE = 512 +ISC_REQ_DATAGRAM = 1024 +ISC_REQ_CONNECTION = 2048 +ISC_REQ_CALL_LEVEL = 4096 +ISC_REQ_FRAGMENT_SUPPLIED = 8192 +ISC_REQ_EXTENDED_ERROR = 16384 +ISC_REQ_STREAM = 32768 +ISC_REQ_INTEGRITY = 65536 +ISC_REQ_IDENTIFY = 131072 +ISC_REQ_NULL_SESSION = 262144 +ISC_REQ_MANUAL_CRED_VALIDATION = 524288 +ISC_REQ_RESERVED1 = 1048576 +ISC_REQ_FRAGMENT_TO_FIT = 2097152 +ISC_REQ_HTTP = 0x10000000 +ISC_RET_DELEGATE = 1 +ISC_RET_MUTUAL_AUTH = 2 +ISC_RET_REPLAY_DETECT = 4 +ISC_RET_SEQUENCE_DETECT = 8 +ISC_RET_CONFIDENTIALITY = 16 +ISC_RET_USE_SESSION_KEY = 32 +ISC_RET_USED_COLLECTED_CREDS = 64 +ISC_RET_USED_SUPPLIED_CREDS = 128 +ISC_RET_ALLOCATED_MEMORY = 256 +ISC_RET_USED_DCE_STYLE = 512 +ISC_RET_DATAGRAM = 1024 +ISC_RET_CONNECTION = 2048 +ISC_RET_INTERMEDIATE_RETURN = 4096 +ISC_RET_CALL_LEVEL = 8192 +ISC_RET_EXTENDED_ERROR = 16384 +ISC_RET_STREAM = 32768 +ISC_RET_INTEGRITY = 65536 +ISC_RET_IDENTIFY = 131072 +ISC_RET_NULL_SESSION = 262144 +ISC_RET_MANUAL_CRED_VALIDATION = 524288 +ISC_RET_RESERVED1 = 1048576 +ISC_RET_FRAGMENT_ONLY = 2097152 + +ASC_REQ_DELEGATE = 1 +ASC_REQ_MUTUAL_AUTH = 2 +ASC_REQ_REPLAY_DETECT = 4 +ASC_REQ_SEQUENCE_DETECT = 8 +ASC_REQ_CONFIDENTIALITY = 16 +ASC_REQ_USE_SESSION_KEY = 32 +ASC_REQ_ALLOCATE_MEMORY = 256 +ASC_REQ_USE_DCE_STYLE = 512 +ASC_REQ_DATAGRAM = 1024 +ASC_REQ_CONNECTION = 2048 +ASC_REQ_CALL_LEVEL = 4096 +ASC_REQ_EXTENDED_ERROR = 32768 +ASC_REQ_STREAM = 65536 +ASC_REQ_INTEGRITY = 131072 +ASC_REQ_LICENSING = 262144 +ASC_REQ_IDENTIFY = 524288 +ASC_REQ_ALLOW_NULL_SESSION = 1048576 +ASC_REQ_ALLOW_NON_USER_LOGONS = 2097152 +ASC_REQ_ALLOW_CONTEXT_REPLAY = 4194304 +ASC_REQ_FRAGMENT_TO_FIT = 8388608 +ASC_REQ_FRAGMENT_SUPPLIED = 8192 +ASC_REQ_NO_TOKEN = 16777216 +ASC_RET_DELEGATE = 1 +ASC_RET_MUTUAL_AUTH = 2 +ASC_RET_REPLAY_DETECT = 4 +ASC_RET_SEQUENCE_DETECT = 8 +ASC_RET_CONFIDENTIALITY = 16 +ASC_RET_USE_SESSION_KEY = 32 +ASC_RET_ALLOCATED_MEMORY = 256 +ASC_RET_USED_DCE_STYLE = 512 +ASC_RET_DATAGRAM = 1024 +ASC_RET_CONNECTION = 2048 +ASC_RET_CALL_LEVEL = 8192 +ASC_RET_THIRD_LEG_FAILED = 16384 +ASC_RET_EXTENDED_ERROR = 32768 +ASC_RET_STREAM = 65536 +ASC_RET_INTEGRITY = 131072 +ASC_RET_LICENSING = 262144 +ASC_RET_IDENTIFY = 524288 +ASC_RET_NULL_SESSION = 1048576 +ASC_RET_ALLOW_NON_USER_LOGONS = 2097152 +ASC_RET_ALLOW_CONTEXT_REPLAY = 4194304 +ASC_RET_FRAGMENT_ONLY = 8388608 + +SECPKG_CRED_ATTR_NAMES = 1 +SECPKG_ATTR_SIZES = 0 +SECPKG_ATTR_NAMES = 1 +SECPKG_ATTR_LIFESPAN = 2 +SECPKG_ATTR_DCE_INFO = 3 +SECPKG_ATTR_STREAM_SIZES = 4 +SECPKG_ATTR_KEY_INFO = 5 +SECPKG_ATTR_AUTHORITY = 6 +SECPKG_ATTR_PROTO_INFO = 7 +SECPKG_ATTR_PASSWORD_EXPIRY = 8 +SECPKG_ATTR_SESSION_KEY = 9 +SECPKG_ATTR_PACKAGE_INFO = 10 +SECPKG_ATTR_USER_FLAGS = 11 +SECPKG_ATTR_NEGOTIATION_INFO = 12 +SECPKG_ATTR_NATIVE_NAMES = 13 +SECPKG_ATTR_FLAGS = 14 +SECPKG_ATTR_USE_VALIDATED = 15 +SECPKG_ATTR_CREDENTIAL_NAME = 16 +SECPKG_ATTR_TARGET_INFORMATION = 17 +SECPKG_ATTR_ACCESS_TOKEN = 18 +SECPKG_ATTR_TARGET = 19 +SECPKG_ATTR_AUTHENTICATION_ID = 20 + +## attributes from schannel.h +SECPKG_ATTR_REMOTE_CERT_CONTEXT = 83 +SECPKG_ATTR_LOCAL_CERT_CONTEXT = 84 +SECPKG_ATTR_ROOT_STORE = 85 +SECPKG_ATTR_SUPPORTED_ALGS = 86 +SECPKG_ATTR_CIPHER_STRENGTHS = 87 +SECPKG_ATTR_SUPPORTED_PROTOCOLS = 88 +SECPKG_ATTR_ISSUER_LIST_EX = 89 +SECPKG_ATTR_CONNECTION_INFO = 90 +SECPKG_ATTR_EAP_KEY_BLOCK = 91 +SECPKG_ATTR_MAPPED_CRED_ATTR = 92 +SECPKG_ATTR_SESSION_INFO = 93 +SECPKG_ATTR_APP_DATA = 94 + +SECPKG_NEGOTIATION_COMPLETE = 0 +SECPKG_NEGOTIATION_OPTIMISTIC = 1 +SECPKG_NEGOTIATION_IN_PROGRESS = 2 +SECPKG_NEGOTIATION_DIRECT = 3 +SECPKG_NEGOTIATION_TRY_MULTICRED = 4 +SECPKG_CONTEXT_EXPORT_RESET_NEW = 1 +SECPKG_CONTEXT_EXPORT_DELETE_OLD = 2 +SECQOP_WRAP_NO_ENCRYPT = (-2147483647) +SECURITY_ENTRYPOINT_ANSIW = "InitSecurityInterfaceW" +SECURITY_ENTRYPOINT_ANSIA = "InitSecurityInterfaceA" +SECURITY_ENTRYPOINT16 = "INITSECURITYINTERFACEA" +SECURITY_ENTRYPOINT_ANSI = SECURITY_ENTRYPOINT_ANSIW +SECURITY_ENTRYPOINT_ANSI = SECURITY_ENTRYPOINT_ANSIA +SECURITY_ENTRYPOINT = SECURITY_ENTRYPOINT16 +SECURITY_ENTRYPOINT_ANSI = SECURITY_ENTRYPOINT16 +SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION = 1 +SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_2 = 2 +SASL_OPTION_SEND_SIZE = 1 +SASL_OPTION_RECV_SIZE = 2 +SASL_OPTION_AUTHZ_STRING = 3 +SASL_OPTION_AUTHZ_PROCESSING = 4 +SEC_WINNT_AUTH_IDENTITY_ANSI = 1 +SEC_WINNT_AUTH_IDENTITY_UNICODE = 2 +SEC_WINNT_AUTH_IDENTITY_VERSION = 512 +SEC_WINNT_AUTH_IDENTITY_MARSHALLED = 4 +SEC_WINNT_AUTH_IDENTITY_ONLY = 8 +SECPKG_OPTIONS_TYPE_UNKNOWN = 0 +SECPKG_OPTIONS_TYPE_LSA = 1 +SECPKG_OPTIONS_TYPE_SSPI = 2 +SECPKG_OPTIONS_PERMANENT = 1 + +SEC_E_INSUFFICIENT_MEMORY = -2146893056 +SEC_E_INVALID_HANDLE = -2146893055 +SEC_E_UNSUPPORTED_FUNCTION = -2146893054 +SEC_E_TARGET_UNKNOWN = -2146893053 +SEC_E_INTERNAL_ERROR = -2146893052 +SEC_E_SECPKG_NOT_FOUND = -2146893051 +SEC_E_NOT_OWNER = -2146893050 +SEC_E_CANNOT_INSTALL = -2146893049 +SEC_E_INVALID_TOKEN = -2146893048 +SEC_E_CANNOT_PACK = -2146893047 +SEC_E_QOP_NOT_SUPPORTED = -2146893046 +SEC_E_NO_IMPERSONATION = -2146893045 +SEC_E_LOGON_DENIED = -2146893044 +SEC_E_UNKNOWN_CREDENTIALS = -2146893043 +SEC_E_NO_CREDENTIALS = -2146893042 +SEC_E_MESSAGE_ALTERED = -2146893041 +SEC_E_OUT_OF_SEQUENCE = -2146893040 +SEC_E_NO_AUTHENTICATING_AUTHORITY = -2146893039 +SEC_I_CONTINUE_NEEDED = 590610 +SEC_I_COMPLETE_NEEDED = 590611 +SEC_I_COMPLETE_AND_CONTINUE = 590612 +SEC_I_LOCAL_LOGON = 590613 +SEC_E_BAD_PKGID = -2146893034 +SEC_E_CONTEXT_EXPIRED = -2146893033 +SEC_I_CONTEXT_EXPIRED = 590615 +SEC_E_INCOMPLETE_MESSAGE = -2146893032 +SEC_E_INCOMPLETE_CREDENTIALS = -2146893024 +SEC_E_BUFFER_TOO_SMALL = -2146893023 +SEC_I_INCOMPLETE_CREDENTIALS = 590624 +SEC_I_RENEGOTIATE = 590625 +SEC_E_WRONG_PRINCIPAL = -2146893022 +SEC_I_NO_LSA_CONTEXT = 590627 +SEC_E_TIME_SKEW = -2146893020 +SEC_E_UNTRUSTED_ROOT = -2146893019 +SEC_E_ILLEGAL_MESSAGE = -2146893018 +SEC_E_CERT_UNKNOWN = -2146893017 +SEC_E_CERT_EXPIRED = -2146893016 +SEC_E_ENCRYPT_FAILURE = -2146893015 +SEC_E_DECRYPT_FAILURE = -2146893008 +SEC_E_ALGORITHM_MISMATCH = -2146893007 +SEC_E_SECURITY_QOS_FAILED = -2146893006 +SEC_E_UNFINISHED_CONTEXT_DELETED = -2146893005 +SEC_E_NO_TGT_REPLY = -2146893004 +SEC_E_NO_IP_ADDRESSES = -2146893003 +SEC_E_WRONG_CREDENTIAL_HANDLE = -2146893002 +SEC_E_CRYPTO_SYSTEM_INVALID = -2146893001 +SEC_E_MAX_REFERRALS_EXCEEDED = -2146893000 +SEC_E_MUST_BE_KDC = -2146892999 +SEC_E_STRONG_CRYPTO_NOT_SUPPORTED = -2146892998 +SEC_E_TOO_MANY_PRINCIPALS = -2146892997 +SEC_E_NO_PA_DATA = -2146892996 +SEC_E_PKINIT_NAME_MISMATCH = -2146892995 +SEC_E_SMARTCARD_LOGON_REQUIRED = -2146892994 +SEC_E_SHUTDOWN_IN_PROGRESS = -2146892993 +SEC_E_KDC_INVALID_REQUEST = -2146892992 +SEC_E_KDC_UNABLE_TO_REFER = -2146892991 +SEC_E_KDC_UNKNOWN_ETYPE = -2146892990 +SEC_E_UNSUPPORTED_PREAUTH = -2146892989 +SEC_E_DELEGATION_REQUIRED = -2146892987 +SEC_E_BAD_BINDINGS = -2146892986 +SEC_E_MULTIPLE_ACCOUNTS = -2146892985 +SEC_E_NO_KERB_KEY = -2146892984 + +ERROR_IPSEC_QM_POLICY_EXISTS = 13000 +ERROR_IPSEC_QM_POLICY_NOT_FOUND = 13001 +ERROR_IPSEC_QM_POLICY_IN_USE = 13002 +ERROR_IPSEC_MM_POLICY_EXISTS = 13003 +ERROR_IPSEC_MM_POLICY_NOT_FOUND = 13004 +ERROR_IPSEC_MM_POLICY_IN_USE = 13005 +ERROR_IPSEC_MM_FILTER_EXISTS = 13006 +ERROR_IPSEC_MM_FILTER_NOT_FOUND = 13007 +ERROR_IPSEC_TRANSPORT_FILTER_EXISTS = 13008 +ERROR_IPSEC_TRANSPORT_FILTER_NOT_FOUND = 13009 +ERROR_IPSEC_MM_AUTH_EXISTS = 13010 +ERROR_IPSEC_MM_AUTH_NOT_FOUND = 13011 +ERROR_IPSEC_MM_AUTH_IN_USE = 13012 +ERROR_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND = 13013 +ERROR_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND = 13014 +ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND = 13015 +ERROR_IPSEC_TUNNEL_FILTER_EXISTS = 13016 +ERROR_IPSEC_TUNNEL_FILTER_NOT_FOUND = 13017 +ERROR_IPSEC_MM_FILTER_PENDING_DELETION = 13018 +ERROR_IPSEC_TRANSPORT_FILTER_PENDING_DELETION = 13019 +ERROR_IPSEC_TUNNEL_FILTER_PENDING_DELETION = 13020 +ERROR_IPSEC_MM_POLICY_PENDING_DELETION = 13021 +ERROR_IPSEC_MM_AUTH_PENDING_DELETION = 13022 +ERROR_IPSEC_QM_POLICY_PENDING_DELETION = 13023 +WARNING_IPSEC_MM_POLICY_PRUNED = 13024 +WARNING_IPSEC_QM_POLICY_PRUNED = 13025 +ERROR_IPSEC_IKE_NEG_STATUS_BEGIN = 13800 +ERROR_IPSEC_IKE_AUTH_FAIL = 13801 +ERROR_IPSEC_IKE_ATTRIB_FAIL = 13802 +ERROR_IPSEC_IKE_NEGOTIATION_PENDING = 13803 +ERROR_IPSEC_IKE_GENERAL_PROCESSING_ERROR = 13804 +ERROR_IPSEC_IKE_TIMED_OUT = 13805 +ERROR_IPSEC_IKE_NO_CERT = 13806 +ERROR_IPSEC_IKE_SA_DELETED = 13807 +ERROR_IPSEC_IKE_SA_REAPED = 13808 +ERROR_IPSEC_IKE_MM_ACQUIRE_DROP = 13809 +ERROR_IPSEC_IKE_QM_ACQUIRE_DROP = 13810 +ERROR_IPSEC_IKE_QUEUE_DROP_MM = 13811 +ERROR_IPSEC_IKE_QUEUE_DROP_NO_MM = 13812 +ERROR_IPSEC_IKE_DROP_NO_RESPONSE = 13813 +ERROR_IPSEC_IKE_MM_DELAY_DROP = 13814 +ERROR_IPSEC_IKE_QM_DELAY_DROP = 13815 +ERROR_IPSEC_IKE_ERROR = 13816 +ERROR_IPSEC_IKE_CRL_FAILED = 13817 +ERROR_IPSEC_IKE_INVALID_KEY_USAGE = 13818 +ERROR_IPSEC_IKE_INVALID_CERT_TYPE = 13819 +ERROR_IPSEC_IKE_NO_PRIVATE_KEY = 13820 +ERROR_IPSEC_IKE_DH_FAIL = 13822 +ERROR_IPSEC_IKE_INVALID_HEADER = 13824 +ERROR_IPSEC_IKE_NO_POLICY = 13825 +ERROR_IPSEC_IKE_INVALID_SIGNATURE = 13826 +ERROR_IPSEC_IKE_KERBEROS_ERROR = 13827 +ERROR_IPSEC_IKE_NO_PUBLIC_KEY = 13828 +ERROR_IPSEC_IKE_PROCESS_ERR = 13829 +ERROR_IPSEC_IKE_PROCESS_ERR_SA = 13830 +ERROR_IPSEC_IKE_PROCESS_ERR_PROP = 13831 +ERROR_IPSEC_IKE_PROCESS_ERR_TRANS = 13832 +ERROR_IPSEC_IKE_PROCESS_ERR_KE = 13833 +ERROR_IPSEC_IKE_PROCESS_ERR_ID = 13834 +ERROR_IPSEC_IKE_PROCESS_ERR_CERT = 13835 +ERROR_IPSEC_IKE_PROCESS_ERR_CERT_REQ = 13836 +ERROR_IPSEC_IKE_PROCESS_ERR_HASH = 13837 +ERROR_IPSEC_IKE_PROCESS_ERR_SIG = 13838 +ERROR_IPSEC_IKE_PROCESS_ERR_NONCE = 13839 +ERROR_IPSEC_IKE_PROCESS_ERR_NOTIFY = 13840 +ERROR_IPSEC_IKE_PROCESS_ERR_DELETE = 13841 +ERROR_IPSEC_IKE_PROCESS_ERR_VENDOR = 13842 +ERROR_IPSEC_IKE_INVALID_PAYLOAD = 13843 +ERROR_IPSEC_IKE_LOAD_SOFT_SA = 13844 +ERROR_IPSEC_IKE_SOFT_SA_TORN_DOWN = 13845 +ERROR_IPSEC_IKE_INVALID_COOKIE = 13846 +ERROR_IPSEC_IKE_NO_PEER_CERT = 13847 +ERROR_IPSEC_IKE_PEER_CRL_FAILED = 13848 +ERROR_IPSEC_IKE_POLICY_CHANGE = 13849 +ERROR_IPSEC_IKE_NO_MM_POLICY = 13850 +ERROR_IPSEC_IKE_NOTCBPRIV = 13851 +ERROR_IPSEC_IKE_SECLOADFAIL = 13852 +ERROR_IPSEC_IKE_FAILSSPINIT = 13853 +ERROR_IPSEC_IKE_FAILQUERYSSP = 13854 +ERROR_IPSEC_IKE_SRVACQFAIL = 13855 +ERROR_IPSEC_IKE_SRVQUERYCRED = 13856 +ERROR_IPSEC_IKE_GETSPIFAIL = 13857 +ERROR_IPSEC_IKE_INVALID_FILTER = 13858 +ERROR_IPSEC_IKE_OUT_OF_MEMORY = 13859 +ERROR_IPSEC_IKE_ADD_UPDATE_KEY_FAILED = 13860 +ERROR_IPSEC_IKE_INVALID_POLICY = 13861 +ERROR_IPSEC_IKE_UNKNOWN_DOI = 13862 +ERROR_IPSEC_IKE_INVALID_SITUATION = 13863 +ERROR_IPSEC_IKE_DH_FAILURE = 13864 +ERROR_IPSEC_IKE_INVALID_GROUP = 13865 +ERROR_IPSEC_IKE_ENCRYPT = 13866 +ERROR_IPSEC_IKE_DECRYPT = 13867 +ERROR_IPSEC_IKE_POLICY_MATCH = 13868 +ERROR_IPSEC_IKE_UNSUPPORTED_ID = 13869 +ERROR_IPSEC_IKE_INVALID_HASH = 13870 +ERROR_IPSEC_IKE_INVALID_HASH_ALG = 13871 +ERROR_IPSEC_IKE_INVALID_HASH_SIZE = 13872 +ERROR_IPSEC_IKE_INVALID_ENCRYPT_ALG = 13873 +ERROR_IPSEC_IKE_INVALID_AUTH_ALG = 13874 +ERROR_IPSEC_IKE_INVALID_SIG = 13875 +ERROR_IPSEC_IKE_LOAD_FAILED = 13876 +ERROR_IPSEC_IKE_RPC_DELETE = 13877 +ERROR_IPSEC_IKE_BENIGN_REINIT = 13878 +ERROR_IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY = 13879 +ERROR_IPSEC_IKE_INVALID_CERT_KEYLEN = 13881 +ERROR_IPSEC_IKE_MM_LIMIT = 13882 +ERROR_IPSEC_IKE_NEGOTIATION_DISABLED = 13883 +ERROR_IPSEC_IKE_NEG_STATUS_END = 13884 +CRYPT_E_MSG_ERROR = ((-2146889727)) +CRYPT_E_UNKNOWN_ALGO = ((-2146889726)) +CRYPT_E_OID_FORMAT = ((-2146889725)) +CRYPT_E_INVALID_MSG_TYPE = ((-2146889724)) +CRYPT_E_UNEXPECTED_ENCODING = ((-2146889723)) +CRYPT_E_AUTH_ATTR_MISSING = ((-2146889722)) +CRYPT_E_HASH_VALUE = ((-2146889721)) +CRYPT_E_INVALID_INDEX = ((-2146889720)) +CRYPT_E_ALREADY_DECRYPTED = ((-2146889719)) +CRYPT_E_NOT_DECRYPTED = ((-2146889718)) +CRYPT_E_RECIPIENT_NOT_FOUND = ((-2146889717)) +CRYPT_E_CONTROL_TYPE = ((-2146889716)) +CRYPT_E_ISSUER_SERIALNUMBER = ((-2146889715)) +CRYPT_E_SIGNER_NOT_FOUND = ((-2146889714)) +CRYPT_E_ATTRIBUTES_MISSING = ((-2146889713)) +CRYPT_E_STREAM_MSG_NOT_READY = ((-2146889712)) +CRYPT_E_STREAM_INSUFFICIENT_DATA = ((-2146889711)) +CRYPT_I_NEW_PROTECTION_REQUIRED = (593938) +CRYPT_E_BAD_LEN = ((-2146885631)) +CRYPT_E_BAD_ENCODE = ((-2146885630)) +CRYPT_E_FILE_ERROR = ((-2146885629)) +CRYPT_E_NOT_FOUND = ((-2146885628)) +CRYPT_E_EXISTS = ((-2146885627)) +CRYPT_E_NO_PROVIDER = ((-2146885626)) +CRYPT_E_SELF_SIGNED = ((-2146885625)) +CRYPT_E_DELETED_PREV = ((-2146885624)) +CRYPT_E_NO_MATCH = ((-2146885623)) +CRYPT_E_UNEXPECTED_MSG_TYPE = ((-2146885622)) +CRYPT_E_NO_KEY_PROPERTY = ((-2146885621)) +CRYPT_E_NO_DECRYPT_CERT = ((-2146885620)) +CRYPT_E_BAD_MSG = ((-2146885619)) +CRYPT_E_NO_SIGNER = ((-2146885618)) +CRYPT_E_PENDING_CLOSE = ((-2146885617)) +CRYPT_E_REVOKED = ((-2146885616)) +CRYPT_E_NO_REVOCATION_DLL = ((-2146885615)) +CRYPT_E_NO_REVOCATION_CHECK = ((-2146885614)) +CRYPT_E_REVOCATION_OFFLINE = ((-2146885613)) +CRYPT_E_NOT_IN_REVOCATION_DATABASE = ((-2146885612)) +CRYPT_E_INVALID_NUMERIC_STRING = ((-2146885600)) +CRYPT_E_INVALID_PRINTABLE_STRING = ((-2146885599)) +CRYPT_E_INVALID_IA5_STRING = ((-2146885598)) +CRYPT_E_INVALID_X500_STRING = ((-2146885597)) +CRYPT_E_NOT_CHAR_STRING = ((-2146885596)) +CRYPT_E_FILERESIZED = ((-2146885595)) +CRYPT_E_SECURITY_SETTINGS = ((-2146885594)) +CRYPT_E_NO_VERIFY_USAGE_DLL = ((-2146885593)) +CRYPT_E_NO_VERIFY_USAGE_CHECK = ((-2146885592)) +CRYPT_E_VERIFY_USAGE_OFFLINE = ((-2146885591)) +CRYPT_E_NOT_IN_CTL = ((-2146885590)) +CRYPT_E_NO_TRUSTED_SIGNER = ((-2146885589)) +CRYPT_E_MISSING_PUBKEY_PARA = ((-2146885588)) +CRYPT_E_OSS_ERROR = ((-2146881536)) + +## Kerberos message types for LsaCallAuthenticationPackage (from ntsecapi.h) +KerbDebugRequestMessage = 0 +KerbQueryTicketCacheMessage = 1 +KerbChangeMachinePasswordMessage = 2 +KerbVerifyPacMessage = 3 +KerbRetrieveTicketMessage = 4 +KerbUpdateAddressesMessage = 5 +KerbPurgeTicketCacheMessage = 6 +KerbChangePasswordMessage = 7 +KerbRetrieveEncodedTicketMessage = 8 +KerbDecryptDataMessage = 9 +KerbAddBindingCacheEntryMessage = 10 +KerbSetPasswordMessage = 11 +KerbSetPasswordExMessage = 12 +KerbVerifyCredentialsMessage = 13 +KerbQueryTicketCacheExMessage = 14 +KerbPurgeTicketCacheExMessage = 15 +KerbRefreshSmartcardCredentialsMessage = 16 +KerbAddExtraCredentialsMessage = 17 +KerbQuerySupplementalCredentialsMessage = 18 + +## messages used with msv1_0 from ntsecapi.h +MsV1_0Lm20ChallengeRequest = 0 +MsV1_0Lm20GetChallengeResponse = 1 +MsV1_0EnumerateUsers = 2 +MsV1_0GetUserInfo = 3 +MsV1_0ReLogonUsers = 4 +MsV1_0ChangePassword = 5 +MsV1_0ChangeCachedPassword = 6 +MsV1_0GenericPassthrough = 7 +MsV1_0CacheLogon = 8 +MsV1_0SubAuth = 9 +MsV1_0DeriveCredential = 10 +MsV1_0CacheLookup = 11 +MsV1_0SetProcessOption = 12 + +SEC_E_OK = 0 diff --git a/Lib/site-packages/win32/lib/win32con.py b/Lib/site-packages/win32/lib/win32con.py new file mode 100644 index 0000000..6222414 --- /dev/null +++ b/Lib/site-packages/win32/lib/win32con.py @@ -0,0 +1,5033 @@ +# Generated by h2py from commdlg.h (plus modifications 4jan98) +WINVER = 1280 +WM_USER = 1024 +PY_0U = 0 +OFN_READONLY = 1 +OFN_OVERWRITEPROMPT = 2 +OFN_HIDEREADONLY = 4 +OFN_NOCHANGEDIR = 8 +OFN_SHOWHELP = 16 +OFN_ENABLEHOOK = 32 +OFN_ENABLETEMPLATE = 64 +OFN_ENABLETEMPLATEHANDLE = 128 +OFN_NOVALIDATE = 256 +OFN_ALLOWMULTISELECT = 512 +OFN_EXTENSIONDIFFERENT = 1024 +OFN_PATHMUSTEXIST = 2048 +OFN_FILEMUSTEXIST = 4096 +OFN_CREATEPROMPT = 8192 +OFN_SHAREAWARE = 16384 +OFN_NOREADONLYRETURN = 32768 +OFN_NOTESTFILECREATE = 65536 +OFN_NONETWORKBUTTON = 131072 +OFN_NOLONGNAMES = 262144 +OFN_EXPLORER = 524288 # new look commdlg +OFN_NODEREFERENCELINKS = 1048576 +OFN_LONGNAMES = 2097152 # force long names for 3.x modules +OFN_ENABLEINCLUDENOTIFY = 4194304 # send include message to callback +OFN_ENABLESIZING = 8388608 +OFN_DONTADDTORECENT = 33554432 +OFN_FORCESHOWHIDDEN = 268435456 # Show All files including System and hidden files +OFN_EX_NOPLACESBAR = 1 +OFN_SHAREFALLTHROUGH = 2 +OFN_SHARENOWARN = 1 +OFN_SHAREWARN = 0 +CDN_FIRST = (PY_0U-601) +CDN_LAST = (PY_0U-699) +CDN_INITDONE = (CDN_FIRST - 0) +CDN_SELCHANGE = (CDN_FIRST - 1) +CDN_FOLDERCHANGE = (CDN_FIRST - 2) +CDN_SHAREVIOLATION = (CDN_FIRST - 3) +CDN_HELP = (CDN_FIRST - 4) +CDN_FILEOK = (CDN_FIRST - 5) +CDN_TYPECHANGE = (CDN_FIRST - 6) +CDN_INCLUDEITEM = (CDN_FIRST - 7) +CDM_FIRST = (WM_USER + 100) +CDM_LAST = (WM_USER + 200) +CDM_GETSPEC = (CDM_FIRST + 0) +CDM_GETFILEPATH = (CDM_FIRST + 1) +CDM_GETFOLDERPATH = (CDM_FIRST + 2) +CDM_GETFOLDERIDLIST = (CDM_FIRST + 3) +CDM_SETCONTROLTEXT = (CDM_FIRST + 4) +CDM_HIDECONTROL = (CDM_FIRST + 5) +CDM_SETDEFEXT = (CDM_FIRST + 6) +CC_RGBINIT = 1 +CC_FULLOPEN = 2 +CC_PREVENTFULLOPEN = 4 +CC_SHOWHELP = 8 +CC_ENABLEHOOK = 16 +CC_ENABLETEMPLATE = 32 +CC_ENABLETEMPLATEHANDLE = 64 +CC_SOLIDCOLOR = 128 +CC_ANYCOLOR = 256 +FR_DOWN = 1 +FR_WHOLEWORD = 2 +FR_MATCHCASE = 4 +FR_FINDNEXT = 8 +FR_REPLACE = 16 +FR_REPLACEALL = 32 +FR_DIALOGTERM = 64 +FR_SHOWHELP = 128 +FR_ENABLEHOOK = 256 +FR_ENABLETEMPLATE = 512 +FR_NOUPDOWN = 1024 +FR_NOMATCHCASE = 2048 +FR_NOWHOLEWORD = 4096 +FR_ENABLETEMPLATEHANDLE = 8192 +FR_HIDEUPDOWN = 16384 +FR_HIDEMATCHCASE = 32768 +FR_HIDEWHOLEWORD = 65536 +CF_SCREENFONTS = 1 +CF_PRINTERFONTS = 2 +CF_BOTH = (CF_SCREENFONTS | CF_PRINTERFONTS) +CF_SHOWHELP = 4 +CF_ENABLEHOOK = 8 +CF_ENABLETEMPLATE = 16 +CF_ENABLETEMPLATEHANDLE = 32 +CF_INITTOLOGFONTSTRUCT = 64 +CF_USESTYLE = 128 +CF_EFFECTS = 256 +CF_APPLY = 512 +CF_ANSIONLY = 1024 +CF_SCRIPTSONLY = CF_ANSIONLY +CF_NOVECTORFONTS = 2048 +CF_NOOEMFONTS = CF_NOVECTORFONTS +CF_NOSIMULATIONS = 4096 +CF_LIMITSIZE = 8192 +CF_FIXEDPITCHONLY = 16384 +CF_WYSIWYG = 32768 # must also have CF_SCREENFONTS & CF_PRINTERFONTS +CF_FORCEFONTEXIST = 65536 +CF_SCALABLEONLY = 131072 +CF_TTONLY = 262144 +CF_NOFACESEL = 524288 +CF_NOSTYLESEL = 1048576 +CF_NOSIZESEL = 2097152 +CF_SELECTSCRIPT = 4194304 +CF_NOSCRIPTSEL = 8388608 +CF_NOVERTFONTS = 16777216 +SIMULATED_FONTTYPE = 32768 +PRINTER_FONTTYPE = 16384 +SCREEN_FONTTYPE = 8192 +BOLD_FONTTYPE = 256 +ITALIC_FONTTYPE = 512 +REGULAR_FONTTYPE = 1024 +OPENTYPE_FONTTYPE = 65536 +TYPE1_FONTTYPE = 131072 +DSIG_FONTTYPE = 262144 +WM_CHOOSEFONT_GETLOGFONT = (WM_USER + 1) +WM_CHOOSEFONT_SETLOGFONT = (WM_USER + 101) +WM_CHOOSEFONT_SETFLAGS = (WM_USER + 102) +LBSELCHSTRINGA = "commdlg_LBSelChangedNotify" +SHAREVISTRINGA = "commdlg_ShareViolation" +FILEOKSTRINGA = "commdlg_FileNameOK" +COLOROKSTRINGA = "commdlg_ColorOK" +SETRGBSTRINGA = "commdlg_SetRGBColor" +HELPMSGSTRINGA = "commdlg_help" +FINDMSGSTRINGA = "commdlg_FindReplace" +LBSELCHSTRING = LBSELCHSTRINGA +SHAREVISTRING = SHAREVISTRINGA +FILEOKSTRING = FILEOKSTRINGA +COLOROKSTRING = COLOROKSTRINGA +SETRGBSTRING = SETRGBSTRINGA +HELPMSGSTRING = HELPMSGSTRINGA +FINDMSGSTRING = FINDMSGSTRINGA +CD_LBSELNOITEMS = -1 +CD_LBSELCHANGE = 0 +CD_LBSELSUB = 1 +CD_LBSELADD = 2 +PD_ALLPAGES = 0 +PD_SELECTION = 1 +PD_PAGENUMS = 2 +PD_NOSELECTION = 4 +PD_NOPAGENUMS = 8 +PD_COLLATE = 16 +PD_PRINTTOFILE = 32 +PD_PRINTSETUP = 64 +PD_NOWARNING = 128 +PD_RETURNDC = 256 +PD_RETURNIC = 512 +PD_RETURNDEFAULT = 1024 +PD_SHOWHELP = 2048 +PD_ENABLEPRINTHOOK = 4096 +PD_ENABLESETUPHOOK = 8192 +PD_ENABLEPRINTTEMPLATE = 16384 +PD_ENABLESETUPTEMPLATE = 32768 +PD_ENABLEPRINTTEMPLATEHANDLE = 65536 +PD_ENABLESETUPTEMPLATEHANDLE = 131072 +PD_USEDEVMODECOPIES = 262144 +PD_DISABLEPRINTTOFILE = 524288 +PD_HIDEPRINTTOFILE = 1048576 +PD_NONETWORKBUTTON = 2097152 +DN_DEFAULTPRN = 1 +WM_PSD_PAGESETUPDLG = (WM_USER ) +WM_PSD_FULLPAGERECT = (WM_USER+1) +WM_PSD_MINMARGINRECT = (WM_USER+2) +WM_PSD_MARGINRECT = (WM_USER+3) +WM_PSD_GREEKTEXTRECT = (WM_USER+4) +WM_PSD_ENVSTAMPRECT = (WM_USER+5) +WM_PSD_YAFULLPAGERECT = (WM_USER+6) +PSD_DEFAULTMINMARGINS = 0 # default (printer's) +PSD_INWININIINTLMEASURE = 0 # 1st of 4 possible +PSD_MINMARGINS = 1 # use caller's +PSD_MARGINS = 2 # use caller's +PSD_INTHOUSANDTHSOFINCHES = 4 # 2nd of 4 possible +PSD_INHUNDREDTHSOFMILLIMETERS = 8 # 3rd of 4 possible +PSD_DISABLEMARGINS = 16 +PSD_DISABLEPRINTER = 32 +PSD_NOWARNING = 128 # must be same as PD_* +PSD_DISABLEORIENTATION = 256 +PSD_RETURNDEFAULT = 1024 # must be same as PD_* +PSD_DISABLEPAPER = 512 +PSD_SHOWHELP = 2048 # must be same as PD_* +PSD_ENABLEPAGESETUPHOOK = 8192 # must be same as PD_* +PSD_ENABLEPAGESETUPTEMPLATE = 32768 # must be same as PD_* +PSD_ENABLEPAGESETUPTEMPLATEHANDLE = 131072 # must be same as PD_* +PSD_ENABLEPAGEPAINTHOOK = 262144 +PSD_DISABLEPAGEPAINTING = 524288 +PSD_NONETWORKBUTTON = 2097152 # must be same as PD_* + +# Generated by h2py from winreg.h +HKEY_CLASSES_ROOT = -2147483648 +HKEY_CURRENT_USER = -2147483647 +HKEY_LOCAL_MACHINE = -2147483646 +HKEY_USERS = -2147483645 +HKEY_PERFORMANCE_DATA = -2147483644 +HKEY_CURRENT_CONFIG = -2147483643 +HKEY_DYN_DATA = -2147483642 +HKEY_PERFORMANCE_TEXT = -2147483568 # ?? 4Jan98 +HKEY_PERFORMANCE_NLSTEXT = -2147483552 # ?? 4Jan98 + +# Generated by h2py from winuser.h +HWND_BROADCAST = 65535 +HWND_DESKTOP = 0 +HWND_TOP = 0 +HWND_BOTTOM = 1 +HWND_TOPMOST = -1 +HWND_NOTOPMOST = -2 +HWND_MESSAGE = -3 + +# winuser.h line 4601 +SM_CXSCREEN = 0 +SM_CYSCREEN = 1 +SM_CXVSCROLL = 2 +SM_CYHSCROLL = 3 +SM_CYCAPTION = 4 +SM_CXBORDER = 5 +SM_CYBORDER = 6 +SM_CXDLGFRAME = 7 +SM_CYDLGFRAME = 8 +SM_CYVTHUMB = 9 +SM_CXHTHUMB = 10 +SM_CXICON = 11 +SM_CYICON = 12 +SM_CXCURSOR = 13 +SM_CYCURSOR = 14 +SM_CYMENU = 15 +SM_CXFULLSCREEN = 16 +SM_CYFULLSCREEN = 17 +SM_CYKANJIWINDOW = 18 +SM_MOUSEPRESENT = 19 +SM_CYVSCROLL = 20 +SM_CXHSCROLL = 21 +SM_DEBUG = 22 +SM_SWAPBUTTON = 23 +SM_RESERVED1 = 24 +SM_RESERVED2 = 25 +SM_RESERVED3 = 26 +SM_RESERVED4 = 27 +SM_CXMIN = 28 +SM_CYMIN = 29 +SM_CXSIZE = 30 +SM_CYSIZE = 31 +SM_CXFRAME = 32 +SM_CYFRAME = 33 +SM_CXMINTRACK = 34 +SM_CYMINTRACK = 35 +SM_CXDOUBLECLK = 36 +SM_CYDOUBLECLK = 37 +SM_CXICONSPACING = 38 +SM_CYICONSPACING = 39 +SM_MENUDROPALIGNMENT = 40 +SM_PENWINDOWS = 41 +SM_DBCSENABLED = 42 +SM_CMOUSEBUTTONS = 43 +SM_CXFIXEDFRAME = SM_CXDLGFRAME +SM_CYFIXEDFRAME = SM_CYDLGFRAME +SM_CXSIZEFRAME = SM_CXFRAME +SM_CYSIZEFRAME = SM_CYFRAME +SM_SECURE = 44 +SM_CXEDGE = 45 +SM_CYEDGE = 46 +SM_CXMINSPACING = 47 +SM_CYMINSPACING = 48 +SM_CXSMICON = 49 +SM_CYSMICON = 50 +SM_CYSMCAPTION = 51 +SM_CXSMSIZE = 52 +SM_CYSMSIZE = 53 +SM_CXMENUSIZE = 54 +SM_CYMENUSIZE = 55 +SM_ARRANGE = 56 +SM_CXMINIMIZED = 57 +SM_CYMINIMIZED = 58 +SM_CXMAXTRACK = 59 +SM_CYMAXTRACK = 60 +SM_CXMAXIMIZED = 61 +SM_CYMAXIMIZED = 62 +SM_NETWORK = 63 +SM_CLEANBOOT = 67 +SM_CXDRAG = 68 +SM_CYDRAG = 69 +SM_SHOWSOUNDS = 70 +SM_CXMENUCHECK = 71 +SM_CYMENUCHECK = 72 +SM_SLOWMACHINE = 73 +SM_MIDEASTENABLED = 74 +SM_MOUSEWHEELPRESENT = 75 +SM_XVIRTUALSCREEN = 76 +SM_YVIRTUALSCREEN = 77 +SM_CXVIRTUALSCREEN = 78 +SM_CYVIRTUALSCREEN = 79 +SM_CMONITORS = 80 +SM_SAMEDISPLAYFORMAT = 81 +SM_CMETRICS = 83 +MNC_IGNORE = 0 +MNC_CLOSE = 1 +MNC_EXECUTE = 2 +MNC_SELECT = 3 +MNS_NOCHECK = -2147483648 +MNS_MODELESS = 1073741824 +MNS_DRAGDROP = 536870912 +MNS_AUTODISMISS = 268435456 +MNS_NOTIFYBYPOS = 134217728 +MNS_CHECKORBMP = 67108864 +MIM_MAXHEIGHT = 1 +MIM_BACKGROUND = 2 +MIM_HELPID = 4 +MIM_MENUDATA = 8 +MIM_STYLE = 16 +MIM_APPLYTOSUBMENUS = -2147483648 +MND_CONTINUE = 0 +MND_ENDMENU = 1 +MNGOF_GAP = 3 +MNGO_NOINTERFACE = 0 +MNGO_NOERROR = 1 +MIIM_STATE = 1 +MIIM_ID = 2 +MIIM_SUBMENU = 4 +MIIM_CHECKMARKS = 8 +MIIM_TYPE = 16 +MIIM_DATA = 32 +MIIM_STRING = 64 +MIIM_BITMAP = 128 +MIIM_FTYPE = 256 +HBMMENU_CALLBACK = -1 +HBMMENU_SYSTEM = 1 +HBMMENU_MBAR_RESTORE = 2 +HBMMENU_MBAR_MINIMIZE = 3 +HBMMENU_MBAR_CLOSE = 5 +HBMMENU_MBAR_CLOSE_D = 6 +HBMMENU_MBAR_MINIMIZE_D = 7 +HBMMENU_POPUP_CLOSE = 8 +HBMMENU_POPUP_RESTORE = 9 +HBMMENU_POPUP_MAXIMIZE = 10 +HBMMENU_POPUP_MINIMIZE = 11 +GMDI_USEDISABLED = 1 +GMDI_GOINTOPOPUPS = 2 +TPM_LEFTBUTTON = 0 +TPM_RIGHTBUTTON = 2 +TPM_LEFTALIGN = 0 +TPM_CENTERALIGN = 4 +TPM_RIGHTALIGN = 8 +TPM_TOPALIGN = 0 +TPM_VCENTERALIGN = 16 +TPM_BOTTOMALIGN = 32 +TPM_HORIZONTAL = 0 +TPM_VERTICAL = 64 +TPM_NONOTIFY = 128 +TPM_RETURNCMD = 256 +TPM_RECURSE = 1 +DOF_EXECUTABLE = 32769 +DOF_DOCUMENT = 32770 +DOF_DIRECTORY = 32771 +DOF_MULTIPLE = 32772 +DOF_PROGMAN = 1 +DOF_SHELLDATA = 2 +DO_DROPFILE = 1162627398 +DO_PRINTFILE = 1414419024 +DT_TOP = 0 +DT_LEFT = 0 +DT_CENTER = 1 +DT_RIGHT = 2 +DT_VCENTER = 4 +DT_BOTTOM = 8 +DT_WORDBREAK = 16 +DT_SINGLELINE = 32 +DT_EXPANDTABS = 64 +DT_TABSTOP = 128 +DT_NOCLIP = 256 +DT_EXTERNALLEADING = 512 +DT_CALCRECT = 1024 +DT_NOPREFIX = 2048 +DT_INTERNAL = 4096 +DT_EDITCONTROL = 8192 +DT_PATH_ELLIPSIS = 16384 +DT_END_ELLIPSIS = 32768 +DT_MODIFYSTRING = 65536 +DT_RTLREADING = 131072 +DT_WORD_ELLIPSIS = 262144 +DST_COMPLEX = 0 +DST_TEXT = 1 +DST_PREFIXTEXT = 2 +DST_ICON = 3 +DST_BITMAP = 4 +DSS_NORMAL = 0 +DSS_UNION = 16 +DSS_DISABLED = 32 +DSS_MONO = 128 +DSS_RIGHT = 32768 +DCX_WINDOW = 1 +DCX_CACHE = 2 +DCX_NORESETATTRS = 4 +DCX_CLIPCHILDREN = 8 +DCX_CLIPSIBLINGS = 16 +DCX_PARENTCLIP = 32 +DCX_EXCLUDERGN = 64 +DCX_INTERSECTRGN = 128 +DCX_EXCLUDEUPDATE = 256 +DCX_INTERSECTUPDATE = 512 +DCX_LOCKWINDOWUPDATE = 1024 +DCX_VALIDATE = 2097152 +CUDR_NORMAL = 0 +CUDR_NOSNAPTOGRID = 1 +CUDR_NORESOLVEPOSITIONS = 2 +CUDR_NOCLOSEGAPS = 4 +CUDR_NEGATIVECOORDS = 8 +CUDR_NOPRIMARY = 16 +RDW_INVALIDATE = 1 +RDW_INTERNALPAINT = 2 +RDW_ERASE = 4 +RDW_VALIDATE = 8 +RDW_NOINTERNALPAINT = 16 +RDW_NOERASE = 32 +RDW_NOCHILDREN = 64 +RDW_ALLCHILDREN = 128 +RDW_UPDATENOW = 256 +RDW_ERASENOW = 512 +RDW_FRAME = 1024 +RDW_NOFRAME = 2048 +SW_SCROLLCHILDREN = 1 +SW_INVALIDATE = 2 +SW_ERASE = 4 +SW_SMOOTHSCROLL = 16 # Use smooth scrolling +ESB_ENABLE_BOTH = 0 +ESB_DISABLE_BOTH = 3 +ESB_DISABLE_LEFT = 1 +ESB_DISABLE_RIGHT = 2 +ESB_DISABLE_UP = 1 +ESB_DISABLE_DOWN = 2 +ESB_DISABLE_LTUP = ESB_DISABLE_LEFT +ESB_DISABLE_RTDN = ESB_DISABLE_RIGHT +HELPINFO_WINDOW = 1 +HELPINFO_MENUITEM = 2 +MB_OK = 0 +MB_OKCANCEL = 1 +MB_ABORTRETRYIGNORE = 2 +MB_YESNOCANCEL = 3 +MB_YESNO = 4 +MB_RETRYCANCEL = 5 +MB_ICONHAND = 16 +MB_ICONQUESTION = 32 +MB_ICONEXCLAMATION = 48 +MB_ICONASTERISK = 64 +MB_ICONWARNING = MB_ICONEXCLAMATION +MB_ICONERROR = MB_ICONHAND +MB_ICONINFORMATION = MB_ICONASTERISK +MB_ICONSTOP = MB_ICONHAND +MB_DEFBUTTON1 = 0 +MB_DEFBUTTON2 = 256 +MB_DEFBUTTON3 = 512 +MB_DEFBUTTON4 = 768 +MB_APPLMODAL = 0 +MB_SYSTEMMODAL = 4096 +MB_TASKMODAL = 8192 +MB_HELP = 16384 +MB_NOFOCUS = 32768 +MB_SETFOREGROUND = 65536 +MB_DEFAULT_DESKTOP_ONLY = 131072 +MB_TOPMOST = 262144 +MB_RIGHT = 524288 +MB_RTLREADING = 1048576 +MB_SERVICE_NOTIFICATION = 2097152 +MB_TYPEMASK = 15 +MB_USERICON = 128 +MB_ICONMASK = 240 +MB_DEFMASK = 3840 +MB_MODEMASK = 12288 +MB_MISCMASK = 49152 +# winuser.h line 6373 +CWP_ALL = 0 +CWP_SKIPINVISIBLE = 1 +CWP_SKIPDISABLED = 2 +CWP_SKIPTRANSPARENT = 4 +CTLCOLOR_MSGBOX = 0 +CTLCOLOR_EDIT = 1 +CTLCOLOR_LISTBOX = 2 +CTLCOLOR_BTN = 3 +CTLCOLOR_DLG = 4 +CTLCOLOR_SCROLLBAR = 5 +CTLCOLOR_STATIC = 6 +CTLCOLOR_MAX = 7 +COLOR_SCROLLBAR = 0 +COLOR_BACKGROUND = 1 +COLOR_ACTIVECAPTION = 2 +COLOR_INACTIVECAPTION = 3 +COLOR_MENU = 4 +COLOR_WINDOW = 5 +COLOR_WINDOWFRAME = 6 +COLOR_MENUTEXT = 7 +COLOR_WINDOWTEXT = 8 +COLOR_CAPTIONTEXT = 9 +COLOR_ACTIVEBORDER = 10 +COLOR_INACTIVEBORDER = 11 +COLOR_APPWORKSPACE = 12 +COLOR_HIGHLIGHT = 13 +COLOR_HIGHLIGHTTEXT = 14 +COLOR_BTNFACE = 15 +COLOR_BTNSHADOW = 16 +COLOR_GRAYTEXT = 17 +COLOR_BTNTEXT = 18 +COLOR_INACTIVECAPTIONTEXT = 19 +COLOR_BTNHIGHLIGHT = 20 +COLOR_3DDKSHADOW = 21 +COLOR_3DLIGHT = 22 +COLOR_INFOTEXT = 23 +COLOR_INFOBK = 24 +COLOR_HOTLIGHT = 26 +COLOR_GRADIENTACTIVECAPTION = 27 +COLOR_GRADIENTINACTIVECAPTION = 28 +COLOR_DESKTOP = COLOR_BACKGROUND +COLOR_3DFACE = COLOR_BTNFACE +COLOR_3DSHADOW = COLOR_BTNSHADOW +COLOR_3DHIGHLIGHT = COLOR_BTNHIGHLIGHT +COLOR_3DHILIGHT = COLOR_BTNHIGHLIGHT +COLOR_BTNHILIGHT = COLOR_BTNHIGHLIGHT +GW_HWNDFIRST = 0 +GW_HWNDLAST = 1 +GW_HWNDNEXT = 2 +GW_HWNDPREV = 3 +GW_OWNER = 4 +GW_CHILD = 5 +GW_ENABLEDPOPUP = 6 +GW_MAX = 6 +MF_INSERT = 0 +MF_CHANGE = 128 +MF_APPEND = 256 +MF_DELETE = 512 +MF_REMOVE = 4096 +MF_BYCOMMAND = 0 +MF_BYPOSITION = 1024 +MF_SEPARATOR = 2048 +MF_ENABLED = 0 +MF_GRAYED = 1 +MF_DISABLED = 2 +MF_UNCHECKED = 0 +MF_CHECKED = 8 +MF_USECHECKBITMAPS = 512 +MF_STRING = 0 +MF_BITMAP = 4 +MF_OWNERDRAW = 256 +MF_POPUP = 16 +MF_MENUBARBREAK = 32 +MF_MENUBREAK = 64 +MF_UNHILITE = 0 +MF_HILITE = 128 +MF_DEFAULT = 4096 +MF_SYSMENU = 8192 +MF_HELP = 16384 +MF_RIGHTJUSTIFY = 16384 +MF_MOUSESELECT = 32768 +MF_END = 128 +MFT_STRING = MF_STRING +MFT_BITMAP = MF_BITMAP +MFT_MENUBARBREAK = MF_MENUBARBREAK +MFT_MENUBREAK = MF_MENUBREAK +MFT_OWNERDRAW = MF_OWNERDRAW +MFT_RADIOCHECK = 512 +MFT_SEPARATOR = MF_SEPARATOR +MFT_RIGHTORDER = 8192 +MFT_RIGHTJUSTIFY = MF_RIGHTJUSTIFY +MFS_GRAYED = 3 +MFS_DISABLED = MFS_GRAYED +MFS_CHECKED = MF_CHECKED +MFS_HILITE = MF_HILITE +MFS_ENABLED = MF_ENABLED +MFS_UNCHECKED = MF_UNCHECKED +MFS_UNHILITE = MF_UNHILITE +MFS_DEFAULT = MF_DEFAULT +MFS_MASK = 4235 +MFS_HOTTRACKDRAWN = 268435456 +MFS_CACHEDBMP = 536870912 +MFS_BOTTOMGAPDROP = 1073741824 +MFS_TOPGAPDROP = -2147483648 +MFS_GAPDROP = -1073741824 +SC_SIZE = 61440 +SC_MOVE = 61456 +SC_MINIMIZE = 61472 +SC_MAXIMIZE = 61488 +SC_NEXTWINDOW = 61504 +SC_PREVWINDOW = 61520 +SC_CLOSE = 61536 +SC_VSCROLL = 61552 +SC_HSCROLL = 61568 +SC_MOUSEMENU = 61584 +SC_KEYMENU = 61696 +SC_ARRANGE = 61712 +SC_RESTORE = 61728 +SC_TASKLIST = 61744 +SC_SCREENSAVE = 61760 +SC_HOTKEY = 61776 +SC_DEFAULT = 61792 +SC_MONITORPOWER = 61808 +SC_CONTEXTHELP = 61824 +SC_SEPARATOR = 61455 +SC_ICON = SC_MINIMIZE +SC_ZOOM = SC_MAXIMIZE +IDC_ARROW = 32512 +IDC_IBEAM = 32513 +IDC_WAIT = 32514 +IDC_CROSS = 32515 +IDC_UPARROW = 32516 +IDC_SIZE = 32640 # OBSOLETE: use IDC_SIZEALL +IDC_ICON = 32641 # OBSOLETE: use IDC_ARROW +IDC_SIZENWSE = 32642 +IDC_SIZENESW = 32643 +IDC_SIZEWE = 32644 +IDC_SIZENS = 32645 +IDC_SIZEALL = 32646 +IDC_NO = 32648 +IDC_HAND = 32649 +IDC_APPSTARTING = 32650 +IDC_HELP = 32651 +IMAGE_BITMAP = 0 +IMAGE_ICON = 1 +IMAGE_CURSOR = 2 +IMAGE_ENHMETAFILE = 3 +LR_DEFAULTCOLOR = 0 +LR_MONOCHROME = 1 +LR_COLOR = 2 +LR_COPYRETURNORG = 4 +LR_COPYDELETEORG = 8 +LR_LOADFROMFILE = 16 +LR_LOADTRANSPARENT = 32 +LR_DEFAULTSIZE = 64 +LR_LOADREALSIZE = 128 +LR_LOADMAP3DCOLORS = 4096 +LR_CREATEDIBSECTION = 8192 +LR_COPYFROMRESOURCE = 16384 +LR_SHARED = 32768 +DI_MASK = 1 +DI_IMAGE = 2 +DI_NORMAL = 3 +DI_COMPAT = 4 +DI_DEFAULTSIZE = 8 +RES_ICON = 1 +RES_CURSOR = 2 +OBM_CLOSE = 32754 +OBM_UPARROW = 32753 +OBM_DNARROW = 32752 +OBM_RGARROW = 32751 +OBM_LFARROW = 32750 +OBM_REDUCE = 32749 +OBM_ZOOM = 32748 +OBM_RESTORE = 32747 +OBM_REDUCED = 32746 +OBM_ZOOMD = 32745 +OBM_RESTORED = 32744 +OBM_UPARROWD = 32743 +OBM_DNARROWD = 32742 +OBM_RGARROWD = 32741 +OBM_LFARROWD = 32740 +OBM_MNARROW = 32739 +OBM_COMBO = 32738 +OBM_UPARROWI = 32737 +OBM_DNARROWI = 32736 +OBM_RGARROWI = 32735 +OBM_LFARROWI = 32734 +OBM_OLD_CLOSE = 32767 +OBM_SIZE = 32766 +OBM_OLD_UPARROW = 32765 +OBM_OLD_DNARROW = 32764 +OBM_OLD_RGARROW = 32763 +OBM_OLD_LFARROW = 32762 +OBM_BTSIZE = 32761 +OBM_CHECK = 32760 +OBM_CHECKBOXES = 32759 +OBM_BTNCORNERS = 32758 +OBM_OLD_REDUCE = 32757 +OBM_OLD_ZOOM = 32756 +OBM_OLD_RESTORE = 32755 +OCR_NORMAL = 32512 +OCR_IBEAM = 32513 +OCR_WAIT = 32514 +OCR_CROSS = 32515 +OCR_UP = 32516 +OCR_SIZE = 32640 +OCR_ICON = 32641 +OCR_SIZENWSE = 32642 +OCR_SIZENESW = 32643 +OCR_SIZEWE = 32644 +OCR_SIZENS = 32645 +OCR_SIZEALL = 32646 +OCR_ICOCUR = 32647 +OCR_NO = 32648 +OCR_HAND = 32649 +OCR_APPSTARTING = 32650 +# winuser.h line 7455 +OIC_SAMPLE = 32512 +OIC_HAND = 32513 +OIC_QUES = 32514 +OIC_BANG = 32515 +OIC_NOTE = 32516 +OIC_WINLOGO = 32517 +OIC_WARNING = OIC_BANG +OIC_ERROR = OIC_HAND +OIC_INFORMATION = OIC_NOTE +ORD_LANGDRIVER = 1 +IDI_APPLICATION = 32512 +IDI_HAND = 32513 +IDI_QUESTION = 32514 +IDI_EXCLAMATION = 32515 +IDI_ASTERISK = 32516 +IDI_WINLOGO = 32517 +IDI_WARNING = IDI_EXCLAMATION +IDI_ERROR = IDI_HAND +IDI_INFORMATION = IDI_ASTERISK +IDOK = 1 +IDCANCEL = 2 +IDABORT = 3 +IDRETRY = 4 +IDIGNORE = 5 +IDYES = 6 +IDNO = 7 +IDCLOSE = 8 +IDHELP = 9 +ES_LEFT = 0 +ES_CENTER = 1 +ES_RIGHT = 2 +ES_MULTILINE = 4 +ES_UPPERCASE = 8 +ES_LOWERCASE = 16 +ES_PASSWORD = 32 +ES_AUTOVSCROLL = 64 +ES_AUTOHSCROLL = 128 +ES_NOHIDESEL = 256 +ES_OEMCONVERT = 1024 +ES_READONLY = 2048 +ES_WANTRETURN = 4096 +ES_NUMBER = 8192 +EN_SETFOCUS = 256 +EN_KILLFOCUS = 512 +EN_CHANGE = 768 +EN_UPDATE = 1024 +EN_ERRSPACE = 1280 +EN_MAXTEXT = 1281 +EN_HSCROLL = 1537 +EN_VSCROLL = 1538 +EC_LEFTMARGIN = 1 +EC_RIGHTMARGIN = 2 +EC_USEFONTINFO = 65535 +EMSIS_COMPOSITIONSTRING = 1 +EIMES_GETCOMPSTRATONCE = 1 +EIMES_CANCELCOMPSTRINFOCUS = 2 +EIMES_COMPLETECOMPSTRKILLFOCUS = 4 +EM_GETSEL = 176 +EM_SETSEL = 177 +EM_GETRECT = 178 +EM_SETRECT = 179 +EM_SETRECTNP = 180 +EM_SCROLL = 181 +EM_LINESCROLL = 182 +EM_SCROLLCARET = 183 +EM_GETMODIFY = 184 +EM_SETMODIFY = 185 +EM_GETLINECOUNT = 186 +EM_LINEINDEX = 187 +EM_SETHANDLE = 188 +EM_GETHANDLE = 189 +EM_GETTHUMB = 190 +EM_LINELENGTH = 193 +EM_REPLACESEL = 194 +EM_GETLINE = 196 +EM_LIMITTEXT = 197 +EM_CANUNDO = 198 +EM_UNDO = 199 +EM_FMTLINES = 200 +EM_LINEFROMCHAR = 201 +EM_SETTABSTOPS = 203 +EM_SETPASSWORDCHAR = 204 +EM_EMPTYUNDOBUFFER = 205 +EM_GETFIRSTVISIBLELINE = 206 +EM_SETREADONLY = 207 +EM_SETWORDBREAKPROC = 208 +EM_GETWORDBREAKPROC = 209 +EM_GETPASSWORDCHAR = 210 +EM_SETMARGINS = 211 +EM_GETMARGINS = 212 +EM_SETLIMITTEXT = EM_LIMITTEXT +EM_GETLIMITTEXT = 213 +EM_POSFROMCHAR = 214 +EM_CHARFROMPOS = 215 +EM_SETIMESTATUS = 216 +EM_GETIMESTATUS = 217 +WB_LEFT = 0 +WB_RIGHT = 1 +WB_ISDELIMITER = 2 +BS_PUSHBUTTON = 0 +BS_DEFPUSHBUTTON = 1 +BS_CHECKBOX = 2 +BS_AUTOCHECKBOX = 3 +BS_RADIOBUTTON = 4 +BS_3STATE = 5 +BS_AUTO3STATE = 6 +BS_GROUPBOX = 7 +BS_USERBUTTON = 8 +BS_AUTORADIOBUTTON = 9 +BS_OWNERDRAW = 11 +BS_LEFTTEXT = 32 +BS_TEXT = 0 +BS_ICON = 64 +BS_BITMAP = 128 +BS_LEFT = 256 +BS_RIGHT = 512 +BS_CENTER = 768 +BS_TOP = 1024 +BS_BOTTOM = 2048 +BS_VCENTER = 3072 +BS_PUSHLIKE = 4096 +BS_MULTILINE = 8192 +BS_NOTIFY = 16384 +BS_FLAT = 32768 +BS_RIGHTBUTTON = BS_LEFTTEXT +BN_CLICKED = 0 +BN_PAINT = 1 +BN_HILITE = 2 +BN_UNHILITE = 3 +BN_DISABLE = 4 +BN_DOUBLECLICKED = 5 +BN_PUSHED = BN_HILITE +BN_UNPUSHED = BN_UNHILITE +BN_DBLCLK = BN_DOUBLECLICKED +BN_SETFOCUS = 6 +BN_KILLFOCUS = 7 +BM_GETCHECK = 240 +BM_SETCHECK = 241 +BM_GETSTATE = 242 +BM_SETSTATE = 243 +BM_SETSTYLE = 244 +BM_CLICK = 245 +BM_GETIMAGE = 246 +BM_SETIMAGE = 247 +BST_UNCHECKED = 0 +BST_CHECKED = 1 +BST_INDETERMINATE = 2 +BST_PUSHED = 4 +BST_FOCUS = 8 +SS_LEFT = 0 +SS_CENTER = 1 +SS_RIGHT = 2 +SS_ICON = 3 +SS_BLACKRECT = 4 +SS_GRAYRECT = 5 +SS_WHITERECT = 6 +SS_BLACKFRAME = 7 +SS_GRAYFRAME = 8 +SS_WHITEFRAME = 9 +SS_USERITEM = 10 +SS_SIMPLE = 11 +SS_LEFTNOWORDWRAP = 12 +SS_BITMAP = 14 +SS_OWNERDRAW = 13 +SS_ENHMETAFILE = 15 +SS_ETCHEDHORZ = 16 +SS_ETCHEDVERT = 17 +SS_ETCHEDFRAME = 18 +SS_TYPEMASK = 31 +SS_NOPREFIX = 128 +SS_NOTIFY = 256 +SS_CENTERIMAGE = 512 +SS_RIGHTJUST = 1024 +SS_REALSIZEIMAGE = 2048 +SS_SUNKEN = 4096 +SS_ENDELLIPSIS = 16384 +SS_PATHELLIPSIS = 32768 +SS_WORDELLIPSIS = 49152 +SS_ELLIPSISMASK = 49152 +STM_SETICON = 368 +STM_GETICON = 369 +STM_SETIMAGE = 370 +STM_GETIMAGE = 371 +STN_CLICKED = 0 +STN_DBLCLK = 1 +STN_ENABLE = 2 +STN_DISABLE = 3 +STM_MSGMAX = 372 +DWL_MSGRESULT = 0 +DWL_DLGPROC = 4 +DWL_USER = 8 +DDL_READWRITE = 0 +DDL_READONLY = 1 +DDL_HIDDEN = 2 +DDL_SYSTEM = 4 +DDL_DIRECTORY = 16 +DDL_ARCHIVE = 32 +DDL_POSTMSGS = 8192 +DDL_DRIVES = 16384 +DDL_EXCLUSIVE = 32768 + +#from winuser.h line 153 +RT_CURSOR = 1 +RT_BITMAP = 2 +RT_ICON = 3 +RT_MENU = 4 +RT_DIALOG = 5 +RT_STRING = 6 +RT_FONTDIR = 7 +RT_FONT = 8 +RT_ACCELERATOR = 9 +RT_RCDATA = 10 +RT_MESSAGETABLE = 11 +DIFFERENCE = 11 +RT_GROUP_CURSOR = (RT_CURSOR + DIFFERENCE) +RT_GROUP_ICON = (RT_ICON + DIFFERENCE) +RT_VERSION = 16 +RT_DLGINCLUDE = 17 +RT_PLUGPLAY = 19 +RT_VXD = 20 +RT_ANICURSOR = 21 +RT_ANIICON = 22 +RT_HTML = 23 +# from winuser.h line 218 +SB_HORZ = 0 +SB_VERT = 1 +SB_CTL = 2 +SB_BOTH = 3 +SB_LINEUP = 0 +SB_LINELEFT = 0 +SB_LINEDOWN = 1 +SB_LINERIGHT = 1 +SB_PAGEUP = 2 +SB_PAGELEFT = 2 +SB_PAGEDOWN = 3 +SB_PAGERIGHT = 3 +SB_THUMBPOSITION = 4 +SB_THUMBTRACK = 5 +SB_TOP = 6 +SB_LEFT = 6 +SB_BOTTOM = 7 +SB_RIGHT = 7 +SB_ENDSCROLL = 8 +SW_HIDE = 0 +SW_SHOWNORMAL = 1 +SW_NORMAL = 1 +SW_SHOWMINIMIZED = 2 +SW_SHOWMAXIMIZED = 3 +SW_MAXIMIZE = 3 +SW_SHOWNOACTIVATE = 4 +SW_SHOW = 5 +SW_MINIMIZE = 6 +SW_SHOWMINNOACTIVE = 7 +SW_SHOWNA = 8 +SW_RESTORE = 9 +SW_SHOWDEFAULT = 10 +SW_FORCEMINIMIZE = 11 +SW_MAX = 11 +HIDE_WINDOW = 0 +SHOW_OPENWINDOW = 1 +SHOW_ICONWINDOW = 2 +SHOW_FULLSCREEN = 3 +SHOW_OPENNOACTIVATE = 4 +SW_PARENTCLOSING = 1 +SW_OTHERZOOM = 2 +SW_PARENTOPENING = 3 +SW_OTHERUNZOOM = 4 +AW_HOR_POSITIVE = 1 +AW_HOR_NEGATIVE = 2 +AW_VER_POSITIVE = 4 +AW_VER_NEGATIVE = 8 +AW_CENTER = 16 +AW_HIDE = 65536 +AW_ACTIVATE = 131072 +AW_SLIDE = 262144 +AW_BLEND = 524288 +KF_EXTENDED = 256 +KF_DLGMODE = 2048 +KF_MENUMODE = 4096 +KF_ALTDOWN = 8192 +KF_REPEAT = 16384 +KF_UP = 32768 +VK_LBUTTON = 1 +VK_RBUTTON = 2 +VK_CANCEL = 3 +VK_MBUTTON = 4 +VK_BACK = 8 +VK_TAB = 9 +VK_CLEAR = 12 +VK_RETURN = 13 +VK_SHIFT = 16 +VK_CONTROL = 17 +VK_MENU = 18 +VK_PAUSE = 19 +VK_CAPITAL = 20 +VK_KANA = 21 +VK_HANGEUL = 21 # old name - should be here for compatibility +VK_HANGUL = 21 +VK_JUNJA = 23 +VK_FINAL = 24 +VK_HANJA = 25 +VK_KANJI = 25 +VK_ESCAPE = 27 +VK_CONVERT = 28 +VK_NONCONVERT = 29 +VK_ACCEPT = 30 +VK_MODECHANGE = 31 +VK_SPACE = 32 +VK_PRIOR = 33 +VK_NEXT = 34 +VK_END = 35 +VK_HOME = 36 +VK_LEFT = 37 +VK_UP = 38 +VK_RIGHT = 39 +VK_DOWN = 40 +VK_SELECT = 41 +VK_PRINT = 42 +VK_EXECUTE = 43 +VK_SNAPSHOT = 44 +VK_INSERT = 45 +VK_DELETE = 46 +VK_HELP = 47 +VK_LWIN = 91 +VK_RWIN = 92 +VK_APPS = 93 +VK_NUMPAD0 = 96 +VK_NUMPAD1 = 97 +VK_NUMPAD2 = 98 +VK_NUMPAD3 = 99 +VK_NUMPAD4 = 100 +VK_NUMPAD5 = 101 +VK_NUMPAD6 = 102 +VK_NUMPAD7 = 103 +VK_NUMPAD8 = 104 +VK_NUMPAD9 = 105 +VK_MULTIPLY = 106 +VK_ADD = 107 +VK_SEPARATOR = 108 +VK_SUBTRACT = 109 +VK_DECIMAL = 110 +VK_DIVIDE = 111 +VK_F1 = 112 +VK_F2 = 113 +VK_F3 = 114 +VK_F4 = 115 +VK_F5 = 116 +VK_F6 = 117 +VK_F7 = 118 +VK_F8 = 119 +VK_F9 = 120 +VK_F10 = 121 +VK_F11 = 122 +VK_F12 = 123 +VK_F13 = 124 +VK_F14 = 125 +VK_F15 = 126 +VK_F16 = 127 +VK_F17 = 128 +VK_F18 = 129 +VK_F19 = 130 +VK_F20 = 131 +VK_F21 = 132 +VK_F22 = 133 +VK_F23 = 134 +VK_F24 = 135 +VK_NUMLOCK = 144 +VK_SCROLL = 145 +VK_LSHIFT = 160 +VK_RSHIFT = 161 +VK_LCONTROL = 162 +VK_RCONTROL = 163 +VK_LMENU = 164 +VK_RMENU = 165 +VK_PROCESSKEY = 229 +VK_ATTN = 246 +VK_CRSEL = 247 +VK_EXSEL = 248 +VK_EREOF = 249 +VK_PLAY = 250 +VK_ZOOM = 251 +VK_NONAME = 252 +VK_PA1 = 253 +VK_OEM_CLEAR = 254 +# multi-media related "keys" +MOUSEEVENTF_XDOWN = 0x0080 +MOUSEEVENTF_XUP = 0x0100 +MOUSEEVENTF_WHEEL = 0x0800 +VK_XBUTTON1 = 0x05 +VK_XBUTTON2 = 0x06 +VK_VOLUME_MUTE = 0xAD +VK_VOLUME_DOWN = 0xAE +VK_VOLUME_UP = 0xAF +VK_MEDIA_NEXT_TRACK = 0xB0 +VK_MEDIA_PREV_TRACK = 0xB1 +VK_MEDIA_PLAY_PAUSE = 0xB3 +VK_BROWSER_BACK = 0xA6 +VK_BROWSER_FORWARD = 0xA7 +WH_MIN = (-1) +WH_MSGFILTER = (-1) +WH_JOURNALRECORD = 0 +WH_JOURNALPLAYBACK = 1 +WH_KEYBOARD = 2 +WH_GETMESSAGE = 3 +WH_CALLWNDPROC = 4 +WH_CBT = 5 +WH_SYSMSGFILTER = 6 +WH_MOUSE = 7 +WH_HARDWARE = 8 +WH_DEBUG = 9 +WH_SHELL = 10 +WH_FOREGROUNDIDLE = 11 +WH_CALLWNDPROCRET = 12 +WH_KEYBOARD_LL = 13 +WH_MOUSE_LL = 14 +WH_MAX = 14 +WH_MINHOOK = WH_MIN +WH_MAXHOOK = WH_MAX +HC_ACTION = 0 +HC_GETNEXT = 1 +HC_SKIP = 2 +HC_NOREMOVE = 3 +HC_NOREM = HC_NOREMOVE +HC_SYSMODALON = 4 +HC_SYSMODALOFF = 5 +HCBT_MOVESIZE = 0 +HCBT_MINMAX = 1 +HCBT_QS = 2 +HCBT_CREATEWND = 3 +HCBT_DESTROYWND = 4 +HCBT_ACTIVATE = 5 +HCBT_CLICKSKIPPED = 6 +HCBT_KEYSKIPPED = 7 +HCBT_SYSCOMMAND = 8 +HCBT_SETFOCUS = 9 +MSGF_DIALOGBOX = 0 +MSGF_MESSAGEBOX = 1 +MSGF_MENU = 2 +#MSGF_MOVE = 3 +#MSGF_SIZE = 4 +MSGF_SCROLLBAR = 5 +MSGF_NEXTWINDOW = 6 +#MSGF_MAINLOOP = 8 +MSGF_MAX = 8 +MSGF_USER = 4096 +HSHELL_WINDOWCREATED = 1 +HSHELL_WINDOWDESTROYED = 2 +HSHELL_ACTIVATESHELLWINDOW = 3 +HSHELL_WINDOWACTIVATED = 4 +HSHELL_GETMINRECT = 5 +HSHELL_REDRAW = 6 +HSHELL_TASKMAN = 7 +HSHELL_LANGUAGE = 8 +HSHELL_ACCESSIBILITYSTATE = 11 +ACCESS_STICKYKEYS = 1 +ACCESS_FILTERKEYS = 2 +ACCESS_MOUSEKEYS = 3 +# winuser.h line 624 +LLKHF_EXTENDED = 1 +LLKHF_INJECTED = 16 +LLKHF_ALTDOWN = 32 +LLKHF_UP = 128 +LLMHF_INJECTED = 1 +# line 692 +HKL_PREV = 0 +HKL_NEXT = 1 +KLF_ACTIVATE = 1 +KLF_SUBSTITUTE_OK = 2 +KLF_UNLOADPREVIOUS = 4 +KLF_REORDER = 8 +KLF_REPLACELANG = 16 +KLF_NOTELLSHELL = 128 +KLF_SETFORPROCESS = 256 +KL_NAMELENGTH = 9 +DESKTOP_READOBJECTS = 1 +DESKTOP_CREATEWINDOW = 2 +DESKTOP_CREATEMENU = 4 +DESKTOP_HOOKCONTROL = 8 +DESKTOP_JOURNALRECORD = 16 +DESKTOP_JOURNALPLAYBACK = 32 +DESKTOP_ENUMERATE = 64 +DESKTOP_WRITEOBJECTS = 128 +DESKTOP_SWITCHDESKTOP = 256 +DF_ALLOWOTHERACCOUNTHOOK = 1 +WINSTA_ENUMDESKTOPS = 1 +WINSTA_READATTRIBUTES = 2 +WINSTA_ACCESSCLIPBOARD = 4 +WINSTA_CREATEDESKTOP = 8 +WINSTA_WRITEATTRIBUTES = 16 +WINSTA_ACCESSGLOBALATOMS = 32 +WINSTA_EXITWINDOWS = 64 +WINSTA_ENUMERATE = 256 +WINSTA_READSCREEN = 512 +WSF_VISIBLE = 1 +UOI_FLAGS = 1 +UOI_NAME = 2 +UOI_TYPE = 3 +UOI_USER_SID = 4 +GWL_WNDPROC = (-4) +GWL_HINSTANCE = (-6) +GWL_HWNDPARENT = (-8) +GWL_STYLE = (-16) +GWL_EXSTYLE = (-20) +GWL_USERDATA = (-21) +GWL_ID = (-12) +GCL_MENUNAME = (-8) +GCL_HBRBACKGROUND = (-10) +GCL_HCURSOR = (-12) +GCL_HICON = (-14) +GCL_HMODULE = (-16) +GCL_CBWNDEXTRA = (-18) +GCL_CBCLSEXTRA = (-20) +GCL_WNDPROC = (-24) +GCL_STYLE = (-26) +GCW_ATOM = (-32) +GCL_HICONSM = (-34) +# line 1291 +WM_NULL = 0 +WM_CREATE = 1 +WM_DESTROY = 2 +WM_MOVE = 3 +WM_SIZE = 5 +WM_ACTIVATE = 6 +WA_INACTIVE = 0 +WA_ACTIVE = 1 +WA_CLICKACTIVE = 2 +WM_SETFOCUS = 7 +WM_KILLFOCUS = 8 +WM_ENABLE = 10 +WM_SETREDRAW = 11 +WM_SETTEXT = 12 +WM_GETTEXT = 13 +WM_GETTEXTLENGTH = 14 +WM_PAINT = 15 +WM_CLOSE = 16 +WM_QUERYENDSESSION = 17 +WM_QUIT = 18 +WM_QUERYOPEN = 19 +WM_ERASEBKGND = 20 +WM_SYSCOLORCHANGE = 21 +WM_ENDSESSION = 22 +WM_SHOWWINDOW = 24 +WM_WININICHANGE = 26 +WM_SETTINGCHANGE = WM_WININICHANGE +WM_DEVMODECHANGE = 27 +WM_ACTIVATEAPP = 28 +WM_FONTCHANGE = 29 +WM_TIMECHANGE = 30 +WM_CANCELMODE = 31 +WM_SETCURSOR = 32 +WM_MOUSEACTIVATE = 33 +WM_CHILDACTIVATE = 34 +WM_QUEUESYNC = 35 +WM_GETMINMAXINFO = 36 +WM_PAINTICON = 38 +WM_ICONERASEBKGND = 39 +WM_NEXTDLGCTL = 40 +WM_SPOOLERSTATUS = 42 +WM_DRAWITEM = 43 +WM_MEASUREITEM = 44 +WM_DELETEITEM = 45 +WM_VKEYTOITEM = 46 +WM_CHARTOITEM = 47 +WM_SETFONT = 48 +WM_GETFONT = 49 +WM_SETHOTKEY = 50 +WM_GETHOTKEY = 51 +WM_QUERYDRAGICON = 55 +WM_COMPAREITEM = 57 +WM_GETOBJECT = 61 +WM_COMPACTING = 65 +WM_COMMNOTIFY = 68 +WM_WINDOWPOSCHANGING = 70 +WM_WINDOWPOSCHANGED = 71 +WM_POWER = 72 +PWR_OK = 1 +PWR_FAIL = (-1) +PWR_SUSPENDREQUEST = 1 +PWR_SUSPENDRESUME = 2 +PWR_CRITICALRESUME = 3 +WM_COPYDATA = 74 +WM_CANCELJOURNAL = 75 +WM_NOTIFY = 78 +WM_INPUTLANGCHANGEREQUEST = 80 +WM_INPUTLANGCHANGE = 81 +WM_TCARD = 82 +WM_HELP = 83 +WM_USERCHANGED = 84 +WM_NOTIFYFORMAT = 85 +NFR_ANSI = 1 +NFR_UNICODE = 2 +NF_QUERY = 3 +NF_REQUERY = 4 +WM_CONTEXTMENU = 123 +WM_STYLECHANGING = 124 +WM_STYLECHANGED = 125 +WM_DISPLAYCHANGE = 126 +WM_GETICON = 127 +WM_SETICON = 128 +WM_NCCREATE = 129 +WM_NCDESTROY = 130 +WM_NCCALCSIZE = 131 +WM_NCHITTEST = 132 +WM_NCPAINT = 133 +WM_NCACTIVATE = 134 +WM_GETDLGCODE = 135 +WM_SYNCPAINT = 136 +WM_NCMOUSEMOVE = 160 +WM_NCLBUTTONDOWN = 161 +WM_NCLBUTTONUP = 162 +WM_NCLBUTTONDBLCLK = 163 +WM_NCRBUTTONDOWN = 164 +WM_NCRBUTTONUP = 165 +WM_NCRBUTTONDBLCLK = 166 +WM_NCMBUTTONDOWN = 167 +WM_NCMBUTTONUP = 168 +WM_NCMBUTTONDBLCLK = 169 +WM_KEYFIRST = 256 +WM_KEYDOWN = 256 +WM_KEYUP = 257 +WM_CHAR = 258 +WM_DEADCHAR = 259 +WM_SYSKEYDOWN = 260 +WM_SYSKEYUP = 261 +WM_SYSCHAR = 262 +WM_SYSDEADCHAR = 263 +WM_KEYLAST = 264 +WM_IME_STARTCOMPOSITION = 269 +WM_IME_ENDCOMPOSITION = 270 +WM_IME_COMPOSITION = 271 +WM_IME_KEYLAST = 271 +WM_INITDIALOG = 272 +WM_COMMAND = 273 +WM_SYSCOMMAND = 274 +WM_TIMER = 275 +WM_HSCROLL = 276 +WM_VSCROLL = 277 +WM_INITMENU = 278 +WM_INITMENUPOPUP = 279 +WM_MENUSELECT = 287 +WM_MENUCHAR = 288 +WM_ENTERIDLE = 289 +WM_MENURBUTTONUP = 290 +WM_MENUDRAG = 291 +WM_MENUGETOBJECT = 292 +WM_UNINITMENUPOPUP = 293 +WM_MENUCOMMAND = 294 +WM_CTLCOLORMSGBOX = 306 +WM_CTLCOLOREDIT = 307 +WM_CTLCOLORLISTBOX = 308 +WM_CTLCOLORBTN = 309 +WM_CTLCOLORDLG = 310 +WM_CTLCOLORSCROLLBAR = 311 +WM_CTLCOLORSTATIC = 312 +WM_MOUSEFIRST = 512 +WM_MOUSEMOVE = 512 +WM_LBUTTONDOWN = 513 +WM_LBUTTONUP = 514 +WM_LBUTTONDBLCLK = 515 +WM_RBUTTONDOWN = 516 +WM_RBUTTONUP = 517 +WM_RBUTTONDBLCLK = 518 +WM_MBUTTONDOWN = 519 +WM_MBUTTONUP = 520 +WM_MBUTTONDBLCLK = 521 +WM_MOUSEWHEEL = 522 +WM_MOUSELAST = 522 +WHEEL_DELTA = 120 # Value for rolling one detent +WHEEL_PAGESCROLL = -1 # Scroll one page +WM_PARENTNOTIFY = 528 +MENULOOP_WINDOW = 0 +MENULOOP_POPUP = 1 +WM_ENTERMENULOOP = 529 +WM_EXITMENULOOP = 530 +WM_NEXTMENU = 531 +WM_SIZING = 532 +WM_CAPTURECHANGED = 533 +WM_MOVING = 534 +WM_POWERBROADCAST = 536 +PBT_APMQUERYSUSPEND = 0 +PBT_APMQUERYSTANDBY = 1 +PBT_APMQUERYSUSPENDFAILED = 2 +PBT_APMQUERYSTANDBYFAILED = 3 +PBT_APMSUSPEND = 4 +PBT_APMSTANDBY = 5 +PBT_APMRESUMECRITICAL = 6 +PBT_APMRESUMESUSPEND = 7 +PBT_APMRESUMESTANDBY = 8 +PBTF_APMRESUMEFROMFAILURE = 1 +PBT_APMBATTERYLOW = 9 +PBT_APMPOWERSTATUSCHANGE = 10 +PBT_APMOEMEVENT = 11 +PBT_APMRESUMEAUTOMATIC = 18 +WM_DEVICECHANGE = 537 +WM_MDICREATE = 544 +WM_MDIDESTROY = 545 +WM_MDIACTIVATE = 546 +WM_MDIRESTORE = 547 +WM_MDINEXT = 548 +WM_MDIMAXIMIZE = 549 +WM_MDITILE = 550 +WM_MDICASCADE = 551 +WM_MDIICONARRANGE = 552 +WM_MDIGETACTIVE = 553 +WM_MDISETMENU = 560 +WM_ENTERSIZEMOVE = 561 +WM_EXITSIZEMOVE = 562 +WM_DROPFILES = 563 +WM_MDIREFRESHMENU = 564 +WM_IME_SETCONTEXT = 641 +WM_IME_NOTIFY = 642 +WM_IME_CONTROL = 643 +WM_IME_COMPOSITIONFULL = 644 +WM_IME_SELECT = 645 +WM_IME_CHAR = 646 +WM_IME_REQUEST = 648 +WM_IME_KEYDOWN = 656 +WM_IME_KEYUP = 657 +WM_MOUSEHOVER = 673 +WM_MOUSELEAVE = 675 +WM_CUT = 768 +WM_COPY = 769 +WM_PASTE = 770 +WM_CLEAR = 771 +WM_UNDO = 772 +WM_RENDERFORMAT = 773 +WM_RENDERALLFORMATS = 774 +WM_DESTROYCLIPBOARD = 775 +WM_DRAWCLIPBOARD = 776 +WM_PAINTCLIPBOARD = 777 +WM_VSCROLLCLIPBOARD = 778 +WM_SIZECLIPBOARD = 779 +WM_ASKCBFORMATNAME = 780 +WM_CHANGECBCHAIN = 781 +WM_HSCROLLCLIPBOARD = 782 +WM_QUERYNEWPALETTE = 783 +WM_PALETTEISCHANGING = 784 +WM_PALETTECHANGED = 785 +WM_HOTKEY = 786 +WM_PRINT = 791 +WM_PRINTCLIENT = 792 +WM_HANDHELDFIRST = 856 +WM_HANDHELDLAST = 863 +WM_AFXFIRST = 864 +WM_AFXLAST = 895 +WM_PENWINFIRST = 896 +WM_PENWINLAST = 911 +WM_APP = 32768 +WMSZ_LEFT = 1 +WMSZ_RIGHT = 2 +WMSZ_TOP = 3 +WMSZ_TOPLEFT = 4 +WMSZ_TOPRIGHT = 5 +WMSZ_BOTTOM = 6 +WMSZ_BOTTOMLEFT = 7 +WMSZ_BOTTOMRIGHT = 8 +#ST_BEGINSWP = 0 +#ST_ENDSWP = 1 +HTERROR = (-2) +HTTRANSPARENT = (-1) +HTNOWHERE = 0 +HTCLIENT = 1 +HTCAPTION = 2 +HTSYSMENU = 3 +HTGROWBOX = 4 +HTSIZE = HTGROWBOX +HTMENU = 5 +HTHSCROLL = 6 +HTVSCROLL = 7 +HTMINBUTTON = 8 +HTMAXBUTTON = 9 +HTLEFT = 10 +HTRIGHT = 11 +HTTOP = 12 +HTTOPLEFT = 13 +HTTOPRIGHT = 14 +HTBOTTOM = 15 +HTBOTTOMLEFT = 16 +HTBOTTOMRIGHT = 17 +HTBORDER = 18 +HTREDUCE = HTMINBUTTON +HTZOOM = HTMAXBUTTON +HTSIZEFIRST = HTLEFT +HTSIZELAST = HTBOTTOMRIGHT +HTOBJECT = 19 +HTCLOSE = 20 +HTHELP = 21 +SMTO_NORMAL = 0 +SMTO_BLOCK = 1 +SMTO_ABORTIFHUNG = 2 +SMTO_NOTIMEOUTIFNOTHUNG = 8 +MA_ACTIVATE = 1 +MA_ACTIVATEANDEAT = 2 +MA_NOACTIVATE = 3 +MA_NOACTIVATEANDEAT = 4 +ICON_SMALL = 0 +ICON_BIG = 1 +SIZE_RESTORED = 0 +SIZE_MINIMIZED = 1 +SIZE_MAXIMIZED = 2 +SIZE_MAXSHOW = 3 +SIZE_MAXHIDE = 4 +SIZENORMAL = SIZE_RESTORED +SIZEICONIC = SIZE_MINIMIZED +SIZEFULLSCREEN = SIZE_MAXIMIZED +SIZEZOOMSHOW = SIZE_MAXSHOW +SIZEZOOMHIDE = SIZE_MAXHIDE +WVR_ALIGNTOP = 16 +WVR_ALIGNLEFT = 32 +WVR_ALIGNBOTTOM = 64 +WVR_ALIGNRIGHT = 128 +WVR_HREDRAW = 256 +WVR_VREDRAW = 512 +WVR_REDRAW = (WVR_HREDRAW | WVR_VREDRAW) +WVR_VALIDRECTS = 1024 +MK_LBUTTON = 1 +MK_RBUTTON = 2 +MK_SHIFT = 4 +MK_CONTROL = 8 +MK_MBUTTON = 16 +TME_HOVER = 1 +TME_LEAVE = 2 +TME_QUERY = 1073741824 +TME_CANCEL = -2147483648 +HOVER_DEFAULT = -1 +WS_OVERLAPPED = 0 +WS_POPUP = -2147483648 +WS_CHILD = 1073741824 +WS_MINIMIZE = 536870912 +WS_VISIBLE = 268435456 +WS_DISABLED = 134217728 +WS_CLIPSIBLINGS = 67108864 +WS_CLIPCHILDREN = 33554432 +WS_MAXIMIZE = 16777216 +WS_CAPTION = 12582912 +WS_BORDER = 8388608 +WS_DLGFRAME = 4194304 +WS_VSCROLL = 2097152 +WS_HSCROLL = 1048576 +WS_SYSMENU = 524288 +WS_THICKFRAME = 262144 +WS_GROUP = 131072 +WS_TABSTOP = 65536 +WS_MINIMIZEBOX = 131072 +WS_MAXIMIZEBOX = 65536 +WS_TILED = WS_OVERLAPPED +WS_ICONIC = WS_MINIMIZE +WS_SIZEBOX = WS_THICKFRAME +WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED | \ + WS_CAPTION | \ + WS_SYSMENU | \ + WS_THICKFRAME | \ + WS_MINIMIZEBOX | \ + WS_MAXIMIZEBOX) +WS_POPUPWINDOW = (WS_POPUP | \ + WS_BORDER | \ + WS_SYSMENU) +WS_CHILDWINDOW = (WS_CHILD) +WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW +WS_EX_DLGMODALFRAME = 1 +WS_EX_NOPARENTNOTIFY = 4 +WS_EX_TOPMOST = 8 +WS_EX_ACCEPTFILES = 16 +WS_EX_TRANSPARENT = 32 +WS_EX_MDICHILD = 64 +WS_EX_TOOLWINDOW = 128 +WS_EX_WINDOWEDGE = 256 +WS_EX_CLIENTEDGE = 512 +WS_EX_CONTEXTHELP = 1024 +WS_EX_RIGHT = 4096 +WS_EX_LEFT = 0 +WS_EX_RTLREADING = 8192 +WS_EX_LTRREADING = 0 +WS_EX_LEFTSCROLLBAR = 16384 +WS_EX_RIGHTSCROLLBAR = 0 +WS_EX_CONTROLPARENT = 65536 +WS_EX_STATICEDGE = 131072 +WS_EX_APPWINDOW = 262144 +WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE) +WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST) +WS_EX_LAYERED = 0x00080000 +WS_EX_NOINHERITLAYOUT = 0x00100000 +WS_EX_LAYOUTRTL = 0x00400000 +WS_EX_COMPOSITED = 0x02000000 +WS_EX_NOACTIVATE = 0x08000000 + +CS_VREDRAW = 1 +CS_HREDRAW = 2 +#CS_KEYCVTWINDOW = 0x0004 +CS_DBLCLKS = 8 +CS_OWNDC = 32 +CS_CLASSDC = 64 +CS_PARENTDC = 128 +#CS_NOKEYCVT = 0x0100 +CS_NOCLOSE = 512 +CS_SAVEBITS = 2048 +CS_BYTEALIGNCLIENT = 4096 +CS_BYTEALIGNWINDOW = 8192 +CS_GLOBALCLASS = 16384 +CS_IME = 65536 +PRF_CHECKVISIBLE = 1 +PRF_NONCLIENT = 2 +PRF_CLIENT = 4 +PRF_ERASEBKGND = 8 +PRF_CHILDREN = 16 +PRF_OWNED = 32 +BDR_RAISEDOUTER = 1 +BDR_SUNKENOUTER = 2 +BDR_RAISEDINNER = 4 +BDR_SUNKENINNER = 8 +BDR_OUTER = 3 +BDR_INNER = 12 +#BDR_RAISED = 0x0005 +#BDR_SUNKEN = 0x000a +EDGE_RAISED = (BDR_RAISEDOUTER | BDR_RAISEDINNER) +EDGE_SUNKEN = (BDR_SUNKENOUTER | BDR_SUNKENINNER) +EDGE_ETCHED = (BDR_SUNKENOUTER | BDR_RAISEDINNER) +EDGE_BUMP = (BDR_RAISEDOUTER | BDR_SUNKENINNER) + +# winuser.h line 2879 +ISMEX_NOSEND = 0 +ISMEX_SEND = 1 +ISMEX_NOTIFY = 2 +ISMEX_CALLBACK = 4 +ISMEX_REPLIED = 8 +CW_USEDEFAULT = -2147483648 +FLASHW_STOP = 0 +FLASHW_CAPTION = 1 +FLASHW_TRAY = 2 +FLASHW_ALL = (FLASHW_CAPTION | FLASHW_TRAY) +FLASHW_TIMER = 4 +FLASHW_TIMERNOFG = 12 + +# winuser.h line 7963 +DS_ABSALIGN = 1 +DS_SYSMODAL = 2 +DS_LOCALEDIT = 32 +DS_SETFONT = 64 +DS_MODALFRAME = 128 +DS_NOIDLEMSG = 256 +DS_SETFOREGROUND = 512 +DS_3DLOOK = 4 +DS_FIXEDSYS = 8 +DS_NOFAILCREATE = 16 +DS_CONTROL = 1024 +DS_CENTER = 2048 +DS_CENTERMOUSE = 4096 +DS_CONTEXTHELP = 8192 +DM_GETDEFID = (WM_USER+0) +DM_SETDEFID = (WM_USER+1) +DM_REPOSITION = (WM_USER+2) +#PSM_PAGEINFO = (WM_USER+100) +#PSM_SHEETINFO = (WM_USER+101) +#PSI_SETACTIVE = 0x0001 +#PSI_KILLACTIVE = 0x0002 +#PSI_APPLY = 0x0003 +#PSI_RESET = 0x0004 +#PSI_HASHELP = 0x0005 +#PSI_HELP = 0x0006 +#PSI_CHANGED = 0x0001 +#PSI_GUISTART = 0x0002 +#PSI_REBOOT = 0x0003 +#PSI_GETSIBLINGS = 0x0004 +DC_HASDEFID = 21323 +DLGC_WANTARROWS = 1 +DLGC_WANTTAB = 2 +DLGC_WANTALLKEYS = 4 +DLGC_WANTMESSAGE = 4 +DLGC_HASSETSEL = 8 +DLGC_DEFPUSHBUTTON = 16 +DLGC_UNDEFPUSHBUTTON = 32 +DLGC_RADIOBUTTON = 64 +DLGC_WANTCHARS = 128 +DLGC_STATIC = 256 +DLGC_BUTTON = 8192 +LB_CTLCODE = 0 +LB_OKAY = 0 +LB_ERR = (-1) +LB_ERRSPACE = (-2) +LBN_ERRSPACE = (-2) +LBN_SELCHANGE = 1 +LBN_DBLCLK = 2 +LBN_SELCANCEL = 3 +LBN_SETFOCUS = 4 +LBN_KILLFOCUS = 5 +LB_ADDSTRING = 384 +LB_INSERTSTRING = 385 +LB_DELETESTRING = 386 +LB_SELITEMRANGEEX = 387 +LB_RESETCONTENT = 388 +LB_SETSEL = 389 +LB_SETCURSEL = 390 +LB_GETSEL = 391 +LB_GETCURSEL = 392 +LB_GETTEXT = 393 +LB_GETTEXTLEN = 394 +LB_GETCOUNT = 395 +LB_SELECTSTRING = 396 +LB_DIR = 397 +LB_GETTOPINDEX = 398 +LB_FINDSTRING = 399 +LB_GETSELCOUNT = 400 +LB_GETSELITEMS = 401 +LB_SETTABSTOPS = 402 +LB_GETHORIZONTALEXTENT = 403 +LB_SETHORIZONTALEXTENT = 404 +LB_SETCOLUMNWIDTH = 405 +LB_ADDFILE = 406 +LB_SETTOPINDEX = 407 +LB_GETITEMRECT = 408 +LB_GETITEMDATA = 409 +LB_SETITEMDATA = 410 +LB_SELITEMRANGE = 411 +LB_SETANCHORINDEX = 412 +LB_GETANCHORINDEX = 413 +LB_SETCARETINDEX = 414 +LB_GETCARETINDEX = 415 +LB_SETITEMHEIGHT = 416 +LB_GETITEMHEIGHT = 417 +LB_FINDSTRINGEXACT = 418 +LB_SETLOCALE = 421 +LB_GETLOCALE = 422 +LB_SETCOUNT = 423 +LB_INITSTORAGE = 424 +LB_ITEMFROMPOINT = 425 +LB_MSGMAX = 432 +LBS_NOTIFY = 1 +LBS_SORT = 2 +LBS_NOREDRAW = 4 +LBS_MULTIPLESEL = 8 +LBS_OWNERDRAWFIXED = 16 +LBS_OWNERDRAWVARIABLE = 32 +LBS_HASSTRINGS = 64 +LBS_USETABSTOPS = 128 +LBS_NOINTEGRALHEIGHT = 256 +LBS_MULTICOLUMN = 512 +LBS_WANTKEYBOARDINPUT = 1024 +LBS_EXTENDEDSEL = 2048 +LBS_DISABLENOSCROLL = 4096 +LBS_NODATA = 8192 +LBS_NOSEL = 16384 +LBS_STANDARD = (LBS_NOTIFY | LBS_SORT | WS_VSCROLL | WS_BORDER) +CB_OKAY = 0 +CB_ERR = (-1) +CB_ERRSPACE = (-2) +CBN_ERRSPACE = (-1) +CBN_SELCHANGE = 1 +CBN_DBLCLK = 2 +CBN_SETFOCUS = 3 +CBN_KILLFOCUS = 4 +CBN_EDITCHANGE = 5 +CBN_EDITUPDATE = 6 +CBN_DROPDOWN = 7 +CBN_CLOSEUP = 8 +CBN_SELENDOK = 9 +CBN_SELENDCANCEL = 10 +CBS_SIMPLE = 1 +CBS_DROPDOWN = 2 +CBS_DROPDOWNLIST = 3 +CBS_OWNERDRAWFIXED = 16 +CBS_OWNERDRAWVARIABLE = 32 +CBS_AUTOHSCROLL = 64 +CBS_OEMCONVERT = 128 +CBS_SORT = 256 +CBS_HASSTRINGS = 512 +CBS_NOINTEGRALHEIGHT = 1024 +CBS_DISABLENOSCROLL = 2048 +CBS_UPPERCASE = 8192 +CBS_LOWERCASE = 16384 +CB_GETEDITSEL = 320 +CB_LIMITTEXT = 321 +CB_SETEDITSEL = 322 +CB_ADDSTRING = 323 +CB_DELETESTRING = 324 +CB_DIR = 325 +CB_GETCOUNT = 326 +CB_GETCURSEL = 327 +CB_GETLBTEXT = 328 +CB_GETLBTEXTLEN = 329 +CB_INSERTSTRING = 330 +CB_RESETCONTENT = 331 +CB_FINDSTRING = 332 +CB_SELECTSTRING = 333 +CB_SETCURSEL = 334 +CB_SHOWDROPDOWN = 335 +CB_GETITEMDATA = 336 +CB_SETITEMDATA = 337 +CB_GETDROPPEDCONTROLRECT = 338 +CB_SETITEMHEIGHT = 339 +CB_GETITEMHEIGHT = 340 +CB_SETEXTENDEDUI = 341 +CB_GETEXTENDEDUI = 342 +CB_GETDROPPEDSTATE = 343 +CB_FINDSTRINGEXACT = 344 +CB_SETLOCALE = 345 +CB_GETLOCALE = 346 +CB_GETTOPINDEX = 347 +CB_SETTOPINDEX = 348 +CB_GETHORIZONTALEXTENT = 349 +CB_SETHORIZONTALEXTENT = 350 +CB_GETDROPPEDWIDTH = 351 +CB_SETDROPPEDWIDTH = 352 +CB_INITSTORAGE = 353 +CB_MSGMAX = 354 +SBS_HORZ = 0 +SBS_VERT = 1 +SBS_TOPALIGN = 2 +SBS_LEFTALIGN = 2 +SBS_BOTTOMALIGN = 4 +SBS_RIGHTALIGN = 4 +SBS_SIZEBOXTOPLEFTALIGN = 2 +SBS_SIZEBOXBOTTOMRIGHTALIGN = 4 +SBS_SIZEBOX = 8 +SBS_SIZEGRIP = 16 +SBM_SETPOS = 224 +SBM_GETPOS = 225 +SBM_SETRANGE = 226 +SBM_SETRANGEREDRAW = 230 +SBM_GETRANGE = 227 +SBM_ENABLE_ARROWS = 228 +SBM_SETSCROLLINFO = 233 +SBM_GETSCROLLINFO = 234 +SIF_RANGE = 1 +SIF_PAGE = 2 +SIF_POS = 4 +SIF_DISABLENOSCROLL = 8 +SIF_TRACKPOS = 16 +SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS) +MDIS_ALLCHILDSTYLES = 1 +MDITILE_VERTICAL = 0 +MDITILE_HORIZONTAL = 1 +MDITILE_SKIPDISABLED = 2 + +IMC_GETCANDIDATEPOS = 7 +IMC_SETCANDIDATEPOS = 8 +IMC_GETCOMPOSITIONFONT = 9 +IMC_SETCOMPOSITIONFONT = 10 +IMC_GETCOMPOSITIONWINDOW = 11 +IMC_SETCOMPOSITIONWINDOW = 12 +IMC_GETSTATUSWINDOWPOS = 15 +IMC_SETSTATUSWINDOWPOS = 16 +IMC_CLOSESTATUSWINDOW = 33 +IMC_OPENSTATUSWINDOW = 34 +# Generated by h2py from \msvc20\include\winnt.h +# hacked and split by mhammond. +DELETE = (65536) +READ_CONTROL = (131072) +WRITE_DAC = (262144) +WRITE_OWNER = (524288) +SYNCHRONIZE = (1048576) +STANDARD_RIGHTS_REQUIRED = (983040) +STANDARD_RIGHTS_READ = (READ_CONTROL) +STANDARD_RIGHTS_WRITE = (READ_CONTROL) +STANDARD_RIGHTS_EXECUTE = (READ_CONTROL) +STANDARD_RIGHTS_ALL = (2031616) +SPECIFIC_RIGHTS_ALL = (65535) +ACCESS_SYSTEM_SECURITY = (16777216) +MAXIMUM_ALLOWED = (33554432) +GENERIC_READ = (-2147483648) +GENERIC_WRITE = (1073741824) +GENERIC_EXECUTE = (536870912) +GENERIC_ALL = (268435456) + +SERVICE_KERNEL_DRIVER = 1 +SERVICE_FILE_SYSTEM_DRIVER = 2 +SERVICE_ADAPTER = 4 +SERVICE_RECOGNIZER_DRIVER = 8 +SERVICE_DRIVER = (SERVICE_KERNEL_DRIVER | \ + SERVICE_FILE_SYSTEM_DRIVER | \ + SERVICE_RECOGNIZER_DRIVER) +SERVICE_WIN32_OWN_PROCESS = 16 +SERVICE_WIN32_SHARE_PROCESS = 32 +SERVICE_WIN32 = (SERVICE_WIN32_OWN_PROCESS | \ + SERVICE_WIN32_SHARE_PROCESS) +SERVICE_INTERACTIVE_PROCESS = 256 +SERVICE_TYPE_ALL = (SERVICE_WIN32 | \ + SERVICE_ADAPTER | \ + SERVICE_DRIVER | \ + SERVICE_INTERACTIVE_PROCESS) +SERVICE_BOOT_START = 0 +SERVICE_SYSTEM_START = 1 +SERVICE_AUTO_START = 2 +SERVICE_DEMAND_START = 3 +SERVICE_DISABLED = 4 +SERVICE_ERROR_IGNORE = 0 +SERVICE_ERROR_NORMAL = 1 +SERVICE_ERROR_SEVERE = 2 +SERVICE_ERROR_CRITICAL = 3 +TAPE_ERASE_SHORT = 0 +TAPE_ERASE_LONG = 1 +TAPE_LOAD = 0 +TAPE_UNLOAD = 1 +TAPE_TENSION = 2 +TAPE_LOCK = 3 +TAPE_UNLOCK = 4 +TAPE_FORMAT = 5 +TAPE_SETMARKS = 0 +TAPE_FILEMARKS = 1 +TAPE_SHORT_FILEMARKS = 2 +TAPE_LONG_FILEMARKS = 3 +TAPE_ABSOLUTE_POSITION = 0 +TAPE_LOGICAL_POSITION = 1 +TAPE_PSEUDO_LOGICAL_POSITION = 2 +TAPE_REWIND = 0 +TAPE_ABSOLUTE_BLOCK = 1 +TAPE_LOGICAL_BLOCK = 2 +TAPE_PSEUDO_LOGICAL_BLOCK = 3 +TAPE_SPACE_END_OF_DATA = 4 +TAPE_SPACE_RELATIVE_BLOCKS = 5 +TAPE_SPACE_FILEMARKS = 6 +TAPE_SPACE_SEQUENTIAL_FMKS = 7 +TAPE_SPACE_SETMARKS = 8 +TAPE_SPACE_SEQUENTIAL_SMKS = 9 +TAPE_DRIVE_FIXED = 1 +TAPE_DRIVE_SELECT = 2 +TAPE_DRIVE_INITIATOR = 4 +TAPE_DRIVE_ERASE_SHORT = 16 +TAPE_DRIVE_ERASE_LONG = 32 +TAPE_DRIVE_ERASE_BOP_ONLY = 64 +TAPE_DRIVE_ERASE_IMMEDIATE = 128 +TAPE_DRIVE_TAPE_CAPACITY = 256 +TAPE_DRIVE_TAPE_REMAINING = 512 +TAPE_DRIVE_FIXED_BLOCK = 1024 +TAPE_DRIVE_VARIABLE_BLOCK = 2048 +TAPE_DRIVE_WRITE_PROTECT = 4096 +TAPE_DRIVE_EOT_WZ_SIZE = 8192 +TAPE_DRIVE_ECC = 65536 +TAPE_DRIVE_COMPRESSION = 131072 +TAPE_DRIVE_PADDING = 262144 +TAPE_DRIVE_REPORT_SMKS = 524288 +TAPE_DRIVE_GET_ABSOLUTE_BLK = 1048576 +TAPE_DRIVE_GET_LOGICAL_BLK = 2097152 +TAPE_DRIVE_SET_EOT_WZ_SIZE = 4194304 +TAPE_DRIVE_LOAD_UNLOAD = -2147483647 +TAPE_DRIVE_TENSION = -2147483646 +TAPE_DRIVE_LOCK_UNLOCK = -2147483644 +TAPE_DRIVE_REWIND_IMMEDIATE = -2147483640 +TAPE_DRIVE_SET_BLOCK_SIZE = -2147483632 +TAPE_DRIVE_LOAD_UNLD_IMMED = -2147483616 +TAPE_DRIVE_TENSION_IMMED = -2147483584 +TAPE_DRIVE_LOCK_UNLK_IMMED = -2147483520 +TAPE_DRIVE_SET_ECC = -2147483392 +TAPE_DRIVE_SET_COMPRESSION = -2147483136 +TAPE_DRIVE_SET_PADDING = -2147482624 +TAPE_DRIVE_SET_REPORT_SMKS = -2147481600 +TAPE_DRIVE_ABSOLUTE_BLK = -2147479552 +TAPE_DRIVE_ABS_BLK_IMMED = -2147475456 +TAPE_DRIVE_LOGICAL_BLK = -2147467264 +TAPE_DRIVE_LOG_BLK_IMMED = -2147450880 +TAPE_DRIVE_END_OF_DATA = -2147418112 +TAPE_DRIVE_RELATIVE_BLKS = -2147352576 +TAPE_DRIVE_FILEMARKS = -2147221504 +TAPE_DRIVE_SEQUENTIAL_FMKS = -2146959360 +TAPE_DRIVE_SETMARKS = -2146435072 +TAPE_DRIVE_SEQUENTIAL_SMKS = -2145386496 +TAPE_DRIVE_REVERSE_POSITION = -2143289344 +TAPE_DRIVE_SPACE_IMMEDIATE = -2139095040 +TAPE_DRIVE_WRITE_SETMARKS = -2130706432 +TAPE_DRIVE_WRITE_FILEMARKS = -2113929216 +TAPE_DRIVE_WRITE_SHORT_FMKS = -2080374784 +TAPE_DRIVE_WRITE_LONG_FMKS = -2013265920 +TAPE_DRIVE_WRITE_MARK_IMMED = -1879048192 +TAPE_DRIVE_FORMAT = -1610612736 +TAPE_DRIVE_FORMAT_IMMEDIATE = -1073741824 +TAPE_FIXED_PARTITIONS = 0 +TAPE_SELECT_PARTITIONS = 1 +TAPE_INITIATOR_PARTITIONS = 2 +# Generated by h2py from \msvc20\include\winnt.h +# hacked and split by mhammond. + +APPLICATION_ERROR_MASK = 536870912 +ERROR_SEVERITY_SUCCESS = 0 +ERROR_SEVERITY_INFORMATIONAL = 1073741824 +ERROR_SEVERITY_WARNING = -2147483648 +ERROR_SEVERITY_ERROR = -1073741824 +MINCHAR = 128 +MAXCHAR = 127 +MINSHORT = 32768 +MAXSHORT = 32767 +MINLONG = -2147483648 +MAXLONG = 2147483647 +MAXBYTE = 255 +MAXWORD = 65535 +MAXDWORD = -1 +LANG_NEUTRAL = 0 +LANG_BULGARIAN = 2 +LANG_CHINESE = 4 +LANG_CROATIAN = 26 +LANG_CZECH = 5 +LANG_DANISH = 6 +LANG_DUTCH = 19 +LANG_ENGLISH = 9 +LANG_FINNISH = 11 +LANG_FRENCH = 12 +LANG_GERMAN = 7 +LANG_GREEK = 8 +LANG_HUNGARIAN = 14 +LANG_ICELANDIC = 15 +LANG_ITALIAN = 16 +LANG_JAPANESE = 17 +LANG_KOREAN = 18 +LANG_NORWEGIAN = 20 +LANG_POLISH = 21 +LANG_PORTUGUESE = 22 +LANG_ROMANIAN = 24 +LANG_RUSSIAN = 25 +LANG_SLOVAK = 27 +LANG_SLOVENIAN = 36 +LANG_SPANISH = 10 +LANG_SWEDISH = 29 +LANG_TURKISH = 31 +SUBLANG_NEUTRAL = 0 +SUBLANG_DEFAULT = 1 +SUBLANG_SYS_DEFAULT = 2 +SUBLANG_CHINESE_TRADITIONAL = 1 +SUBLANG_CHINESE_SIMPLIFIED = 2 +SUBLANG_CHINESE_HONGKONG = 3 +SUBLANG_CHINESE_SINGAPORE = 4 +SUBLANG_DUTCH = 1 +SUBLANG_DUTCH_BELGIAN = 2 +SUBLANG_ENGLISH_US = 1 +SUBLANG_ENGLISH_UK = 2 +SUBLANG_ENGLISH_AUS = 3 +SUBLANG_ENGLISH_CAN = 4 +SUBLANG_ENGLISH_NZ = 5 +SUBLANG_ENGLISH_EIRE = 6 +SUBLANG_FRENCH = 1 +SUBLANG_FRENCH_BELGIAN = 2 +SUBLANG_FRENCH_CANADIAN = 3 +SUBLANG_FRENCH_SWISS = 4 +SUBLANG_GERMAN = 1 +SUBLANG_GERMAN_SWISS = 2 +SUBLANG_GERMAN_AUSTRIAN = 3 +SUBLANG_ITALIAN = 1 +SUBLANG_ITALIAN_SWISS = 2 +SUBLANG_NORWEGIAN_BOKMAL = 1 +SUBLANG_NORWEGIAN_NYNORSK = 2 +SUBLANG_PORTUGUESE = 2 +SUBLANG_PORTUGUESE_BRAZILIAN = 1 +SUBLANG_SPANISH = 1 +SUBLANG_SPANISH_MEXICAN = 2 +SUBLANG_SPANISH_MODERN = 3 +SORT_DEFAULT = 0 +SORT_JAPANESE_XJIS = 0 +SORT_JAPANESE_UNICODE = 1 +SORT_CHINESE_BIG5 = 0 +SORT_CHINESE_UNICODE = 1 +SORT_KOREAN_KSC = 0 +SORT_KOREAN_UNICODE = 1 +def PRIMARYLANGID(lgid): return ((lgid) & 1023) + +def SUBLANGID(lgid): return ((lgid) >> 10) + +NLS_VALID_LOCALE_MASK = 1048575 +CONTEXT_PORTABLE_32BIT = 1048576 +CONTEXT_ALPHA = 131072 +CONTEXT_CONTROL = (CONTEXT_ALPHA | 1) +CONTEXT_FLOATING_POINT = (CONTEXT_ALPHA | 2) +CONTEXT_INTEGER = (CONTEXT_ALPHA | 4) +CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_FLOATING_POINT | CONTEXT_INTEGER) +SIZE_OF_80387_REGISTERS = 80 +CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_FLOATING_POINT | CONTEXT_INTEGER) +CONTEXT_CONTROL = 1 +CONTEXT_FLOATING_POINT = 2 +CONTEXT_INTEGER = 4 +CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_FLOATING_POINT | CONTEXT_INTEGER) +PROCESS_TERMINATE = (1) +PROCESS_CREATE_THREAD = (2) +PROCESS_VM_OPERATION = (8) +PROCESS_VM_READ = (16) +PROCESS_VM_WRITE = (32) +PROCESS_DUP_HANDLE = (64) +PROCESS_CREATE_PROCESS = (128) +PROCESS_SET_QUOTA = (256) +PROCESS_SET_INFORMATION = (512) +PROCESS_QUERY_INFORMATION = (1024) +PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 4095) +THREAD_TERMINATE = (1) +THREAD_SUSPEND_RESUME = (2) +THREAD_GET_CONTEXT = (8) +THREAD_SET_CONTEXT = (16) +THREAD_SET_INFORMATION = (32) +THREAD_QUERY_INFORMATION = (64) +THREAD_SET_THREAD_TOKEN = (128) +THREAD_IMPERSONATE = (256) +THREAD_DIRECT_IMPERSONATION = (512) +TLS_MINIMUM_AVAILABLE = 64 +EVENT_MODIFY_STATE = 2 +MUTANT_QUERY_STATE = 1 +SEMAPHORE_MODIFY_STATE = 2 +TIME_ZONE_ID_UNKNOWN = 0 +TIME_ZONE_ID_STANDARD = 1 +TIME_ZONE_ID_DAYLIGHT = 2 +PROCESSOR_INTEL_386 = 386 +PROCESSOR_INTEL_486 = 486 +PROCESSOR_INTEL_PENTIUM = 586 +PROCESSOR_INTEL_860 = 860 +PROCESSOR_MIPS_R2000 = 2000 +PROCESSOR_MIPS_R3000 = 3000 +PROCESSOR_MIPS_R4000 = 4000 +PROCESSOR_ALPHA_21064 = 21064 +PROCESSOR_PPC_601 = 601 +PROCESSOR_PPC_603 = 603 +PROCESSOR_PPC_604 = 604 +PROCESSOR_PPC_620 = 620 +SECTION_QUERY = 1 +SECTION_MAP_WRITE = 2 +SECTION_MAP_READ = 4 +SECTION_MAP_EXECUTE = 8 +SECTION_EXTEND_SIZE = 16 +PAGE_NOACCESS = 1 +PAGE_READONLY = 2 +PAGE_READWRITE = 4 +PAGE_WRITECOPY = 8 +PAGE_EXECUTE = 16 +PAGE_EXECUTE_READ = 32 +PAGE_EXECUTE_READWRITE = 64 +PAGE_EXECUTE_WRITECOPY = 128 +PAGE_GUARD = 256 +PAGE_NOCACHE = 512 +MEM_COMMIT = 4096 +MEM_RESERVE = 8192 +MEM_DECOMMIT = 16384 +MEM_RELEASE = 32768 +MEM_FREE = 65536 +MEM_PRIVATE = 131072 +MEM_MAPPED = 262144 +MEM_TOP_DOWN = 1048576 + +# Generated by h2py from \msvc20\include\winnt.h +# hacked and split by mhammond. +SEC_FILE = 8388608 +SEC_IMAGE = 16777216 +SEC_RESERVE = 67108864 +SEC_COMMIT = 134217728 +SEC_NOCACHE = 268435456 +MEM_IMAGE = SEC_IMAGE +FILE_SHARE_READ = 1 +FILE_SHARE_WRITE = 2 +FILE_SHARE_DELETE = 4 +FILE_ATTRIBUTE_READONLY = 1 +FILE_ATTRIBUTE_HIDDEN = 2 +FILE_ATTRIBUTE_SYSTEM = 4 +FILE_ATTRIBUTE_DIRECTORY = 16 +FILE_ATTRIBUTE_ARCHIVE = 32 +FILE_ATTRIBUTE_DEVICE = 64 +FILE_ATTRIBUTE_NORMAL = 128 +FILE_ATTRIBUTE_TEMPORARY = 256 +FILE_ATTRIBUTE_SPARSE_FILE = 512 +FILE_ATTRIBUTE_REPARSE_POINT = 1024 +FILE_ATTRIBUTE_COMPRESSED = 2048 +FILE_ATTRIBUTE_OFFLINE = 4096 +FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 8192 +FILE_ATTRIBUTE_ENCRYPTED = 16384 +FILE_ATTRIBUTE_VIRTUAL = 65536 +# These FILE_ATTRIBUTE_* flags are apparently old definitions from Windows 95 +# and conflict with current values above - but they live on for b/w compat... +FILE_ATTRIBUTE_ATOMIC_WRITE = 512 +FILE_ATTRIBUTE_XACTION_WRITE = 1024 + +FILE_NOTIFY_CHANGE_FILE_NAME = 1 +FILE_NOTIFY_CHANGE_DIR_NAME = 2 +FILE_NOTIFY_CHANGE_ATTRIBUTES = 4 +FILE_NOTIFY_CHANGE_SIZE = 8 +FILE_NOTIFY_CHANGE_LAST_WRITE = 16 +FILE_NOTIFY_CHANGE_SECURITY = 256 +FILE_CASE_SENSITIVE_SEARCH = 1 +FILE_CASE_PRESERVED_NAMES = 2 +FILE_UNICODE_ON_DISK = 4 +FILE_PERSISTENT_ACLS = 8 +FILE_FILE_COMPRESSION = 16 +FILE_VOLUME_IS_COMPRESSED = 32768 +IO_COMPLETION_MODIFY_STATE = 2 +DUPLICATE_CLOSE_SOURCE = 1 +DUPLICATE_SAME_ACCESS = 2 +SID_MAX_SUB_AUTHORITIES = (15) +SECURITY_NULL_RID = (0) +SECURITY_WORLD_RID = (0) +SECURITY_LOCAL_RID = (0X00000000) +SECURITY_CREATOR_OWNER_RID = (0) +SECURITY_CREATOR_GROUP_RID = (1) +SECURITY_DIALUP_RID = (1) +SECURITY_NETWORK_RID = (2) +SECURITY_BATCH_RID = (3) +SECURITY_INTERACTIVE_RID = (4) +SECURITY_SERVICE_RID = (6) +SECURITY_ANONYMOUS_LOGON_RID = (7) +SECURITY_LOGON_IDS_RID = (5) +SECURITY_LOGON_IDS_RID_COUNT = (3) +SECURITY_LOCAL_SYSTEM_RID = (18) +SECURITY_NT_NON_UNIQUE = (21) +SECURITY_BUILTIN_DOMAIN_RID = (32) +DOMAIN_USER_RID_ADMIN = (500) +DOMAIN_USER_RID_GUEST = (501) +DOMAIN_GROUP_RID_ADMINS = (512) +DOMAIN_GROUP_RID_USERS = (513) +DOMAIN_GROUP_RID_GUESTS = (514) +DOMAIN_ALIAS_RID_ADMINS = (544) +DOMAIN_ALIAS_RID_USERS = (545) +DOMAIN_ALIAS_RID_GUESTS = (546) +DOMAIN_ALIAS_RID_POWER_USERS = (547) +DOMAIN_ALIAS_RID_ACCOUNT_OPS = (548) +DOMAIN_ALIAS_RID_SYSTEM_OPS = (549) +DOMAIN_ALIAS_RID_PRINT_OPS = (550) +DOMAIN_ALIAS_RID_BACKUP_OPS = (551) +DOMAIN_ALIAS_RID_REPLICATOR = (552) +SE_GROUP_MANDATORY = (1) +SE_GROUP_ENABLED_BY_DEFAULT = (2) +SE_GROUP_ENABLED = (4) +SE_GROUP_OWNER = (8) +SE_GROUP_LOGON_ID = (-1073741824) +ACL_REVISION = (2) +ACL_REVISION1 = (1) +ACL_REVISION2 = (2) +ACCESS_ALLOWED_ACE_TYPE = (0) +ACCESS_DENIED_ACE_TYPE = (1) +SYSTEM_AUDIT_ACE_TYPE = (2) +SYSTEM_ALARM_ACE_TYPE = (3) +OBJECT_INHERIT_ACE = (1) +CONTAINER_INHERIT_ACE = (2) +NO_PROPAGATE_INHERIT_ACE = (4) +INHERIT_ONLY_ACE = (8) +VALID_INHERIT_FLAGS = (15) +SUCCESSFUL_ACCESS_ACE_FLAG = (64) +FAILED_ACCESS_ACE_FLAG = (128) +SECURITY_DESCRIPTOR_REVISION = (1) +SECURITY_DESCRIPTOR_REVISION1 = (1) +SECURITY_DESCRIPTOR_MIN_LENGTH = (20) +SE_OWNER_DEFAULTED = (1) +SE_GROUP_DEFAULTED = (2) +SE_DACL_PRESENT = (4) +SE_DACL_DEFAULTED = (8) +SE_SACL_PRESENT = (16) +SE_SACL_DEFAULTED = (32) +SE_SELF_RELATIVE = (32768) +SE_PRIVILEGE_ENABLED_BY_DEFAULT = (1) +SE_PRIVILEGE_ENABLED = (2) +SE_PRIVILEGE_USED_FOR_ACCESS = (-2147483648) +PRIVILEGE_SET_ALL_NECESSARY = (1) +SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege" +SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege" +SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege" +SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege" +SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege" +SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege" +SE_TCB_NAME = "SeTcbPrivilege" +SE_SECURITY_NAME = "SeSecurityPrivilege" +SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege" +SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege" +SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege" +SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege" +SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege" +SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege" +SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege" +SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege" +SE_BACKUP_NAME = "SeBackupPrivilege" +SE_RESTORE_NAME = "SeRestorePrivilege" +SE_SHUTDOWN_NAME = "SeShutdownPrivilege" +SE_DEBUG_NAME = "SeDebugPrivilege" +SE_AUDIT_NAME = "SeAuditPrivilege" +SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege" +SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege" +SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege" + +TOKEN_ASSIGN_PRIMARY = (1) +TOKEN_DUPLICATE = (2) +TOKEN_IMPERSONATE = (4) +TOKEN_QUERY = (8) +TOKEN_QUERY_SOURCE = (16) +TOKEN_ADJUST_PRIVILEGES = (32) +TOKEN_ADJUST_GROUPS = (64) +TOKEN_ADJUST_DEFAULT = (128) +TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |\ + TOKEN_ASSIGN_PRIMARY |\ + TOKEN_DUPLICATE |\ + TOKEN_IMPERSONATE |\ + TOKEN_QUERY |\ + TOKEN_QUERY_SOURCE |\ + TOKEN_ADJUST_PRIVILEGES |\ + TOKEN_ADJUST_GROUPS |\ + TOKEN_ADJUST_DEFAULT) +TOKEN_READ = (STANDARD_RIGHTS_READ |\ + TOKEN_QUERY) +TOKEN_WRITE = (STANDARD_RIGHTS_WRITE |\ + TOKEN_ADJUST_PRIVILEGES |\ + TOKEN_ADJUST_GROUPS |\ + TOKEN_ADJUST_DEFAULT) +TOKEN_EXECUTE = (STANDARD_RIGHTS_EXECUTE) +TOKEN_SOURCE_LENGTH = 8 + +KEY_QUERY_VALUE = (1) +KEY_SET_VALUE = (2) +KEY_CREATE_SUB_KEY = (4) +KEY_ENUMERATE_SUB_KEYS = (8) +KEY_NOTIFY = (16) +KEY_CREATE_LINK = (32) +KEY_WOW64_32KEY = 512 +KEY_WOW64_64KEY = 256 +KEY_WOW64_RES = 768 +KEY_READ = ((STANDARD_RIGHTS_READ |\ + KEY_QUERY_VALUE |\ + KEY_ENUMERATE_SUB_KEYS |\ + KEY_NOTIFY) \ + & \ + (~SYNCHRONIZE)) +KEY_WRITE = ((STANDARD_RIGHTS_WRITE |\ + KEY_SET_VALUE |\ + KEY_CREATE_SUB_KEY) \ + & \ + (~SYNCHRONIZE)) +KEY_EXECUTE = ((KEY_READ) \ + & \ + (~SYNCHRONIZE)) +KEY_ALL_ACCESS = ((STANDARD_RIGHTS_ALL |\ + KEY_QUERY_VALUE |\ + KEY_SET_VALUE |\ + KEY_CREATE_SUB_KEY |\ + KEY_ENUMERATE_SUB_KEYS |\ + KEY_NOTIFY |\ + KEY_CREATE_LINK) \ + & \ + (~SYNCHRONIZE)) +REG_NOTIFY_CHANGE_ATTRIBUTES = (2) +REG_NOTIFY_CHANGE_SECURITY = (8) +REG_RESOURCE_REQUIREMENTS_LIST = ( 10 ) +REG_NONE = ( 0 ) # No value type +REG_SZ = ( 1 ) # Unicode nul terminated string +REG_EXPAND_SZ = ( 2 ) # Unicode nul terminated string + # (with environment variable references) +REG_BINARY = ( 3 ) # Free form binary +REG_DWORD = ( 4 ) # 32-bit number +REG_DWORD_LITTLE_ENDIAN = ( 4 ) # 32-bit number (same as REG_DWORD) +REG_DWORD_BIG_ENDIAN = ( 5 ) # 32-bit number +REG_LINK = ( 6 ) # Symbolic Link (unicode) +REG_MULTI_SZ = ( 7 ) # Multiple Unicode strings +REG_RESOURCE_LIST = ( 8 ) # Resource list in the resource map +REG_FULL_RESOURCE_DESCRIPTOR =( 9 ) # Resource list in the hardware description +REG_RESOURCE_REQUIREMENTS_LIST = ( 10 ) +REG_QWORD = ( 11 ) # 64-bit number +REG_QWORD_LITTLE_ENDIAN = ( 11 ) # 64-bit number (same as REG_QWORD) + + +# Generated by h2py from \msvc20\include\winnt.h +# hacked and split by mhammond. +# Included from string.h +_NLSCMPERROR = 2147483647 +NULL = 0 +HEAP_NO_SERIALIZE = 1 +HEAP_GROWABLE = 2 +HEAP_GENERATE_EXCEPTIONS = 4 +HEAP_ZERO_MEMORY = 8 +HEAP_REALLOC_IN_PLACE_ONLY = 16 +HEAP_TAIL_CHECKING_ENABLED = 32 +HEAP_FREE_CHECKING_ENABLED = 64 +HEAP_DISABLE_COALESCE_ON_FREE = 128 +IS_TEXT_UNICODE_ASCII16 = 1 +IS_TEXT_UNICODE_REVERSE_ASCII16 = 16 +IS_TEXT_UNICODE_STATISTICS = 2 +IS_TEXT_UNICODE_REVERSE_STATISTICS = 32 +IS_TEXT_UNICODE_CONTROLS = 4 +IS_TEXT_UNICODE_REVERSE_CONTROLS = 64 +IS_TEXT_UNICODE_SIGNATURE = 8 +IS_TEXT_UNICODE_REVERSE_SIGNATURE = 128 +IS_TEXT_UNICODE_ILLEGAL_CHARS = 256 +IS_TEXT_UNICODE_ODD_LENGTH = 512 +IS_TEXT_UNICODE_DBCS_LEADBYTE = 1024 +IS_TEXT_UNICODE_NULL_BYTES = 4096 +IS_TEXT_UNICODE_UNICODE_MASK = 15 +IS_TEXT_UNICODE_REVERSE_MASK = 240 +IS_TEXT_UNICODE_NOT_UNICODE_MASK = 3840 +IS_TEXT_UNICODE_NOT_ASCII_MASK = 61440 +COMPRESSION_FORMAT_NONE = (0) +COMPRESSION_FORMAT_DEFAULT = (1) +COMPRESSION_FORMAT_LZNT1 = (2) +COMPRESSION_ENGINE_STANDARD = (0) +COMPRESSION_ENGINE_MAXIMUM = (256) +MESSAGE_RESOURCE_UNICODE = 1 +RTL_CRITSECT_TYPE = 0 +RTL_RESOURCE_TYPE = 1 +DLL_PROCESS_ATTACH = 1 +DLL_THREAD_ATTACH = 2 +DLL_THREAD_DETACH = 3 +DLL_PROCESS_DETACH = 0 +EVENTLOG_SEQUENTIAL_READ = 0X0001 +EVENTLOG_SEEK_READ = 0X0002 +EVENTLOG_FORWARDS_READ = 0X0004 +EVENTLOG_BACKWARDS_READ = 0X0008 +EVENTLOG_SUCCESS = 0X0000 +EVENTLOG_ERROR_TYPE = 1 +EVENTLOG_WARNING_TYPE = 2 +EVENTLOG_INFORMATION_TYPE = 4 +EVENTLOG_AUDIT_SUCCESS = 8 +EVENTLOG_AUDIT_FAILURE = 16 +EVENTLOG_START_PAIRED_EVENT = 1 +EVENTLOG_END_PAIRED_EVENT = 2 +EVENTLOG_END_ALL_PAIRED_EVENTS = 4 +EVENTLOG_PAIRED_EVENT_ACTIVE = 8 +EVENTLOG_PAIRED_EVENT_INACTIVE = 16 +# Generated by h2py from \msvc20\include\winnt.h +# hacked and split by mhammond. +OWNER_SECURITY_INFORMATION = (0X00000001) +GROUP_SECURITY_INFORMATION = (0X00000002) +DACL_SECURITY_INFORMATION = (0X00000004) +SACL_SECURITY_INFORMATION = (0X00000008) +IMAGE_SIZEOF_FILE_HEADER = 20 +IMAGE_FILE_MACHINE_UNKNOWN = 0 +IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16 +IMAGE_SIZEOF_ROM_OPTIONAL_HEADER = 56 +IMAGE_SIZEOF_STD_OPTIONAL_HEADER = 28 +IMAGE_SIZEOF_NT_OPTIONAL_HEADER = 224 +IMAGE_NT_OPTIONAL_HDR_MAGIC = 267 +IMAGE_ROM_OPTIONAL_HDR_MAGIC = 263 +IMAGE_SIZEOF_SHORT_NAME = 8 +IMAGE_SIZEOF_SECTION_HEADER = 40 +IMAGE_SIZEOF_SYMBOL = 18 +IMAGE_SYM_CLASS_NULL = 0 +IMAGE_SYM_CLASS_AUTOMATIC = 1 +IMAGE_SYM_CLASS_EXTERNAL = 2 +IMAGE_SYM_CLASS_STATIC = 3 +IMAGE_SYM_CLASS_REGISTER = 4 +IMAGE_SYM_CLASS_EXTERNAL_DEF = 5 +IMAGE_SYM_CLASS_LABEL = 6 +IMAGE_SYM_CLASS_UNDEFINED_LABEL = 7 +IMAGE_SYM_CLASS_MEMBER_OF_STRUCT = 8 +IMAGE_SYM_CLASS_ARGUMENT = 9 +IMAGE_SYM_CLASS_STRUCT_TAG = 10 +IMAGE_SYM_CLASS_MEMBER_OF_UNION = 11 +IMAGE_SYM_CLASS_UNION_TAG = 12 +IMAGE_SYM_CLASS_TYPE_DEFINITION = 13 +IMAGE_SYM_CLASS_UNDEFINED_STATIC = 14 +IMAGE_SYM_CLASS_ENUM_TAG = 15 +IMAGE_SYM_CLASS_MEMBER_OF_ENUM = 16 +IMAGE_SYM_CLASS_REGISTER_PARAM = 17 +IMAGE_SYM_CLASS_BIT_FIELD = 18 +IMAGE_SYM_CLASS_BLOCK = 100 +IMAGE_SYM_CLASS_FUNCTION = 101 +IMAGE_SYM_CLASS_END_OF_STRUCT = 102 +IMAGE_SYM_CLASS_FILE = 103 +IMAGE_SYM_CLASS_SECTION = 104 +IMAGE_SYM_CLASS_WEAK_EXTERNAL = 105 +N_BTMASK = 15 +N_TMASK = 48 +N_TMASK1 = 192 +N_TMASK2 = 240 +N_BTSHFT = 4 +N_TSHIFT = 2 +IMAGE_SIZEOF_AUX_SYMBOL = 18 +IMAGE_COMDAT_SELECT_NODUPLICATES = 1 +IMAGE_COMDAT_SELECT_ANY = 2 +IMAGE_COMDAT_SELECT_SAME_SIZE = 3 +IMAGE_COMDAT_SELECT_EXACT_MATCH = 4 +IMAGE_COMDAT_SELECT_ASSOCIATIVE = 5 +IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY = 1 +IMAGE_WEAK_EXTERN_SEARCH_LIBRARY = 2 +IMAGE_WEAK_EXTERN_SEARCH_ALIAS = 3 +IMAGE_SIZEOF_RELOCATION = 10 +IMAGE_REL_I386_SECTION = 10 +IMAGE_REL_I386_SECREL = 11 +IMAGE_REL_MIPS_REFHALF = 1 +IMAGE_REL_MIPS_REFWORD = 2 +IMAGE_REL_MIPS_JMPADDR = 3 +IMAGE_REL_MIPS_REFHI = 4 +IMAGE_REL_MIPS_REFLO = 5 +IMAGE_REL_MIPS_GPREL = 6 +IMAGE_REL_MIPS_LITERAL = 7 +IMAGE_REL_MIPS_SECTION = 10 +IMAGE_REL_MIPS_SECREL = 11 +IMAGE_REL_MIPS_REFWORDNB = 34 +IMAGE_REL_MIPS_PAIR = 37 +IMAGE_REL_ALPHA_ABSOLUTE = 0 +IMAGE_REL_ALPHA_REFLONG = 1 +IMAGE_REL_ALPHA_REFQUAD = 2 +IMAGE_REL_ALPHA_GPREL32 = 3 +IMAGE_REL_ALPHA_LITERAL = 4 +IMAGE_REL_ALPHA_LITUSE = 5 +IMAGE_REL_ALPHA_GPDISP = 6 +IMAGE_REL_ALPHA_BRADDR = 7 +IMAGE_REL_ALPHA_HINT = 8 +IMAGE_REL_ALPHA_INLINE_REFLONG = 9 +IMAGE_REL_ALPHA_REFHI = 10 +IMAGE_REL_ALPHA_REFLO = 11 +IMAGE_REL_ALPHA_PAIR = 12 +IMAGE_REL_ALPHA_MATCH = 13 +IMAGE_REL_ALPHA_SECTION = 14 +IMAGE_REL_ALPHA_SECREL = 15 +IMAGE_REL_ALPHA_REFLONGNB = 16 +IMAGE_SIZEOF_BASE_RELOCATION = 8 +IMAGE_REL_BASED_ABSOLUTE = 0 +IMAGE_REL_BASED_HIGH = 1 +IMAGE_REL_BASED_LOW = 2 +IMAGE_REL_BASED_HIGHLOW = 3 +IMAGE_REL_BASED_HIGHADJ = 4 +IMAGE_REL_BASED_MIPS_JMPADDR = 5 +IMAGE_SIZEOF_LINENUMBER = 6 +IMAGE_ARCHIVE_START_SIZE = 8 +IMAGE_ARCHIVE_START = "!\n" +IMAGE_ARCHIVE_END = "`\n" +IMAGE_ARCHIVE_PAD = "\n" +IMAGE_ARCHIVE_LINKER_MEMBER = "/ " +IMAGE_ARCHIVE_LONGNAMES_MEMBER = "// " +IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR = 60 +IMAGE_ORDINAL_FLAG = -2147483648 +def IMAGE_SNAP_BY_ORDINAL(Ordinal): return ((Ordinal & IMAGE_ORDINAL_FLAG) != 0) + +def IMAGE_ORDINAL(Ordinal): return (Ordinal & 65535) + +IMAGE_RESOURCE_NAME_IS_STRING = -2147483648 +IMAGE_RESOURCE_DATA_IS_DIRECTORY = -2147483648 +IMAGE_DEBUG_TYPE_UNKNOWN = 0 +IMAGE_DEBUG_TYPE_COFF = 1 +IMAGE_DEBUG_TYPE_CODEVIEW = 2 +IMAGE_DEBUG_TYPE_FPO = 3 +IMAGE_DEBUG_TYPE_MISC = 4 +IMAGE_DEBUG_TYPE_EXCEPTION = 5 +IMAGE_DEBUG_TYPE_FIXUP = 6 +IMAGE_DEBUG_TYPE_OMAP_TO_SRC = 7 +IMAGE_DEBUG_TYPE_OMAP_FROM_SRC = 8 +FRAME_FPO = 0 +FRAME_TRAP = 1 +FRAME_TSS = 2 +SIZEOF_RFPO_DATA = 16 +IMAGE_DEBUG_MISC_EXENAME = 1 +IMAGE_SEPARATE_DEBUG_SIGNATURE = 18756 +# Generated by h2py from \msvcnt\include\wingdi.h +# hacked and split manually by mhammond. +NEWFRAME = 1 +ABORTDOC = 2 +NEXTBAND = 3 +SETCOLORTABLE = 4 +GETCOLORTABLE = 5 +FLUSHOUTPUT = 6 +DRAFTMODE = 7 +QUERYESCSUPPORT = 8 +SETABORTPROC = 9 +STARTDOC = 10 +ENDDOC = 11 +GETPHYSPAGESIZE = 12 +GETPRINTINGOFFSET = 13 +GETSCALINGFACTOR = 14 +MFCOMMENT = 15 +GETPENWIDTH = 16 +SETCOPYCOUNT = 17 +SELECTPAPERSOURCE = 18 +DEVICEDATA = 19 +PASSTHROUGH = 19 +GETTECHNOLGY = 20 +GETTECHNOLOGY = 20 +SETLINECAP = 21 +SETLINEJOIN = 22 +SETMITERLIMIT = 23 +BANDINFO = 24 +DRAWPATTERNRECT = 25 +GETVECTORPENSIZE = 26 +GETVECTORBRUSHSIZE = 27 +ENABLEDUPLEX = 28 +GETSETPAPERBINS = 29 +GETSETPRINTORIENT = 30 +ENUMPAPERBINS = 31 +SETDIBSCALING = 32 +EPSPRINTING = 33 +ENUMPAPERMETRICS = 34 +GETSETPAPERMETRICS = 35 +POSTSCRIPT_DATA = 37 +POSTSCRIPT_IGNORE = 38 +MOUSETRAILS = 39 +GETDEVICEUNITS = 42 +GETEXTENDEDTEXTMETRICS = 256 +GETEXTENTTABLE = 257 +GETPAIRKERNTABLE = 258 +GETTRACKKERNTABLE = 259 +EXTTEXTOUT = 512 +GETFACENAME = 513 +DOWNLOADFACE = 514 +ENABLERELATIVEWIDTHS = 768 +ENABLEPAIRKERNING = 769 +SETKERNTRACK = 770 +SETALLJUSTVALUES = 771 +SETCHARSET = 772 +STRETCHBLT = 2048 +GETSETSCREENPARAMS = 3072 +BEGIN_PATH = 4096 +CLIP_TO_PATH = 4097 +END_PATH = 4098 +EXT_DEVICE_CAPS = 4099 +RESTORE_CTM = 4100 +SAVE_CTM = 4101 +SET_ARC_DIRECTION = 4102 +SET_BACKGROUND_COLOR = 4103 +SET_POLY_MODE = 4104 +SET_SCREEN_ANGLE = 4105 +SET_SPREAD = 4106 +TRANSFORM_CTM = 4107 +SET_CLIP_BOX = 4108 +SET_BOUNDS = 4109 +SET_MIRROR_MODE = 4110 +OPENCHANNEL = 4110 +DOWNLOADHEADER = 4111 +CLOSECHANNEL = 4112 +POSTSCRIPT_PASSTHROUGH = 4115 +ENCAPSULATED_POSTSCRIPT = 4116 +SP_NOTREPORTED = 16384 +SP_ERROR = (-1) +SP_APPABORT = (-2) +SP_USERABORT = (-3) +SP_OUTOFDISK = (-4) +SP_OUTOFMEMORY = (-5) +PR_JOBSTATUS = 0 + +## GDI object types +OBJ_PEN = 1 +OBJ_BRUSH = 2 +OBJ_DC = 3 +OBJ_METADC = 4 +OBJ_PAL = 5 +OBJ_FONT = 6 +OBJ_BITMAP = 7 +OBJ_REGION = 8 +OBJ_METAFILE = 9 +OBJ_MEMDC = 10 +OBJ_EXTPEN = 11 +OBJ_ENHMETADC = 12 +OBJ_ENHMETAFILE = 13 +OBJ_COLORSPACE = 14 + +MWT_IDENTITY = 1 +MWT_LEFTMULTIPLY = 2 +MWT_RIGHTMULTIPLY = 3 +MWT_MIN = MWT_IDENTITY +MWT_MAX = MWT_RIGHTMULTIPLY +BI_RGB = 0 +BI_RLE8 = 1 +BI_RLE4 = 2 +BI_BITFIELDS = 3 +TMPF_FIXED_PITCH = 1 +TMPF_VECTOR = 2 +TMPF_DEVICE = 8 +TMPF_TRUETYPE = 4 +NTM_REGULAR = 64 +NTM_BOLD = 32 +NTM_ITALIC = 1 +LF_FACESIZE = 32 +LF_FULLFACESIZE = 64 +OUT_DEFAULT_PRECIS = 0 +OUT_STRING_PRECIS = 1 +OUT_CHARACTER_PRECIS = 2 +OUT_STROKE_PRECIS = 3 +OUT_TT_PRECIS = 4 +OUT_DEVICE_PRECIS = 5 +OUT_RASTER_PRECIS = 6 +OUT_TT_ONLY_PRECIS = 7 +OUT_OUTLINE_PRECIS = 8 +CLIP_DEFAULT_PRECIS = 0 +CLIP_CHARACTER_PRECIS = 1 +CLIP_STROKE_PRECIS = 2 +CLIP_MASK = 15 +CLIP_LH_ANGLES = (1<<4) +CLIP_TT_ALWAYS = (2<<4) +CLIP_EMBEDDED = (8<<4) +DEFAULT_QUALITY = 0 +DRAFT_QUALITY = 1 +PROOF_QUALITY = 2 +NONANTIALIASED_QUALITY = 3 +ANTIALIASED_QUALITY = 4 +CLEARTYPE_QUALITY = 5 +CLEARTYPE_NATURAL_QUALITY = 6 +DEFAULT_PITCH = 0 +FIXED_PITCH = 1 +VARIABLE_PITCH = 2 +ANSI_CHARSET = 0 +DEFAULT_CHARSET = 1 +SYMBOL_CHARSET = 2 +SHIFTJIS_CHARSET = 128 +HANGEUL_CHARSET = 129 +CHINESEBIG5_CHARSET = 136 +OEM_CHARSET = 255 +JOHAB_CHARSET = 130 +HEBREW_CHARSET = 177 +ARABIC_CHARSET = 178 +GREEK_CHARSET = 161 +TURKISH_CHARSET = 162 +VIETNAMESE_CHARSET = 163 +THAI_CHARSET = 222 +EASTEUROPE_CHARSET = 238 +RUSSIAN_CHARSET = 204 +MAC_CHARSET = 77 +BALTIC_CHARSET = 186 +FF_DONTCARE = (0<<4) +FF_ROMAN = (1<<4) +FF_SWISS = (2<<4) +FF_MODERN = (3<<4) +FF_SCRIPT = (4<<4) +FF_DECORATIVE = (5<<4) +FW_DONTCARE = 0 +FW_THIN = 100 +FW_EXTRALIGHT = 200 +FW_LIGHT = 300 +FW_NORMAL = 400 +FW_MEDIUM = 500 +FW_SEMIBOLD = 600 +FW_BOLD = 700 +FW_EXTRABOLD = 800 +FW_HEAVY = 900 +FW_ULTRALIGHT = FW_EXTRALIGHT +FW_REGULAR = FW_NORMAL +FW_DEMIBOLD = FW_SEMIBOLD +FW_ULTRABOLD = FW_EXTRABOLD +FW_BLACK = FW_HEAVY +# Generated by h2py from \msvcnt\include\wingdi.h +# hacked and split manually by mhammond. +BS_SOLID = 0 +BS_NULL = 1 +BS_HOLLOW = BS_NULL +BS_HATCHED = 2 +BS_PATTERN = 3 +BS_INDEXED = 4 +BS_DIBPATTERN = 5 +BS_DIBPATTERNPT = 6 +BS_PATTERN8X8 = 7 +BS_DIBPATTERN8X8 = 8 +HS_HORIZONTAL = 0 +HS_VERTICAL = 1 +HS_FDIAGONAL = 2 +HS_BDIAGONAL = 3 +HS_CROSS = 4 +HS_DIAGCROSS = 5 +HS_FDIAGONAL1 = 6 +HS_BDIAGONAL1 = 7 +HS_SOLID = 8 +HS_DENSE1 = 9 +HS_DENSE2 = 10 +HS_DENSE3 = 11 +HS_DENSE4 = 12 +HS_DENSE5 = 13 +HS_DENSE6 = 14 +HS_DENSE7 = 15 +HS_DENSE8 = 16 +HS_NOSHADE = 17 +HS_HALFTONE = 18 +HS_SOLIDCLR = 19 +HS_DITHEREDCLR = 20 +HS_SOLIDTEXTCLR = 21 +HS_DITHEREDTEXTCLR = 22 +HS_SOLIDBKCLR = 23 +HS_DITHEREDBKCLR = 24 +HS_API_MAX = 25 +PS_SOLID = 0 +PS_DASH = 1 +PS_DOT = 2 +PS_DASHDOT = 3 +PS_DASHDOTDOT = 4 +PS_NULL = 5 +PS_INSIDEFRAME = 6 +PS_USERSTYLE = 7 +PS_ALTERNATE = 8 +PS_STYLE_MASK = 15 +PS_ENDCAP_ROUND = 0 +PS_ENDCAP_SQUARE = 256 +PS_ENDCAP_FLAT = 512 +PS_ENDCAP_MASK = 3840 +PS_JOIN_ROUND = 0 +PS_JOIN_BEVEL = 4096 +PS_JOIN_MITER = 8192 +PS_JOIN_MASK = 61440 +PS_COSMETIC = 0 +PS_GEOMETRIC = 65536 +PS_TYPE_MASK = 983040 +AD_COUNTERCLOCKWISE = 1 +AD_CLOCKWISE = 2 +DRIVERVERSION = 0 +TECHNOLOGY = 2 +HORZSIZE = 4 +VERTSIZE = 6 +HORZRES = 8 +VERTRES = 10 +BITSPIXEL = 12 +PLANES = 14 +NUMBRUSHES = 16 +NUMPENS = 18 +NUMMARKERS = 20 +NUMFONTS = 22 +NUMCOLORS = 24 +PDEVICESIZE = 26 +CURVECAPS = 28 +LINECAPS = 30 +POLYGONALCAPS = 32 +TEXTCAPS = 34 +CLIPCAPS = 36 +RASTERCAPS = 38 +ASPECTX = 40 +ASPECTY = 42 +ASPECTXY = 44 +LOGPIXELSX = 88 +LOGPIXELSY = 90 +SIZEPALETTE = 104 +NUMRESERVED = 106 +COLORRES = 108 + +PHYSICALWIDTH = 110 +PHYSICALHEIGHT = 111 +PHYSICALOFFSETX = 112 +PHYSICALOFFSETY = 113 +SCALINGFACTORX = 114 +SCALINGFACTORY = 115 +VREFRESH = 116 +DESKTOPVERTRES = 117 +DESKTOPHORZRES = 118 +BLTALIGNMENT = 119 +SHADEBLENDCAPS = 120 +COLORMGMTCAPS = 121 + +DT_PLOTTER = 0 +DT_RASDISPLAY = 1 +DT_RASPRINTER = 2 +DT_RASCAMERA = 3 +DT_CHARSTREAM = 4 +DT_METAFILE = 5 +DT_DISPFILE = 6 +CC_NONE = 0 +CC_CIRCLES = 1 +CC_PIE = 2 +CC_CHORD = 4 +CC_ELLIPSES = 8 +CC_WIDE = 16 +CC_STYLED = 32 +CC_WIDESTYLED = 64 +CC_INTERIORS = 128 +CC_ROUNDRECT = 256 +LC_NONE = 0 +LC_POLYLINE = 2 +LC_MARKER = 4 +LC_POLYMARKER = 8 +LC_WIDE = 16 +LC_STYLED = 32 +LC_WIDESTYLED = 64 +LC_INTERIORS = 128 +PC_NONE = 0 +PC_POLYGON = 1 +PC_RECTANGLE = 2 +PC_WINDPOLYGON = 4 +PC_TRAPEZOID = 4 +PC_SCANLINE = 8 +PC_WIDE = 16 +PC_STYLED = 32 +PC_WIDESTYLED = 64 +PC_INTERIORS = 128 +CP_NONE = 0 +CP_RECTANGLE = 1 +CP_REGION = 2 +TC_OP_CHARACTER = 1 +TC_OP_STROKE = 2 +TC_CP_STROKE = 4 +TC_CR_90 = 8 +TC_CR_ANY = 16 +TC_SF_X_YINDEP = 32 +TC_SA_DOUBLE = 64 +TC_SA_INTEGER = 128 +TC_SA_CONTIN = 256 +TC_EA_DOUBLE = 512 +TC_IA_ABLE = 1024 +TC_UA_ABLE = 2048 +TC_SO_ABLE = 4096 +TC_RA_ABLE = 8192 +TC_VA_ABLE = 16384 +TC_RESERVED = 32768 +TC_SCROLLBLT = 65536 +RC_BITBLT = 1 +RC_BANDING = 2 +RC_SCALING = 4 +RC_BITMAP64 = 8 +RC_GDI20_OUTPUT = 16 +RC_GDI20_STATE = 32 +RC_SAVEBITMAP = 64 +RC_DI_BITMAP = 128 +RC_PALETTE = 256 +RC_DIBTODEV = 512 +RC_BIGFONT = 1024 +RC_STRETCHBLT = 2048 +RC_FLOODFILL = 4096 +RC_STRETCHDIB = 8192 +RC_OP_DX_OUTPUT = 16384 +RC_DEVBITS = 32768 +DIB_RGB_COLORS = 0 +DIB_PAL_COLORS = 1 +DIB_PAL_INDICES = 2 +DIB_PAL_PHYSINDICES = 2 +DIB_PAL_LOGINDICES = 4 +SYSPAL_ERROR = 0 +SYSPAL_STATIC = 1 +SYSPAL_NOSTATIC = 2 +CBM_CREATEDIB = 2 +CBM_INIT = 4 +FLOODFILLBORDER = 0 +FLOODFILLSURFACE = 1 +CCHDEVICENAME = 32 +CCHFORMNAME = 32 +# Generated by h2py from \msvcnt\include\wingdi.h +# hacked and split manually by mhammond. + +# DEVMODE.dmFields +DM_SPECVERSION = 800 +DM_ORIENTATION = 1 +DM_PAPERSIZE = 2 +DM_PAPERLENGTH = 4 +DM_PAPERWIDTH = 8 +DM_SCALE = 16 +DM_POSITION = 32 +DM_NUP = 64 +DM_DISPLAYORIENTATION = 128 +DM_COPIES = 256 +DM_DEFAULTSOURCE = 512 +DM_PRINTQUALITY = 1024 +DM_COLOR = 2048 +DM_DUPLEX = 4096 +DM_YRESOLUTION = 8192 +DM_TTOPTION = 16384 +DM_COLLATE = 32768 +DM_FORMNAME = 65536 +DM_LOGPIXELS = 131072 +DM_BITSPERPEL = 262144 +DM_PELSWIDTH = 524288 +DM_PELSHEIGHT = 1048576 +DM_DISPLAYFLAGS = 2097152 +DM_DISPLAYFREQUENCY = 4194304 +DM_ICMMETHOD = 8388608 +DM_ICMINTENT = 16777216 +DM_MEDIATYPE = 33554432 +DM_DITHERTYPE = 67108864 +DM_PANNINGWIDTH = 134217728 +DM_PANNINGHEIGHT = 268435456 +DM_DISPLAYFIXEDOUTPUT = 536870912 + +# DEVMODE.dmOrientation +DMORIENT_PORTRAIT = 1 +DMORIENT_LANDSCAPE = 2 + +# DEVMODE.dmDisplayOrientation +DMDO_DEFAULT = 0 +DMDO_90 = 1 +DMDO_180 = 2 +DMDO_270 = 3 + +# DEVMODE.dmDisplayFixedOutput +DMDFO_DEFAULT = 0 +DMDFO_STRETCH = 1 +DMDFO_CENTER = 2 + +# DEVMODE.dmPaperSize +DMPAPER_LETTER = 1 +DMPAPER_LETTERSMALL = 2 +DMPAPER_TABLOID = 3 +DMPAPER_LEDGER = 4 +DMPAPER_LEGAL = 5 +DMPAPER_STATEMENT = 6 +DMPAPER_EXECUTIVE = 7 +DMPAPER_A3 = 8 +DMPAPER_A4 = 9 +DMPAPER_A4SMALL = 10 +DMPAPER_A5 = 11 +DMPAPER_B4 = 12 +DMPAPER_B5 = 13 +DMPAPER_FOLIO = 14 +DMPAPER_QUARTO = 15 +DMPAPER_10X14 = 16 +DMPAPER_11X17 = 17 +DMPAPER_NOTE = 18 +DMPAPER_ENV_9 = 19 +DMPAPER_ENV_10 = 20 +DMPAPER_ENV_11 = 21 +DMPAPER_ENV_12 = 22 +DMPAPER_ENV_14 = 23 +DMPAPER_CSHEET = 24 +DMPAPER_DSHEET = 25 +DMPAPER_ESHEET = 26 +DMPAPER_ENV_DL = 27 +DMPAPER_ENV_C5 = 28 +DMPAPER_ENV_C3 = 29 +DMPAPER_ENV_C4 = 30 +DMPAPER_ENV_C6 = 31 +DMPAPER_ENV_C65 = 32 +DMPAPER_ENV_B4 = 33 +DMPAPER_ENV_B5 = 34 +DMPAPER_ENV_B6 = 35 +DMPAPER_ENV_ITALY = 36 +DMPAPER_ENV_MONARCH = 37 +DMPAPER_ENV_PERSONAL = 38 +DMPAPER_FANFOLD_US = 39 +DMPAPER_FANFOLD_STD_GERMAN = 40 +DMPAPER_FANFOLD_LGL_GERMAN = 41 +DMPAPER_ISO_B4 = 42 +DMPAPER_JAPANESE_POSTCARD = 43 +DMPAPER_9X11 = 44 +DMPAPER_10X11 = 45 +DMPAPER_15X11 = 46 +DMPAPER_ENV_INVITE = 47 +DMPAPER_RESERVED_48 = 48 +DMPAPER_RESERVED_49 = 49 +DMPAPER_LETTER_EXTRA = 50 +DMPAPER_LEGAL_EXTRA = 51 +DMPAPER_TABLOID_EXTRA = 52 +DMPAPER_A4_EXTRA = 53 +DMPAPER_LETTER_TRANSVERSE = 54 +DMPAPER_A4_TRANSVERSE = 55 +DMPAPER_LETTER_EXTRA_TRANSVERSE = 56 +DMPAPER_A_PLUS = 57 +DMPAPER_B_PLUS = 58 +DMPAPER_LETTER_PLUS = 59 +DMPAPER_A4_PLUS = 60 +DMPAPER_A5_TRANSVERSE = 61 +DMPAPER_B5_TRANSVERSE = 62 +DMPAPER_A3_EXTRA = 63 +DMPAPER_A5_EXTRA = 64 +DMPAPER_B5_EXTRA = 65 +DMPAPER_A2 = 66 +DMPAPER_A3_TRANSVERSE = 67 +DMPAPER_A3_EXTRA_TRANSVERSE = 68 +DMPAPER_DBL_JAPANESE_POSTCARD = 69 +DMPAPER_A6 = 70 +DMPAPER_JENV_KAKU2 = 71 +DMPAPER_JENV_KAKU3 = 72 +DMPAPER_JENV_CHOU3 = 73 +DMPAPER_JENV_CHOU4 = 74 +DMPAPER_LETTER_ROTATED = 75 +DMPAPER_A3_ROTATED = 76 +DMPAPER_A4_ROTATED = 77 +DMPAPER_A5_ROTATED = 78 +DMPAPER_B4_JIS_ROTATED = 79 +DMPAPER_B5_JIS_ROTATED = 80 +DMPAPER_JAPANESE_POSTCARD_ROTATED = 81 +DMPAPER_DBL_JAPANESE_POSTCARD_ROTATED = 82 +DMPAPER_A6_ROTATED = 83 +DMPAPER_JENV_KAKU2_ROTATED = 84 +DMPAPER_JENV_KAKU3_ROTATED = 85 +DMPAPER_JENV_CHOU3_ROTATED = 86 +DMPAPER_JENV_CHOU4_ROTATED = 87 +DMPAPER_B6_JIS = 88 +DMPAPER_B6_JIS_ROTATED = 89 +DMPAPER_12X11 = 90 +DMPAPER_JENV_YOU4 = 91 +DMPAPER_JENV_YOU4_ROTATED = 92 +DMPAPER_P16K = 93 +DMPAPER_P32K = 94 +DMPAPER_P32KBIG = 95 +DMPAPER_PENV_1 = 96 +DMPAPER_PENV_2 = 97 +DMPAPER_PENV_3 = 98 +DMPAPER_PENV_4 = 99 +DMPAPER_PENV_5 = 100 +DMPAPER_PENV_6 = 101 +DMPAPER_PENV_7 = 102 +DMPAPER_PENV_8 = 103 +DMPAPER_PENV_9 = 104 +DMPAPER_PENV_10 = 105 +DMPAPER_P16K_ROTATED = 106 +DMPAPER_P32K_ROTATED = 107 +DMPAPER_P32KBIG_ROTATED = 108 +DMPAPER_PENV_1_ROTATED = 109 +DMPAPER_PENV_2_ROTATED = 110 +DMPAPER_PENV_3_ROTATED = 111 +DMPAPER_PENV_4_ROTATED = 112 +DMPAPER_PENV_5_ROTATED = 113 +DMPAPER_PENV_6_ROTATED = 114 +DMPAPER_PENV_7_ROTATED = 115 +DMPAPER_PENV_8_ROTATED = 116 +DMPAPER_PENV_9_ROTATED = 117 +DMPAPER_PENV_10_ROTATED = 118 +DMPAPER_LAST = DMPAPER_PENV_10_ROTATED +DMPAPER_USER = 256 + +# DEVMODE.dmDefaultSource +DMBIN_UPPER = 1 +DMBIN_ONLYONE = 1 +DMBIN_LOWER = 2 +DMBIN_MIDDLE = 3 +DMBIN_MANUAL = 4 +DMBIN_ENVELOPE = 5 +DMBIN_ENVMANUAL = 6 +DMBIN_AUTO = 7 +DMBIN_TRACTOR = 8 +DMBIN_SMALLFMT = 9 +DMBIN_LARGEFMT = 10 +DMBIN_LARGECAPACITY = 11 +DMBIN_CASSETTE = 14 +DMBIN_FORMSOURCE = 15 +DMBIN_LAST = DMBIN_FORMSOURCE +DMBIN_USER = 256 + +# DEVMODE.dmPrintQuality +DMRES_DRAFT = (-1) +DMRES_LOW = (-2) +DMRES_MEDIUM = (-3) +DMRES_HIGH = (-4) + +# DEVMODE.dmColor +DMCOLOR_MONOCHROME = 1 +DMCOLOR_COLOR = 2 + +# DEVMODE.dmDuplex +DMDUP_SIMPLEX = 1 +DMDUP_VERTICAL = 2 +DMDUP_HORIZONTAL = 3 + +# DEVMODE.dmTTOption +DMTT_BITMAP = 1 +DMTT_DOWNLOAD = 2 +DMTT_SUBDEV = 3 +DMTT_DOWNLOAD_OUTLINE = 4 + +# DEVMODE.dmCollate +DMCOLLATE_FALSE = 0 +DMCOLLATE_TRUE = 1 + +# DEVMODE.dmDisplayFlags +DM_GRAYSCALE = 1 +DM_INTERLACED = 2 + +# DEVMODE.dmICMMethod +DMICMMETHOD_NONE = 1 +DMICMMETHOD_SYSTEM = 2 +DMICMMETHOD_DRIVER = 3 +DMICMMETHOD_DEVICE = 4 +DMICMMETHOD_USER = 256 + +# DEVMODE.dmICMIntent +DMICM_SATURATE = 1 +DMICM_CONTRAST = 2 +DMICM_COLORIMETRIC = 3 +DMICM_ABS_COLORIMETRIC = 4 +DMICM_USER = 256 + +# DEVMODE.dmMediaType +DMMEDIA_STANDARD = 1 +DMMEDIA_TRANSPARENCY = 2 +DMMEDIA_GLOSSY = 3 +DMMEDIA_USER = 256 + +# DEVMODE.dmDitherType +DMDITHER_NONE = 1 +DMDITHER_COARSE = 2 +DMDITHER_FINE = 3 +DMDITHER_LINEART = 4 +DMDITHER_ERRORDIFFUSION = 5 +DMDITHER_RESERVED6 = 6 +DMDITHER_RESERVED7 = 7 +DMDITHER_RESERVED8 = 8 +DMDITHER_RESERVED9 = 9 +DMDITHER_GRAYSCALE = 10 +DMDITHER_USER = 256 + +# DEVMODE.dmNup +DMNUP_SYSTEM = 1 +DMNUP_ONEUP = 2 + +# used with ExtEscape +FEATURESETTING_NUP = 0 +FEATURESETTING_OUTPUT = 1 +FEATURESETTING_PSLEVEL = 2 +FEATURESETTING_CUSTPAPER = 3 +FEATURESETTING_MIRROR = 4 +FEATURESETTING_NEGATIVE = 5 +FEATURESETTING_PROTOCOL = 6 +FEATURESETTING_PRIVATE_BEGIN = 0x1000 +FEATURESETTING_PRIVATE_END = 0x1FFF + +RDH_RECTANGLES = 1 +GGO_METRICS = 0 +GGO_BITMAP = 1 +GGO_NATIVE = 2 +TT_POLYGON_TYPE = 24 +TT_PRIM_LINE = 1 +TT_PRIM_QSPLINE = 2 +TT_AVAILABLE = 1 +TT_ENABLED = 2 +DM_UPDATE = 1 +DM_COPY = 2 +DM_PROMPT = 4 +DM_MODIFY = 8 +DM_IN_BUFFER = DM_MODIFY +DM_IN_PROMPT = DM_PROMPT +DM_OUT_BUFFER = DM_COPY +DM_OUT_DEFAULT = DM_UPDATE + +# DISPLAY_DEVICE.StateFlags +DISPLAY_DEVICE_ATTACHED_TO_DESKTOP = 1 +DISPLAY_DEVICE_MULTI_DRIVER = 2 +DISPLAY_DEVICE_PRIMARY_DEVICE = 4 +DISPLAY_DEVICE_MIRRORING_DRIVER = 8 +DISPLAY_DEVICE_VGA_COMPATIBLE = 16 +DISPLAY_DEVICE_REMOVABLE = 32 +DISPLAY_DEVICE_MODESPRUNED = 134217728 +DISPLAY_DEVICE_REMOTE = 67108864 +DISPLAY_DEVICE_DISCONNECT = 33554432 + +# DeviceCapabilities types +DC_FIELDS = 1 +DC_PAPERS = 2 +DC_PAPERSIZE = 3 +DC_MINEXTENT = 4 +DC_MAXEXTENT = 5 +DC_BINS = 6 +DC_DUPLEX = 7 +DC_SIZE = 8 +DC_EXTRA = 9 +DC_VERSION = 10 +DC_DRIVER = 11 +DC_BINNAMES = 12 +DC_ENUMRESOLUTIONS = 13 +DC_FILEDEPENDENCIES = 14 +DC_TRUETYPE = 15 +DC_PAPERNAMES = 16 +DC_ORIENTATION = 17 +DC_COPIES = 18 +DC_BINADJUST = 19 +DC_EMF_COMPLIANT = 20 +DC_DATATYPE_PRODUCED = 21 +DC_COLLATE = 22 +DC_MANUFACTURER = 23 +DC_MODEL = 24 +DC_PERSONALITY = 25 +DC_PRINTRATE = 26 +DC_PRINTRATEUNIT = 27 +DC_PRINTERMEM = 28 +DC_MEDIAREADY = 29 +DC_STAPLE = 30 +DC_PRINTRATEPPM = 31 +DC_COLORDEVICE = 32 +DC_NUP = 33 +DC_MEDIATYPENAMES = 34 +DC_MEDIATYPES = 35 + +PRINTRATEUNIT_PPM = 1 +PRINTRATEUNIT_CPS = 2 +PRINTRATEUNIT_LPM = 3 +PRINTRATEUNIT_IPM = 4 + +# TrueType constants +DCTT_BITMAP = 1 +DCTT_DOWNLOAD = 2 +DCTT_SUBDEV = 4 +DCTT_DOWNLOAD_OUTLINE = 8 + +DCBA_FACEUPNONE = 0 +DCBA_FACEUPCENTER = 1 +DCBA_FACEUPLEFT = 2 +DCBA_FACEUPRIGHT = 3 +DCBA_FACEDOWNNONE = 256 +DCBA_FACEDOWNCENTER = 257 +DCBA_FACEDOWNLEFT = 258 +DCBA_FACEDOWNRIGHT = 259 + +CA_NEGATIVE = 1 +CA_LOG_FILTER = 2 +ILLUMINANT_DEVICE_DEFAULT = 0 +ILLUMINANT_A = 1 +ILLUMINANT_B = 2 +ILLUMINANT_C = 3 +ILLUMINANT_D50 = 4 +ILLUMINANT_D55 = 5 +ILLUMINANT_D65 = 6 +ILLUMINANT_D75 = 7 +ILLUMINANT_F2 = 8 +ILLUMINANT_MAX_INDEX = ILLUMINANT_F2 +ILLUMINANT_TUNGSTEN = ILLUMINANT_A +ILLUMINANT_DAYLIGHT = ILLUMINANT_C +ILLUMINANT_FLUORESCENT = ILLUMINANT_F2 +ILLUMINANT_NTSC = ILLUMINANT_C + +# Generated by h2py from \msvcnt\include\wingdi.h +# hacked and split manually by mhammond. +FONTMAPPER_MAX = 10 +ENHMETA_SIGNATURE = 1179469088 +ENHMETA_STOCK_OBJECT = -2147483648 +EMR_HEADER = 1 +EMR_POLYBEZIER = 2 +EMR_POLYGON = 3 +EMR_POLYLINE = 4 +EMR_POLYBEZIERTO = 5 +EMR_POLYLINETO = 6 +EMR_POLYPOLYLINE = 7 +EMR_POLYPOLYGON = 8 +EMR_SETWINDOWEXTEX = 9 +EMR_SETWINDOWORGEX = 10 +EMR_SETVIEWPORTEXTEX = 11 +EMR_SETVIEWPORTORGEX = 12 +EMR_SETBRUSHORGEX = 13 +EMR_EOF = 14 +EMR_SETPIXELV = 15 +EMR_SETMAPPERFLAGS = 16 +EMR_SETMAPMODE = 17 +EMR_SETBKMODE = 18 +EMR_SETPOLYFILLMODE = 19 +EMR_SETROP2 = 20 +EMR_SETSTRETCHBLTMODE = 21 +EMR_SETTEXTALIGN = 22 +EMR_SETCOLORADJUSTMENT = 23 +EMR_SETTEXTCOLOR = 24 +EMR_SETBKCOLOR = 25 +EMR_OFFSETCLIPRGN = 26 +EMR_MOVETOEX = 27 +EMR_SETMETARGN = 28 +EMR_EXCLUDECLIPRECT = 29 +EMR_INTERSECTCLIPRECT = 30 +EMR_SCALEVIEWPORTEXTEX = 31 +EMR_SCALEWINDOWEXTEX = 32 +EMR_SAVEDC = 33 +EMR_RESTOREDC = 34 +EMR_SETWORLDTRANSFORM = 35 +EMR_MODIFYWORLDTRANSFORM = 36 +EMR_SELECTOBJECT = 37 +EMR_CREATEPEN = 38 +EMR_CREATEBRUSHINDIRECT = 39 +EMR_DELETEOBJECT = 40 +EMR_ANGLEARC = 41 +EMR_ELLIPSE = 42 +EMR_RECTANGLE = 43 +EMR_ROUNDRECT = 44 +EMR_ARC = 45 +EMR_CHORD = 46 +EMR_PIE = 47 +EMR_SELECTPALETTE = 48 +EMR_CREATEPALETTE = 49 +EMR_SETPALETTEENTRIES = 50 +EMR_RESIZEPALETTE = 51 +EMR_REALIZEPALETTE = 52 +EMR_EXTFLOODFILL = 53 +EMR_LINETO = 54 +EMR_ARCTO = 55 +EMR_POLYDRAW = 56 +EMR_SETARCDIRECTION = 57 +EMR_SETMITERLIMIT = 58 +EMR_BEGINPATH = 59 +EMR_ENDPATH = 60 +EMR_CLOSEFIGURE = 61 +EMR_FILLPATH = 62 +EMR_STROKEANDFILLPATH = 63 +EMR_STROKEPATH = 64 +EMR_FLATTENPATH = 65 +EMR_WIDENPATH = 66 +EMR_SELECTCLIPPATH = 67 +EMR_ABORTPATH = 68 +EMR_GDICOMMENT = 70 +EMR_FILLRGN = 71 +EMR_FRAMERGN = 72 +EMR_INVERTRGN = 73 +EMR_PAINTRGN = 74 +EMR_EXTSELECTCLIPRGN = 75 +EMR_BITBLT = 76 +EMR_STRETCHBLT = 77 +EMR_MASKBLT = 78 +EMR_PLGBLT = 79 +EMR_SETDIBITSTODEVICE = 80 +EMR_STRETCHDIBITS = 81 +EMR_EXTCREATEFONTINDIRECTW = 82 +EMR_EXTTEXTOUTA = 83 +EMR_EXTTEXTOUTW = 84 +EMR_POLYBEZIER16 = 85 +EMR_POLYGON16 = 86 +EMR_POLYLINE16 = 87 +EMR_POLYBEZIERTO16 = 88 +EMR_POLYLINETO16 = 89 +EMR_POLYPOLYLINE16 = 90 +EMR_POLYPOLYGON16 = 91 +EMR_POLYDRAW16 = 92 +EMR_CREATEMONOBRUSH = 93 +EMR_CREATEDIBPATTERNBRUSHPT = 94 +EMR_EXTCREATEPEN = 95 +EMR_POLYTEXTOUTA = 96 +EMR_POLYTEXTOUTW = 97 +EMR_MIN = 1 +EMR_MAX = 97 +# Generated by h2py from \msvcnt\include\wingdi.h +# hacked and split manually by mhammond. +PANOSE_COUNT = 10 +PAN_FAMILYTYPE_INDEX = 0 +PAN_SERIFSTYLE_INDEX = 1 +PAN_WEIGHT_INDEX = 2 +PAN_PROPORTION_INDEX = 3 +PAN_CONTRAST_INDEX = 4 +PAN_STROKEVARIATION_INDEX = 5 +PAN_ARMSTYLE_INDEX = 6 +PAN_LETTERFORM_INDEX = 7 +PAN_MIDLINE_INDEX = 8 +PAN_XHEIGHT_INDEX = 9 +PAN_CULTURE_LATIN = 0 +PAN_ANY = 0 +PAN_NO_FIT = 1 +PAN_FAMILY_TEXT_DISPLAY = 2 +PAN_FAMILY_SCRIPT = 3 +PAN_FAMILY_DECORATIVE = 4 +PAN_FAMILY_PICTORIAL = 5 +PAN_SERIF_COVE = 2 +PAN_SERIF_OBTUSE_COVE = 3 +PAN_SERIF_SQUARE_COVE = 4 +PAN_SERIF_OBTUSE_SQUARE_COVE = 5 +PAN_SERIF_SQUARE = 6 +PAN_SERIF_THIN = 7 +PAN_SERIF_BONE = 8 +PAN_SERIF_EXAGGERATED = 9 +PAN_SERIF_TRIANGLE = 10 +PAN_SERIF_NORMAL_SANS = 11 +PAN_SERIF_OBTUSE_SANS = 12 +PAN_SERIF_PERP_SANS = 13 +PAN_SERIF_FLARED = 14 +PAN_SERIF_ROUNDED = 15 +PAN_WEIGHT_VERY_LIGHT = 2 +PAN_WEIGHT_LIGHT = 3 +PAN_WEIGHT_THIN = 4 +PAN_WEIGHT_BOOK = 5 +PAN_WEIGHT_MEDIUM = 6 +PAN_WEIGHT_DEMI = 7 +PAN_WEIGHT_BOLD = 8 +PAN_WEIGHT_HEAVY = 9 +PAN_WEIGHT_BLACK = 10 +PAN_WEIGHT_NORD = 11 +PAN_PROP_OLD_STYLE = 2 +PAN_PROP_MODERN = 3 +PAN_PROP_EVEN_WIDTH = 4 +PAN_PROP_EXPANDED = 5 +PAN_PROP_CONDENSED = 6 +PAN_PROP_VERY_EXPANDED = 7 +PAN_PROP_VERY_CONDENSED = 8 +PAN_PROP_MONOSPACED = 9 +PAN_CONTRAST_NONE = 2 +PAN_CONTRAST_VERY_LOW = 3 +PAN_CONTRAST_LOW = 4 +PAN_CONTRAST_MEDIUM_LOW = 5 +PAN_CONTRAST_MEDIUM = 6 +PAN_CONTRAST_MEDIUM_HIGH = 7 +PAN_CONTRAST_HIGH = 8 +PAN_CONTRAST_VERY_HIGH = 9 +PAN_STROKE_GRADUAL_DIAG = 2 +PAN_STROKE_GRADUAL_TRAN = 3 +PAN_STROKE_GRADUAL_VERT = 4 +PAN_STROKE_GRADUAL_HORZ = 5 +PAN_STROKE_RAPID_VERT = 6 +PAN_STROKE_RAPID_HORZ = 7 +PAN_STROKE_INSTANT_VERT = 8 +PAN_STRAIGHT_ARMS_HORZ = 2 +PAN_STRAIGHT_ARMS_WEDGE = 3 +PAN_STRAIGHT_ARMS_VERT = 4 +PAN_STRAIGHT_ARMS_SINGLE_SERIF = 5 +PAN_STRAIGHT_ARMS_DOUBLE_SERIF = 6 +PAN_BENT_ARMS_HORZ = 7 +PAN_BENT_ARMS_WEDGE = 8 +PAN_BENT_ARMS_VERT = 9 +PAN_BENT_ARMS_SINGLE_SERIF = 10 +PAN_BENT_ARMS_DOUBLE_SERIF = 11 +PAN_LETT_NORMAL_CONTACT = 2 +PAN_LETT_NORMAL_WEIGHTED = 3 +PAN_LETT_NORMAL_BOXED = 4 +PAN_LETT_NORMAL_FLATTENED = 5 +PAN_LETT_NORMAL_ROUNDED = 6 +PAN_LETT_NORMAL_OFF_CENTER = 7 +PAN_LETT_NORMAL_SQUARE = 8 +PAN_LETT_OBLIQUE_CONTACT = 9 +PAN_LETT_OBLIQUE_WEIGHTED = 10 +PAN_LETT_OBLIQUE_BOXED = 11 +PAN_LETT_OBLIQUE_FLATTENED = 12 +PAN_LETT_OBLIQUE_ROUNDED = 13 +PAN_LETT_OBLIQUE_OFF_CENTER = 14 +PAN_LETT_OBLIQUE_SQUARE = 15 +PAN_MIDLINE_STANDARD_TRIMMED = 2 +PAN_MIDLINE_STANDARD_POINTED = 3 +PAN_MIDLINE_STANDARD_SERIFED = 4 +PAN_MIDLINE_HIGH_TRIMMED = 5 +PAN_MIDLINE_HIGH_POINTED = 6 +PAN_MIDLINE_HIGH_SERIFED = 7 +PAN_MIDLINE_CONSTANT_TRIMMED = 8 +PAN_MIDLINE_CONSTANT_POINTED = 9 +PAN_MIDLINE_CONSTANT_SERIFED = 10 +PAN_MIDLINE_LOW_TRIMMED = 11 +PAN_MIDLINE_LOW_POINTED = 12 +PAN_MIDLINE_LOW_SERIFED = 13 +PAN_XHEIGHT_CONSTANT_SMALL = 2 +PAN_XHEIGHT_CONSTANT_STD = 3 +PAN_XHEIGHT_CONSTANT_LARGE = 4 +PAN_XHEIGHT_DUCKING_SMALL = 5 +PAN_XHEIGHT_DUCKING_STD = 6 +PAN_XHEIGHT_DUCKING_LARGE = 7 +ELF_VENDOR_SIZE = 4 +ELF_VERSION = 0 +ELF_CULTURE_LATIN = 0 +RASTER_FONTTYPE = 1 +DEVICE_FONTTYPE = 2 +TRUETYPE_FONTTYPE = 4 +def PALETTEINDEX(i): return ((16777216 | (i))) + +PC_RESERVED = 1 +PC_EXPLICIT = 2 +PC_NOCOLLAPSE = 4 +def GetRValue(rgb): return rgb & 0xff + +def GetGValue(rgb): return (rgb >> 8) & 0xff + +def GetBValue(rgb): return (rgb >> 16) & 0xff + +TRANSPARENT = 1 +OPAQUE = 2 +BKMODE_LAST = 2 +GM_COMPATIBLE = 1 +GM_ADVANCED = 2 +GM_LAST = 2 +PT_CLOSEFIGURE = 1 +PT_LINETO = 2 +PT_BEZIERTO = 4 +PT_MOVETO = 6 +MM_TEXT = 1 +MM_LOMETRIC = 2 +MM_HIMETRIC = 3 +MM_LOENGLISH = 4 +MM_HIENGLISH = 5 +MM_TWIPS = 6 +MM_ISOTROPIC = 7 +MM_ANISOTROPIC = 8 +MM_MIN = MM_TEXT +MM_MAX = MM_ANISOTROPIC +MM_MAX_FIXEDSCALE = MM_TWIPS +ABSOLUTE = 1 +RELATIVE = 2 +WHITE_BRUSH = 0 +LTGRAY_BRUSH = 1 +GRAY_BRUSH = 2 +DKGRAY_BRUSH = 3 +BLACK_BRUSH = 4 +NULL_BRUSH = 5 +HOLLOW_BRUSH = NULL_BRUSH +WHITE_PEN = 6 +BLACK_PEN = 7 +NULL_PEN = 8 +OEM_FIXED_FONT = 10 +ANSI_FIXED_FONT = 11 +ANSI_VAR_FONT = 12 +SYSTEM_FONT = 13 +DEVICE_DEFAULT_FONT = 14 +DEFAULT_PALETTE = 15 +SYSTEM_FIXED_FONT = 16 +STOCK_LAST = 16 +CLR_INVALID = -1 + +DC_BRUSH = 18 +DC_PEN = 19 + +# Exception/Status codes from winuser.h and winnt.h +STATUS_WAIT_0 = 0 +STATUS_ABANDONED_WAIT_0 = 128 +STATUS_USER_APC = 192 +STATUS_TIMEOUT = 258 +STATUS_PENDING = 259 +STATUS_SEGMENT_NOTIFICATION = 1073741829 +STATUS_GUARD_PAGE_VIOLATION = -2147483647 +STATUS_DATATYPE_MISALIGNMENT = -2147483646 +STATUS_BREAKPOINT = -2147483645 +STATUS_SINGLE_STEP = -2147483644 +STATUS_ACCESS_VIOLATION = -1073741819 +STATUS_IN_PAGE_ERROR = -1073741818 +STATUS_INVALID_HANDLE = -1073741816 +STATUS_NO_MEMORY = -1073741801 +STATUS_ILLEGAL_INSTRUCTION = -1073741795 +STATUS_NONCONTINUABLE_EXCEPTION = -1073741787 +STATUS_INVALID_DISPOSITION = -1073741786 +STATUS_ARRAY_BOUNDS_EXCEEDED = -1073741684 +STATUS_FLOAT_DENORMAL_OPERAND = -1073741683 +STATUS_FLOAT_DIVIDE_BY_ZERO = -1073741682 +STATUS_FLOAT_INEXACT_RESULT = -1073741681 +STATUS_FLOAT_INVALID_OPERATION = -1073741680 +STATUS_FLOAT_OVERFLOW = -1073741679 +STATUS_FLOAT_STACK_CHECK = -1073741678 +STATUS_FLOAT_UNDERFLOW = -1073741677 +STATUS_INTEGER_DIVIDE_BY_ZERO = -1073741676 +STATUS_INTEGER_OVERFLOW = -1073741675 +STATUS_PRIVILEGED_INSTRUCTION = -1073741674 +STATUS_STACK_OVERFLOW = -1073741571 +STATUS_CONTROL_C_EXIT = -1073741510 + + +WAIT_FAILED = -1 +WAIT_OBJECT_0 = STATUS_WAIT_0 + 0 + +WAIT_ABANDONED = STATUS_ABANDONED_WAIT_0 + 0 +WAIT_ABANDONED_0 = STATUS_ABANDONED_WAIT_0 + 0 + +WAIT_TIMEOUT = STATUS_TIMEOUT +WAIT_IO_COMPLETION = STATUS_USER_APC +STILL_ACTIVE = STATUS_PENDING +EXCEPTION_ACCESS_VIOLATION = STATUS_ACCESS_VIOLATION +EXCEPTION_DATATYPE_MISALIGNMENT = STATUS_DATATYPE_MISALIGNMENT +EXCEPTION_BREAKPOINT = STATUS_BREAKPOINT +EXCEPTION_SINGLE_STEP = STATUS_SINGLE_STEP +EXCEPTION_ARRAY_BOUNDS_EXCEEDED = STATUS_ARRAY_BOUNDS_EXCEEDED +EXCEPTION_FLT_DENORMAL_OPERAND = STATUS_FLOAT_DENORMAL_OPERAND +EXCEPTION_FLT_DIVIDE_BY_ZERO = STATUS_FLOAT_DIVIDE_BY_ZERO +EXCEPTION_FLT_INEXACT_RESULT = STATUS_FLOAT_INEXACT_RESULT +EXCEPTION_FLT_INVALID_OPERATION = STATUS_FLOAT_INVALID_OPERATION +EXCEPTION_FLT_OVERFLOW = STATUS_FLOAT_OVERFLOW +EXCEPTION_FLT_STACK_CHECK = STATUS_FLOAT_STACK_CHECK +EXCEPTION_FLT_UNDERFLOW = STATUS_FLOAT_UNDERFLOW +EXCEPTION_INT_DIVIDE_BY_ZERO = STATUS_INTEGER_DIVIDE_BY_ZERO +EXCEPTION_INT_OVERFLOW = STATUS_INTEGER_OVERFLOW +EXCEPTION_PRIV_INSTRUCTION = STATUS_PRIVILEGED_INSTRUCTION +EXCEPTION_IN_PAGE_ERROR = STATUS_IN_PAGE_ERROR +EXCEPTION_ILLEGAL_INSTRUCTION = STATUS_ILLEGAL_INSTRUCTION +EXCEPTION_NONCONTINUABLE_EXCEPTION = STATUS_NONCONTINUABLE_EXCEPTION +EXCEPTION_STACK_OVERFLOW = STATUS_STACK_OVERFLOW +EXCEPTION_INVALID_DISPOSITION = STATUS_INVALID_DISPOSITION +EXCEPTION_GUARD_PAGE = STATUS_GUARD_PAGE_VIOLATION +EXCEPTION_INVALID_HANDLE = STATUS_INVALID_HANDLE +CONTROL_C_EXIT = STATUS_CONTROL_C_EXIT + +# winuser.h line 8594 +# constants used with SystemParametersInfo +SPI_GETBEEP = 1 +SPI_SETBEEP = 2 +SPI_GETMOUSE = 3 +SPI_SETMOUSE = 4 +SPI_GETBORDER = 5 +SPI_SETBORDER = 6 +SPI_GETKEYBOARDSPEED = 10 +SPI_SETKEYBOARDSPEED = 11 +SPI_LANGDRIVER = 12 +SPI_ICONHORIZONTALSPACING = 13 +SPI_GETSCREENSAVETIMEOUT = 14 +SPI_SETSCREENSAVETIMEOUT = 15 +SPI_GETSCREENSAVEACTIVE = 16 +SPI_SETSCREENSAVEACTIVE = 17 +SPI_GETGRIDGRANULARITY = 18 +SPI_SETGRIDGRANULARITY = 19 +SPI_SETDESKWALLPAPER = 20 +SPI_SETDESKPATTERN = 21 +SPI_GETKEYBOARDDELAY = 22 +SPI_SETKEYBOARDDELAY = 23 +SPI_ICONVERTICALSPACING = 24 +SPI_GETICONTITLEWRAP = 25 +SPI_SETICONTITLEWRAP = 26 +SPI_GETMENUDROPALIGNMENT = 27 +SPI_SETMENUDROPALIGNMENT = 28 +SPI_SETDOUBLECLKWIDTH = 29 +SPI_SETDOUBLECLKHEIGHT = 30 +SPI_GETICONTITLELOGFONT = 31 +SPI_SETDOUBLECLICKTIME = 32 +SPI_SETMOUSEBUTTONSWAP = 33 +SPI_SETICONTITLELOGFONT = 34 +SPI_GETFASTTASKSWITCH = 35 +SPI_SETFASTTASKSWITCH = 36 +SPI_SETDRAGFULLWINDOWS = 37 +SPI_GETDRAGFULLWINDOWS = 38 +SPI_GETNONCLIENTMETRICS = 41 +SPI_SETNONCLIENTMETRICS = 42 +SPI_GETMINIMIZEDMETRICS = 43 +SPI_SETMINIMIZEDMETRICS = 44 +SPI_GETICONMETRICS = 45 +SPI_SETICONMETRICS = 46 +SPI_SETWORKAREA = 47 +SPI_GETWORKAREA = 48 +SPI_SETPENWINDOWS = 49 +SPI_GETFILTERKEYS = 50 +SPI_SETFILTERKEYS = 51 +SPI_GETTOGGLEKEYS = 52 +SPI_SETTOGGLEKEYS = 53 +SPI_GETMOUSEKEYS = 54 +SPI_SETMOUSEKEYS = 55 +SPI_GETSHOWSOUNDS = 56 +SPI_SETSHOWSOUNDS = 57 +SPI_GETSTICKYKEYS = 58 +SPI_SETSTICKYKEYS = 59 +SPI_GETACCESSTIMEOUT = 60 +SPI_SETACCESSTIMEOUT = 61 +SPI_GETSERIALKEYS = 62 +SPI_SETSERIALKEYS = 63 +SPI_GETSOUNDSENTRY = 64 +SPI_SETSOUNDSENTRY = 65 +SPI_GETHIGHCONTRAST = 66 +SPI_SETHIGHCONTRAST = 67 +SPI_GETKEYBOARDPREF = 68 +SPI_SETKEYBOARDPREF = 69 +SPI_GETSCREENREADER = 70 +SPI_SETSCREENREADER = 71 +SPI_GETANIMATION = 72 +SPI_SETANIMATION = 73 +SPI_GETFONTSMOOTHING = 74 +SPI_SETFONTSMOOTHING = 75 +SPI_SETDRAGWIDTH = 76 +SPI_SETDRAGHEIGHT = 77 +SPI_SETHANDHELD = 78 +SPI_GETLOWPOWERTIMEOUT = 79 +SPI_GETPOWEROFFTIMEOUT = 80 +SPI_SETLOWPOWERTIMEOUT = 81 +SPI_SETPOWEROFFTIMEOUT = 82 +SPI_GETLOWPOWERACTIVE = 83 +SPI_GETPOWEROFFACTIVE = 84 +SPI_SETLOWPOWERACTIVE = 85 +SPI_SETPOWEROFFACTIVE = 86 +SPI_SETCURSORS = 87 +SPI_SETICONS = 88 +SPI_GETDEFAULTINPUTLANG = 89 +SPI_SETDEFAULTINPUTLANG = 90 +SPI_SETLANGTOGGLE = 91 +SPI_GETWINDOWSEXTENSION = 92 +SPI_SETMOUSETRAILS = 93 +SPI_GETMOUSETRAILS = 94 +SPI_GETSNAPTODEFBUTTON = 95 +SPI_SETSNAPTODEFBUTTON = 96 +SPI_SETSCREENSAVERRUNNING = 97 +SPI_SCREENSAVERRUNNING = SPI_SETSCREENSAVERRUNNING +SPI_GETMOUSEHOVERWIDTH = 98 +SPI_SETMOUSEHOVERWIDTH = 99 +SPI_GETMOUSEHOVERHEIGHT = 100 +SPI_SETMOUSEHOVERHEIGHT = 101 +SPI_GETMOUSEHOVERTIME = 102 +SPI_SETMOUSEHOVERTIME = 103 +SPI_GETWHEELSCROLLLINES = 104 +SPI_SETWHEELSCROLLLINES = 105 +SPI_GETMENUSHOWDELAY = 106 +SPI_SETMENUSHOWDELAY = 107 + +SPI_GETSHOWIMEUI = 110 +SPI_SETSHOWIMEUI = 111 +SPI_GETMOUSESPEED = 112 +SPI_SETMOUSESPEED = 113 +SPI_GETSCREENSAVERRUNNING = 114 +SPI_GETDESKWALLPAPER = 115 + +SPI_GETACTIVEWINDOWTRACKING = 4096 +SPI_SETACTIVEWINDOWTRACKING = 4097 +SPI_GETMENUANIMATION = 4098 +SPI_SETMENUANIMATION = 4099 +SPI_GETCOMBOBOXANIMATION = 4100 +SPI_SETCOMBOBOXANIMATION = 4101 +SPI_GETLISTBOXSMOOTHSCROLLING = 4102 +SPI_SETLISTBOXSMOOTHSCROLLING = 4103 +SPI_GETGRADIENTCAPTIONS = 4104 +SPI_SETGRADIENTCAPTIONS = 4105 +SPI_GETKEYBOARDCUES = 4106 +SPI_SETKEYBOARDCUES = 4107 +SPI_GETMENUUNDERLINES = 4106 +SPI_SETMENUUNDERLINES = 4107 +SPI_GETACTIVEWNDTRKZORDER = 4108 +SPI_SETACTIVEWNDTRKZORDER = 4109 +SPI_GETHOTTRACKING = 4110 +SPI_SETHOTTRACKING = 4111 + +SPI_GETMENUFADE = 4114 +SPI_SETMENUFADE = 4115 +SPI_GETSELECTIONFADE = 4116 +SPI_SETSELECTIONFADE = 4117 +SPI_GETTOOLTIPANIMATION = 4118 +SPI_SETTOOLTIPANIMATION = 4119 +SPI_GETTOOLTIPFADE = 4120 +SPI_SETTOOLTIPFADE = 4121 +SPI_GETCURSORSHADOW = 4122 +SPI_SETCURSORSHADOW = 4123 +SPI_GETMOUSESONAR = 4124 +SPI_SETMOUSESONAR = 4125 +SPI_GETMOUSECLICKLOCK = 4126 +SPI_SETMOUSECLICKLOCK = 4127 +SPI_GETMOUSEVANISH = 4128 +SPI_SETMOUSEVANISH = 4129 +SPI_GETFLATMENU = 4130 +SPI_SETFLATMENU = 4131 +SPI_GETDROPSHADOW = 4132 +SPI_SETDROPSHADOW = 4133 +SPI_GETBLOCKSENDINPUTRESETS = 4134 +SPI_SETBLOCKSENDINPUTRESETS = 4135 +SPI_GETUIEFFECTS = 4158 +SPI_SETUIEFFECTS = 4159 + +SPI_GETFOREGROUNDLOCKTIMEOUT = 8192 +SPI_SETFOREGROUNDLOCKTIMEOUT = 8193 +SPI_GETACTIVEWNDTRKTIMEOUT = 8194 +SPI_SETACTIVEWNDTRKTIMEOUT = 8195 +SPI_GETFOREGROUNDFLASHCOUNT = 8196 +SPI_SETFOREGROUNDFLASHCOUNT = 8197 +SPI_GETCARETWIDTH = 8198 +SPI_SETCARETWIDTH = 8199 +SPI_GETMOUSECLICKLOCKTIME = 8200 +SPI_SETMOUSECLICKLOCKTIME = 8201 +SPI_GETFONTSMOOTHINGTYPE = 8202 +SPI_SETFONTSMOOTHINGTYPE = 8203 +SPI_GETFONTSMOOTHINGCONTRAST = 8204 +SPI_SETFONTSMOOTHINGCONTRAST = 8205 +SPI_GETFOCUSBORDERWIDTH = 8206 +SPI_SETFOCUSBORDERWIDTH = 8207 +SPI_GETFOCUSBORDERHEIGHT = 8208 +SPI_SETFOCUSBORDERHEIGHT = 8209 +SPI_GETFONTSMOOTHINGORIENTATION = 8210 +SPI_SETFONTSMOOTHINGORIENTATION = 8211 + +# fWinIni flags for SystemParametersInfo +SPIF_UPDATEINIFILE = 1 +SPIF_SENDWININICHANGE = 2 +SPIF_SENDCHANGE = SPIF_SENDWININICHANGE + +# used with SystemParametersInfo and SPI_GETFONTSMOOTHINGTYPE/SPI_SETFONTSMOOTHINGTYPE +FE_FONTSMOOTHINGSTANDARD = 1 +FE_FONTSMOOTHINGCLEARTYPE = 2 +FE_FONTSMOOTHINGDOCKING = 32768 + +METRICS_USEDEFAULT = -1 +ARW_BOTTOMLEFT = 0 +ARW_BOTTOMRIGHT = 1 +ARW_TOPLEFT = 2 +ARW_TOPRIGHT = 3 +ARW_STARTMASK = 3 +ARW_STARTRIGHT = 1 +ARW_STARTTOP = 2 +ARW_LEFT = 0 +ARW_RIGHT = 0 +ARW_UP = 4 +ARW_DOWN = 4 +ARW_HIDE = 8 +#ARW_VALID = 0x000F +SERKF_SERIALKEYSON = 1 +SERKF_AVAILABLE = 2 +SERKF_INDICATOR = 4 +HCF_HIGHCONTRASTON = 1 +HCF_AVAILABLE = 2 +HCF_HOTKEYACTIVE = 4 +HCF_CONFIRMHOTKEY = 8 +HCF_HOTKEYSOUND = 16 +HCF_INDICATOR = 32 +HCF_HOTKEYAVAILABLE = 64 +CDS_UPDATEREGISTRY = 1 +CDS_TEST = 2 +CDS_FULLSCREEN = 4 +CDS_GLOBAL = 8 +CDS_SET_PRIMARY = 16 +CDS_RESET = 1073741824 +CDS_SETRECT = 536870912 +CDS_NORESET = 268435456 + +# return values from ChangeDisplaySettings and ChangeDisplaySettingsEx +DISP_CHANGE_SUCCESSFUL = 0 +DISP_CHANGE_RESTART = 1 +DISP_CHANGE_FAILED = -1 +DISP_CHANGE_BADMODE = -2 +DISP_CHANGE_NOTUPDATED = -3 +DISP_CHANGE_BADFLAGS = -4 +DISP_CHANGE_BADPARAM = -5 +DISP_CHANGE_BADDUALVIEW = -6 + +ENUM_CURRENT_SETTINGS = -1 +ENUM_REGISTRY_SETTINGS = -2 +FKF_FILTERKEYSON = 1 +FKF_AVAILABLE = 2 +FKF_HOTKEYACTIVE = 4 +FKF_CONFIRMHOTKEY = 8 +FKF_HOTKEYSOUND = 16 +FKF_INDICATOR = 32 +FKF_CLICKON = 64 +SKF_STICKYKEYSON = 1 +SKF_AVAILABLE = 2 +SKF_HOTKEYACTIVE = 4 +SKF_CONFIRMHOTKEY = 8 +SKF_HOTKEYSOUND = 16 +SKF_INDICATOR = 32 +SKF_AUDIBLEFEEDBACK = 64 +SKF_TRISTATE = 128 +SKF_TWOKEYSOFF = 256 +SKF_LALTLATCHED = 268435456 +SKF_LCTLLATCHED = 67108864 +SKF_LSHIFTLATCHED = 16777216 +SKF_RALTLATCHED = 536870912 +SKF_RCTLLATCHED = 134217728 +SKF_RSHIFTLATCHED = 33554432 +SKF_LWINLATCHED = 1073741824 +SKF_RWINLATCHED = -2147483648 +SKF_LALTLOCKED = 1048576 +SKF_LCTLLOCKED = 262144 +SKF_LSHIFTLOCKED = 65536 +SKF_RALTLOCKED = 2097152 +SKF_RCTLLOCKED = 524288 +SKF_RSHIFTLOCKED = 131072 +SKF_LWINLOCKED = 4194304 +SKF_RWINLOCKED = 8388608 +MKF_MOUSEKEYSON = 1 +MKF_AVAILABLE = 2 +MKF_HOTKEYACTIVE = 4 +MKF_CONFIRMHOTKEY = 8 +MKF_HOTKEYSOUND = 16 +MKF_INDICATOR = 32 +MKF_MODIFIERS = 64 +MKF_REPLACENUMBERS = 128 +MKF_LEFTBUTTONSEL = 268435456 +MKF_RIGHTBUTTONSEL = 536870912 +MKF_LEFTBUTTONDOWN = 16777216 +MKF_RIGHTBUTTONDOWN = 33554432 +MKF_MOUSEMODE = -2147483648 +ATF_TIMEOUTON = 1 +ATF_ONOFFFEEDBACK = 2 +SSGF_NONE = 0 +SSGF_DISPLAY = 3 +SSTF_NONE = 0 +SSTF_CHARS = 1 +SSTF_BORDER = 2 +SSTF_DISPLAY = 3 +SSWF_NONE = 0 +SSWF_TITLE = 1 +SSWF_WINDOW = 2 +SSWF_DISPLAY = 3 +SSWF_CUSTOM = 4 +SSF_SOUNDSENTRYON = 1 +SSF_AVAILABLE = 2 +SSF_INDICATOR = 4 +TKF_TOGGLEKEYSON = 1 +TKF_AVAILABLE = 2 +TKF_HOTKEYACTIVE = 4 +TKF_CONFIRMHOTKEY = 8 +TKF_HOTKEYSOUND = 16 +TKF_INDICATOR = 32 +SLE_ERROR = 1 +SLE_MINORERROR = 2 +SLE_WARNING = 3 +MONITOR_DEFAULTTONULL = 0 +MONITOR_DEFAULTTOPRIMARY = 1 +MONITOR_DEFAULTTONEAREST = 2 +MONITORINFOF_PRIMARY = 1 +CCHDEVICENAME = 32 +CHILDID_SELF = 0 +INDEXID_OBJECT = 0 +INDEXID_CONTAINER = 0 +OBJID_WINDOW = 0 +OBJID_SYSMENU = -1 +OBJID_TITLEBAR = -2 +OBJID_MENU = -3 +OBJID_CLIENT = -4 +OBJID_VSCROLL = -5 +OBJID_HSCROLL = -6 +OBJID_SIZEGRIP = -7 +OBJID_CARET = -8 +OBJID_CURSOR = -9 +OBJID_ALERT = -10 +OBJID_SOUND = -11 +EVENT_MIN = 1 +EVENT_MAX = 2147483647 +EVENT_SYSTEM_SOUND = 1 +EVENT_SYSTEM_ALERT = 2 +EVENT_SYSTEM_FOREGROUND = 3 +EVENT_SYSTEM_MENUSTART = 4 +EVENT_SYSTEM_MENUEND = 5 +EVENT_SYSTEM_MENUPOPUPSTART = 6 +EVENT_SYSTEM_MENUPOPUPEND = 7 +EVENT_SYSTEM_CAPTURESTART = 8 +EVENT_SYSTEM_CAPTUREEND = 9 +EVENT_SYSTEM_MOVESIZESTART = 10 +EVENT_SYSTEM_MOVESIZEEND = 11 +EVENT_SYSTEM_CONTEXTHELPSTART = 12 +EVENT_SYSTEM_CONTEXTHELPEND = 13 +EVENT_SYSTEM_DRAGDROPSTART = 14 +EVENT_SYSTEM_DRAGDROPEND = 15 +EVENT_SYSTEM_DIALOGSTART = 16 +EVENT_SYSTEM_DIALOGEND = 17 +EVENT_SYSTEM_SCROLLINGSTART = 18 +EVENT_SYSTEM_SCROLLINGEND = 19 +EVENT_SYSTEM_SWITCHSTART = 20 +EVENT_SYSTEM_SWITCHEND = 21 +EVENT_SYSTEM_MINIMIZESTART = 22 +EVENT_SYSTEM_MINIMIZEEND = 23 +EVENT_OBJECT_CREATE = 32768 +EVENT_OBJECT_DESTROY = 32769 +EVENT_OBJECT_SHOW = 32770 +EVENT_OBJECT_HIDE = 32771 +EVENT_OBJECT_REORDER = 32772 +EVENT_OBJECT_FOCUS = 32773 +EVENT_OBJECT_SELECTION = 32774 +EVENT_OBJECT_SELECTIONADD = 32775 +EVENT_OBJECT_SELECTIONREMOVE = 32776 +EVENT_OBJECT_SELECTIONWITHIN = 32777 +EVENT_OBJECT_STATECHANGE = 32778 +EVENT_OBJECT_LOCATIONCHANGE = 32779 +EVENT_OBJECT_NAMECHANGE = 32780 +EVENT_OBJECT_DESCRIPTIONCHANGE = 32781 +EVENT_OBJECT_VALUECHANGE = 32782 +EVENT_OBJECT_PARENTCHANGE = 32783 +EVENT_OBJECT_HELPCHANGE = 32784 +EVENT_OBJECT_DEFACTIONCHANGE = 32785 +EVENT_OBJECT_ACCELERATORCHANGE = 32786 +SOUND_SYSTEM_STARTUP = 1 +SOUND_SYSTEM_SHUTDOWN = 2 +SOUND_SYSTEM_BEEP = 3 +SOUND_SYSTEM_ERROR = 4 +SOUND_SYSTEM_QUESTION = 5 +SOUND_SYSTEM_WARNING = 6 +SOUND_SYSTEM_INFORMATION = 7 +SOUND_SYSTEM_MAXIMIZE = 8 +SOUND_SYSTEM_MINIMIZE = 9 +SOUND_SYSTEM_RESTOREUP = 10 +SOUND_SYSTEM_RESTOREDOWN = 11 +SOUND_SYSTEM_APPSTART = 12 +SOUND_SYSTEM_FAULT = 13 +SOUND_SYSTEM_APPEND = 14 +SOUND_SYSTEM_MENUCOMMAND = 15 +SOUND_SYSTEM_MENUPOPUP = 16 +CSOUND_SYSTEM = 16 +ALERT_SYSTEM_INFORMATIONAL = 1 +ALERT_SYSTEM_WARNING = 2 +ALERT_SYSTEM_ERROR = 3 +ALERT_SYSTEM_QUERY = 4 +ALERT_SYSTEM_CRITICAL = 5 +CALERT_SYSTEM = 6 +WINEVENT_OUTOFCONTEXT = 0 +WINEVENT_SKIPOWNTHREAD = 1 +WINEVENT_SKIPOWNPROCESS = 2 +WINEVENT_INCONTEXT = 4 +GUI_CARETBLINKING = 1 +GUI_INMOVESIZE = 2 +GUI_INMENUMODE = 4 +GUI_SYSTEMMENUMODE = 8 +GUI_POPUPMENUMODE = 16 +STATE_SYSTEM_UNAVAILABLE = 1 +STATE_SYSTEM_SELECTED = 2 +STATE_SYSTEM_FOCUSED = 4 +STATE_SYSTEM_PRESSED = 8 +STATE_SYSTEM_CHECKED = 16 +STATE_SYSTEM_MIXED = 32 +STATE_SYSTEM_READONLY = 64 +STATE_SYSTEM_HOTTRACKED = 128 +STATE_SYSTEM_DEFAULT = 256 +STATE_SYSTEM_EXPANDED = 512 +STATE_SYSTEM_COLLAPSED = 1024 +STATE_SYSTEM_BUSY = 2048 +STATE_SYSTEM_FLOATING = 4096 +STATE_SYSTEM_MARQUEED = 8192 +STATE_SYSTEM_ANIMATED = 16384 +STATE_SYSTEM_INVISIBLE = 32768 +STATE_SYSTEM_OFFSCREEN = 65536 +STATE_SYSTEM_SIZEABLE = 131072 +STATE_SYSTEM_MOVEABLE = 262144 +STATE_SYSTEM_SELFVOICING = 524288 +STATE_SYSTEM_FOCUSABLE = 1048576 +STATE_SYSTEM_SELECTABLE = 2097152 +STATE_SYSTEM_LINKED = 4194304 +STATE_SYSTEM_TRAVERSED = 8388608 +STATE_SYSTEM_MULTISELECTABLE = 16777216 +STATE_SYSTEM_EXTSELECTABLE = 33554432 +STATE_SYSTEM_ALERT_LOW = 67108864 +STATE_SYSTEM_ALERT_MEDIUM = 134217728 +STATE_SYSTEM_ALERT_HIGH = 268435456 +STATE_SYSTEM_VALID = 536870911 +CCHILDREN_TITLEBAR = 5 +CCHILDREN_SCROLLBAR = 5 +CURSOR_SHOWING = 1 +WS_ACTIVECAPTION = 1 +GA_MIC = 1 +GA_PARENT = 1 +GA_ROOT = 2 +GA_ROOTOWNER = 3 +GA_MAC = 4 + +# winuser.h line 1979 +BF_LEFT = 1 +BF_TOP = 2 +BF_RIGHT = 4 +BF_BOTTOM = 8 +BF_TOPLEFT = (BF_TOP | BF_LEFT) +BF_TOPRIGHT = (BF_TOP | BF_RIGHT) +BF_BOTTOMLEFT = (BF_BOTTOM | BF_LEFT) +BF_BOTTOMRIGHT = (BF_BOTTOM | BF_RIGHT) +BF_RECT = (BF_LEFT | BF_TOP | BF_RIGHT | BF_BOTTOM) +BF_DIAGONAL = 16 +BF_DIAGONAL_ENDTOPRIGHT = (BF_DIAGONAL | BF_TOP | BF_RIGHT) +BF_DIAGONAL_ENDTOPLEFT = (BF_DIAGONAL | BF_TOP | BF_LEFT) +BF_DIAGONAL_ENDBOTTOMLEFT = (BF_DIAGONAL | BF_BOTTOM | BF_LEFT) +BF_DIAGONAL_ENDBOTTOMRIGHT = (BF_DIAGONAL | BF_BOTTOM | BF_RIGHT) +BF_MIDDLE = 2048 +BF_SOFT = 4096 +BF_ADJUST = 8192 +BF_FLAT = 16384 +BF_MONO = 32768 +DFC_CAPTION = 1 +DFC_MENU = 2 +DFC_SCROLL = 3 +DFC_BUTTON = 4 +DFC_POPUPMENU = 5 +DFCS_CAPTIONCLOSE = 0 +DFCS_CAPTIONMIN = 1 +DFCS_CAPTIONMAX = 2 +DFCS_CAPTIONRESTORE = 3 +DFCS_CAPTIONHELP = 4 +DFCS_MENUARROW = 0 +DFCS_MENUCHECK = 1 +DFCS_MENUBULLET = 2 +DFCS_MENUARROWRIGHT = 4 +DFCS_SCROLLUP = 0 +DFCS_SCROLLDOWN = 1 +DFCS_SCROLLLEFT = 2 +DFCS_SCROLLRIGHT = 3 +DFCS_SCROLLCOMBOBOX = 5 +DFCS_SCROLLSIZEGRIP = 8 +DFCS_SCROLLSIZEGRIPRIGHT = 16 +DFCS_BUTTONCHECK = 0 +DFCS_BUTTONRADIOIMAGE = 1 +DFCS_BUTTONRADIOMASK = 2 +DFCS_BUTTONRADIO = 4 +DFCS_BUTTON3STATE = 8 +DFCS_BUTTONPUSH = 16 +DFCS_INACTIVE = 256 +DFCS_PUSHED = 512 +DFCS_CHECKED = 1024 +DFCS_TRANSPARENT = 2048 +DFCS_HOT = 4096 +DFCS_ADJUSTRECT = 8192 +DFCS_FLAT = 16384 +DFCS_MONO = 32768 +DC_ACTIVE = 1 +DC_SMALLCAP = 2 +DC_ICON = 4 +DC_TEXT = 8 +DC_INBUTTON = 16 +DC_GRADIENT = 32 +IDANI_OPEN = 1 +IDANI_CLOSE = 2 +IDANI_CAPTION = 3 +CF_TEXT = 1 +CF_BITMAP = 2 +CF_METAFILEPICT = 3 +CF_SYLK = 4 +CF_DIF = 5 +CF_TIFF = 6 +CF_OEMTEXT = 7 +CF_DIB = 8 +CF_PALETTE = 9 +CF_PENDATA = 10 +CF_RIFF = 11 +CF_WAVE = 12 +CF_UNICODETEXT = 13 +CF_ENHMETAFILE = 14 +CF_HDROP = 15 +CF_LOCALE = 16 +CF_DIBV5 = 17 +CF_MAX = 18 +CF_OWNERDISPLAY = 128 +CF_DSPTEXT = 129 +CF_DSPBITMAP = 130 +CF_DSPMETAFILEPICT = 131 +CF_DSPENHMETAFILE = 142 +CF_PRIVATEFIRST = 512 +CF_PRIVATELAST = 767 +CF_GDIOBJFIRST = 768 +CF_GDIOBJLAST = 1023 +FVIRTKEY =1 +FNOINVERT = 2 +FSHIFT = 4 +FCONTROL = 8 +FALT = 16 +WPF_SETMINPOSITION = 1 +WPF_RESTORETOMAXIMIZED = 2 +ODT_MENU = 1 +ODT_LISTBOX = 2 +ODT_COMBOBOX = 3 +ODT_BUTTON = 4 +ODT_STATIC = 5 +ODA_DRAWENTIRE = 1 +ODA_SELECT = 2 +ODA_FOCUS = 4 +ODS_SELECTED = 1 +ODS_GRAYED = 2 +ODS_DISABLED = 4 +ODS_CHECKED = 8 +ODS_FOCUS = 16 +ODS_DEFAULT = 32 +ODS_COMBOBOXEDIT = 4096 +ODS_HOTLIGHT = 64 +ODS_INACTIVE = 128 +PM_NOREMOVE = 0 +PM_REMOVE = 1 +PM_NOYIELD = 2 +MOD_ALT = 1 +MOD_CONTROL = 2 +MOD_SHIFT = 4 +MOD_WIN = 8 +IDHOT_SNAPWINDOW = (-1) +IDHOT_SNAPDESKTOP = (-2) +#EW_RESTARTWINDOWS = 0x0042 +#EW_REBOOTSYSTEM = 0x0043 +#EW_EXITANDEXECAPP = 0x0044 +ENDSESSION_LOGOFF = -2147483648 +EWX_LOGOFF = 0 +EWX_SHUTDOWN = 1 +EWX_REBOOT = 2 +EWX_FORCE = 4 +EWX_POWEROFF = 8 +EWX_FORCEIFHUNG = 16 +BSM_ALLCOMPONENTS = 0 +BSM_VXDS = 1 +BSM_NETDRIVER = 2 +BSM_INSTALLABLEDRIVERS = 4 +BSM_APPLICATIONS = 8 +BSM_ALLDESKTOPS = 16 +BSF_QUERY = 1 +BSF_IGNORECURRENTTASK = 2 +BSF_FLUSHDISK = 4 +BSF_NOHANG = 8 +BSF_POSTMESSAGE = 16 +BSF_FORCEIFHUNG = 32 +BSF_NOTIMEOUTIFNOTHUNG = 64 +BROADCAST_QUERY_DENY = 1112363332 # Return this value to deny a query. + +DBWF_LPARAMPOINTER = 32768 + +# winuser.h line 3232 +SWP_NOSIZE = 1 +SWP_NOMOVE = 2 +SWP_NOZORDER = 4 +SWP_NOREDRAW = 8 +SWP_NOACTIVATE = 16 +SWP_FRAMECHANGED = 32 +SWP_SHOWWINDOW = 64 +SWP_HIDEWINDOW = 128 +SWP_NOCOPYBITS = 256 +SWP_NOOWNERZORDER = 512 +SWP_NOSENDCHANGING = 1024 +SWP_DRAWFRAME = SWP_FRAMECHANGED +SWP_NOREPOSITION = SWP_NOOWNERZORDER +SWP_DEFERERASE = 8192 +SWP_ASYNCWINDOWPOS = 16384 + +DLGWINDOWEXTRA = 30 +# winuser.h line 4249 +KEYEVENTF_EXTENDEDKEY = 1 +KEYEVENTF_KEYUP = 2 +MOUSEEVENTF_MOVE = 1 +MOUSEEVENTF_LEFTDOWN = 2 +MOUSEEVENTF_LEFTUP = 4 +MOUSEEVENTF_RIGHTDOWN = 8 +MOUSEEVENTF_RIGHTUP = 16 +MOUSEEVENTF_MIDDLEDOWN = 32 +MOUSEEVENTF_MIDDLEUP = 64 +MOUSEEVENTF_ABSOLUTE = 32768 +INPUT_MOUSE = 0 +INPUT_KEYBOARD = 1 +INPUT_HARDWARE = 2 +MWMO_WAITALL = 1 +MWMO_ALERTABLE = 2 +MWMO_INPUTAVAILABLE = 4 +QS_KEY = 1 +QS_MOUSEMOVE = 2 +QS_MOUSEBUTTON = 4 +QS_POSTMESSAGE = 8 +QS_TIMER = 16 +QS_PAINT = 32 +QS_SENDMESSAGE = 64 +QS_HOTKEY = 128 +QS_MOUSE = (QS_MOUSEMOVE | \ + QS_MOUSEBUTTON) +QS_INPUT = (QS_MOUSE | \ + QS_KEY) +QS_ALLEVENTS = (QS_INPUT | \ + QS_POSTMESSAGE | \ + QS_TIMER | \ + QS_PAINT | \ + QS_HOTKEY) +QS_ALLINPUT = (QS_INPUT | \ + QS_POSTMESSAGE | \ + QS_TIMER | \ + QS_PAINT | \ + QS_HOTKEY | \ + QS_SENDMESSAGE) + + +IMN_CLOSESTATUSWINDOW = 1 +IMN_OPENSTATUSWINDOW = 2 +IMN_CHANGECANDIDATE = 3 +IMN_CLOSECANDIDATE = 4 +IMN_OPENCANDIDATE = 5 +IMN_SETCONVERSIONMODE = 6 +IMN_SETSENTENCEMODE = 7 +IMN_SETOPENSTATUS = 8 +IMN_SETCANDIDATEPOS = 9 +IMN_SETCOMPOSITIONFONT = 10 +IMN_SETCOMPOSITIONWINDOW = 11 +IMN_SETSTATUSWINDOWPOS = 12 +IMN_GUIDELINE = 13 +IMN_PRIVATE = 14 + +# winuser.h line 8518 +HELP_CONTEXT = 1 +HELP_QUIT = 2 +HELP_INDEX = 3 +HELP_CONTENTS = 3 +HELP_HELPONHELP = 4 +HELP_SETINDEX = 5 +HELP_SETCONTENTS = 5 +HELP_CONTEXTPOPUP = 8 +HELP_FORCEFILE = 9 +HELP_KEY = 257 +HELP_COMMAND = 258 +HELP_PARTIALKEY = 261 +HELP_MULTIKEY = 513 +HELP_SETWINPOS = 515 +HELP_CONTEXTMENU = 10 +HELP_FINDER = 11 +HELP_WM_HELP = 12 +HELP_SETPOPUP_POS = 13 +HELP_TCARD = 32768 +HELP_TCARD_DATA = 16 +HELP_TCARD_OTHER_CALLER = 17 +IDH_NO_HELP = 28440 +IDH_MISSING_CONTEXT = 28441 # Control doesn't have matching help context +IDH_GENERIC_HELP_BUTTON = 28442 # Property sheet help button +IDH_OK = 28443 +IDH_CANCEL = 28444 +IDH_HELP = 28445 +GR_GDIOBJECTS = 0 # Count of GDI objects +GR_USEROBJECTS = 1 # Count of USER objects +# Generated by h2py from \msvcnt\include\wingdi.h +# manually added (missed by generation some how! +SRCCOPY = 13369376 # dest = source +SRCPAINT = 15597702 # dest = source OR dest +SRCAND = 8913094 # dest = source AND dest +SRCINVERT = 6684742 # dest = source XOR dest +SRCERASE = 4457256 # dest = source AND (NOT dest ) +NOTSRCCOPY = 3342344 # dest = (NOT source) +NOTSRCERASE = 1114278 # dest = (NOT src) AND (NOT dest) +MERGECOPY = 12583114 # dest = (source AND pattern) +MERGEPAINT = 12255782 # dest = (NOT source) OR dest +PATCOPY = 15728673 # dest = pattern +PATPAINT = 16452105 # dest = DPSnoo +PATINVERT = 5898313 # dest = pattern XOR dest +DSTINVERT = 5570569 # dest = (NOT dest) +BLACKNESS = 66 # dest = BLACK +WHITENESS = 16711778 # dest = WHITE + +# hacked and split manually by mhammond. +R2_BLACK = 1 +R2_NOTMERGEPEN = 2 +R2_MASKNOTPEN = 3 +R2_NOTCOPYPEN = 4 +R2_MASKPENNOT = 5 +R2_NOT = 6 +R2_XORPEN = 7 +R2_NOTMASKPEN = 8 +R2_MASKPEN = 9 +R2_NOTXORPEN = 10 +R2_NOP = 11 +R2_MERGENOTPEN = 12 +R2_COPYPEN = 13 +R2_MERGEPENNOT = 14 +R2_MERGEPEN = 15 +R2_WHITE = 16 +R2_LAST = 16 +GDI_ERROR = (-1) +ERROR = 0 +NULLREGION = 1 +SIMPLEREGION = 2 +COMPLEXREGION = 3 +RGN_ERROR = ERROR +RGN_AND = 1 +RGN_OR = 2 +RGN_XOR = 3 +RGN_DIFF = 4 +RGN_COPY = 5 +RGN_MIN = RGN_AND +RGN_MAX = RGN_COPY + +## Stretching modes used with Get/SetStretchBltMode +BLACKONWHITE = 1 +WHITEONBLACK = 2 +COLORONCOLOR = 3 +HALFTONE = 4 +MAXSTRETCHBLTMODE = 4 +STRETCH_ANDSCANS = BLACKONWHITE +STRETCH_ORSCANS = WHITEONBLACK +STRETCH_DELETESCANS = COLORONCOLOR +STRETCH_HALFTONE = HALFTONE + +ALTERNATE = 1 +WINDING = 2 +POLYFILL_LAST = 2 + +## flags used with SetLayout +LAYOUT_RTL = 1 +LAYOUT_BTT = 2 +LAYOUT_VBH = 4 +LAYOUT_ORIENTATIONMASK = LAYOUT_RTL|LAYOUT_BTT|LAYOUT_VBH +LAYOUT_BITMAPORIENTATIONPRESERVED = 8 + +TA_NOUPDATECP = 0 +TA_UPDATECP = 1 +TA_LEFT = 0 +TA_RIGHT = 2 +TA_CENTER = 6 +TA_TOP = 0 +TA_BOTTOM = 8 +TA_BASELINE = 24 +TA_MASK = (TA_BASELINE+TA_CENTER+TA_UPDATECP) +VTA_BASELINE = TA_BASELINE +VTA_LEFT = TA_BOTTOM +VTA_RIGHT = TA_TOP +VTA_CENTER = TA_CENTER +VTA_BOTTOM = TA_RIGHT +VTA_TOP = TA_LEFT +ETO_GRAYED = 1 +ETO_OPAQUE = 2 +ETO_CLIPPED = 4 +ASPECT_FILTERING = 1 +DCB_RESET = 1 +DCB_ACCUMULATE = 2 +DCB_DIRTY = DCB_ACCUMULATE +DCB_SET = (DCB_RESET | DCB_ACCUMULATE) +DCB_ENABLE = 4 +DCB_DISABLE = 8 +META_SETBKCOLOR = 513 +META_SETBKMODE = 258 +META_SETMAPMODE = 259 +META_SETROP2 = 260 +META_SETRELABS = 261 +META_SETPOLYFILLMODE = 262 +META_SETSTRETCHBLTMODE = 263 +META_SETTEXTCHAREXTRA = 264 +META_SETTEXTCOLOR = 521 +META_SETTEXTJUSTIFICATION = 522 +META_SETWINDOWORG = 523 +META_SETWINDOWEXT = 524 +META_SETVIEWPORTORG = 525 +META_SETVIEWPORTEXT = 526 +META_OFFSETWINDOWORG = 527 +META_SCALEWINDOWEXT = 1040 +META_OFFSETVIEWPORTORG = 529 +META_SCALEVIEWPORTEXT = 1042 +META_LINETO = 531 +META_MOVETO = 532 +META_EXCLUDECLIPRECT = 1045 +META_INTERSECTCLIPRECT = 1046 +META_ARC = 2071 +META_ELLIPSE = 1048 +META_FLOODFILL = 1049 +META_PIE = 2074 +META_RECTANGLE = 1051 +META_ROUNDRECT = 1564 +META_PATBLT = 1565 +META_SAVEDC = 30 +META_SETPIXEL = 1055 +META_OFFSETCLIPRGN = 544 +META_TEXTOUT = 1313 +META_BITBLT = 2338 +META_STRETCHBLT = 2851 +META_POLYGON = 804 +META_POLYLINE = 805 +META_ESCAPE = 1574 +META_RESTOREDC = 295 +META_FILLREGION = 552 +META_FRAMEREGION = 1065 +META_INVERTREGION = 298 +META_PAINTREGION = 299 +META_SELECTCLIPREGION = 300 +META_SELECTOBJECT = 301 +META_SETTEXTALIGN = 302 +META_CHORD = 2096 +META_SETMAPPERFLAGS = 561 +META_EXTTEXTOUT = 2610 +META_SETDIBTODEV = 3379 +META_SELECTPALETTE = 564 +META_REALIZEPALETTE = 53 +META_ANIMATEPALETTE = 1078 +META_SETPALENTRIES = 55 +META_POLYPOLYGON = 1336 +META_RESIZEPALETTE = 313 +META_DIBBITBLT = 2368 +META_DIBSTRETCHBLT = 2881 +META_DIBCREATEPATTERNBRUSH = 322 +META_STRETCHDIB = 3907 +META_EXTFLOODFILL = 1352 +META_DELETEOBJECT = 496 +META_CREATEPALETTE = 247 +META_CREATEPATTERNBRUSH = 505 +META_CREATEPENINDIRECT = 762 +META_CREATEFONTINDIRECT = 763 +META_CREATEBRUSHINDIRECT = 764 +META_CREATEREGION = 1791 +FILE_BEGIN = 0 +FILE_CURRENT = 1 +FILE_END = 2 +FILE_FLAG_WRITE_THROUGH = -2147483648 +FILE_FLAG_OVERLAPPED = 1073741824 +FILE_FLAG_NO_BUFFERING = 536870912 +FILE_FLAG_RANDOM_ACCESS = 268435456 +FILE_FLAG_SEQUENTIAL_SCAN = 134217728 +FILE_FLAG_DELETE_ON_CLOSE = 67108864 +FILE_FLAG_BACKUP_SEMANTICS = 33554432 +FILE_FLAG_POSIX_SEMANTICS = 16777216 +CREATE_NEW = 1 +CREATE_ALWAYS = 2 +OPEN_EXISTING = 3 +OPEN_ALWAYS = 4 +TRUNCATE_EXISTING = 5 +PIPE_ACCESS_INBOUND = 1 +PIPE_ACCESS_OUTBOUND = 2 +PIPE_ACCESS_DUPLEX = 3 +PIPE_CLIENT_END = 0 +PIPE_SERVER_END = 1 +PIPE_WAIT = 0 +PIPE_NOWAIT = 1 +PIPE_READMODE_BYTE = 0 +PIPE_READMODE_MESSAGE = 2 +PIPE_TYPE_BYTE = 0 +PIPE_TYPE_MESSAGE = 4 +PIPE_UNLIMITED_INSTANCES = 255 +SECURITY_CONTEXT_TRACKING = 262144 +SECURITY_EFFECTIVE_ONLY = 524288 +SECURITY_SQOS_PRESENT = 1048576 +SECURITY_VALID_SQOS_FLAGS = 2031616 +DTR_CONTROL_DISABLE = 0 +DTR_CONTROL_ENABLE = 1 +DTR_CONTROL_HANDSHAKE = 2 +RTS_CONTROL_DISABLE = 0 +RTS_CONTROL_ENABLE = 1 +RTS_CONTROL_HANDSHAKE = 2 +RTS_CONTROL_TOGGLE = 3 +GMEM_FIXED = 0 +GMEM_MOVEABLE = 2 +GMEM_NOCOMPACT = 16 +GMEM_NODISCARD = 32 +GMEM_ZEROINIT = 64 +GMEM_MODIFY = 128 +GMEM_DISCARDABLE = 256 +GMEM_NOT_BANKED = 4096 +GMEM_SHARE = 8192 +GMEM_DDESHARE = 8192 +GMEM_NOTIFY = 16384 +GMEM_LOWER = GMEM_NOT_BANKED +GMEM_VALID_FLAGS = 32626 +GMEM_INVALID_HANDLE = 32768 +GHND = (GMEM_MOVEABLE | GMEM_ZEROINIT) +GPTR = (GMEM_FIXED | GMEM_ZEROINIT) +GMEM_DISCARDED = 16384 +GMEM_LOCKCOUNT = 255 +LMEM_FIXED = 0 +LMEM_MOVEABLE = 2 +LMEM_NOCOMPACT = 16 +LMEM_NODISCARD = 32 +LMEM_ZEROINIT = 64 +LMEM_MODIFY = 128 +LMEM_DISCARDABLE = 3840 +LMEM_VALID_FLAGS = 3954 +LMEM_INVALID_HANDLE = 32768 +LHND = (LMEM_MOVEABLE | LMEM_ZEROINIT) +LPTR = (LMEM_FIXED | LMEM_ZEROINIT) +NONZEROLHND = (LMEM_MOVEABLE) +NONZEROLPTR = (LMEM_FIXED) +LMEM_DISCARDED = 16384 +LMEM_LOCKCOUNT = 255 +DEBUG_PROCESS = 1 +DEBUG_ONLY_THIS_PROCESS = 2 +CREATE_SUSPENDED = 4 +DETACHED_PROCESS = 8 +CREATE_NEW_CONSOLE = 16 +NORMAL_PRIORITY_CLASS = 32 +IDLE_PRIORITY_CLASS = 64 +HIGH_PRIORITY_CLASS = 128 +REALTIME_PRIORITY_CLASS = 256 +CREATE_NEW_PROCESS_GROUP = 512 +CREATE_UNICODE_ENVIRONMENT = 1024 +CREATE_SEPARATE_WOW_VDM = 2048 +CREATE_SHARED_WOW_VDM = 4096 +CREATE_DEFAULT_ERROR_MODE = 67108864 +CREATE_NO_WINDOW = 134217728 +PROFILE_USER = 268435456 +PROFILE_KERNEL = 536870912 +PROFILE_SERVER = 1073741824 +THREAD_BASE_PRIORITY_LOWRT = 15 +THREAD_BASE_PRIORITY_MAX = 2 +THREAD_BASE_PRIORITY_MIN = -2 +THREAD_BASE_PRIORITY_IDLE = -15 +THREAD_PRIORITY_LOWEST = THREAD_BASE_PRIORITY_MIN +THREAD_PRIORITY_BELOW_NORMAL = THREAD_PRIORITY_LOWEST+1 +THREAD_PRIORITY_HIGHEST = THREAD_BASE_PRIORITY_MAX +THREAD_PRIORITY_ABOVE_NORMAL = THREAD_PRIORITY_HIGHEST-1 +THREAD_PRIORITY_ERROR_RETURN = MAXLONG +THREAD_PRIORITY_TIME_CRITICAL = THREAD_BASE_PRIORITY_LOWRT +THREAD_PRIORITY_IDLE = THREAD_BASE_PRIORITY_IDLE +THREAD_PRIORITY_NORMAL = 0 +THREAD_MODE_BACKGROUND_BEGIN = 0x00010000 +THREAD_MODE_BACKGROUND_END = 0x00020000 + +EXCEPTION_DEBUG_EVENT = 1 +CREATE_THREAD_DEBUG_EVENT = 2 +CREATE_PROCESS_DEBUG_EVENT = 3 +EXIT_THREAD_DEBUG_EVENT = 4 +EXIT_PROCESS_DEBUG_EVENT = 5 +LOAD_DLL_DEBUG_EVENT = 6 +UNLOAD_DLL_DEBUG_EVENT = 7 +OUTPUT_DEBUG_STRING_EVENT = 8 +RIP_EVENT = 9 +DRIVE_UNKNOWN = 0 +DRIVE_NO_ROOT_DIR = 1 +DRIVE_REMOVABLE = 2 +DRIVE_FIXED = 3 +DRIVE_REMOTE = 4 +DRIVE_CDROM = 5 +DRIVE_RAMDISK = 6 +FILE_TYPE_UNKNOWN = 0 +FILE_TYPE_DISK = 1 +FILE_TYPE_CHAR = 2 +FILE_TYPE_PIPE = 3 +FILE_TYPE_REMOTE = 32768 +NOPARITY = 0 +ODDPARITY = 1 +EVENPARITY = 2 +MARKPARITY = 3 +SPACEPARITY = 4 +ONESTOPBIT = 0 +ONE5STOPBITS = 1 +TWOSTOPBITS = 2 +CBR_110 = 110 +CBR_300 = 300 +CBR_600 = 600 +CBR_1200 = 1200 +CBR_2400 = 2400 +CBR_4800 = 4800 +CBR_9600 = 9600 +CBR_14400 = 14400 +CBR_19200 = 19200 +CBR_38400 = 38400 +CBR_56000 = 56000 +CBR_57600 = 57600 +CBR_115200 = 115200 +CBR_128000 = 128000 +CBR_256000 = 256000 +S_QUEUEEMPTY = 0 +S_THRESHOLD = 1 +S_ALLTHRESHOLD = 2 +S_NORMAL = 0 +S_LEGATO = 1 +S_STACCATO = 2 +NMPWAIT_WAIT_FOREVER = -1 +NMPWAIT_NOWAIT = 1 +NMPWAIT_USE_DEFAULT_WAIT = 0 +OF_READ = 0 +OF_WRITE = 1 +OF_READWRITE = 2 +OF_SHARE_COMPAT = 0 +OF_SHARE_EXCLUSIVE = 16 +OF_SHARE_DENY_WRITE = 32 +OF_SHARE_DENY_READ = 48 +OF_SHARE_DENY_NONE = 64 +OF_PARSE = 256 +OF_DELETE = 512 +OF_VERIFY = 1024 +OF_CANCEL = 2048 +OF_CREATE = 4096 +OF_PROMPT = 8192 +OF_EXIST = 16384 +OF_REOPEN = 32768 +OFS_MAXPATHNAME = 128 +MAXINTATOM = 49152 + +# winbase.h +PROCESS_HEAP_REGION = 1 +PROCESS_HEAP_UNCOMMITTED_RANGE = 2 +PROCESS_HEAP_ENTRY_BUSY = 4 +PROCESS_HEAP_ENTRY_MOVEABLE = 16 +PROCESS_HEAP_ENTRY_DDESHARE = 32 +SCS_32BIT_BINARY = 0 +SCS_DOS_BINARY = 1 +SCS_WOW_BINARY = 2 +SCS_PIF_BINARY = 3 +SCS_POSIX_BINARY = 4 +SCS_OS216_BINARY = 5 +SEM_FAILCRITICALERRORS = 1 +SEM_NOGPFAULTERRORBOX = 2 +SEM_NOALIGNMENTFAULTEXCEPT = 4 +SEM_NOOPENFILEERRORBOX = 32768 +LOCKFILE_FAIL_IMMEDIATELY = 1 +LOCKFILE_EXCLUSIVE_LOCK = 2 +HANDLE_FLAG_INHERIT = 1 +HANDLE_FLAG_PROTECT_FROM_CLOSE = 2 +HINSTANCE_ERROR = 32 +GET_TAPE_MEDIA_INFORMATION = 0 +GET_TAPE_DRIVE_INFORMATION = 1 +SET_TAPE_MEDIA_INFORMATION = 0 +SET_TAPE_DRIVE_INFORMATION = 1 +FORMAT_MESSAGE_ALLOCATE_BUFFER = 256 +FORMAT_MESSAGE_IGNORE_INSERTS = 512 +FORMAT_MESSAGE_FROM_STRING = 1024 +FORMAT_MESSAGE_FROM_HMODULE = 2048 +FORMAT_MESSAGE_FROM_SYSTEM = 4096 +FORMAT_MESSAGE_ARGUMENT_ARRAY = 8192 +FORMAT_MESSAGE_MAX_WIDTH_MASK = 255 +BACKUP_INVALID = 0 +BACKUP_DATA = 1 +BACKUP_EA_DATA = 2 +BACKUP_SECURITY_DATA = 3 +BACKUP_ALTERNATE_DATA = 4 +BACKUP_LINK = 5 +BACKUP_PROPERTY_DATA = 6 +BACKUP_OBJECT_ID = 7 +BACKUP_REPARSE_DATA = 8 +BACKUP_SPARSE_BLOCK = 9 + +STREAM_NORMAL_ATTRIBUTE = 0 +STREAM_MODIFIED_WHEN_READ = 1 +STREAM_CONTAINS_SECURITY = 2 +STREAM_CONTAINS_PROPERTIES = 4 +STARTF_USESHOWWINDOW = 1 +STARTF_USESIZE = 2 +STARTF_USEPOSITION = 4 +STARTF_USECOUNTCHARS = 8 +STARTF_USEFILLATTRIBUTE = 16 +STARTF_FORCEONFEEDBACK = 64 +STARTF_FORCEOFFFEEDBACK = 128 +STARTF_USESTDHANDLES = 256 +STARTF_USEHOTKEY = 512 +SHUTDOWN_NORETRY = 1 +DONT_RESOLVE_DLL_REFERENCES = 1 +LOAD_LIBRARY_AS_DATAFILE = 2 +LOAD_WITH_ALTERED_SEARCH_PATH = 8 +DDD_RAW_TARGET_PATH = 1 +DDD_REMOVE_DEFINITION = 2 +DDD_EXACT_MATCH_ON_REMOVE = 4 +MOVEFILE_REPLACE_EXISTING = 1 +MOVEFILE_COPY_ALLOWED = 2 +MOVEFILE_DELAY_UNTIL_REBOOT = 4 +MAX_COMPUTERNAME_LENGTH = 15 +LOGON32_LOGON_INTERACTIVE = 2 +LOGON32_LOGON_NETWORK = 3 +LOGON32_LOGON_BATCH = 4 +LOGON32_LOGON_SERVICE = 5 +LOGON32_LOGON_UNLOCK = 7 +LOGON32_LOGON_NETWORK_CLEARTEXT = 8 +LOGON32_LOGON_NEW_CREDENTIALS = 9 +LOGON32_PROVIDER_DEFAULT = 0 +LOGON32_PROVIDER_WINNT35 = 1 +LOGON32_PROVIDER_WINNT40 = 2 +LOGON32_PROVIDER_WINNT50 = 3 +VER_PLATFORM_WIN32s = 0 +VER_PLATFORM_WIN32_WINDOWS = 1 +VER_PLATFORM_WIN32_NT = 2 +TC_NORMAL = 0 +TC_HARDERR = 1 +TC_GP_TRAP = 2 +TC_SIGNAL = 3 +AC_LINE_OFFLINE = 0 +AC_LINE_ONLINE = 1 +AC_LINE_BACKUP_POWER = 2 +AC_LINE_UNKNOWN = 255 +BATTERY_FLAG_HIGH = 1 +BATTERY_FLAG_LOW = 2 +BATTERY_FLAG_CRITICAL = 4 +BATTERY_FLAG_CHARGING = 8 +BATTERY_FLAG_NO_BATTERY = 128 +BATTERY_FLAG_UNKNOWN = 255 +BATTERY_PERCENTAGE_UNKNOWN = 255 +BATTERY_LIFE_UNKNOWN = -1 + +# Generated by h2py from d:\msdev\include\richedit.h +cchTextLimitDefault = 32767 +WM_CONTEXTMENU = 123 +WM_PRINTCLIENT = 792 +EN_MSGFILTER = 1792 +EN_REQUESTRESIZE = 1793 +EN_SELCHANGE = 1794 +EN_DROPFILES = 1795 +EN_PROTECTED = 1796 +EN_CORRECTTEXT = 1797 +EN_STOPNOUNDO = 1798 +EN_IMECHANGE = 1799 +EN_SAVECLIPBOARD = 1800 +EN_OLEOPFAILED = 1801 +ENM_NONE = 0 +ENM_CHANGE = 1 +ENM_UPDATE = 2 +ENM_SCROLL = 4 +ENM_KEYEVENTS = 65536 +ENM_MOUSEEVENTS = 131072 +ENM_REQUESTRESIZE = 262144 +ENM_SELCHANGE = 524288 +ENM_DROPFILES = 1048576 +ENM_PROTECTED = 2097152 +ENM_CORRECTTEXT = 4194304 +ENM_IMECHANGE = 8388608 +ES_SAVESEL = 32768 +ES_SUNKEN = 16384 +ES_DISABLENOSCROLL = 8192 +ES_SELECTIONBAR = 16777216 +ES_EX_NOCALLOLEINIT = 16777216 +ES_VERTICAL = 4194304 +ES_NOIME = 524288 +ES_SELFIME = 262144 +ECO_AUTOWORDSELECTION = 1 +ECO_AUTOVSCROLL = 64 +ECO_AUTOHSCROLL = 128 +ECO_NOHIDESEL = 256 +ECO_READONLY = 2048 +ECO_WANTRETURN = 4096 +ECO_SAVESEL = 32768 +ECO_SELECTIONBAR = 16777216 +ECO_VERTICAL = 4194304 +ECOOP_SET = 1 +ECOOP_OR = 2 +ECOOP_AND = 3 +ECOOP_XOR = 4 +WB_CLASSIFY = 3 +WB_MOVEWORDLEFT = 4 +WB_MOVEWORDRIGHT = 5 +WB_LEFTBREAK = 6 +WB_RIGHTBREAK = 7 +WB_MOVEWORDPREV = 4 +WB_MOVEWORDNEXT = 5 +WB_PREVBREAK = 6 +WB_NEXTBREAK = 7 +PC_FOLLOWING = 1 +PC_LEADING = 2 +PC_OVERFLOW = 3 +PC_DELIMITER = 4 +WBF_WORDWRAP = 16 +WBF_WORDBREAK = 32 +WBF_OVERFLOW = 64 +WBF_LEVEL1 = 128 +WBF_LEVEL2 = 256 +WBF_CUSTOM = 512 +CFM_BOLD = 1 +CFM_ITALIC = 2 +CFM_UNDERLINE = 4 +CFM_STRIKEOUT = 8 +CFM_PROTECTED = 16 +CFM_SIZE = -2147483648 +CFM_COLOR = 1073741824 +CFM_FACE = 536870912 +CFM_OFFSET = 268435456 +CFM_CHARSET = 134217728 +CFE_BOLD = 1 +CFE_ITALIC = 2 +CFE_UNDERLINE = 4 +CFE_STRIKEOUT = 8 +CFE_PROTECTED = 16 +CFE_AUTOCOLOR = 1073741824 +yHeightCharPtsMost = 1638 +SCF_SELECTION = 1 +SCF_WORD = 2 +SF_TEXT = 1 +SF_RTF = 2 +SF_RTFNOOBJS = 3 +SF_TEXTIZED = 4 +SFF_SELECTION = 32768 +SFF_PLAINRTF = 16384 +MAX_TAB_STOPS = 32 +lDefaultTab = 720 +PFM_STARTINDENT = 1 +PFM_RIGHTINDENT = 2 +PFM_OFFSET = 4 +PFM_ALIGNMENT = 8 +PFM_TABSTOPS = 16 +PFM_NUMBERING = 32 +PFM_OFFSETINDENT = -2147483648 +PFN_BULLET = 1 +PFA_LEFT = 1 +PFA_RIGHT = 2 +PFA_CENTER = 3 +WM_NOTIFY = 78 +SEL_EMPTY = 0 +SEL_TEXT = 1 +SEL_OBJECT = 2 +SEL_MULTICHAR = 4 +SEL_MULTIOBJECT = 8 +OLEOP_DOVERB = 1 +CF_RTF = "Rich Text Format" +CF_RTFNOOBJS = "Rich Text Format Without Objects" +CF_RETEXTOBJ = "RichEdit Text and Objects" + +# From wincon.h +RIGHT_ALT_PRESSED = 1 # the right alt key is pressed. +LEFT_ALT_PRESSED = 2 # the left alt key is pressed. +RIGHT_CTRL_PRESSED = 4 # the right ctrl key is pressed. +LEFT_CTRL_PRESSED = 8 # the left ctrl key is pressed. +SHIFT_PRESSED = 16 # the shift key is pressed. +NUMLOCK_ON = 32 # the numlock light is on. +SCROLLLOCK_ON = 64 # the scrolllock light is on. +CAPSLOCK_ON = 128 # the capslock light is on. +ENHANCED_KEY = 256 # the key is enhanced. +NLS_DBCSCHAR = 65536 # DBCS for JPN: SBCS/DBCS mode. +NLS_ALPHANUMERIC = 0 # DBCS for JPN: Alphanumeric mode. +NLS_KATAKANA = 131072 # DBCS for JPN: Katakana mode. +NLS_HIRAGANA = 262144 # DBCS for JPN: Hiragana mode. +NLS_ROMAN = 4194304 # DBCS for JPN: Roman/Noroman mode. +NLS_IME_CONVERSION = 8388608 # DBCS for JPN: IME conversion. +NLS_IME_DISABLE = 536870912 # DBCS for JPN: IME enable/disable. + +FROM_LEFT_1ST_BUTTON_PRESSED = 1 +RIGHTMOST_BUTTON_PRESSED = 2 +FROM_LEFT_2ND_BUTTON_PRESSED = 4 +FROM_LEFT_3RD_BUTTON_PRESSED = 8 +FROM_LEFT_4TH_BUTTON_PRESSED = 16 + +CTRL_C_EVENT = 0 +CTRL_BREAK_EVENT = 1 +CTRL_CLOSE_EVENT = 2 +CTRL_LOGOFF_EVENT = 5 +CTRL_SHUTDOWN_EVENT = 6 + +MOUSE_MOVED = 1 +DOUBLE_CLICK = 2 +MOUSE_WHEELED = 4 + +#property sheet window messages from prsht.h +PSM_SETCURSEL = (WM_USER + 101) +PSM_REMOVEPAGE = (WM_USER + 102) +PSM_ADDPAGE = (WM_USER + 103) +PSM_CHANGED = (WM_USER + 104) +PSM_RESTARTWINDOWS = (WM_USER + 105) +PSM_REBOOTSYSTEM = (WM_USER + 106) +PSM_CANCELTOCLOSE = (WM_USER + 107) +PSM_QUERYSIBLINGS = (WM_USER + 108) +PSM_UNCHANGED = (WM_USER + 109) +PSM_APPLY = (WM_USER + 110) +PSM_SETTITLEA = (WM_USER + 111) +PSM_SETTITLEW = (WM_USER + 120) +PSM_SETWIZBUTTONS = (WM_USER + 112) +PSM_PRESSBUTTON = (WM_USER + 113) +PSM_SETCURSELID = (WM_USER + 114) +PSM_SETFINISHTEXTA = (WM_USER + 115) +PSM_SETFINISHTEXTW = (WM_USER + 121) +PSM_GETTABCONTROL = (WM_USER + 116) +PSM_ISDIALOGMESSAGE = (WM_USER + 117) +PSM_GETCURRENTPAGEHWND = (WM_USER + 118) +PSM_INSERTPAGE = (WM_USER + 119) +PSM_SETHEADERTITLEA = (WM_USER + 125) +PSM_SETHEADERTITLEW = (WM_USER + 126) +PSM_SETHEADERSUBTITLEA = (WM_USER + 127) +PSM_SETHEADERSUBTITLEW = (WM_USER + 128) +PSM_HWNDTOINDEX = (WM_USER + 129) +PSM_INDEXTOHWND = (WM_USER + 130) +PSM_PAGETOINDEX = (WM_USER + 131) +PSM_INDEXTOPAGE = (WM_USER + 132) +PSM_IDTOINDEX = (WM_USER + 133) +PSM_INDEXTOID = (WM_USER + 134) +PSM_GETRESULT = (WM_USER + 135) +PSM_RECALCPAGESIZES = (WM_USER + 136) + +# GetUserNameEx/GetComputerNameEx +NameUnknown = 0 +NameFullyQualifiedDN = 1 +NameSamCompatible = 2 +NameDisplay = 3 +NameUniqueId = 6 +NameCanonical = 7 +NameUserPrincipal = 8 +NameCanonicalEx = 9 +NameServicePrincipal = 10 +NameDnsDomain = 12 + +ComputerNameNetBIOS = 0 +ComputerNameDnsHostname = 1 +ComputerNameDnsDomain = 2 +ComputerNameDnsFullyQualified = 3 +ComputerNamePhysicalNetBIOS = 4 +ComputerNamePhysicalDnsHostname = 5 +ComputerNamePhysicalDnsDomain = 6 +ComputerNamePhysicalDnsFullyQualified = 7 + +LWA_COLORKEY = 0x00000001 +LWA_ALPHA = 0x00000002 +ULW_COLORKEY = 0x00000001 +ULW_ALPHA = 0x00000002 +ULW_OPAQUE = 0x00000004 + +# WinDef.h +TRUE = 1 +FALSE = 0 +MAX_PATH = 260 +# WinGDI.h +AC_SRC_OVER = 0 +AC_SRC_ALPHA = 1 +GRADIENT_FILL_RECT_H = 0 +GRADIENT_FILL_RECT_V = 1 +GRADIENT_FILL_TRIANGLE = 2 +GRADIENT_FILL_OP_FLAG = 255 + +## flags used with Get/SetSystemFileCacheSize +MM_WORKING_SET_MAX_HARD_ENABLE = 1 +MM_WORKING_SET_MAX_HARD_DISABLE = 2 +MM_WORKING_SET_MIN_HARD_ENABLE = 4 +MM_WORKING_SET_MIN_HARD_DISABLE = 8 + +## Flags for GetFinalPathNameByHandle +VOLUME_NAME_DOS = 0 +VOLUME_NAME_GUID = 1 +VOLUME_NAME_NT = 2 +VOLUME_NAME_NONE = 4 +FILE_NAME_NORMALIZED = 0 +FILE_NAME_OPENED = 8 + +DEVICE_NOTIFY_WINDOW_HANDLE = 0x00000000 +DEVICE_NOTIFY_SERVICE_HANDLE = 0x00000001 + +# From Dbt.h +# Generated by h2py from Dbt.h +WM_DEVICECHANGE = 0x0219 +BSF_QUERY = 0x00000001 +BSF_IGNORECURRENTTASK = 0x00000002 +BSF_FLUSHDISK = 0x00000004 +BSF_NOHANG = 0x00000008 +BSF_POSTMESSAGE = 0x00000010 +BSF_FORCEIFHUNG = 0x00000020 +BSF_NOTIMEOUTIFNOTHUNG = 0x00000040 +BSF_MSGSRV32ISOK = (-2147483648) +BSF_MSGSRV32ISOK_BIT = 31 +BSM_ALLCOMPONENTS = 0x00000000 +BSM_VXDS = 0x00000001 +BSM_NETDRIVER = 0x00000002 +BSM_INSTALLABLEDRIVERS = 0x00000004 +BSM_APPLICATIONS = 0x00000008 +DBT_APPYBEGIN = 0x0000 +DBT_APPYEND = 0x0001 +DBT_DEVNODES_CHANGED = 0x0007 +DBT_QUERYCHANGECONFIG = 0x0017 +DBT_CONFIGCHANGED = 0x0018 +DBT_CONFIGCHANGECANCELED = 0x0019 +DBT_MONITORCHANGE = 0x001B +DBT_SHELLLOGGEDON = 0x0020 +DBT_CONFIGMGAPI32 = 0x0022 +DBT_VXDINITCOMPLETE = 0x0023 +DBT_VOLLOCKQUERYLOCK = 0x8041 +DBT_VOLLOCKLOCKTAKEN = 0x8042 +DBT_VOLLOCKLOCKFAILED = 0x8043 +DBT_VOLLOCKQUERYUNLOCK = 0x8044 +DBT_VOLLOCKLOCKRELEASED = 0x8045 +DBT_VOLLOCKUNLOCKFAILED = 0x8046 +LOCKP_ALLOW_WRITES = 0x01 +LOCKP_FAIL_WRITES = 0x00 +LOCKP_FAIL_MEM_MAPPING = 0x02 +LOCKP_ALLOW_MEM_MAPPING = 0x00 +LOCKP_USER_MASK = 0x03 +LOCKP_LOCK_FOR_FORMAT = 0x04 +LOCKF_LOGICAL_LOCK = 0x00 +LOCKF_PHYSICAL_LOCK = 0x01 +DBT_NO_DISK_SPACE = 0x0047 +DBT_LOW_DISK_SPACE = 0x0048 +DBT_CONFIGMGPRIVATE = 0x7FFF +DBT_DEVICEARRIVAL = 0x8000 +DBT_DEVICEQUERYREMOVE = 0x8001 +DBT_DEVICEQUERYREMOVEFAILED = 0x8002 +DBT_DEVICEREMOVEPENDING = 0x8003 +DBT_DEVICEREMOVECOMPLETE = 0x8004 +DBT_DEVICETYPESPECIFIC = 0x8005 +DBT_CUSTOMEVENT = 0x8006 +DBT_DEVTYP_OEM = 0x00000000 +DBT_DEVTYP_DEVNODE = 0x00000001 +DBT_DEVTYP_VOLUME = 0x00000002 +DBT_DEVTYP_PORT = 0x00000003 +DBT_DEVTYP_NET = 0x00000004 +DBT_DEVTYP_DEVICEINTERFACE = 0x00000005 +DBT_DEVTYP_HANDLE = 0x00000006 +DBTF_MEDIA = 0x0001 +DBTF_NET = 0x0002 +DBTF_RESOURCE = 0x00000001 +DBTF_XPORT = 0x00000002 +DBTF_SLOWNET = 0x00000004 +DBT_VPOWERDAPI = 0x8100 +DBT_USERDEFINED = 0xFFFF diff --git a/Lib/site-packages/win32/lib/win32cryptcon.py b/Lib/site-packages/win32/lib/win32cryptcon.py new file mode 100644 index 0000000..f56b5e2 --- /dev/null +++ b/Lib/site-packages/win32/lib/win32cryptcon.py @@ -0,0 +1,1900 @@ +# Generated by h2py from WinCrypt.h +def GET_ALG_CLASS(x): return (x & (7 << 13)) + +def GET_ALG_TYPE(x): return (x & (15 << 9)) + +def GET_ALG_SID(x): return (x & (511)) + +ALG_CLASS_ANY = (0) +ALG_CLASS_SIGNATURE = (1 << 13) +ALG_CLASS_MSG_ENCRYPT = (2 << 13) +ALG_CLASS_DATA_ENCRYPT = (3 << 13) +ALG_CLASS_HASH = (4 << 13) +ALG_CLASS_KEY_EXCHANGE = (5 << 13) +ALG_CLASS_ALL = (7 << 13) +ALG_TYPE_ANY = (0) +ALG_TYPE_DSS = (1 << 9) +ALG_TYPE_RSA = (2 << 9) +ALG_TYPE_BLOCK = (3 << 9) +ALG_TYPE_STREAM = (4 << 9) +ALG_TYPE_DH = (5 << 9) +ALG_TYPE_SECURECHANNEL = (6 << 9) +ALG_SID_ANY = (0) +ALG_SID_RSA_ANY = 0 +ALG_SID_RSA_PKCS = 1 +ALG_SID_RSA_MSATWORK = 2 +ALG_SID_RSA_ENTRUST = 3 +ALG_SID_RSA_PGP = 4 +ALG_SID_DSS_ANY = 0 +ALG_SID_DSS_PKCS = 1 +ALG_SID_DSS_DMS = 2 +ALG_SID_DES = 1 +ALG_SID_3DES = 3 +ALG_SID_DESX = 4 +ALG_SID_IDEA = 5 +ALG_SID_CAST = 6 +ALG_SID_SAFERSK64 = 7 +ALG_SID_SAFERSK128 = 8 +ALG_SID_3DES_112 = 9 +ALG_SID_CYLINK_MEK = 12 +ALG_SID_RC5 = 13 +ALG_SID_AES_128 = 14 +ALG_SID_AES_192 = 15 +ALG_SID_AES_256 = 16 +ALG_SID_AES = 17 +ALG_SID_SKIPJACK = 10 +ALG_SID_TEK = 11 +CRYPT_MODE_CBCI = 6 +CRYPT_MODE_CFBP = 7 +CRYPT_MODE_OFBP = 8 +CRYPT_MODE_CBCOFM = 9 +CRYPT_MODE_CBCOFMI = 10 +ALG_SID_RC2 = 2 +ALG_SID_RC4 = 1 +ALG_SID_SEAL = 2 +ALG_SID_DH_SANDF = 1 +ALG_SID_DH_EPHEM = 2 +ALG_SID_AGREED_KEY_ANY = 3 +ALG_SID_KEA = 4 +ALG_SID_MD2 = 1 +ALG_SID_MD4 = 2 +ALG_SID_MD5 = 3 +ALG_SID_SHA = 4 +ALG_SID_SHA1 = 4 +ALG_SID_MAC = 5 +ALG_SID_RIPEMD = 6 +ALG_SID_RIPEMD160 = 7 +ALG_SID_SSL3SHAMD5 = 8 +ALG_SID_HMAC = 9 +ALG_SID_TLS1PRF = 10 +ALG_SID_HASH_REPLACE_OWF = 11 +ALG_SID_SHA_256 = 12 +ALG_SID_SHA_384 = 13 +ALG_SID_SHA_512 = 14 +ALG_SID_SSL3_MASTER = 1 +ALG_SID_SCHANNEL_MASTER_HASH = 2 +ALG_SID_SCHANNEL_MAC_KEY = 3 +ALG_SID_PCT1_MASTER = 4 +ALG_SID_SSL2_MASTER = 5 +ALG_SID_TLS1_MASTER = 6 +ALG_SID_SCHANNEL_ENC_KEY = 7 +ALG_SID_EXAMPLE = 80 +CALG_MD2 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD2) +CALG_MD4 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD4) +CALG_MD5 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD5) +CALG_SHA = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA) +CALG_SHA1 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA1) +CALG_MAC = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MAC) +CALG_RSA_SIGN = (ALG_CLASS_SIGNATURE | ALG_TYPE_RSA | ALG_SID_RSA_ANY) +CALG_DSS_SIGN = (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | ALG_SID_DSS_ANY) +CALG_NO_SIGN = (ALG_CLASS_SIGNATURE | ALG_TYPE_ANY | ALG_SID_ANY) +CALG_RSA_KEYX = (ALG_CLASS_KEY_EXCHANGE|ALG_TYPE_RSA|ALG_SID_RSA_ANY) +CALG_DES = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_DES) +CALG_3DES_112 = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_3DES_112) +CALG_3DES = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_3DES) +CALG_DESX = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_DESX) +CALG_RC2 = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_RC2) +CALG_RC4 = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_STREAM|ALG_SID_RC4) +CALG_SEAL = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_STREAM|ALG_SID_SEAL) +CALG_DH_SF = (ALG_CLASS_KEY_EXCHANGE|ALG_TYPE_DH|ALG_SID_DH_SANDF) +CALG_DH_EPHEM = (ALG_CLASS_KEY_EXCHANGE|ALG_TYPE_DH|ALG_SID_DH_EPHEM) +CALG_AGREEDKEY_ANY = (ALG_CLASS_KEY_EXCHANGE|ALG_TYPE_DH|ALG_SID_AGREED_KEY_ANY) +CALG_KEA_KEYX = (ALG_CLASS_KEY_EXCHANGE|ALG_TYPE_DH|ALG_SID_KEA) +CALG_HUGHES_MD5 = (ALG_CLASS_KEY_EXCHANGE|ALG_TYPE_ANY|ALG_SID_MD5) +CALG_SKIPJACK = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_SKIPJACK) +CALG_TEK = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_TEK) +CALG_CYLINK_MEK = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_CYLINK_MEK) +CALG_SSL3_SHAMD5 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SSL3SHAMD5) +CALG_SSL3_MASTER = (ALG_CLASS_MSG_ENCRYPT|ALG_TYPE_SECURECHANNEL|ALG_SID_SSL3_MASTER) +CALG_SCHANNEL_MASTER_HASH = (ALG_CLASS_MSG_ENCRYPT|ALG_TYPE_SECURECHANNEL|ALG_SID_SCHANNEL_MASTER_HASH) +CALG_SCHANNEL_MAC_KEY = (ALG_CLASS_MSG_ENCRYPT|ALG_TYPE_SECURECHANNEL|ALG_SID_SCHANNEL_MAC_KEY) +CALG_SCHANNEL_ENC_KEY = (ALG_CLASS_MSG_ENCRYPT|ALG_TYPE_SECURECHANNEL|ALG_SID_SCHANNEL_ENC_KEY) +CALG_PCT1_MASTER = (ALG_CLASS_MSG_ENCRYPT|ALG_TYPE_SECURECHANNEL|ALG_SID_PCT1_MASTER) +CALG_SSL2_MASTER = (ALG_CLASS_MSG_ENCRYPT|ALG_TYPE_SECURECHANNEL|ALG_SID_SSL2_MASTER) +CALG_TLS1_MASTER = (ALG_CLASS_MSG_ENCRYPT|ALG_TYPE_SECURECHANNEL|ALG_SID_TLS1_MASTER) +CALG_RC5 = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_RC5) +CALG_HMAC = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC) +CALG_TLS1PRF = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_TLS1PRF) +CALG_HASH_REPLACE_OWF = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HASH_REPLACE_OWF) +CALG_AES_128 = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_AES_128) +CALG_AES_192 = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_AES_192) +CALG_AES_256 = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_AES_256) +CALG_AES = (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_AES) +CALG_SHA_256 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256) +CALG_SHA_384 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_384) +CALG_SHA_512 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_512) +CRYPT_VERIFYCONTEXT = (-268435456) +CRYPT_NEWKEYSET = 0x00000008 +CRYPT_DELETEKEYSET = 0x00000010 +CRYPT_MACHINE_KEYSET = 0x00000020 +CRYPT_SILENT = 0x00000040 +CRYPT_EXPORTABLE = 0x00000001 +CRYPT_USER_PROTECTED = 0x00000002 +CRYPT_CREATE_SALT = 0x00000004 +CRYPT_UPDATE_KEY = 0x00000008 +CRYPT_NO_SALT = 0x00000010 +CRYPT_PREGEN = 0x00000040 +CRYPT_RECIPIENT = 0x00000010 +CRYPT_INITIATOR = 0x00000040 +CRYPT_ONLINE = 0x00000080 +CRYPT_SF = 0x00000100 +CRYPT_CREATE_IV = 0x00000200 +CRYPT_KEK = 0x00000400 +CRYPT_DATA_KEY = 0x00000800 +CRYPT_VOLATILE = 0x00001000 +CRYPT_SGCKEY = 0x00002000 +CRYPT_ARCHIVABLE = 0x00004000 +RSA1024BIT_KEY = 0x04000000 +CRYPT_SERVER = 0x00000400 +KEY_LENGTH_MASK = (-65536) +CRYPT_Y_ONLY = 0x00000001 +CRYPT_SSL2_FALLBACK = 0x00000002 +CRYPT_DESTROYKEY = 0x00000004 +CRYPT_OAEP = 0x00000040 +CRYPT_BLOB_VER3 = 0x00000080 +CRYPT_IPSEC_HMAC_KEY = 0x00000100 +CRYPT_DECRYPT_RSA_NO_PADDING_CHECK = 0x00000020 +CRYPT_SECRETDIGEST = 0x00000001 +CRYPT_OWF_REPL_LM_HASH = 0x00000001 +CRYPT_LITTLE_ENDIAN = 0x00000001 +CRYPT_NOHASHOID = 0x00000001 +CRYPT_TYPE2_FORMAT = 0x00000002 +CRYPT_X931_FORMAT = 0x00000004 +CRYPT_MACHINE_DEFAULT = 0x00000001 +CRYPT_USER_DEFAULT = 0x00000002 +CRYPT_DELETE_DEFAULT = 0x00000004 +SIMPLEBLOB = 0x1 +PUBLICKEYBLOB = 0x6 +PRIVATEKEYBLOB = 0x7 +PLAINTEXTKEYBLOB = 0x8 +OPAQUEKEYBLOB = 0x9 +PUBLICKEYBLOBEX = 0xA +SYMMETRICWRAPKEYBLOB = 0xB +AT_KEYEXCHANGE = 1 +AT_SIGNATURE = 2 +CRYPT_USERDATA = 1 +KP_IV = 1 +KP_SALT = 2 +KP_PADDING = 3 +KP_MODE = 4 +KP_MODE_BITS = 5 +KP_PERMISSIONS = 6 +KP_ALGID = 7 +KP_BLOCKLEN = 8 +KP_KEYLEN = 9 +KP_SALT_EX = 10 +KP_P = 11 +KP_G = 12 +KP_Q = 13 +KP_X = 14 +KP_Y = 15 +KP_RA = 16 +KP_RB = 17 +KP_INFO = 18 +KP_EFFECTIVE_KEYLEN = 19 +KP_SCHANNEL_ALG = 20 +KP_CLIENT_RANDOM = 21 +KP_SERVER_RANDOM = 22 +KP_RP = 23 +KP_PRECOMP_MD5 = 24 +KP_PRECOMP_SHA = 25 +KP_CERTIFICATE = 26 +KP_CLEAR_KEY = 27 +KP_PUB_EX_LEN = 28 +KP_PUB_EX_VAL = 29 +KP_KEYVAL = 30 +KP_ADMIN_PIN = 31 +KP_KEYEXCHANGE_PIN = 32 +KP_SIGNATURE_PIN = 33 +KP_PREHASH = 34 +KP_ROUNDS = 35 +KP_OAEP_PARAMS = 36 +KP_CMS_KEY_INFO = 37 +KP_CMS_DH_KEY_INFO = 38 +KP_PUB_PARAMS = 39 +KP_VERIFY_PARAMS = 40 +KP_HIGHEST_VERSION = 41 +KP_GET_USE_COUNT = 42 +PKCS5_PADDING = 1 +RANDOM_PADDING = 2 +ZERO_PADDING = 3 +CRYPT_MODE_CBC = 1 +CRYPT_MODE_ECB = 2 +CRYPT_MODE_OFB = 3 +CRYPT_MODE_CFB = 4 +CRYPT_MODE_CTS = 5 +CRYPT_ENCRYPT = 0x0001 +CRYPT_DECRYPT = 0x0002 +CRYPT_EXPORT = 0x0004 +CRYPT_READ = 0x0008 +CRYPT_WRITE = 0x0010 +CRYPT_MAC = 0x0020 +CRYPT_EXPORT_KEY = 0x0040 +CRYPT_IMPORT_KEY = 0x0080 +CRYPT_ARCHIVE = 0x0100 +HP_ALGID = 0x0001 +HP_HASHVAL = 0x0002 +HP_HASHSIZE = 0x0004 +HP_HMAC_INFO = 0x0005 +HP_TLS1PRF_LABEL = 0x0006 +HP_TLS1PRF_SEED = 0x0007 + +CRYPT_FAILED = 0 +CRYPT_SUCCEED = 1 +def RCRYPT_SUCCEEDED(rt): return ((rt) == CRYPT_SUCCEED) +def RCRYPT_FAILED(rt): return ((rt) == CRYPT_FAILED) + +PP_ENUMALGS = 1 +PP_ENUMCONTAINERS = 2 +PP_IMPTYPE = 3 +PP_NAME = 4 +PP_VERSION = 5 +PP_CONTAINER = 6 +PP_CHANGE_PASSWORD = 7 +PP_KEYSET_SEC_DESCR = 8 +PP_CERTCHAIN = 9 +PP_KEY_TYPE_SUBTYPE = 10 +PP_PROVTYPE = 16 +PP_KEYSTORAGE = 17 +PP_APPLI_CERT = 18 +PP_SYM_KEYSIZE = 19 +PP_SESSION_KEYSIZE = 20 +PP_UI_PROMPT = 21 +PP_ENUMALGS_EX = 22 +PP_ENUMMANDROOTS = 25 +PP_ENUMELECTROOTS = 26 +PP_KEYSET_TYPE = 27 +PP_ADMIN_PIN = 31 +PP_KEYEXCHANGE_PIN = 32 +PP_SIGNATURE_PIN = 33 +PP_SIG_KEYSIZE_INC = 34 +PP_KEYX_KEYSIZE_INC = 35 +PP_UNIQUE_CONTAINER = 36 +PP_SGC_INFO = 37 +PP_USE_HARDWARE_RNG = 38 +PP_KEYSPEC = 39 +PP_ENUMEX_SIGNING_PROT = 40 +PP_CRYPT_COUNT_KEY_USE = 41 +CRYPT_FIRST = 1 +CRYPT_NEXT = 2 +CRYPT_SGC_ENUM = 4 +CRYPT_IMPL_HARDWARE = 1 +CRYPT_IMPL_SOFTWARE = 2 +CRYPT_IMPL_MIXED = 3 +CRYPT_IMPL_UNKNOWN = 4 +CRYPT_IMPL_REMOVABLE = 8 +CRYPT_SEC_DESCR = 0x00000001 +CRYPT_PSTORE = 0x00000002 +CRYPT_UI_PROMPT = 0x00000004 +CRYPT_FLAG_PCT1 = 0x0001 +CRYPT_FLAG_SSL2 = 0x0002 +CRYPT_FLAG_SSL3 = 0x0004 +CRYPT_FLAG_TLS1 = 0x0008 +CRYPT_FLAG_IPSEC = 0x0010 +CRYPT_FLAG_SIGNING = 0x0020 +CRYPT_SGC = 0x0001 +CRYPT_FASTSGC = 0x0002 +PP_CLIENT_HWND = 1 +PP_CONTEXT_INFO = 11 +PP_KEYEXCHANGE_KEYSIZE = 12 +PP_SIGNATURE_KEYSIZE = 13 +PP_KEYEXCHANGE_ALG = 14 +PP_SIGNATURE_ALG = 15 +PP_DELETEKEY = 24 +PROV_RSA_FULL = 1 +PROV_RSA_SIG = 2 +PROV_DSS = 3 +PROV_FORTEZZA = 4 +PROV_MS_EXCHANGE = 5 +PROV_SSL = 6 +PROV_RSA_SCHANNEL = 12 +PROV_DSS_DH = 13 +PROV_EC_ECDSA_SIG = 14 +PROV_EC_ECNRA_SIG = 15 +PROV_EC_ECDSA_FULL = 16 +PROV_EC_ECNRA_FULL = 17 +PROV_DH_SCHANNEL = 18 +PROV_SPYRUS_LYNKS = 20 +PROV_RNG = 21 +PROV_INTEL_SEC = 22 +PROV_REPLACE_OWF = 23 +PROV_RSA_AES = 24 +MS_DEF_PROV_A = "Microsoft Base Cryptographic Provider v1.0" +MS_DEF_PROV = MS_DEF_PROV_A +MS_ENHANCED_PROV_A = "Microsoft Enhanced Cryptographic Provider v1.0" +MS_ENHANCED_PROV = MS_ENHANCED_PROV_A +MS_STRONG_PROV_A = "Microsoft Strong Cryptographic Provider" +MS_STRONG_PROV = MS_STRONG_PROV_A +MS_DEF_RSA_SIG_PROV_A = "Microsoft RSA Signature Cryptographic Provider" +MS_DEF_RSA_SIG_PROV = MS_DEF_RSA_SIG_PROV_A +MS_DEF_RSA_SCHANNEL_PROV_A = "Microsoft RSA SChannel Cryptographic Provider" +MS_DEF_RSA_SCHANNEL_PROV = MS_DEF_RSA_SCHANNEL_PROV_A +MS_DEF_DSS_PROV_A = "Microsoft Base DSS Cryptographic Provider" +MS_DEF_DSS_PROV = MS_DEF_DSS_PROV_A +MS_DEF_DSS_DH_PROV_A = "Microsoft Base DSS and Diffie-Hellman Cryptographic Provider" +MS_DEF_DSS_DH_PROV = MS_DEF_DSS_DH_PROV_A +MS_ENH_DSS_DH_PROV_A = "Microsoft Enhanced DSS and Diffie-Hellman Cryptographic Provider" +MS_ENH_DSS_DH_PROV = MS_ENH_DSS_DH_PROV_A +MS_DEF_DH_SCHANNEL_PROV_A = "Microsoft DH SChannel Cryptographic Provider" +MS_DEF_DH_SCHANNEL_PROV = MS_DEF_DH_SCHANNEL_PROV_A +MS_SCARD_PROV_A = "Microsoft Base Smart Card Crypto Provider" +MS_SCARD_PROV = MS_SCARD_PROV_A +MS_ENH_RSA_AES_PROV_A = "Microsoft Enhanced RSA and AES Cryptographic Provider" +MS_ENH_RSA_AES_PROV = MS_ENH_RSA_AES_PROV_A +MAXUIDLEN = 64 +EXPO_OFFLOAD_REG_VALUE = "ExpoOffload" +EXPO_OFFLOAD_FUNC_NAME = "OffloadModExpo" +szKEY_CRYPTOAPI_PRIVATE_KEY_OPTIONS = \ + "Software\\Policies\\Microsoft\\Cryptography" +szFORCE_KEY_PROTECTION = "ForceKeyProtection" +dwFORCE_KEY_PROTECTION_DISABLED = 0x0 +dwFORCE_KEY_PROTECTION_USER_SELECT = 0x1 +dwFORCE_KEY_PROTECTION_HIGH = 0x2 +szKEY_CACHE_ENABLED = "CachePrivateKeys" +szKEY_CACHE_SECONDS = "PrivateKeyLifetimeSeconds" +CUR_BLOB_VERSION = 2 +SCHANNEL_MAC_KEY = 0x00000000 +SCHANNEL_ENC_KEY = 0x00000001 +INTERNATIONAL_USAGE = 0x00000001 +szOID_RSA = "1.2.840.113549" +szOID_PKCS = "1.2.840.113549.1" +szOID_RSA_HASH = "1.2.840.113549.2" +szOID_RSA_ENCRYPT = "1.2.840.113549.3" +szOID_PKCS_1 = "1.2.840.113549.1.1" +szOID_PKCS_2 = "1.2.840.113549.1.2" +szOID_PKCS_3 = "1.2.840.113549.1.3" +szOID_PKCS_4 = "1.2.840.113549.1.4" +szOID_PKCS_5 = "1.2.840.113549.1.5" +szOID_PKCS_6 = "1.2.840.113549.1.6" +szOID_PKCS_7 = "1.2.840.113549.1.7" +szOID_PKCS_8 = "1.2.840.113549.1.8" +szOID_PKCS_9 = "1.2.840.113549.1.9" +szOID_PKCS_10 = "1.2.840.113549.1.10" +szOID_PKCS_12 = "1.2.840.113549.1.12" +szOID_RSA_RSA = "1.2.840.113549.1.1.1" +szOID_RSA_MD2RSA = "1.2.840.113549.1.1.2" +szOID_RSA_MD4RSA = "1.2.840.113549.1.1.3" +szOID_RSA_MD5RSA = "1.2.840.113549.1.1.4" +szOID_RSA_SHA1RSA = "1.2.840.113549.1.1.5" +szOID_RSA_SETOAEP_RSA = "1.2.840.113549.1.1.6" +szOID_RSA_DH = "1.2.840.113549.1.3.1" +szOID_RSA_data = "1.2.840.113549.1.7.1" +szOID_RSA_signedData = "1.2.840.113549.1.7.2" +szOID_RSA_envelopedData = "1.2.840.113549.1.7.3" +szOID_RSA_signEnvData = "1.2.840.113549.1.7.4" +szOID_RSA_digestedData = "1.2.840.113549.1.7.5" +szOID_RSA_hashedData = "1.2.840.113549.1.7.5" +szOID_RSA_encryptedData = "1.2.840.113549.1.7.6" +szOID_RSA_emailAddr = "1.2.840.113549.1.9.1" +szOID_RSA_unstructName = "1.2.840.113549.1.9.2" +szOID_RSA_contentType = "1.2.840.113549.1.9.3" +szOID_RSA_messageDigest = "1.2.840.113549.1.9.4" +szOID_RSA_signingTime = "1.2.840.113549.1.9.5" +szOID_RSA_counterSign = "1.2.840.113549.1.9.6" +szOID_RSA_challengePwd = "1.2.840.113549.1.9.7" +szOID_RSA_unstructAddr = "1.2.840.113549.1.9.8" +szOID_RSA_extCertAttrs = "1.2.840.113549.1.9.9" +szOID_RSA_certExtensions = "1.2.840.113549.1.9.14" +szOID_RSA_SMIMECapabilities = "1.2.840.113549.1.9.15" +szOID_RSA_preferSignedData = "1.2.840.113549.1.9.15.1" +szOID_RSA_SMIMEalg = "1.2.840.113549.1.9.16.3" +szOID_RSA_SMIMEalgESDH = "1.2.840.113549.1.9.16.3.5" +szOID_RSA_SMIMEalgCMS3DESwrap = "1.2.840.113549.1.9.16.3.6" +szOID_RSA_SMIMEalgCMSRC2wrap = "1.2.840.113549.1.9.16.3.7" +szOID_RSA_MD2 = "1.2.840.113549.2.2" +szOID_RSA_MD4 = "1.2.840.113549.2.4" +szOID_RSA_MD5 = "1.2.840.113549.2.5" +szOID_RSA_RC2CBC = "1.2.840.113549.3.2" +szOID_RSA_RC4 = "1.2.840.113549.3.4" +szOID_RSA_DES_EDE3_CBC = "1.2.840.113549.3.7" +szOID_RSA_RC5_CBCPad = "1.2.840.113549.3.9" +szOID_ANSI_X942 = "1.2.840.10046" +szOID_ANSI_X942_DH = "1.2.840.10046.2.1" +szOID_X957 = "1.2.840.10040" +szOID_X957_DSA = "1.2.840.10040.4.1" +szOID_X957_SHA1DSA = "1.2.840.10040.4.3" +szOID_DS = "2.5" +szOID_DSALG = "2.5.8" +szOID_DSALG_CRPT = "2.5.8.1" +szOID_DSALG_HASH = "2.5.8.2" +szOID_DSALG_SIGN = "2.5.8.3" +szOID_DSALG_RSA = "2.5.8.1.1" +szOID_OIW = "1.3.14" +szOID_OIWSEC = "1.3.14.3.2" +szOID_OIWSEC_md4RSA = "1.3.14.3.2.2" +szOID_OIWSEC_md5RSA = "1.3.14.3.2.3" +szOID_OIWSEC_md4RSA2 = "1.3.14.3.2.4" +szOID_OIWSEC_desECB = "1.3.14.3.2.6" +szOID_OIWSEC_desCBC = "1.3.14.3.2.7" +szOID_OIWSEC_desOFB = "1.3.14.3.2.8" +szOID_OIWSEC_desCFB = "1.3.14.3.2.9" +szOID_OIWSEC_desMAC = "1.3.14.3.2.10" +szOID_OIWSEC_rsaSign = "1.3.14.3.2.11" +szOID_OIWSEC_dsa = "1.3.14.3.2.12" +szOID_OIWSEC_shaDSA = "1.3.14.3.2.13" +szOID_OIWSEC_mdc2RSA = "1.3.14.3.2.14" +szOID_OIWSEC_shaRSA = "1.3.14.3.2.15" +szOID_OIWSEC_dhCommMod = "1.3.14.3.2.16" +szOID_OIWSEC_desEDE = "1.3.14.3.2.17" +szOID_OIWSEC_sha = "1.3.14.3.2.18" +szOID_OIWSEC_mdc2 = "1.3.14.3.2.19" +szOID_OIWSEC_dsaComm = "1.3.14.3.2.20" +szOID_OIWSEC_dsaCommSHA = "1.3.14.3.2.21" +szOID_OIWSEC_rsaXchg = "1.3.14.3.2.22" +szOID_OIWSEC_keyHashSeal = "1.3.14.3.2.23" +szOID_OIWSEC_md2RSASign = "1.3.14.3.2.24" +szOID_OIWSEC_md5RSASign = "1.3.14.3.2.25" +szOID_OIWSEC_sha1 = "1.3.14.3.2.26" +szOID_OIWSEC_dsaSHA1 = "1.3.14.3.2.27" +szOID_OIWSEC_dsaCommSHA1 = "1.3.14.3.2.28" +szOID_OIWSEC_sha1RSASign = "1.3.14.3.2.29" +szOID_OIWDIR = "1.3.14.7.2" +szOID_OIWDIR_CRPT = "1.3.14.7.2.1" +szOID_OIWDIR_HASH = "1.3.14.7.2.2" +szOID_OIWDIR_SIGN = "1.3.14.7.2.3" +szOID_OIWDIR_md2 = "1.3.14.7.2.2.1" +szOID_OIWDIR_md2RSA = "1.3.14.7.2.3.1" +szOID_INFOSEC = "2.16.840.1.101.2.1" +szOID_INFOSEC_sdnsSignature = "2.16.840.1.101.2.1.1.1" +szOID_INFOSEC_mosaicSignature = "2.16.840.1.101.2.1.1.2" +szOID_INFOSEC_sdnsConfidentiality = "2.16.840.1.101.2.1.1.3" +szOID_INFOSEC_mosaicConfidentiality = "2.16.840.1.101.2.1.1.4" +szOID_INFOSEC_sdnsIntegrity = "2.16.840.1.101.2.1.1.5" +szOID_INFOSEC_mosaicIntegrity = "2.16.840.1.101.2.1.1.6" +szOID_INFOSEC_sdnsTokenProtection = "2.16.840.1.101.2.1.1.7" +szOID_INFOSEC_mosaicTokenProtection = "2.16.840.1.101.2.1.1.8" +szOID_INFOSEC_sdnsKeyManagement = "2.16.840.1.101.2.1.1.9" +szOID_INFOSEC_mosaicKeyManagement = "2.16.840.1.101.2.1.1.10" +szOID_INFOSEC_sdnsKMandSig = "2.16.840.1.101.2.1.1.11" +szOID_INFOSEC_mosaicKMandSig = "2.16.840.1.101.2.1.1.12" +szOID_INFOSEC_SuiteASignature = "2.16.840.1.101.2.1.1.13" +szOID_INFOSEC_SuiteAConfidentiality = "2.16.840.1.101.2.1.1.14" +szOID_INFOSEC_SuiteAIntegrity = "2.16.840.1.101.2.1.1.15" +szOID_INFOSEC_SuiteATokenProtection = "2.16.840.1.101.2.1.1.16" +szOID_INFOSEC_SuiteAKeyManagement = "2.16.840.1.101.2.1.1.17" +szOID_INFOSEC_SuiteAKMandSig = "2.16.840.1.101.2.1.1.18" +szOID_INFOSEC_mosaicUpdatedSig = "2.16.840.1.101.2.1.1.19" +szOID_INFOSEC_mosaicKMandUpdSig = "2.16.840.1.101.2.1.1.20" +szOID_INFOSEC_mosaicUpdatedInteg = "2.16.840.1.101.2.1.1.21" +szOID_COMMON_NAME = "2.5.4.3" +szOID_SUR_NAME = "2.5.4.4" +szOID_DEVICE_SERIAL_NUMBER = "2.5.4.5" +szOID_COUNTRY_NAME = "2.5.4.6" +szOID_LOCALITY_NAME = "2.5.4.7" +szOID_STATE_OR_PROVINCE_NAME = "2.5.4.8" +szOID_STREET_ADDRESS = "2.5.4.9" +szOID_ORGANIZATION_NAME = "2.5.4.10" +szOID_ORGANIZATIONAL_UNIT_NAME = "2.5.4.11" +szOID_TITLE = "2.5.4.12" +szOID_DESCRIPTION = "2.5.4.13" +szOID_SEARCH_GUIDE = "2.5.4.14" +szOID_BUSINESS_CATEGORY = "2.5.4.15" +szOID_POSTAL_ADDRESS = "2.5.4.16" +szOID_POSTAL_CODE = "2.5.4.17" +szOID_POST_OFFICE_BOX = "2.5.4.18" +szOID_PHYSICAL_DELIVERY_OFFICE_NAME = "2.5.4.19" +szOID_TELEPHONE_NUMBER = "2.5.4.20" +szOID_TELEX_NUMBER = "2.5.4.21" +szOID_TELETEXT_TERMINAL_IDENTIFIER = "2.5.4.22" +szOID_FACSIMILE_TELEPHONE_NUMBER = "2.5.4.23" +szOID_X21_ADDRESS = "2.5.4.24" +szOID_INTERNATIONAL_ISDN_NUMBER = "2.5.4.25" +szOID_REGISTERED_ADDRESS = "2.5.4.26" +szOID_DESTINATION_INDICATOR = "2.5.4.27" +szOID_PREFERRED_DELIVERY_METHOD = "2.5.4.28" +szOID_PRESENTATION_ADDRESS = "2.5.4.29" +szOID_SUPPORTED_APPLICATION_CONTEXT = "2.5.4.30" +szOID_MEMBER = "2.5.4.31" +szOID_OWNER = "2.5.4.32" +szOID_ROLE_OCCUPANT = "2.5.4.33" +szOID_SEE_ALSO = "2.5.4.34" +szOID_USER_PASSWORD = "2.5.4.35" +szOID_USER_CERTIFICATE = "2.5.4.36" +szOID_CA_CERTIFICATE = "2.5.4.37" +szOID_AUTHORITY_REVOCATION_LIST = "2.5.4.38" +szOID_CERTIFICATE_REVOCATION_LIST = "2.5.4.39" +szOID_CROSS_CERTIFICATE_PAIR = "2.5.4.40" +szOID_GIVEN_NAME = "2.5.4.42" +szOID_INITIALS = "2.5.4.43" +szOID_DN_QUALIFIER = "2.5.4.46" +szOID_DOMAIN_COMPONENT = "0.9.2342.19200300.100.1.25" +szOID_PKCS_12_FRIENDLY_NAME_ATTR = "1.2.840.113549.1.9.20" +szOID_PKCS_12_LOCAL_KEY_ID = "1.2.840.113549.1.9.21" +szOID_PKCS_12_KEY_PROVIDER_NAME_ATTR = "1.3.6.1.4.1.311.17.1" +szOID_LOCAL_MACHINE_KEYSET = "1.3.6.1.4.1.311.17.2" +szOID_KEYID_RDN = "1.3.6.1.4.1.311.10.7.1" +CERT_RDN_ANY_TYPE = 0 +CERT_RDN_ENCODED_BLOB = 1 +CERT_RDN_OCTET_STRING = 2 +CERT_RDN_NUMERIC_STRING = 3 +CERT_RDN_PRINTABLE_STRING = 4 +CERT_RDN_TELETEX_STRING = 5 +CERT_RDN_T61_STRING = 5 +CERT_RDN_VIDEOTEX_STRING = 6 +CERT_RDN_IA5_STRING = 7 +CERT_RDN_GRAPHIC_STRING = 8 +CERT_RDN_VISIBLE_STRING = 9 +CERT_RDN_ISO646_STRING = 9 +CERT_RDN_GENERAL_STRING = 10 +CERT_RDN_UNIVERSAL_STRING = 11 +CERT_RDN_INT4_STRING = 11 +CERT_RDN_BMP_STRING = 12 +CERT_RDN_UNICODE_STRING = 12 +CERT_RDN_UTF8_STRING = 13 +CERT_RDN_TYPE_MASK = 0x000000FF +CERT_RDN_FLAGS_MASK = (-16777216) +CERT_RDN_ENABLE_T61_UNICODE_FLAG = (-2147483648) +CERT_RDN_ENABLE_UTF8_UNICODE_FLAG = 0x20000000 +CERT_RDN_DISABLE_CHECK_TYPE_FLAG = 0x40000000 +CERT_RDN_DISABLE_IE4_UTF8_FLAG = 0x01000000 +CERT_RSA_PUBLIC_KEY_OBJID = szOID_RSA_RSA +CERT_DEFAULT_OID_PUBLIC_KEY_SIGN = szOID_RSA_RSA +CERT_DEFAULT_OID_PUBLIC_KEY_XCHG = szOID_RSA_RSA +CERT_V1 = 0 +CERT_V2 = 1 +CERT_V3 = 2 +CERT_INFO_VERSION_FLAG = 1 +CERT_INFO_SERIAL_NUMBER_FLAG = 2 +CERT_INFO_SIGNATURE_ALGORITHM_FLAG = 3 +CERT_INFO_ISSUER_FLAG = 4 +CERT_INFO_NOT_BEFORE_FLAG = 5 +CERT_INFO_NOT_AFTER_FLAG = 6 +CERT_INFO_SUBJECT_FLAG = 7 +CERT_INFO_SUBJECT_PUBLIC_KEY_INFO_FLAG = 8 +CERT_INFO_ISSUER_UNIQUE_ID_FLAG = 9 +CERT_INFO_SUBJECT_UNIQUE_ID_FLAG = 10 +CERT_INFO_EXTENSION_FLAG = 11 +CRL_V1 = 0 +CRL_V2 = 1 +CERT_REQUEST_V1 = 0 +CERT_KEYGEN_REQUEST_V1 = 0 +CTL_V1 = 0 +CERT_ENCODING_TYPE_MASK = 0x0000FFFF +CMSG_ENCODING_TYPE_MASK = (-65536) +def GET_CERT_ENCODING_TYPE(X): return (X & CERT_ENCODING_TYPE_MASK) + +def GET_CMSG_ENCODING_TYPE(X): return (X & CMSG_ENCODING_TYPE_MASK) + +CRYPT_ASN_ENCODING = 0x00000001 +CRYPT_NDR_ENCODING = 0x00000002 +X509_ASN_ENCODING = 0x00000001 +X509_NDR_ENCODING = 0x00000002 +PKCS_7_ASN_ENCODING = 0x00010000 +PKCS_7_NDR_ENCODING = 0x00020000 +CRYPT_FORMAT_STR_MULTI_LINE = 0x0001 +CRYPT_FORMAT_STR_NO_HEX = 0x0010 +CRYPT_FORMAT_SIMPLE = 0x0001 +CRYPT_FORMAT_X509 = 0x0002 +CRYPT_FORMAT_OID = 0x0004 +CRYPT_FORMAT_RDN_SEMICOLON = 0x0100 +CRYPT_FORMAT_RDN_CRLF = 0x0200 +CRYPT_FORMAT_RDN_UNQUOTE = 0x0400 +CRYPT_FORMAT_RDN_REVERSE = 0x0800 +CRYPT_FORMAT_COMMA = 0x1000 +CRYPT_FORMAT_SEMICOLON = CRYPT_FORMAT_RDN_SEMICOLON +CRYPT_FORMAT_CRLF = CRYPT_FORMAT_RDN_CRLF +CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG = 0x8 +CRYPT_ENCODE_ALLOC_FLAG = 0x8000 +CRYPT_UNICODE_NAME_ENCODE_ENABLE_T61_UNICODE_FLAG = \ + CERT_RDN_ENABLE_T61_UNICODE_FLAG +CRYPT_UNICODE_NAME_ENCODE_ENABLE_UTF8_UNICODE_FLAG = \ + CERT_RDN_ENABLE_UTF8_UNICODE_FLAG +CRYPT_UNICODE_NAME_ENCODE_DISABLE_CHECK_TYPE_FLAG = \ + CERT_RDN_DISABLE_CHECK_TYPE_FLAG +CRYPT_SORTED_CTL_ENCODE_HASHED_SUBJECT_IDENTIFIER_FLAG = 0x10000 +CRYPT_DECODE_NOCOPY_FLAG = 0x1 +CRYPT_DECODE_TO_BE_SIGNED_FLAG = 0x2 +CRYPT_DECODE_SHARE_OID_STRING_FLAG = 0x4 +CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG = 0x8 +CRYPT_DECODE_ALLOC_FLAG = 0x8000 +CRYPT_UNICODE_NAME_DECODE_DISABLE_IE4_UTF8_FLAG = \ + CERT_RDN_DISABLE_IE4_UTF8_FLAG + +CRYPT_ENCODE_DECODE_NONE = 0 +X509_CERT = 1 +X509_CERT_TO_BE_SIGNED = 2 +X509_CERT_CRL_TO_BE_SIGNED = 3 +X509_CERT_REQUEST_TO_BE_SIGNED = 4 +X509_EXTENSIONS = 5 +X509_NAME_VALUE = 6 +X509_NAME = 7 +X509_PUBLIC_KEY_INFO = 8 +X509_AUTHORITY_KEY_ID = 9 +X509_KEY_ATTRIBUTES = 10 +X509_KEY_USAGE_RESTRICTION = 11 +X509_ALTERNATE_NAME = 12 +X509_BASIC_CONSTRAINTS = 13 +X509_KEY_USAGE = 14 +X509_BASIC_CONSTRAINTS2 = 15 +X509_CERT_POLICIES = 16 +PKCS_UTC_TIME = 17 +PKCS_TIME_REQUEST = 18 +RSA_CSP_PUBLICKEYBLOB = 19 +X509_UNICODE_NAME = 20 +X509_KEYGEN_REQUEST_TO_BE_SIGNED = 21 +PKCS_ATTRIBUTE = 22 +PKCS_CONTENT_INFO_SEQUENCE_OF_ANY = 23 +X509_UNICODE_NAME_VALUE = 24 +X509_ANY_STRING = X509_NAME_VALUE +X509_UNICODE_ANY_STRING = X509_UNICODE_NAME_VALUE +X509_OCTET_STRING = 25 +X509_BITS = 26 +X509_INTEGER = 27 +X509_MULTI_BYTE_INTEGER = 28 +X509_ENUMERATED = 29 +X509_CHOICE_OF_TIME = 30 +X509_AUTHORITY_KEY_ID2 = 31 +X509_AUTHORITY_INFO_ACCESS = 32 +X509_SUBJECT_INFO_ACCESS = X509_AUTHORITY_INFO_ACCESS +X509_CRL_REASON_CODE = X509_ENUMERATED +PKCS_CONTENT_INFO = 33 +X509_SEQUENCE_OF_ANY = 34 +X509_CRL_DIST_POINTS = 35 +X509_ENHANCED_KEY_USAGE = 36 +PKCS_CTL = 37 +X509_MULTI_BYTE_UINT = 38 +X509_DSS_PUBLICKEY = X509_MULTI_BYTE_UINT +X509_DSS_PARAMETERS = 39 +X509_DSS_SIGNATURE = 40 +PKCS_RC2_CBC_PARAMETERS = 41 +PKCS_SMIME_CAPABILITIES = 42 +X509_QC_STATEMENTS_EXT = 42 +PKCS_RSA_PRIVATE_KEY = 43 +PKCS_PRIVATE_KEY_INFO = 44 +PKCS_ENCRYPTED_PRIVATE_KEY_INFO = 45 +X509_PKIX_POLICY_QUALIFIER_USERNOTICE = 46 +X509_DH_PUBLICKEY = X509_MULTI_BYTE_UINT +X509_DH_PARAMETERS = 47 +PKCS_ATTRIBUTES = 48 +PKCS_SORTED_CTL = 49 +X509_ECC_SIGNATURE = 47 +X942_DH_PARAMETERS = 50 +X509_BITS_WITHOUT_TRAILING_ZEROES = 51 +X942_OTHER_INFO = 52 +X509_CERT_PAIR = 53 +X509_ISSUING_DIST_POINT = 54 +X509_NAME_CONSTRAINTS = 55 +X509_POLICY_MAPPINGS = 56 +X509_POLICY_CONSTRAINTS = 57 +X509_CROSS_CERT_DIST_POINTS = 58 +CMC_DATA = 59 +CMC_RESPONSE = 60 +CMC_STATUS = 61 +CMC_ADD_EXTENSIONS = 62 +CMC_ADD_ATTRIBUTES = 63 +X509_CERTIFICATE_TEMPLATE = 64 +OCSP_SIGNED_REQUEST = 65 +OCSP_REQUEST = 66 +OCSP_RESPONSE = 67 +OCSP_BASIC_SIGNED_RESPONSE = 68 +OCSP_BASIC_RESPONSE = 69 +X509_LOGOTYPE_EXT = 70 +X509_BIOMETRIC_EXT = 71 +CNG_RSA_PUBLIC_KEY_BLOB = 72 +X509_OBJECT_IDENTIFIER = 73 +X509_ALGORITHM_IDENTIFIER = 74 +PKCS_RSA_SSA_PSS_PARAMETERS = 75 +PKCS_RSAES_OAEP_PARAMETERS = 76 +ECC_CMS_SHARED_INFO = 77 +TIMESTAMP_REQUEST = 78 +TIMESTAMP_RESPONSE = 79 +TIMESTAMP_INFO = 80 +X509_CERT_BUNDLE = 81 +PKCS7_SIGNER_INFO = 500 +CMS_SIGNER_INFO = 501 + +szOID_AUTHORITY_KEY_IDENTIFIER = "2.5.29.1" +szOID_KEY_ATTRIBUTES = "2.5.29.2" +szOID_CERT_POLICIES_95 = "2.5.29.3" +szOID_KEY_USAGE_RESTRICTION = "2.5.29.4" +szOID_SUBJECT_ALT_NAME = "2.5.29.7" +szOID_ISSUER_ALT_NAME = "2.5.29.8" +szOID_BASIC_CONSTRAINTS = "2.5.29.10" +szOID_KEY_USAGE = "2.5.29.15" +szOID_PRIVATEKEY_USAGE_PERIOD = "2.5.29.16" +szOID_BASIC_CONSTRAINTS2 = "2.5.29.19" +szOID_CERT_POLICIES = "2.5.29.32" +szOID_ANY_CERT_POLICY = "2.5.29.32.0" +szOID_AUTHORITY_KEY_IDENTIFIER2 = "2.5.29.35" +szOID_SUBJECT_KEY_IDENTIFIER = "2.5.29.14" +szOID_SUBJECT_ALT_NAME2 = "2.5.29.17" +szOID_ISSUER_ALT_NAME2 = "2.5.29.18" +szOID_CRL_REASON_CODE = "2.5.29.21" +szOID_REASON_CODE_HOLD = "2.5.29.23" +szOID_CRL_DIST_POINTS = "2.5.29.31" +szOID_ENHANCED_KEY_USAGE = "2.5.29.37" +szOID_CRL_NUMBER = "2.5.29.20" +szOID_DELTA_CRL_INDICATOR = "2.5.29.27" +szOID_ISSUING_DIST_POINT = "2.5.29.28" +szOID_FRESHEST_CRL = "2.5.29.46" +szOID_NAME_CONSTRAINTS = "2.5.29.30" +szOID_POLICY_MAPPINGS = "2.5.29.33" +szOID_LEGACY_POLICY_MAPPINGS = "2.5.29.5" +szOID_POLICY_CONSTRAINTS = "2.5.29.36" +szOID_RENEWAL_CERTIFICATE = "1.3.6.1.4.1.311.13.1" +szOID_ENROLLMENT_NAME_VALUE_PAIR = "1.3.6.1.4.1.311.13.2.1" +szOID_ENROLLMENT_CSP_PROVIDER = "1.3.6.1.4.1.311.13.2.2" +szOID_OS_VERSION = "1.3.6.1.4.1.311.13.2.3" +szOID_ENROLLMENT_AGENT = "1.3.6.1.4.1.311.20.2.1" +szOID_PKIX = "1.3.6.1.5.5.7" +szOID_PKIX_PE = "1.3.6.1.5.5.7.1" +szOID_AUTHORITY_INFO_ACCESS = "1.3.6.1.5.5.7.1.1" +szOID_CERT_EXTENSIONS = "1.3.6.1.4.1.311.2.1.14" +szOID_NEXT_UPDATE_LOCATION = "1.3.6.1.4.1.311.10.2" +szOID_REMOVE_CERTIFICATE = "1.3.6.1.4.1.311.10.8.1" +szOID_CROSS_CERT_DIST_POINTS = "1.3.6.1.4.1.311.10.9.1" +szOID_CTL = "1.3.6.1.4.1.311.10.1" +szOID_SORTED_CTL = "1.3.6.1.4.1.311.10.1.1" +szOID_SERIALIZED = "1.3.6.1.4.1.311.10.3.3.1" +szOID_NT_PRINCIPAL_NAME = "1.3.6.1.4.1.311.20.2.3" +szOID_PRODUCT_UPDATE = "1.3.6.1.4.1.311.31.1" +szOID_ANY_APPLICATION_POLICY = "1.3.6.1.4.1.311.10.12.1" +szOID_AUTO_ENROLL_CTL_USAGE = "1.3.6.1.4.1.311.20.1" +szOID_ENROLL_CERTTYPE_EXTENSION = "1.3.6.1.4.1.311.20.2" +szOID_CERT_MANIFOLD = "1.3.6.1.4.1.311.20.3" +szOID_CERTSRV_CA_VERSION = "1.3.6.1.4.1.311.21.1" +szOID_CERTSRV_PREVIOUS_CERT_HASH = "1.3.6.1.4.1.311.21.2" +szOID_CRL_VIRTUAL_BASE = "1.3.6.1.4.1.311.21.3" +szOID_CRL_NEXT_PUBLISH = "1.3.6.1.4.1.311.21.4" +szOID_KP_CA_EXCHANGE = "1.3.6.1.4.1.311.21.5" +szOID_KP_KEY_RECOVERY_AGENT = "1.3.6.1.4.1.311.21.6" +szOID_CERTIFICATE_TEMPLATE = "1.3.6.1.4.1.311.21.7" +szOID_ENTERPRISE_OID_ROOT = "1.3.6.1.4.1.311.21.8" +szOID_RDN_DUMMY_SIGNER = "1.3.6.1.4.1.311.21.9" +szOID_APPLICATION_CERT_POLICIES = "1.3.6.1.4.1.311.21.10" +szOID_APPLICATION_POLICY_MAPPINGS = "1.3.6.1.4.1.311.21.11" +szOID_APPLICATION_POLICY_CONSTRAINTS = "1.3.6.1.4.1.311.21.12" +szOID_ARCHIVED_KEY_ATTR = "1.3.6.1.4.1.311.21.13" +szOID_CRL_SELF_CDP = "1.3.6.1.4.1.311.21.14" +szOID_REQUIRE_CERT_CHAIN_POLICY = "1.3.6.1.4.1.311.21.15" +szOID_ARCHIVED_KEY_CERT_HASH = "1.3.6.1.4.1.311.21.16" +szOID_ISSUED_CERT_HASH = "1.3.6.1.4.1.311.21.17" +szOID_DS_EMAIL_REPLICATION = "1.3.6.1.4.1.311.21.19" +szOID_REQUEST_CLIENT_INFO = "1.3.6.1.4.1.311.21.20" +szOID_ENCRYPTED_KEY_HASH = "1.3.6.1.4.1.311.21.21" +szOID_CERTSRV_CROSSCA_VERSION = "1.3.6.1.4.1.311.21.22" +szOID_NTDS_REPLICATION = "1.3.6.1.4.1.311.25.1" +szOID_SUBJECT_DIR_ATTRS = "2.5.29.9" +szOID_PKIX_KP = "1.3.6.1.5.5.7.3" +szOID_PKIX_KP_SERVER_AUTH = "1.3.6.1.5.5.7.3.1" +szOID_PKIX_KP_CLIENT_AUTH = "1.3.6.1.5.5.7.3.2" +szOID_PKIX_KP_CODE_SIGNING = "1.3.6.1.5.5.7.3.3" +szOID_PKIX_KP_EMAIL_PROTECTION = "1.3.6.1.5.5.7.3.4" +szOID_PKIX_KP_IPSEC_END_SYSTEM = "1.3.6.1.5.5.7.3.5" +szOID_PKIX_KP_IPSEC_TUNNEL = "1.3.6.1.5.5.7.3.6" +szOID_PKIX_KP_IPSEC_USER = "1.3.6.1.5.5.7.3.7" +szOID_PKIX_KP_TIMESTAMP_SIGNING = "1.3.6.1.5.5.7.3.8" +szOID_IPSEC_KP_IKE_INTERMEDIATE = "1.3.6.1.5.5.8.2.2" +szOID_KP_CTL_USAGE_SIGNING = "1.3.6.1.4.1.311.10.3.1" +szOID_KP_TIME_STAMP_SIGNING = "1.3.6.1.4.1.311.10.3.2" +szOID_SERVER_GATED_CRYPTO = "1.3.6.1.4.1.311.10.3.3" +szOID_SGC_NETSCAPE = "2.16.840.1.113730.4.1" +szOID_KP_EFS = "1.3.6.1.4.1.311.10.3.4" +szOID_EFS_RECOVERY = "1.3.6.1.4.1.311.10.3.4.1" +szOID_WHQL_CRYPTO = "1.3.6.1.4.1.311.10.3.5" +szOID_NT5_CRYPTO = "1.3.6.1.4.1.311.10.3.6" +szOID_OEM_WHQL_CRYPTO = "1.3.6.1.4.1.311.10.3.7" +szOID_EMBEDDED_NT_CRYPTO = "1.3.6.1.4.1.311.10.3.8" +szOID_ROOT_LIST_SIGNER = "1.3.6.1.4.1.311.10.3.9" +szOID_KP_QUALIFIED_SUBORDINATION = "1.3.6.1.4.1.311.10.3.10" +szOID_KP_KEY_RECOVERY = "1.3.6.1.4.1.311.10.3.11" +szOID_KP_DOCUMENT_SIGNING = "1.3.6.1.4.1.311.10.3.12" +szOID_KP_LIFETIME_SIGNING = "1.3.6.1.4.1.311.10.3.13" +szOID_KP_MOBILE_DEVICE_SOFTWARE = "1.3.6.1.4.1.311.10.3.14" +szOID_DRM = "1.3.6.1.4.1.311.10.5.1" +szOID_DRM_INDIVIDUALIZATION = "1.3.6.1.4.1.311.10.5.2" +szOID_LICENSES = "1.3.6.1.4.1.311.10.6.1" +szOID_LICENSE_SERVER = "1.3.6.1.4.1.311.10.6.2" +szOID_KP_SMARTCARD_LOGON = "1.3.6.1.4.1.311.20.2.2" +szOID_YESNO_TRUST_ATTR = "1.3.6.1.4.1.311.10.4.1" +szOID_PKIX_POLICY_QUALIFIER_CPS = "1.3.6.1.5.5.7.2.1" +szOID_PKIX_POLICY_QUALIFIER_USERNOTICE = "1.3.6.1.5.5.7.2.2" +szOID_CERT_POLICIES_95_QUALIFIER1 = "2.16.840.1.113733.1.7.1.1" +CERT_UNICODE_RDN_ERR_INDEX_MASK = 0x3FF +CERT_UNICODE_RDN_ERR_INDEX_SHIFT = 22 +CERT_UNICODE_ATTR_ERR_INDEX_MASK = 0x003F +CERT_UNICODE_ATTR_ERR_INDEX_SHIFT = 16 +CERT_UNICODE_VALUE_ERR_INDEX_MASK = 0x0000FFFF +CERT_UNICODE_VALUE_ERR_INDEX_SHIFT = 0 +CERT_DIGITAL_SIGNATURE_KEY_USAGE = 0x80 +CERT_NON_REPUDIATION_KEY_USAGE = 0x40 +CERT_KEY_ENCIPHERMENT_KEY_USAGE = 0x20 +CERT_DATA_ENCIPHERMENT_KEY_USAGE = 0x10 +CERT_KEY_AGREEMENT_KEY_USAGE = 0x08 +CERT_KEY_CERT_SIGN_KEY_USAGE = 0x04 +CERT_OFFLINE_CRL_SIGN_KEY_USAGE = 0x02 +CERT_CRL_SIGN_KEY_USAGE = 0x02 +CERT_ENCIPHER_ONLY_KEY_USAGE = 0x01 +CERT_DECIPHER_ONLY_KEY_USAGE = 0x80 +CERT_ALT_NAME_OTHER_NAME = 1 +CERT_ALT_NAME_RFC822_NAME = 2 +CERT_ALT_NAME_DNS_NAME = 3 +CERT_ALT_NAME_X400_ADDRESS = 4 +CERT_ALT_NAME_DIRECTORY_NAME = 5 +CERT_ALT_NAME_EDI_PARTY_NAME = 6 +CERT_ALT_NAME_URL = 7 +CERT_ALT_NAME_IP_ADDRESS = 8 +CERT_ALT_NAME_REGISTERED_ID = 9 +CERT_ALT_NAME_ENTRY_ERR_INDEX_MASK = 0xFF +CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT = 16 +CERT_ALT_NAME_VALUE_ERR_INDEX_MASK = 0x0000FFFF +CERT_ALT_NAME_VALUE_ERR_INDEX_SHIFT = 0 +CERT_CA_SUBJECT_FLAG = 0x80 +CERT_END_ENTITY_SUBJECT_FLAG = 0x40 +szOID_PKIX_ACC_DESCR = "1.3.6.1.5.5.7.48" +szOID_PKIX_OCSP = "1.3.6.1.5.5.7.48.1" +szOID_PKIX_CA_ISSUERS = "1.3.6.1.5.5.7.48.2" +CRL_REASON_UNSPECIFIED = 0 +CRL_REASON_KEY_COMPROMISE = 1 +CRL_REASON_CA_COMPROMISE = 2 +CRL_REASON_AFFILIATION_CHANGED = 3 +CRL_REASON_SUPERSEDED = 4 +CRL_REASON_CESSATION_OF_OPERATION = 5 +CRL_REASON_CERTIFICATE_HOLD = 6 +CRL_REASON_REMOVE_FROM_CRL = 8 +CRL_DIST_POINT_NO_NAME = 0 +CRL_DIST_POINT_FULL_NAME = 1 +CRL_DIST_POINT_ISSUER_RDN_NAME = 2 +CRL_REASON_UNUSED_FLAG = 0x80 +CRL_REASON_KEY_COMPROMISE_FLAG = 0x40 +CRL_REASON_CA_COMPROMISE_FLAG = 0x20 +CRL_REASON_AFFILIATION_CHANGED_FLAG = 0x10 +CRL_REASON_SUPERSEDED_FLAG = 0x08 +CRL_REASON_CESSATION_OF_OPERATION_FLAG = 0x04 +CRL_REASON_CERTIFICATE_HOLD_FLAG = 0x02 +CRL_DIST_POINT_ERR_INDEX_MASK = 0x7F +CRL_DIST_POINT_ERR_INDEX_SHIFT = 24 + +CRL_DIST_POINT_ERR_CRL_ISSUER_BIT = (-2147483648) + +CROSS_CERT_DIST_POINT_ERR_INDEX_MASK = 0xFF +CROSS_CERT_DIST_POINT_ERR_INDEX_SHIFT = 24 + +CERT_EXCLUDED_SUBTREE_BIT = (-2147483648) + +SORTED_CTL_EXT_FLAGS_OFFSET = (0*4) +SORTED_CTL_EXT_COUNT_OFFSET = (1*4) +SORTED_CTL_EXT_MAX_COLLISION_OFFSET = (2*4) +SORTED_CTL_EXT_HASH_BUCKET_OFFSET = (3*4) +SORTED_CTL_EXT_HASHED_SUBJECT_IDENTIFIER_FLAG = 0x1 +CERT_DSS_R_LEN = 20 +CERT_DSS_S_LEN = 20 +CERT_DSS_SIGNATURE_LEN = (CERT_DSS_R_LEN + CERT_DSS_S_LEN) +CERT_MAX_ASN_ENCODED_DSS_SIGNATURE_LEN = (2 + 2*(2 + 20 +1)) +CRYPT_X942_COUNTER_BYTE_LENGTH = 4 +CRYPT_X942_KEY_LENGTH_BYTE_LENGTH = 4 +CRYPT_X942_PUB_INFO_BYTE_LENGTH = (512/8) +CRYPT_RC2_40BIT_VERSION = 160 +CRYPT_RC2_56BIT_VERSION = 52 +CRYPT_RC2_64BIT_VERSION = 120 +CRYPT_RC2_128BIT_VERSION = 58 +szOID_VERISIGN_PRIVATE_6_9 = "2.16.840.1.113733.1.6.9" +szOID_VERISIGN_ONSITE_JURISDICTION_HASH = "2.16.840.1.113733.1.6.11" +szOID_VERISIGN_BITSTRING_6_13 = "2.16.840.1.113733.1.6.13" +szOID_VERISIGN_ISS_STRONG_CRYPTO = "2.16.840.1.113733.1.8.1" +szOID_NETSCAPE = "2.16.840.1.113730" +szOID_NETSCAPE_CERT_EXTENSION = "2.16.840.1.113730.1" +szOID_NETSCAPE_CERT_TYPE = "2.16.840.1.113730.1.1" +szOID_NETSCAPE_BASE_URL = "2.16.840.1.113730.1.2" +szOID_NETSCAPE_REVOCATION_URL = "2.16.840.1.113730.1.3" +szOID_NETSCAPE_CA_REVOCATION_URL = "2.16.840.1.113730.1.4" +szOID_NETSCAPE_CERT_RENEWAL_URL = "2.16.840.1.113730.1.7" +szOID_NETSCAPE_CA_POLICY_URL = "2.16.840.1.113730.1.8" +szOID_NETSCAPE_SSL_SERVER_NAME = "2.16.840.1.113730.1.12" +szOID_NETSCAPE_COMMENT = "2.16.840.1.113730.1.13" +szOID_NETSCAPE_DATA_TYPE = "2.16.840.1.113730.2" +szOID_NETSCAPE_CERT_SEQUENCE = "2.16.840.1.113730.2.5" +NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE = 0x80 +NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE = 0x40 +NETSCAPE_SMIME_CERT_TYPE = 0x20 +NETSCAPE_SIGN_CERT_TYPE = 0x10 +NETSCAPE_SSL_CA_CERT_TYPE = 0x04 +NETSCAPE_SMIME_CA_CERT_TYPE = 0x02 +NETSCAPE_SIGN_CA_CERT_TYPE = 0x01 +szOID_CT_PKI_DATA = "1.3.6.1.5.5.7.12.2" +szOID_CT_PKI_RESPONSE = "1.3.6.1.5.5.7.12.3" +szOID_PKIX_NO_SIGNATURE = "1.3.6.1.5.5.7.6.2" +szOID_CMC = "1.3.6.1.5.5.7.7" +szOID_CMC_STATUS_INFO = "1.3.6.1.5.5.7.7.1" +szOID_CMC_IDENTIFICATION = "1.3.6.1.5.5.7.7.2" +szOID_CMC_IDENTITY_PROOF = "1.3.6.1.5.5.7.7.3" +szOID_CMC_DATA_RETURN = "1.3.6.1.5.5.7.7.4" +szOID_CMC_TRANSACTION_ID = "1.3.6.1.5.5.7.7.5" +szOID_CMC_SENDER_NONCE = "1.3.6.1.5.5.7.7.6" +szOID_CMC_RECIPIENT_NONCE = "1.3.6.1.5.5.7.7.7" +szOID_CMC_ADD_EXTENSIONS = "1.3.6.1.5.5.7.7.8" +szOID_CMC_ENCRYPTED_POP = "1.3.6.1.5.5.7.7.9" +szOID_CMC_DECRYPTED_POP = "1.3.6.1.5.5.7.7.10" +szOID_CMC_LRA_POP_WITNESS = "1.3.6.1.5.5.7.7.11" +szOID_CMC_GET_CERT = "1.3.6.1.5.5.7.7.15" +szOID_CMC_GET_CRL = "1.3.6.1.5.5.7.7.16" +szOID_CMC_REVOKE_REQUEST = "1.3.6.1.5.5.7.7.17" +szOID_CMC_REG_INFO = "1.3.6.1.5.5.7.7.18" +szOID_CMC_RESPONSE_INFO = "1.3.6.1.5.5.7.7.19" +szOID_CMC_QUERY_PENDING = "1.3.6.1.5.5.7.7.21" +szOID_CMC_ID_POP_LINK_RANDOM = "1.3.6.1.5.5.7.7.22" +szOID_CMC_ID_POP_LINK_WITNESS = "1.3.6.1.5.5.7.7.23" +szOID_CMC_ID_CONFIRM_CERT_ACCEPTANCE = "1.3.6.1.5.5.7.7.24" +szOID_CMC_ADD_ATTRIBUTES = "1.3.6.1.4.1.311.10.10.1" +CMC_TAGGED_CERT_REQUEST_CHOICE = 1 +CMC_OTHER_INFO_NO_CHOICE = 0 +CMC_OTHER_INFO_FAIL_CHOICE = 1 +CMC_OTHER_INFO_PEND_CHOICE = 2 +CMC_STATUS_SUCCESS = 0 +CMC_STATUS_FAILED = 2 +CMC_STATUS_PENDING = 3 +CMC_STATUS_NO_SUPPORT = 4 +CMC_STATUS_CONFIRM_REQUIRED = 5 +CMC_FAIL_BAD_ALG = 0 +CMC_FAIL_BAD_MESSAGE_CHECK = 1 +CMC_FAIL_BAD_REQUEST = 2 +CMC_FAIL_BAD_TIME = 3 +CMC_FAIL_BAD_CERT_ID = 4 +CMC_FAIL_UNSUPORTED_EXT = 5 +CMC_FAIL_MUST_ARCHIVE_KEYS = 6 +CMC_FAIL_BAD_IDENTITY = 7 +CMC_FAIL_POP_REQUIRED = 8 +CMC_FAIL_POP_FAILED = 9 +CMC_FAIL_NO_KEY_REUSE = 10 +CMC_FAIL_INTERNAL_CA_ERROR = 11 +CMC_FAIL_TRY_LATER = 12 +CRYPT_OID_ENCODE_OBJECT_FUNC = "CryptDllEncodeObject" +CRYPT_OID_DECODE_OBJECT_FUNC = "CryptDllDecodeObject" +CRYPT_OID_ENCODE_OBJECT_EX_FUNC = "CryptDllEncodeObjectEx" +CRYPT_OID_DECODE_OBJECT_EX_FUNC = "CryptDllDecodeObjectEx" +CRYPT_OID_CREATE_COM_OBJECT_FUNC = "CryptDllCreateCOMObject" +CRYPT_OID_VERIFY_REVOCATION_FUNC = "CertDllVerifyRevocation" +CRYPT_OID_VERIFY_CTL_USAGE_FUNC = "CertDllVerifyCTLUsage" +CRYPT_OID_FORMAT_OBJECT_FUNC = "CryptDllFormatObject" +CRYPT_OID_FIND_OID_INFO_FUNC = "CryptDllFindOIDInfo" +CRYPT_OID_FIND_LOCALIZED_NAME_FUNC = "CryptDllFindLocalizedName" + +CRYPT_OID_REGPATH = "Software\\Microsoft\\Cryptography\\OID" +CRYPT_OID_REG_ENCODING_TYPE_PREFIX = "EncodingType " +CRYPT_OID_REG_DLL_VALUE_NAME = "Dll" +CRYPT_OID_REG_FUNC_NAME_VALUE_NAME = "FuncName" +CRYPT_OID_REG_FUNC_NAME_VALUE_NAME_A = "FuncName" +CRYPT_OID_REG_FLAGS_VALUE_NAME = "CryptFlags" +CRYPT_DEFAULT_OID = "DEFAULT" +CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG = 1 +CRYPT_GET_INSTALLED_OID_FUNC_FLAG = 0x1 +CRYPT_REGISTER_FIRST_INDEX = 0 +CRYPT_REGISTER_LAST_INDEX = (-1) +CRYPT_MATCH_ANY_ENCODING_TYPE = (-1) +CRYPT_HASH_ALG_OID_GROUP_ID = 1 +CRYPT_ENCRYPT_ALG_OID_GROUP_ID = 2 +CRYPT_PUBKEY_ALG_OID_GROUP_ID = 3 +CRYPT_SIGN_ALG_OID_GROUP_ID = 4 +CRYPT_RDN_ATTR_OID_GROUP_ID = 5 +CRYPT_EXT_OR_ATTR_OID_GROUP_ID = 6 +CRYPT_ENHKEY_USAGE_OID_GROUP_ID = 7 +CRYPT_POLICY_OID_GROUP_ID = 8 +CRYPT_TEMPLATE_OID_GROUP_ID = 9 +CRYPT_LAST_OID_GROUP_ID = 9 +CRYPT_FIRST_ALG_OID_GROUP_ID = CRYPT_HASH_ALG_OID_GROUP_ID +CRYPT_LAST_ALG_OID_GROUP_ID = CRYPT_SIGN_ALG_OID_GROUP_ID +CRYPT_OID_INHIBIT_SIGNATURE_FORMAT_FLAG = 0x1 +CRYPT_OID_USE_PUBKEY_PARA_FOR_PKCS7_FLAG = 0x2 +CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG = 0x4 +CRYPT_OID_INFO_OID_KEY = 1 +CRYPT_OID_INFO_NAME_KEY = 2 +CRYPT_OID_INFO_ALGID_KEY = 3 +CRYPT_OID_INFO_SIGN_KEY = 4 +CRYPT_INSTALL_OID_INFO_BEFORE_FLAG = 1 +CRYPT_LOCALIZED_NAME_ENCODING_TYPE = 0 +CRYPT_LOCALIZED_NAME_OID = "LocalizedNames" +szOID_PKCS_7_DATA = "1.2.840.113549.1.7.1" +szOID_PKCS_7_SIGNED = "1.2.840.113549.1.7.2" +szOID_PKCS_7_ENVELOPED = "1.2.840.113549.1.7.3" +szOID_PKCS_7_SIGNEDANDENVELOPED = "1.2.840.113549.1.7.4" +szOID_PKCS_7_DIGESTED = "1.2.840.113549.1.7.5" +szOID_PKCS_7_ENCRYPTED = "1.2.840.113549.1.7.6" +szOID_PKCS_9_CONTENT_TYPE = "1.2.840.113549.1.9.3" +szOID_PKCS_9_MESSAGE_DIGEST = "1.2.840.113549.1.9.4" +CMSG_DATA = 1 +CMSG_SIGNED = 2 +CMSG_ENVELOPED = 3 +CMSG_SIGNED_AND_ENVELOPED = 4 +CMSG_HASHED = 5 +CMSG_ENCRYPTED = 6 + +CMSG_ALL_FLAGS = -1 +CMSG_DATA_FLAG = (1 << CMSG_DATA) +CMSG_SIGNED_FLAG = (1 << CMSG_SIGNED) +CMSG_ENVELOPED_FLAG = (1 << CMSG_ENVELOPED) +CMSG_SIGNED_AND_ENVELOPED_FLAG = (1 << CMSG_SIGNED_AND_ENVELOPED) +CMSG_HASHED_FLAG = (1 << CMSG_HASHED) +CMSG_ENCRYPTED_FLAG = (1 << CMSG_ENCRYPTED) +CERT_ID_ISSUER_SERIAL_NUMBER = 1 +CERT_ID_KEY_IDENTIFIER = 2 +CERT_ID_SHA1_HASH = 3 +CMSG_KEY_AGREE_EPHEMERAL_KEY_CHOICE = 1 +CMSG_KEY_AGREE_STATIC_KEY_CHOICE = 2 +CMSG_MAIL_LIST_HANDLE_KEY_CHOICE = 1 +CMSG_KEY_TRANS_RECIPIENT = 1 +CMSG_KEY_AGREE_RECIPIENT = 2 +CMSG_MAIL_LIST_RECIPIENT = 3 +CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG = (-2147483648) +CMSG_RC4_NO_SALT_FLAG = 0x40000000 +CMSG_INDEFINITE_LENGTH = ((-1)) +CMSG_BARE_CONTENT_FLAG = 0x00000001 +CMSG_LENGTH_ONLY_FLAG = 0x00000002 +CMSG_DETACHED_FLAG = 0x00000004 +CMSG_AUTHENTICATED_ATTRIBUTES_FLAG = 0x00000008 +CMSG_CONTENTS_OCTETS_FLAG = 0x00000010 +CMSG_MAX_LENGTH_FLAG = 0x00000020 +CMSG_CMS_ENCAPSULATED_CONTENT_FLAG = 0x00000040 +CMSG_CRYPT_RELEASE_CONTEXT_FLAG = 0x00008000 +CMSG_TYPE_PARAM = 1 +CMSG_CONTENT_PARAM = 2 +CMSG_BARE_CONTENT_PARAM = 3 +CMSG_INNER_CONTENT_TYPE_PARAM = 4 +CMSG_SIGNER_COUNT_PARAM = 5 +CMSG_SIGNER_INFO_PARAM = 6 +CMSG_SIGNER_CERT_INFO_PARAM = 7 +CMSG_SIGNER_HASH_ALGORITHM_PARAM = 8 +CMSG_SIGNER_AUTH_ATTR_PARAM = 9 +CMSG_SIGNER_UNAUTH_ATTR_PARAM = 10 +CMSG_CERT_COUNT_PARAM = 11 +CMSG_CERT_PARAM = 12 +CMSG_CRL_COUNT_PARAM = 13 +CMSG_CRL_PARAM = 14 +CMSG_ENVELOPE_ALGORITHM_PARAM = 15 +CMSG_RECIPIENT_COUNT_PARAM = 17 +CMSG_RECIPIENT_INDEX_PARAM = 18 +CMSG_RECIPIENT_INFO_PARAM = 19 +CMSG_HASH_ALGORITHM_PARAM = 20 +CMSG_HASH_DATA_PARAM = 21 +CMSG_COMPUTED_HASH_PARAM = 22 +CMSG_ENCRYPT_PARAM = 26 +CMSG_ENCRYPTED_DIGEST = 27 +CMSG_ENCODED_SIGNER = 28 +CMSG_ENCODED_MESSAGE = 29 +CMSG_VERSION_PARAM = 30 +CMSG_ATTR_CERT_COUNT_PARAM = 31 +CMSG_ATTR_CERT_PARAM = 32 +CMSG_CMS_RECIPIENT_COUNT_PARAM = 33 +CMSG_CMS_RECIPIENT_INDEX_PARAM = 34 +CMSG_CMS_RECIPIENT_ENCRYPTED_KEY_INDEX_PARAM = 35 +CMSG_CMS_RECIPIENT_INFO_PARAM = 36 +CMSG_UNPROTECTED_ATTR_PARAM = 37 +CMSG_SIGNER_CERT_ID_PARAM = 38 +CMSG_CMS_SIGNER_INFO_PARAM = 39 +CMSG_SIGNED_DATA_V1 = 1 +CMSG_SIGNED_DATA_V3 = 3 +CMSG_SIGNED_DATA_PKCS_1_5_VERSION = CMSG_SIGNED_DATA_V1 +CMSG_SIGNED_DATA_CMS_VERSION = CMSG_SIGNED_DATA_V3 +CMSG_SIGNER_INFO_V1 = 1 +CMSG_SIGNER_INFO_V3 = 3 +CMSG_SIGNER_INFO_PKCS_1_5_VERSION = CMSG_SIGNER_INFO_V1 +CMSG_SIGNER_INFO_CMS_VERSION = CMSG_SIGNER_INFO_V3 +CMSG_HASHED_DATA_V0 = 0 +CMSG_HASHED_DATA_V2 = 2 +CMSG_HASHED_DATA_PKCS_1_5_VERSION = CMSG_HASHED_DATA_V0 +CMSG_HASHED_DATA_CMS_VERSION = CMSG_HASHED_DATA_V2 +CMSG_ENVELOPED_DATA_V0 = 0 +CMSG_ENVELOPED_DATA_V2 = 2 +CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION = CMSG_ENVELOPED_DATA_V0 +CMSG_ENVELOPED_DATA_CMS_VERSION = CMSG_ENVELOPED_DATA_V2 +CMSG_KEY_AGREE_ORIGINATOR_CERT = 1 +CMSG_KEY_AGREE_ORIGINATOR_PUBLIC_KEY = 2 +CMSG_ENVELOPED_RECIPIENT_V0 = 0 +CMSG_ENVELOPED_RECIPIENT_V2 = 2 +CMSG_ENVELOPED_RECIPIENT_V3 = 3 +CMSG_ENVELOPED_RECIPIENT_V4 = 4 +CMSG_KEY_TRANS_PKCS_1_5_VERSION = CMSG_ENVELOPED_RECIPIENT_V0 +CMSG_KEY_TRANS_CMS_VERSION = CMSG_ENVELOPED_RECIPIENT_V2 +CMSG_KEY_AGREE_VERSION = CMSG_ENVELOPED_RECIPIENT_V3 +CMSG_MAIL_LIST_VERSION = CMSG_ENVELOPED_RECIPIENT_V4 +CMSG_CTRL_VERIFY_SIGNATURE = 1 +CMSG_CTRL_DECRYPT = 2 +CMSG_CTRL_VERIFY_HASH = 5 +CMSG_CTRL_ADD_SIGNER = 6 +CMSG_CTRL_DEL_SIGNER = 7 +CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR = 8 +CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR = 9 +CMSG_CTRL_ADD_CERT = 10 +CMSG_CTRL_DEL_CERT = 11 +CMSG_CTRL_ADD_CRL = 12 +CMSG_CTRL_DEL_CRL = 13 +CMSG_CTRL_ADD_ATTR_CERT = 14 +CMSG_CTRL_DEL_ATTR_CERT = 15 +CMSG_CTRL_KEY_TRANS_DECRYPT = 16 +CMSG_CTRL_KEY_AGREE_DECRYPT = 17 +CMSG_CTRL_MAIL_LIST_DECRYPT = 18 +CMSG_CTRL_VERIFY_SIGNATURE_EX = 19 +CMSG_CTRL_ADD_CMS_SIGNER_INFO = 20 +CMSG_VERIFY_SIGNER_PUBKEY = 1 +CMSG_VERIFY_SIGNER_CERT = 2 +CMSG_VERIFY_SIGNER_CHAIN = 3 +CMSG_VERIFY_SIGNER_NULL = 4 +CMSG_OID_GEN_ENCRYPT_KEY_FUNC = "CryptMsgDllGenEncryptKey" +CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC = "CryptMsgDllExportEncryptKey" +CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC = "CryptMsgDllImportEncryptKey" +CMSG_CONTENT_ENCRYPT_PAD_ENCODED_LEN_FLAG = 0x00000001 +CMSG_DEFAULT_INSTALLABLE_FUNC_OID = 1 +CMSG_CONTENT_ENCRYPT_FREE_PARA_FLAG = 0x00000001 +CMSG_CONTENT_ENCRYPT_RELEASE_CONTEXT_FLAG = 0x00008000 +CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC = "CryptMsgDllGenContentEncryptKey" +CMSG_KEY_TRANS_ENCRYPT_FREE_PARA_FLAG = 0x00000001 +CMSG_OID_EXPORT_KEY_TRANS_FUNC = "CryptMsgDllExportKeyTrans" +CMSG_KEY_AGREE_ENCRYPT_FREE_PARA_FLAG = 0x00000001 +CMSG_KEY_AGREE_ENCRYPT_FREE_MATERIAL_FLAG = 0x00000002 +CMSG_KEY_AGREE_ENCRYPT_FREE_PUBKEY_ALG_FLAG = 0x00000004 +CMSG_KEY_AGREE_ENCRYPT_FREE_PUBKEY_PARA_FLAG = 0x00000008 +CMSG_KEY_AGREE_ENCRYPT_FREE_PUBKEY_BITS_FLAG = 0x00000010 +CMSG_OID_EXPORT_KEY_AGREE_FUNC = "CryptMsgDllExportKeyAgree" +CMSG_MAIL_LIST_ENCRYPT_FREE_PARA_FLAG = 0x00000001 +CMSG_OID_EXPORT_MAIL_LIST_FUNC = "CryptMsgDllExportMailList" +CMSG_OID_IMPORT_KEY_TRANS_FUNC = "CryptMsgDllImportKeyTrans" +CMSG_OID_IMPORT_KEY_AGREE_FUNC = "CryptMsgDllImportKeyAgree" +CMSG_OID_IMPORT_MAIL_LIST_FUNC = "CryptMsgDllImportMailList" + +# Certificate property id's used with CertGetCertificateContextProperty +CERT_KEY_PROV_HANDLE_PROP_ID = 1 +CERT_KEY_PROV_INFO_PROP_ID = 2 +CERT_SHA1_HASH_PROP_ID = 3 +CERT_MD5_HASH_PROP_ID = 4 +CERT_HASH_PROP_ID = CERT_SHA1_HASH_PROP_ID +CERT_KEY_CONTEXT_PROP_ID = 5 +CERT_KEY_SPEC_PROP_ID = 6 +CERT_IE30_RESERVED_PROP_ID = 7 +CERT_PUBKEY_HASH_RESERVED_PROP_ID = 8 +CERT_ENHKEY_USAGE_PROP_ID = 9 +CERT_CTL_USAGE_PROP_ID = CERT_ENHKEY_USAGE_PROP_ID +CERT_NEXT_UPDATE_LOCATION_PROP_ID = 10 +CERT_FRIENDLY_NAME_PROP_ID = 11 +CERT_PVK_FILE_PROP_ID = 12 +CERT_DESCRIPTION_PROP_ID = 13 +CERT_ACCESS_STATE_PROP_ID = 14 +CERT_SIGNATURE_HASH_PROP_ID = 15 +CERT_SMART_CARD_DATA_PROP_ID = 16 +CERT_EFS_PROP_ID = 17 +CERT_FORTEZZA_DATA_PROP_ID = 18 +CERT_ARCHIVED_PROP_ID = 19 +CERT_KEY_IDENTIFIER_PROP_ID = 20 +CERT_AUTO_ENROLL_PROP_ID = 21 +CERT_PUBKEY_ALG_PARA_PROP_ID = 22 +CERT_CROSS_CERT_DIST_POINTS_PROP_ID = 23 +CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID = 24 +CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID = 25 +CERT_ENROLLMENT_PROP_ID = 26 +CERT_DATE_STAMP_PROP_ID = 27 +CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID = 28 +CERT_SUBJECT_NAME_MD5_HASH_PROP_ID = 29 +CERT_EXTENDED_ERROR_INFO_PROP_ID = 30 +CERT_RENEWAL_PROP_ID = 64 +CERT_ARCHIVED_KEY_HASH_PROP_ID = 65 +CERT_AUTO_ENROLL_RETRY_PROP_ID = 66 +CERT_AIA_URL_RETRIEVED_PROP_ID = 67 +CERT_AUTHORITY_INFO_ACCESS_PROP_ID = 68 +CERT_BACKED_UP_PROP_ID = 69 +CERT_OCSP_RESPONSE_PROP_ID = 70 +CERT_REQUEST_ORIGINATOR_PROP_ID = 71 +CERT_SOURCE_LOCATION_PROP_ID = 72 +CERT_SOURCE_URL_PROP_ID = 73 +CERT_NEW_KEY_PROP_ID = 74 +CERT_OCSP_CACHE_PREFIX_PROP_ID = 75 +CERT_SMART_CARD_ROOT_INFO_PROP_ID = 76 +CERT_NO_AUTO_EXPIRE_CHECK_PROP_ID = 77 +CERT_NCRYPT_KEY_HANDLE_PROP_ID = 78 +CERT_HCRYPTPROV_OR_NCRYPT_KEY_HANDLE_PROP_ID = 79 +CERT_SUBJECT_INFO_ACCESS_PROP_ID = 80 +CERT_CA_OCSP_AUTHORITY_INFO_ACCESS_PROP_ID = 81 +CERT_CA_DISABLE_CRL_PROP_ID = 82 +CERT_ROOT_PROGRAM_CERT_POLICIES_PROP_ID = 83 +CERT_ROOT_PROGRAM_NAME_CONSTRAINTS_PROP_ID = 84 +CERT_SUBJECT_OCSP_AUTHORITY_INFO_ACCESS_PROP_ID = 85 +CERT_SUBJECT_DISABLE_CRL_PROP_ID = 86 +CERT_CEP_PROP_ID = 87 +CERT_SIGN_HASH_CNG_ALG_PROP_ID = 89 +CERT_SCARD_PIN_ID_PROP_ID = 90 +CERT_SCARD_PIN_INFO_PROP_ID = 91 +CERT_FIRST_RESERVED_PROP_ID = 92 +CERT_LAST_RESERVED_PROP_ID = 0x00007FFF +CERT_FIRST_USER_PROP_ID = 0x00008000 +CERT_LAST_USER_PROP_ID = 0x0000FFFF + +szOID_CERT_PROP_ID_PREFIX = "1.3.6.1.4.1.311.10.11." +szOID_CERT_KEY_IDENTIFIER_PROP_ID = "1.3.6.1.4.1.311.10.11.20" +szOID_CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID = \ + "1.3.6.1.4.1.311.10.11.28" +szOID_CERT_SUBJECT_NAME_MD5_HASH_PROP_ID = \ + "1.3.6.1.4.1.311.10.11.29" +CERT_ACCESS_STATE_WRITE_PERSIST_FLAG = 0x1 +CERT_ACCESS_STATE_SYSTEM_STORE_FLAG = 0x2 +CERT_ACCESS_STATE_LM_SYSTEM_STORE_FLAG = 0x4 +CERT_SET_KEY_PROV_HANDLE_PROP_ID = 0x00000001 +CERT_SET_KEY_CONTEXT_PROP_ID = 0x00000001 +sz_CERT_STORE_PROV_MEMORY = "Memory" +sz_CERT_STORE_PROV_FILENAME_W = "File" +sz_CERT_STORE_PROV_FILENAME = sz_CERT_STORE_PROV_FILENAME_W +sz_CERT_STORE_PROV_SYSTEM_W = "System" +sz_CERT_STORE_PROV_SYSTEM = sz_CERT_STORE_PROV_SYSTEM_W +sz_CERT_STORE_PROV_PKCS7 = "PKCS7" +sz_CERT_STORE_PROV_SERIALIZED = "Serialized" +sz_CERT_STORE_PROV_COLLECTION = "Collection" +sz_CERT_STORE_PROV_SYSTEM_REGISTRY_W = "SystemRegistry" +sz_CERT_STORE_PROV_SYSTEM_REGISTRY = sz_CERT_STORE_PROV_SYSTEM_REGISTRY_W +sz_CERT_STORE_PROV_PHYSICAL_W = "Physical" +sz_CERT_STORE_PROV_PHYSICAL = sz_CERT_STORE_PROV_PHYSICAL_W +sz_CERT_STORE_PROV_SMART_CARD_W = "SmartCard" +sz_CERT_STORE_PROV_SMART_CARD = sz_CERT_STORE_PROV_SMART_CARD_W +sz_CERT_STORE_PROV_LDAP_W = "Ldap" +sz_CERT_STORE_PROV_LDAP = sz_CERT_STORE_PROV_LDAP_W +CERT_STORE_SIGNATURE_FLAG = 0x00000001 +CERT_STORE_TIME_VALIDITY_FLAG = 0x00000002 +CERT_STORE_REVOCATION_FLAG = 0x00000004 +CERT_STORE_NO_CRL_FLAG = 0x00010000 +CERT_STORE_NO_ISSUER_FLAG = 0x00020000 +CERT_STORE_BASE_CRL_FLAG = 0x00000100 +CERT_STORE_DELTA_CRL_FLAG = 0x00000200 +CERT_STORE_NO_CRYPT_RELEASE_FLAG = 0x00000001 +CERT_STORE_SET_LOCALIZED_NAME_FLAG = 0x00000002 +CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG = 0x00000004 +CERT_STORE_DELETE_FLAG = 0x00000010 +CERT_STORE_UNSAFE_PHYSICAL_FLAG = 0x00000020 +CERT_STORE_SHARE_STORE_FLAG = 0x00000040 +CERT_STORE_SHARE_CONTEXT_FLAG = 0x00000080 +CERT_STORE_MANIFOLD_FLAG = 0x00000100 +CERT_STORE_ENUM_ARCHIVED_FLAG = 0x00000200 +CERT_STORE_UPDATE_KEYID_FLAG = 0x00000400 +CERT_STORE_BACKUP_RESTORE_FLAG = 0x00000800 +CERT_STORE_READONLY_FLAG = 0x00008000 +CERT_STORE_OPEN_EXISTING_FLAG = 0x00004000 +CERT_STORE_CREATE_NEW_FLAG = 0x00002000 +CERT_STORE_MAXIMUM_ALLOWED_FLAG = 0x00001000 +CERT_SYSTEM_STORE_MASK = (-65536) +CERT_SYSTEM_STORE_RELOCATE_FLAG = (-2147483648) +CERT_SYSTEM_STORE_UNPROTECTED_FLAG = 0x40000000 +CERT_SYSTEM_STORE_LOCATION_MASK = 0x00FF0000 +CERT_SYSTEM_STORE_LOCATION_SHIFT = 16 +CERT_SYSTEM_STORE_CURRENT_USER_ID = 1 +CERT_SYSTEM_STORE_LOCAL_MACHINE_ID = 2 +CERT_SYSTEM_STORE_CURRENT_SERVICE_ID = 4 +CERT_SYSTEM_STORE_SERVICES_ID = 5 +CERT_SYSTEM_STORE_USERS_ID = 6 +CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY_ID = 7 +CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY_ID = 8 +CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE_ID = 9 +CERT_SYSTEM_STORE_CURRENT_USER = \ + (CERT_SYSTEM_STORE_CURRENT_USER_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT) +CERT_SYSTEM_STORE_LOCAL_MACHINE = \ + (CERT_SYSTEM_STORE_LOCAL_MACHINE_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT) +CERT_SYSTEM_STORE_CURRENT_SERVICE = \ + (CERT_SYSTEM_STORE_CURRENT_SERVICE_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT) +CERT_SYSTEM_STORE_SERVICES = \ + (CERT_SYSTEM_STORE_SERVICES_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT) +CERT_SYSTEM_STORE_USERS = \ + (CERT_SYSTEM_STORE_USERS_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT) +CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY = \ + (CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY_ID << \ + CERT_SYSTEM_STORE_LOCATION_SHIFT) +CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY = \ + (CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY_ID << \ + CERT_SYSTEM_STORE_LOCATION_SHIFT) +CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE = \ + (CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE_ID << \ + CERT_SYSTEM_STORE_LOCATION_SHIFT) +CERT_PROT_ROOT_DISABLE_CURRENT_USER_FLAG = 0x1 +CERT_PROT_ROOT_INHIBIT_ADD_AT_INIT_FLAG = 0x2 +CERT_PROT_ROOT_INHIBIT_PURGE_LM_FLAG = 0x4 +CERT_PROT_ROOT_DISABLE_LM_AUTH_FLAG = 0x8 +CERT_PROT_ROOT_ONLY_LM_GPT_FLAG = 0x8 +CERT_PROT_ROOT_DISABLE_NT_AUTH_REQUIRED_FLAG = 0x10 +CERT_PROT_ROOT_DISABLE_NOT_DEFINED_NAME_CONSTRAINT_FLAG = 0x20 +CERT_TRUST_PUB_ALLOW_TRUST_MASK = 0x00000003 +CERT_TRUST_PUB_ALLOW_END_USER_TRUST = 0x00000000 +CERT_TRUST_PUB_ALLOW_MACHINE_ADMIN_TRUST = 0x00000001 +CERT_TRUST_PUB_ALLOW_ENTERPRISE_ADMIN_TRUST = 0x00000002 +CERT_TRUST_PUB_CHECK_PUBLISHER_REV_FLAG = 0x00000100 +CERT_TRUST_PUB_CHECK_TIMESTAMP_REV_FLAG = 0x00000200 + +CERT_AUTH_ROOT_AUTO_UPDATE_LOCAL_MACHINE_REGPATH = r"Software\Microsoft\SystemCertificates\AuthRoot\AutoUpdate" +CERT_AUTH_ROOT_AUTO_UPDATE_DISABLE_UNTRUSTED_ROOT_LOGGING_FLAG = 0x1 +CERT_AUTH_ROOT_AUTO_UPDATE_DISABLE_PARTIAL_CHAIN_LOGGING_FLAG = 0x2 +CERT_AUTH_ROOT_AUTO_UPDATE_ROOT_DIR_URL_VALUE_NAME = "RootDirUrl" +CERT_AUTH_ROOT_AUTO_UPDATE_SYNC_DELTA_TIME_VALUE_NAME = "SyncDeltaTime" +CERT_AUTH_ROOT_AUTO_UPDATE_FLAGS_VALUE_NAME = "Flags" +CERT_AUTH_ROOT_CTL_FILENAME = "authroot.stl" +CERT_AUTH_ROOT_CTL_FILENAME_A = "authroot.stl" +CERT_AUTH_ROOT_CAB_FILENAME = "authrootstl.cab" +CERT_AUTH_ROOT_SEQ_FILENAME = "authrootseq.txt" +CERT_AUTH_ROOT_CERT_EXT = ".crt" + +CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH = r"Software\Policies\Microsoft\SystemCertificates" +CERT_EFSBLOB_REGPATH = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH + r"\EFS" +CERT_EFSBLOB_VALUE_NAME = "EFSBlob" +CERT_PROT_ROOT_FLAGS_REGPATH = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH +r"\Root\ProtectedRoots" +CERT_PROT_ROOT_FLAGS_VALUE_NAME = "Flags" +CERT_TRUST_PUB_SAFER_GROUP_POLICY_REGPATH = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH + r"\TrustedPublisher\Safer" +CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH = r"Software\Microsoft\SystemCertificates" +CERT_TRUST_PUB_SAFER_LOCAL_MACHINE_REGPATH = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH + r"\TrustedPublisher\Safer" +CERT_TRUST_PUB_AUTHENTICODE_FLAGS_VALUE_NAME = "AuthenticodeFlags" +CERT_OCM_SUBCOMPONENTS_LOCAL_MACHINE_REGPATH = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Setup\OC Manager\Subcomponents" +CERT_OCM_SUBCOMPONENTS_ROOT_AUTO_UPDATE_VALUE_NAME = r"RootAutoUpdate" +CERT_DISABLE_ROOT_AUTO_UPDATE_REGPATH = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH + r"\AuthRoot" +CERT_DISABLE_ROOT_AUTO_UPDATE_VALUE_NAME = "DisableRootAutoUpdate" +CERT_AUTH_ROOT_AUTO_UPDATE_LOCAL_MACHINE_REGPATH = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH + r"\AuthRoot\AutoUpdate" + +CERT_REGISTRY_STORE_REMOTE_FLAG = 0x10000 +CERT_REGISTRY_STORE_SERIALIZED_FLAG = 0x20000 +CERT_REGISTRY_STORE_CLIENT_GPT_FLAG = (-2147483648) +CERT_REGISTRY_STORE_LM_GPT_FLAG = 0x01000000 +CERT_REGISTRY_STORE_ROAMING_FLAG = 0x40000 +CERT_REGISTRY_STORE_MY_IE_DIRTY_FLAG = 0x80000 +CERT_IE_DIRTY_FLAGS_REGPATH = r"Software\Microsoft\Cryptography\IEDirtyFlags" + +CERT_FILE_STORE_COMMIT_ENABLE_FLAG = 0x10000 +CERT_LDAP_STORE_SIGN_FLAG = 0x10000 +CERT_LDAP_STORE_AREC_EXCLUSIVE_FLAG = 0x20000 +CERT_LDAP_STORE_OPENED_FLAG = 0x40000 +CERT_LDAP_STORE_UNBIND_FLAG = 0x80000 +CRYPT_OID_OPEN_STORE_PROV_FUNC = "CertDllOpenStoreProv" + +CERT_STORE_PROV_EXTERNAL_FLAG = 0x1 +CERT_STORE_PROV_DELETED_FLAG = 0x2 +CERT_STORE_PROV_NO_PERSIST_FLAG = 0x4 +CERT_STORE_PROV_SYSTEM_STORE_FLAG = 0x8 +CERT_STORE_PROV_LM_SYSTEM_STORE_FLAG = 0x10 +CERT_STORE_PROV_CLOSE_FUNC = 0 +CERT_STORE_PROV_READ_CERT_FUNC = 1 +CERT_STORE_PROV_WRITE_CERT_FUNC = 2 +CERT_STORE_PROV_DELETE_CERT_FUNC = 3 +CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC = 4 +CERT_STORE_PROV_READ_CRL_FUNC = 5 +CERT_STORE_PROV_WRITE_CRL_FUNC = 6 +CERT_STORE_PROV_DELETE_CRL_FUNC = 7 +CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC = 8 +CERT_STORE_PROV_READ_CTL_FUNC = 9 +CERT_STORE_PROV_WRITE_CTL_FUNC = 10 +CERT_STORE_PROV_DELETE_CTL_FUNC = 11 +CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC = 12 +CERT_STORE_PROV_CONTROL_FUNC = 13 +CERT_STORE_PROV_FIND_CERT_FUNC = 14 +CERT_STORE_PROV_FREE_FIND_CERT_FUNC = 15 +CERT_STORE_PROV_GET_CERT_PROPERTY_FUNC = 16 +CERT_STORE_PROV_FIND_CRL_FUNC = 17 +CERT_STORE_PROV_FREE_FIND_CRL_FUNC = 18 +CERT_STORE_PROV_GET_CRL_PROPERTY_FUNC = 19 +CERT_STORE_PROV_FIND_CTL_FUNC = 20 +CERT_STORE_PROV_FREE_FIND_CTL_FUNC = 21 +CERT_STORE_PROV_GET_CTL_PROPERTY_FUNC = 22 +CERT_STORE_PROV_WRITE_ADD_FLAG = 0x1 +CERT_STORE_SAVE_AS_STORE = 1 +CERT_STORE_SAVE_AS_PKCS7 = 2 +CERT_STORE_SAVE_TO_FILE = 1 +CERT_STORE_SAVE_TO_MEMORY = 2 +CERT_STORE_SAVE_TO_FILENAME_A = 3 +CERT_STORE_SAVE_TO_FILENAME_W = 4 +CERT_STORE_SAVE_TO_FILENAME = CERT_STORE_SAVE_TO_FILENAME_W +CERT_CLOSE_STORE_FORCE_FLAG = 0x00000001 +CERT_CLOSE_STORE_CHECK_FLAG = 0x00000002 +CERT_COMPARE_MASK = 0xFFFF +CERT_COMPARE_SHIFT = 16 +CERT_COMPARE_ANY = 0 +CERT_COMPARE_SHA1_HASH = 1 +CERT_COMPARE_NAME = 2 +CERT_COMPARE_ATTR = 3 +CERT_COMPARE_MD5_HASH = 4 +CERT_COMPARE_PROPERTY = 5 +CERT_COMPARE_PUBLIC_KEY = 6 +CERT_COMPARE_HASH = CERT_COMPARE_SHA1_HASH +CERT_COMPARE_NAME_STR_A = 7 +CERT_COMPARE_NAME_STR_W = 8 +CERT_COMPARE_KEY_SPEC = 9 +CERT_COMPARE_ENHKEY_USAGE = 10 +CERT_COMPARE_CTL_USAGE = CERT_COMPARE_ENHKEY_USAGE +CERT_COMPARE_SUBJECT_CERT = 11 +CERT_COMPARE_ISSUER_OF = 12 +CERT_COMPARE_EXISTING = 13 +CERT_COMPARE_SIGNATURE_HASH = 14 +CERT_COMPARE_KEY_IDENTIFIER = 15 +CERT_COMPARE_CERT_ID = 16 +CERT_COMPARE_CROSS_CERT_DIST_POINTS = 17 +CERT_COMPARE_PUBKEY_MD5_HASH = 18 +CERT_FIND_ANY = (CERT_COMPARE_ANY << CERT_COMPARE_SHIFT) +CERT_FIND_SHA1_HASH = (CERT_COMPARE_SHA1_HASH << CERT_COMPARE_SHIFT) +CERT_FIND_MD5_HASH = (CERT_COMPARE_MD5_HASH << CERT_COMPARE_SHIFT) +CERT_FIND_SIGNATURE_HASH = (CERT_COMPARE_SIGNATURE_HASH << CERT_COMPARE_SHIFT) +CERT_FIND_KEY_IDENTIFIER = (CERT_COMPARE_KEY_IDENTIFIER << CERT_COMPARE_SHIFT) +CERT_FIND_HASH = CERT_FIND_SHA1_HASH +CERT_FIND_PROPERTY = (CERT_COMPARE_PROPERTY << CERT_COMPARE_SHIFT) +CERT_FIND_PUBLIC_KEY = (CERT_COMPARE_PUBLIC_KEY << CERT_COMPARE_SHIFT) +CERT_FIND_SUBJECT_NAME = (CERT_COMPARE_NAME << CERT_COMPARE_SHIFT | \ + CERT_INFO_SUBJECT_FLAG) +CERT_FIND_SUBJECT_ATTR = (CERT_COMPARE_ATTR << CERT_COMPARE_SHIFT | \ + CERT_INFO_SUBJECT_FLAG) +CERT_FIND_ISSUER_NAME = (CERT_COMPARE_NAME << CERT_COMPARE_SHIFT | \ + CERT_INFO_ISSUER_FLAG) +CERT_FIND_ISSUER_ATTR = (CERT_COMPARE_ATTR << CERT_COMPARE_SHIFT | \ + CERT_INFO_ISSUER_FLAG) +CERT_FIND_SUBJECT_STR_A = (CERT_COMPARE_NAME_STR_A << CERT_COMPARE_SHIFT | \ + CERT_INFO_SUBJECT_FLAG) +CERT_FIND_SUBJECT_STR_W = (CERT_COMPARE_NAME_STR_W << CERT_COMPARE_SHIFT | \ + CERT_INFO_SUBJECT_FLAG) +CERT_FIND_SUBJECT_STR = CERT_FIND_SUBJECT_STR_W +CERT_FIND_ISSUER_STR_A = (CERT_COMPARE_NAME_STR_A << CERT_COMPARE_SHIFT | \ + CERT_INFO_ISSUER_FLAG) +CERT_FIND_ISSUER_STR_W = (CERT_COMPARE_NAME_STR_W << CERT_COMPARE_SHIFT | \ + CERT_INFO_ISSUER_FLAG) +CERT_FIND_ISSUER_STR = CERT_FIND_ISSUER_STR_W +CERT_FIND_KEY_SPEC = (CERT_COMPARE_KEY_SPEC << CERT_COMPARE_SHIFT) +CERT_FIND_ENHKEY_USAGE = (CERT_COMPARE_ENHKEY_USAGE << CERT_COMPARE_SHIFT) +CERT_FIND_CTL_USAGE = CERT_FIND_ENHKEY_USAGE +CERT_FIND_SUBJECT_CERT = (CERT_COMPARE_SUBJECT_CERT << CERT_COMPARE_SHIFT) +CERT_FIND_ISSUER_OF = (CERT_COMPARE_ISSUER_OF << CERT_COMPARE_SHIFT) +CERT_FIND_EXISTING = (CERT_COMPARE_EXISTING << CERT_COMPARE_SHIFT) +CERT_FIND_CERT_ID = (CERT_COMPARE_CERT_ID << CERT_COMPARE_SHIFT) +CERT_FIND_CROSS_CERT_DIST_POINTS = \ + (CERT_COMPARE_CROSS_CERT_DIST_POINTS << CERT_COMPARE_SHIFT) +CERT_FIND_PUBKEY_MD5_HASH = \ + (CERT_COMPARE_PUBKEY_MD5_HASH << CERT_COMPARE_SHIFT) +CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG = 0x1 +CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG = 0x2 +CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG = 0x4 +CERT_FIND_NO_ENHKEY_USAGE_FLAG = 0x8 +CERT_FIND_OR_ENHKEY_USAGE_FLAG = 0x10 +CERT_FIND_VALID_ENHKEY_USAGE_FLAG = 0x20 +CERT_FIND_OPTIONAL_CTL_USAGE_FLAG = CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG +CERT_FIND_EXT_ONLY_CTL_USAGE_FLAG = \ + CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG +CERT_FIND_PROP_ONLY_CTL_USAGE_FLAG = \ + CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG +CERT_FIND_NO_CTL_USAGE_FLAG = CERT_FIND_NO_ENHKEY_USAGE_FLAG +CERT_FIND_OR_CTL_USAGE_FLAG = CERT_FIND_OR_ENHKEY_USAGE_FLAG +CERT_FIND_VALID_CTL_USAGE_FLAG = CERT_FIND_VALID_ENHKEY_USAGE_FLAG +CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG = (-2147483648) +CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG = 0x40000000 +CTL_ENTRY_FROM_PROP_CHAIN_FLAG = 0x1 +CRL_FIND_ANY = 0 +CRL_FIND_ISSUED_BY = 1 +CRL_FIND_EXISTING = 2 +CRL_FIND_ISSUED_FOR = 3 +CRL_FIND_ISSUED_BY_AKI_FLAG = 0x1 +CRL_FIND_ISSUED_BY_SIGNATURE_FLAG = 0x2 +CRL_FIND_ISSUED_BY_DELTA_FLAG = 0x4 +CRL_FIND_ISSUED_BY_BASE_FLAG = 0x8 +CERT_STORE_ADD_NEW = 1 +CERT_STORE_ADD_USE_EXISTING = 2 +CERT_STORE_ADD_REPLACE_EXISTING = 3 +CERT_STORE_ADD_ALWAYS = 4 +CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES = 5 +CERT_STORE_ADD_NEWER = 6 +CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES = 7 +CERT_STORE_CERTIFICATE_CONTEXT = 1 +CERT_STORE_CRL_CONTEXT = 2 +CERT_STORE_CTL_CONTEXT = 3 + +CERT_STORE_ALL_CONTEXT_FLAG = -1 +CERT_STORE_CERTIFICATE_CONTEXT_FLAG = \ + (1 << CERT_STORE_CERTIFICATE_CONTEXT) +CERT_STORE_CRL_CONTEXT_FLAG = \ + (1 << CERT_STORE_CRL_CONTEXT) +CERT_STORE_CTL_CONTEXT_FLAG = \ + (1 << CERT_STORE_CTL_CONTEXT) +CTL_ANY_SUBJECT_TYPE = 1 +CTL_CERT_SUBJECT_TYPE = 2 +CTL_FIND_ANY = 0 +CTL_FIND_SHA1_HASH = 1 +CTL_FIND_MD5_HASH = 2 +CTL_FIND_USAGE = 3 +CTL_FIND_SUBJECT = 4 +CTL_FIND_EXISTING = 5 +CTL_FIND_NO_LIST_ID_CBDATA = (-1) +CTL_FIND_SAME_USAGE_FLAG = 0x1 +CERT_STORE_CTRL_RESYNC = 1 +CERT_STORE_CTRL_NOTIFY_CHANGE = 2 +CERT_STORE_CTRL_COMMIT = 3 +CERT_STORE_CTRL_AUTO_RESYNC = 4 +CERT_STORE_CTRL_CANCEL_NOTIFY = 5 +CERT_STORE_CTRL_INHIBIT_DUPLICATE_HANDLE_FLAG = 0x1 +CERT_STORE_CTRL_COMMIT_FORCE_FLAG = 0x1 +CERT_STORE_CTRL_COMMIT_CLEAR_FLAG = 0x2 +CERT_STORE_LOCALIZED_NAME_PROP_ID = 0x1000 +CERT_CREATE_CONTEXT_NOCOPY_FLAG = 0x1 +CERT_CREATE_CONTEXT_SORTED_FLAG = 0x2 +CERT_CREATE_CONTEXT_NO_HCRYPTMSG_FLAG = 0x4 +CERT_CREATE_CONTEXT_NO_ENTRY_FLAG = 0x8 + +CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG = 0x1 +CERT_PHYSICAL_STORE_OPEN_DISABLE_FLAG = 0x2 +CERT_PHYSICAL_STORE_REMOTE_OPEN_DISABLE_FLAG = 0x4 +CERT_PHYSICAL_STORE_INSERT_COMPUTER_NAME_ENABLE_FLAG = 0x8 +CERT_PHYSICAL_STORE_PREDEFINED_ENUM_FLAG = 0x1 + +# Names of physical cert stores +CERT_PHYSICAL_STORE_DEFAULT_NAME = ".Default" +CERT_PHYSICAL_STORE_GROUP_POLICY_NAME = ".GroupPolicy" +CERT_PHYSICAL_STORE_LOCAL_MACHINE_NAME = ".LocalMachine" +CERT_PHYSICAL_STORE_DS_USER_CERTIFICATE_NAME = ".UserCertificate" +CERT_PHYSICAL_STORE_LOCAL_MACHINE_GROUP_POLICY_NAME = ".LocalMachineGroupPolicy" +CERT_PHYSICAL_STORE_ENTERPRISE_NAME = ".Enterprise" +CERT_PHYSICAL_STORE_AUTH_ROOT_NAME = ".AuthRoot" +CERT_PHYSICAL_STORE_SMART_CARD_NAME = ".SmartCard" + +CRYPT_OID_OPEN_SYSTEM_STORE_PROV_FUNC = "CertDllOpenSystemStoreProv" +CRYPT_OID_REGISTER_SYSTEM_STORE_FUNC = "CertDllRegisterSystemStore" +CRYPT_OID_UNREGISTER_SYSTEM_STORE_FUNC = "CertDllUnregisterSystemStore" +CRYPT_OID_ENUM_SYSTEM_STORE_FUNC = "CertDllEnumSystemStore" +CRYPT_OID_REGISTER_PHYSICAL_STORE_FUNC = "CertDllRegisterPhysicalStore" +CRYPT_OID_UNREGISTER_PHYSICAL_STORE_FUNC = "CertDllUnregisterPhysicalStore" +CRYPT_OID_ENUM_PHYSICAL_STORE_FUNC = "CertDllEnumPhysicalStore" +CRYPT_OID_SYSTEM_STORE_LOCATION_VALUE_NAME = "SystemStoreLocation" + +CMSG_TRUSTED_SIGNER_FLAG = 0x1 +CMSG_SIGNER_ONLY_FLAG = 0x2 +CMSG_USE_SIGNER_INDEX_FLAG = 0x4 +CMSG_CMS_ENCAPSULATED_CTL_FLAG = 0x00008000 +CMSG_ENCODE_SORTED_CTL_FLAG = 0x1 +CMSG_ENCODE_HASHED_SUBJECT_IDENTIFIER_FLAG = 0x2 +CERT_VERIFY_INHIBIT_CTL_UPDATE_FLAG = 0x1 +CERT_VERIFY_TRUSTED_SIGNERS_FLAG = 0x2 +CERT_VERIFY_NO_TIME_CHECK_FLAG = 0x4 +CERT_VERIFY_ALLOW_MORE_USAGE_FLAG = 0x8 +CERT_VERIFY_UPDATED_CTL_FLAG = 0x1 +CERT_CONTEXT_REVOCATION_TYPE = 1 +CERT_VERIFY_REV_CHAIN_FLAG = 0x00000001 +CERT_VERIFY_CACHE_ONLY_BASED_REVOCATION = 0x00000002 +CERT_VERIFY_REV_ACCUMULATIVE_TIMEOUT_FLAG = 0x00000004 +CERT_UNICODE_IS_RDN_ATTRS_FLAG = 0x1 +CERT_CASE_INSENSITIVE_IS_RDN_ATTRS_FLAG = 0x2 +CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB = 1 +CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT = 2 +CRYPT_VERIFY_CERT_SIGN_SUBJECT_CRL = 3 +CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY = 1 +CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT = 2 +CRYPT_VERIFY_CERT_SIGN_ISSUER_CHAIN = 3 +CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL = 4 +CRYPT_DEFAULT_CONTEXT_AUTO_RELEASE_FLAG = 0x00000001 +CRYPT_DEFAULT_CONTEXT_PROCESS_FLAG = 0x00000002 +CRYPT_DEFAULT_CONTEXT_CERT_SIGN_OID = 1 +CRYPT_DEFAULT_CONTEXT_MULTI_CERT_SIGN_OID = 2 +CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC = "CryptDllExportPublicKeyInfoEx" +CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC = "CryptDllImportPublicKeyInfoEx" +CRYPT_ACQUIRE_CACHE_FLAG = 0x00000001 +CRYPT_ACQUIRE_USE_PROV_INFO_FLAG = 0x00000002 +CRYPT_ACQUIRE_COMPARE_KEY_FLAG = 0x00000004 +CRYPT_ACQUIRE_SILENT_FLAG = 0x00000040 +CRYPT_FIND_USER_KEYSET_FLAG = 0x00000001 +CRYPT_FIND_MACHINE_KEYSET_FLAG = 0x00000002 +CRYPT_FIND_SILENT_KEYSET_FLAG = 0x00000040 +CRYPT_OID_IMPORT_PRIVATE_KEY_INFO_FUNC = "CryptDllImportPrivateKeyInfoEx" +CRYPT_OID_EXPORT_PRIVATE_KEY_INFO_FUNC = "CryptDllExportPrivateKeyInfoEx" +CRYPT_DELETE_KEYSET = CRYPT_DELETEKEYSET +CERT_SIMPLE_NAME_STR = 1 +CERT_OID_NAME_STR = 2 +CERT_X500_NAME_STR = 3 +CERT_NAME_STR_SEMICOLON_FLAG = 0x40000000 +CERT_NAME_STR_NO_PLUS_FLAG = 0x20000000 +CERT_NAME_STR_NO_QUOTING_FLAG = 0x10000000 +CERT_NAME_STR_CRLF_FLAG = 0x08000000 +CERT_NAME_STR_COMMA_FLAG = 0x04000000 +CERT_NAME_STR_REVERSE_FLAG = 0x02000000 +CERT_NAME_STR_DISABLE_IE4_UTF8_FLAG = 0x00010000 +CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG = 0x00020000 +CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG = 0x00040000 +CERT_NAME_EMAIL_TYPE = 1 +CERT_NAME_RDN_TYPE = 2 +CERT_NAME_ATTR_TYPE = 3 +CERT_NAME_SIMPLE_DISPLAY_TYPE = 4 +CERT_NAME_FRIENDLY_DISPLAY_TYPE = 5 +CERT_NAME_DNS_TYPE = 6 +CERT_NAME_URL_TYPE = 7 +CERT_NAME_UPN_TYPE = 8 +CERT_NAME_ISSUER_FLAG = 0x1 +CERT_NAME_DISABLE_IE4_UTF8_FLAG = 0x00010000 +CRYPT_MESSAGE_BARE_CONTENT_OUT_FLAG = 0x00000001 +CRYPT_MESSAGE_ENCAPSULATED_CONTENT_OUT_FLAG = 0x00000002 +CRYPT_MESSAGE_KEYID_SIGNER_FLAG = 0x00000004 +CRYPT_MESSAGE_SILENT_KEYSET_FLAG = 0x00000040 +CRYPT_MESSAGE_KEYID_RECIPIENT_FLAG = 0x4 +CERT_QUERY_OBJECT_FILE = 0x00000001 +CERT_QUERY_OBJECT_BLOB = 0x00000002 +CERT_QUERY_CONTENT_CERT = 1 +CERT_QUERY_CONTENT_CTL = 2 +CERT_QUERY_CONTENT_CRL = 3 +CERT_QUERY_CONTENT_SERIALIZED_STORE = 4 +CERT_QUERY_CONTENT_SERIALIZED_CERT = 5 +CERT_QUERY_CONTENT_SERIALIZED_CTL = 6 +CERT_QUERY_CONTENT_SERIALIZED_CRL = 7 +CERT_QUERY_CONTENT_PKCS7_SIGNED = 8 +CERT_QUERY_CONTENT_PKCS7_UNSIGNED = 9 +CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED = 10 +CERT_QUERY_CONTENT_PKCS10 = 11 +CERT_QUERY_CONTENT_PFX = 12 +CERT_QUERY_CONTENT_CERT_PAIR = 13 +CERT_QUERY_CONTENT_FLAG_CERT = \ + ( 1 << CERT_QUERY_CONTENT_CERT) +CERT_QUERY_CONTENT_FLAG_CTL = \ + ( 1 << CERT_QUERY_CONTENT_CTL) +CERT_QUERY_CONTENT_FLAG_CRL = \ + ( 1 << CERT_QUERY_CONTENT_CRL) +CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE = \ + ( 1 << CERT_QUERY_CONTENT_SERIALIZED_STORE) +CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT = \ + ( 1 << CERT_QUERY_CONTENT_SERIALIZED_CERT) +CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL = \ + ( 1 << CERT_QUERY_CONTENT_SERIALIZED_CTL) +CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL = \ + ( 1 << CERT_QUERY_CONTENT_SERIALIZED_CRL) +CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED = \ + ( 1 << CERT_QUERY_CONTENT_PKCS7_SIGNED) +CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED = \ + ( 1 << CERT_QUERY_CONTENT_PKCS7_UNSIGNED) +CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED = \ + ( 1 << CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED) +CERT_QUERY_CONTENT_FLAG_PKCS10 = \ + ( 1 << CERT_QUERY_CONTENT_PKCS10) +CERT_QUERY_CONTENT_FLAG_PFX = \ + ( 1 << CERT_QUERY_CONTENT_PFX) +CERT_QUERY_CONTENT_FLAG_CERT_PAIR = \ + ( 1 << CERT_QUERY_CONTENT_CERT_PAIR) +CERT_QUERY_CONTENT_FLAG_ALL = \ + CERT_QUERY_CONTENT_FLAG_CERT | \ + CERT_QUERY_CONTENT_FLAG_CTL | \ + CERT_QUERY_CONTENT_FLAG_CRL | \ + CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE | \ + CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT | \ + CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL | \ + CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL | \ + CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED | \ + CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED | \ + CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED | \ + CERT_QUERY_CONTENT_FLAG_PKCS10 | \ + CERT_QUERY_CONTENT_FLAG_PFX | \ + CERT_QUERY_CONTENT_FLAG_CERT_PAIR +CERT_QUERY_FORMAT_BINARY = 1 +CERT_QUERY_FORMAT_BASE64_ENCODED = 2 +CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED = 3 +CERT_QUERY_FORMAT_FLAG_BINARY = \ + ( 1 << CERT_QUERY_FORMAT_BINARY) +CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED = \ + ( 1 << CERT_QUERY_FORMAT_BASE64_ENCODED) +CERT_QUERY_FORMAT_FLAG_ASN_ASCII_HEX_ENCODED = \ + ( 1 << CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED) +CERT_QUERY_FORMAT_FLAG_ALL = \ + CERT_QUERY_FORMAT_FLAG_BINARY | \ + CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED | \ + CERT_QUERY_FORMAT_FLAG_ASN_ASCII_HEX_ENCODED + +CREDENTIAL_OID_PASSWORD_CREDENTIALS_A = 1 +CREDENTIAL_OID_PASSWORD_CREDENTIALS_W = 2 +CREDENTIAL_OID_PASSWORD_CREDENTIALS = CREDENTIAL_OID_PASSWORD_CREDENTIALS_W + +SCHEME_OID_RETRIEVE_ENCODED_OBJECT_FUNC = "SchemeDllRetrieveEncodedObject" +SCHEME_OID_RETRIEVE_ENCODED_OBJECTW_FUNC = "SchemeDllRetrieveEncodedObjectW" +CONTEXT_OID_CREATE_OBJECT_CONTEXT_FUNC = "ContextDllCreateObjectContext" +CONTEXT_OID_CERTIFICATE = 1 +CONTEXT_OID_CRL = 2 +CONTEXT_OID_CTL = 3 +CONTEXT_OID_PKCS7 = 4 +CONTEXT_OID_CAPI2_ANY = 5 +CONTEXT_OID_OCSP_RESP = 6 + +CRYPT_RETRIEVE_MULTIPLE_OBJECTS = 0x00000001 +CRYPT_CACHE_ONLY_RETRIEVAL = 0x00000002 +CRYPT_WIRE_ONLY_RETRIEVAL = 0x00000004 +CRYPT_DONT_CACHE_RESULT = 0x00000008 +CRYPT_ASYNC_RETRIEVAL = 0x00000010 +CRYPT_STICKY_CACHE_RETRIEVAL = 0x00001000 +CRYPT_LDAP_SCOPE_BASE_ONLY_RETRIEVAL = 0x00002000 +CRYPT_OFFLINE_CHECK_RETRIEVAL = 0x00004000 +CRYPT_LDAP_INSERT_ENTRY_ATTRIBUTE = 0x00008000 +CRYPT_LDAP_SIGN_RETRIEVAL = 0x00010000 +CRYPT_NO_AUTH_RETRIEVAL = 0x00020000 +CRYPT_LDAP_AREC_EXCLUSIVE_RETRIEVAL = 0x00040000 +CRYPT_AIA_RETRIEVAL = 0x00080000 +CRYPT_VERIFY_CONTEXT_SIGNATURE = 0x00000020 +CRYPT_VERIFY_DATA_HASH = 0x00000040 +CRYPT_KEEP_TIME_VALID = 0x00000080 +CRYPT_DONT_VERIFY_SIGNATURE = 0x00000100 +CRYPT_DONT_CHECK_TIME_VALIDITY = 0x00000200 +CRYPT_CHECK_FRESHNESS_TIME_VALIDITY = 0x00000400 +CRYPT_ACCUMULATIVE_TIMEOUT = 0x00000800 +CRYPT_PARAM_ASYNC_RETRIEVAL_COMPLETION = 1 +CRYPT_PARAM_CANCEL_ASYNC_RETRIEVAL = 2 +CRYPT_GET_URL_FROM_PROPERTY = 0x00000001 +CRYPT_GET_URL_FROM_EXTENSION = 0x00000002 +CRYPT_GET_URL_FROM_UNAUTH_ATTRIBUTE = 0x00000004 +CRYPT_GET_URL_FROM_AUTH_ATTRIBUTE = 0x00000008 +URL_OID_GET_OBJECT_URL_FUNC = "UrlDllGetObjectUrl" +TIME_VALID_OID_GET_OBJECT_FUNC = "TimeValidDllGetObject" +TIME_VALID_OID_FLUSH_OBJECT_FUNC = "TimeValidDllFlushObject" + +TIME_VALID_OID_GET_CTL = 1 +TIME_VALID_OID_GET_CRL = 2 +TIME_VALID_OID_GET_CRL_FROM_CERT = 3 +TIME_VALID_OID_GET_FRESHEST_CRL_FROM_CERT = 4 +TIME_VALID_OID_GET_FRESHEST_CRL_FROM_CRL = 5 + +TIME_VALID_OID_FLUSH_CTL = 1 +TIME_VALID_OID_FLUSH_CRL = 2 +TIME_VALID_OID_FLUSH_CRL_FROM_CERT = 3 +TIME_VALID_OID_FLUSH_FRESHEST_CRL_FROM_CERT = 4 +TIME_VALID_OID_FLUSH_FRESHEST_CRL_FROM_CRL = 5 + +CRYPTPROTECT_PROMPT_ON_UNPROTECT = 0x1 +CRYPTPROTECT_PROMPT_ON_PROTECT = 0x2 +CRYPTPROTECT_PROMPT_RESERVED = 0x04 +CRYPTPROTECT_PROMPT_STRONG = 0x08 +CRYPTPROTECT_PROMPT_REQUIRE_STRONG = 0x10 +CRYPTPROTECT_UI_FORBIDDEN = 0x1 +CRYPTPROTECT_LOCAL_MACHINE = 0x4 +CRYPTPROTECT_CRED_SYNC = 0x8 +CRYPTPROTECT_AUDIT = 0x10 +CRYPTPROTECT_NO_RECOVERY = 0x20 +CRYPTPROTECT_VERIFY_PROTECTION = 0x40 +CRYPTPROTECT_CRED_REGENERATE = 0x80 +CRYPTPROTECT_FIRST_RESERVED_FLAGVAL = 0x0FFFFFFF +CRYPTPROTECT_LAST_RESERVED_FLAGVAL = (-1) +CRYPTPROTECTMEMORY_BLOCK_SIZE = 16 +CRYPTPROTECTMEMORY_SAME_PROCESS = 0x00 +CRYPTPROTECTMEMORY_CROSS_PROCESS = 0x01 +CRYPTPROTECTMEMORY_SAME_LOGON = 0x02 +CERT_CREATE_SELFSIGN_NO_SIGN = 1 +CERT_CREATE_SELFSIGN_NO_KEY_INFO = 2 +CRYPT_KEYID_MACHINE_FLAG = 0x00000020 +CRYPT_KEYID_ALLOC_FLAG = 0x00008000 +CRYPT_KEYID_DELETE_FLAG = 0x00000010 +CRYPT_KEYID_SET_NEW_FLAG = 0x00002000 +CERT_CHAIN_MAX_AIA_URL_COUNT_IN_CERT_DEFAULT = 5 +CERT_CHAIN_MAX_AIA_URL_RETRIEVAL_COUNT_PER_CHAIN_DEFAULT = 10 +CERT_CHAIN_MAX_AIA_URL_RETRIEVAL_BYTE_COUNT_DEFAULT = 100000 +CERT_CHAIN_MAX_AIA_URL_RETRIEVAL_CERT_COUNT_DEFAULT = 10 +CERT_CHAIN_CACHE_END_CERT = 0x00000001 +CERT_CHAIN_THREAD_STORE_SYNC = 0x00000002 +CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL = 0x00000004 +CERT_CHAIN_USE_LOCAL_MACHINE_STORE = 0x00000008 +CERT_CHAIN_ENABLE_CACHE_AUTO_UPDATE = 0x00000010 +CERT_CHAIN_ENABLE_SHARE_STORE = 0x00000020 +CERT_TRUST_NO_ERROR = 0x00000000 +CERT_TRUST_IS_NOT_TIME_VALID = 0x00000001 +CERT_TRUST_IS_NOT_TIME_NESTED = 0x00000002 +CERT_TRUST_IS_REVOKED = 0x00000004 +CERT_TRUST_IS_NOT_SIGNATURE_VALID = 0x00000008 +CERT_TRUST_IS_NOT_VALID_FOR_USAGE = 0x00000010 +CERT_TRUST_IS_UNTRUSTED_ROOT = 0x00000020 +CERT_TRUST_REVOCATION_STATUS_UNKNOWN = 0x00000040 +CERT_TRUST_IS_CYCLIC = 0x00000080 +CERT_TRUST_INVALID_EXTENSION = 0x00000100 +CERT_TRUST_INVALID_POLICY_CONSTRAINTS = 0x00000200 +CERT_TRUST_INVALID_BASIC_CONSTRAINTS = 0x00000400 +CERT_TRUST_INVALID_NAME_CONSTRAINTS = 0x00000800 +CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT = 0x00001000 +CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT = 0x00002000 +CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT = 0x00004000 +CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT = 0x00008000 +CERT_TRUST_IS_OFFLINE_REVOCATION = 0x01000000 +CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY = 0x02000000 +CERT_TRUST_IS_PARTIAL_CHAIN = 0x00010000 +CERT_TRUST_CTL_IS_NOT_TIME_VALID = 0x00020000 +CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID = 0x00040000 +CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE = 0x00080000 +CERT_TRUST_HAS_EXACT_MATCH_ISSUER = 0x00000001 +CERT_TRUST_HAS_KEY_MATCH_ISSUER = 0x00000002 +CERT_TRUST_HAS_NAME_MATCH_ISSUER = 0x00000004 +CERT_TRUST_IS_SELF_SIGNED = 0x00000008 +CERT_TRUST_HAS_PREFERRED_ISSUER = 0x00000100 +CERT_TRUST_HAS_ISSUANCE_CHAIN_POLICY = 0x00000200 +CERT_TRUST_HAS_VALID_NAME_CONSTRAINTS = 0x00000400 +CERT_TRUST_IS_COMPLEX_CHAIN = 0x00010000 +USAGE_MATCH_TYPE_AND = 0x00000000 +USAGE_MATCH_TYPE_OR = 0x00000001 +CERT_CHAIN_REVOCATION_CHECK_END_CERT = 0x10000000 +CERT_CHAIN_REVOCATION_CHECK_CHAIN = 0x20000000 +CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT = 0x40000000 +CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY = (-2147483648) +CERT_CHAIN_REVOCATION_ACCUMULATIVE_TIMEOUT = 0x08000000 +CERT_CHAIN_DISABLE_PASS1_QUALITY_FILTERING = 0x00000040 +CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS = 0x00000080 +CERT_CHAIN_DISABLE_AUTH_ROOT_AUTO_UPDATE = 0x00000100 +CERT_CHAIN_TIMESTAMP_TIME = 0x00000200 +REVOCATION_OID_CRL_REVOCATION = 1 +CERT_CHAIN_FIND_BY_ISSUER = 1 +CERT_CHAIN_FIND_BY_ISSUER_COMPARE_KEY_FLAG = 0x0001 +CERT_CHAIN_FIND_BY_ISSUER_COMPLEX_CHAIN_FLAG = 0x0002 +CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_URL_FLAG = 0x0004 +CERT_CHAIN_FIND_BY_ISSUER_LOCAL_MACHINE_FLAG = 0x0008 +CERT_CHAIN_FIND_BY_ISSUER_NO_KEY_FLAG = 0x4000 +CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_FLAG = 0x8000 +CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG = 0x00000001 +CERT_CHAIN_POLICY_IGNORE_CTL_NOT_TIME_VALID_FLAG = 0x00000002 +CERT_CHAIN_POLICY_IGNORE_NOT_TIME_NESTED_FLAG = 0x00000004 +CERT_CHAIN_POLICY_IGNORE_INVALID_BASIC_CONSTRAINTS_FLAG = 0x00000008 +CERT_CHAIN_POLICY_IGNORE_ALL_NOT_TIME_VALID_FLAGS = ( \ + CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG | \ + CERT_CHAIN_POLICY_IGNORE_CTL_NOT_TIME_VALID_FLAG | \ + CERT_CHAIN_POLICY_IGNORE_NOT_TIME_NESTED_FLAG \ + ) +CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG = 0x00000010 +CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG = 0x00000020 +CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG = 0x00000040 +CERT_CHAIN_POLICY_IGNORE_INVALID_POLICY_FLAG = 0x00000080 +CERT_CHAIN_POLICY_IGNORE_END_REV_UNKNOWN_FLAG = 0x00000100 +CERT_CHAIN_POLICY_IGNORE_CTL_SIGNER_REV_UNKNOWN_FLAG = 0x00000200 +CERT_CHAIN_POLICY_IGNORE_CA_REV_UNKNOWN_FLAG = 0x00000400 +CERT_CHAIN_POLICY_IGNORE_ROOT_REV_UNKNOWN_FLAG = 0x00000800 +CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS = ( \ + CERT_CHAIN_POLICY_IGNORE_END_REV_UNKNOWN_FLAG | \ + CERT_CHAIN_POLICY_IGNORE_CTL_SIGNER_REV_UNKNOWN_FLAG | \ + CERT_CHAIN_POLICY_IGNORE_CA_REV_UNKNOWN_FLAG | \ + CERT_CHAIN_POLICY_IGNORE_ROOT_REV_UNKNOWN_FLAG \ + ) +CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG = 0x00008000 +CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG = 0x00004000 +CRYPT_OID_VERIFY_CERTIFICATE_CHAIN_POLICY_FUNC = \ + "CertDllVerifyCertificateChainPolicy" +AUTHTYPE_CLIENT = 1 +AUTHTYPE_SERVER = 2 +BASIC_CONSTRAINTS_CERT_CHAIN_POLICY_CA_FLAG = (-2147483648) +BASIC_CONSTRAINTS_CERT_CHAIN_POLICY_END_ENTITY_FLAG = 0x40000000 +MICROSOFT_ROOT_CERT_CHAIN_POLICY_ENABLE_TEST_ROOT_FLAG = 0x00010000 +CRYPT_STRING_BASE64HEADER = 0x00000000 +CRYPT_STRING_BASE64 = 0x00000001 +CRYPT_STRING_BINARY = 0x00000002 +CRYPT_STRING_BASE64REQUESTHEADER = 0x00000003 +CRYPT_STRING_HEX = 0x00000004 +CRYPT_STRING_HEXASCII = 0x00000005 +CRYPT_STRING_BASE64_ANY = 0x00000006 +CRYPT_STRING_ANY = 0x00000007 +CRYPT_STRING_HEX_ANY = 0x00000008 +CRYPT_STRING_BASE64X509CRLHEADER = 0x00000009 +CRYPT_STRING_HEXADDR = 0x0000000a +CRYPT_STRING_HEXASCIIADDR = 0x0000000b +CRYPT_STRING_NOCR = (-2147483648) +CRYPT_USER_KEYSET = 0x00001000 +PKCS12_IMPORT_RESERVED_MASK = (-65536) +REPORT_NO_PRIVATE_KEY = 0x0001 +REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY = 0x0002 +EXPORT_PRIVATE_KEYS = 0x0004 +PKCS12_EXPORT_RESERVED_MASK = (-65536) + +# Certificate store provider types used with CertOpenStore +CERT_STORE_PROV_MSG = 1 +CERT_STORE_PROV_MEMORY = 2 +CERT_STORE_PROV_FILE = 3 +CERT_STORE_PROV_REG = 4 +CERT_STORE_PROV_PKCS7 = 5 +CERT_STORE_PROV_SERIALIZED = 6 +CERT_STORE_PROV_FILENAME = 8 +CERT_STORE_PROV_SYSTEM = 10 +CERT_STORE_PROV_COLLECTION = 11 +CERT_STORE_PROV_SYSTEM_REGISTRY = 13 +CERT_STORE_PROV_PHYSICAL = 14 +CERT_STORE_PROV_SMART_CARD = 15 +CERT_STORE_PROV_LDAP = 16 + +URL_OID_CERTIFICATE_ISSUER = 1 +URL_OID_CERTIFICATE_CRL_DIST_POINT = 2 +URL_OID_CTL_ISSUER = 3 +URL_OID_CTL_NEXT_UPDATE = 4 +URL_OID_CRL_ISSUER = 5 +URL_OID_CERTIFICATE_FRESHEST_CRL = 6 +URL_OID_CRL_FRESHEST_CRL = 7 +URL_OID_CROSS_CERT_DIST_POINT = 8 +URL_OID_CERTIFICATE_OCSP = 9 +URL_OID_CERTIFICATE_OCSP_AND_CRL_DIST_POINT = 10 +URL_OID_CERTIFICATE_CRL_DIST_POINT_AND_OCSP = 11 +URL_OID_CROSS_CERT_SUBJECT_INFO_ACCESS = 12 +URL_OID_CERTIFICATE_ONLY_OCSP = 13 diff --git a/Lib/site-packages/win32/lib/win32evtlogutil.py b/Lib/site-packages/win32/lib/win32evtlogutil.py new file mode 100644 index 0000000..ee7dcf2 --- /dev/null +++ b/Lib/site-packages/win32/lib/win32evtlogutil.py @@ -0,0 +1,152 @@ +"""Event Log Utilities - helper for win32evtlog.pyd +""" + +import win32api, win32con, winerror, win32evtlog + +error = win32api.error # The error the evtlog module raises. + +langid = win32api.MAKELANGID(win32con.LANG_NEUTRAL, win32con.SUBLANG_NEUTRAL) + +def AddSourceToRegistry(appName, msgDLL = None, eventLogType = "Application", eventLogFlags = None): + """Add a source of messages to the event log. + + Allows Python program to register a custom source of messages in the + registry. You must also provide the DLL name that has the message table, so the + full message text appears in the event log. + + Note that the win32evtlog.pyd file has a number of string entries with just "%1" + built in, so many Python programs can simply use this DLL. Disadvantages are that + you do not get language translation, and the full text is stored in the event log, + blowing the size of the log up. + """ + + # When an application uses the RegisterEventSource or OpenEventLog + # function to get a handle of an event log, the event loggging service + # searches for the specified source name in the registry. You can add a + # new source name to the registry by opening a new registry subkey + # under the Application key and adding registry values to the new + # subkey. + + if msgDLL is None: + msgDLL = win32evtlog.__file__ + + # Create a new key for our application + hkey = win32api.RegCreateKey(win32con.HKEY_LOCAL_MACHINE, \ + "SYSTEM\\CurrentControlSet\\Services\\EventLog\\%s\\%s" % (eventLogType, appName)) + + # Add the Event-ID message-file name to the subkey. + win32api.RegSetValueEx(hkey, + "EventMessageFile", # value name \ + 0, # reserved \ + win32con.REG_EXPAND_SZ,# value type \ + msgDLL) + + # Set the supported types flags and add it to the subkey. + if eventLogFlags is None: + eventLogFlags = win32evtlog.EVENTLOG_ERROR_TYPE | win32evtlog.EVENTLOG_WARNING_TYPE | win32evtlog.EVENTLOG_INFORMATION_TYPE + win32api.RegSetValueEx(hkey, # subkey handle \ + "TypesSupported", # value name \ + 0, # reserved \ + win32con.REG_DWORD, # value type \ + eventLogFlags) + win32api.RegCloseKey(hkey) + +def RemoveSourceFromRegistry(appName, eventLogType = "Application"): + """Removes a source of messages from the event log. + """ + + # Delete our key + try: + win32api.RegDeleteKey(win32con.HKEY_LOCAL_MACHINE, \ + "SYSTEM\\CurrentControlSet\\Services\\EventLog\\%s\\%s" % (eventLogType, appName)) + except win32api.error as exc: + if exc.winerror != winerror.ERROR_FILE_NOT_FOUND: + raise + + +def ReportEvent(appName, eventID, eventCategory = 0, eventType=win32evtlog.EVENTLOG_ERROR_TYPE, strings = None, data = None, sid=None): + """Report an event for a previously added event source. + """ + # Get a handle to the Application event log + hAppLog = win32evtlog.RegisterEventSource(None, appName) + + # Now report the event, which will add this event to the event log */ + win32evtlog.ReportEvent(hAppLog, # event-log handle \ + eventType, + eventCategory, + eventID, + sid, + strings, + data) + + win32evtlog.DeregisterEventSource(hAppLog); + +def FormatMessage( eventLogRecord, logType="Application" ): + """Given a tuple from ReadEventLog, and optionally where the event + record came from, load the message, and process message inserts. + + Note that this function may raise win32api.error. See also the + function SafeFormatMessage which will return None if the message can + not be processed. + """ + + # From the event log source name, we know the name of the registry + # key to look under for the name of the message DLL that contains + # the messages we need to extract with FormatMessage. So first get + # the event log source name... + keyName = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\%s\\%s" % (logType, eventLogRecord.SourceName) + + # Now open this key and get the EventMessageFile value, which is + # the name of the message DLL. + handle = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, keyName) + try: + dllNames = win32api.RegQueryValueEx(handle, "EventMessageFile")[0].split(";") + # Win2k etc appear to allow multiple DLL names + data = None + for dllName in dllNames: + try: + # Expand environment variable strings in the message DLL path name, + # in case any are there. + dllName = win32api.ExpandEnvironmentStrings(dllName) + + dllHandle = win32api.LoadLibraryEx(dllName, 0, win32con.LOAD_LIBRARY_AS_DATAFILE) + try: + data = win32api.FormatMessageW(win32con.FORMAT_MESSAGE_FROM_HMODULE, + dllHandle, eventLogRecord.EventID, langid, eventLogRecord.StringInserts) + finally: + win32api.FreeLibrary(dllHandle) + except win32api.error: + pass # Not in this DLL - try the next + if data is not None: + break + finally: + win32api.RegCloseKey(handle) + return data or '' # Don't want "None" ever being returned. + +def SafeFormatMessage( eventLogRecord, logType=None ): + """As for FormatMessage, except returns an error message if + the message can not be processed. + """ + if logType is None: logType = "Application" + try: + return FormatMessage(eventLogRecord, logType) + except win32api.error: + if eventLogRecord.StringInserts is None: + desc = "" + else: + desc = ", ".join(eventLogRecord.StringInserts) + return "" % (winerror.HRESULT_CODE(eventLogRecord.EventID), eventLogRecord.SourceName, desc) + +def FeedEventLogRecords(feeder, machineName = None, logName = "Application", readFlags = None): + if readFlags is None: + readFlags = win32evtlog.EVENTLOG_BACKWARDS_READ|win32evtlog.EVENTLOG_SEQUENTIAL_READ + + h=win32evtlog.OpenEventLog(machineName, logName) + try: + while 1: + objects = win32evtlog.ReadEventLog(h, readFlags, 0) + if not objects: + break + map(lambda item, feeder = feeder: feeder(*(item,)), objects) + finally: + win32evtlog.CloseEventLog(h) diff --git a/Lib/site-packages/win32/lib/win32gui_struct.py b/Lib/site-packages/win32/lib/win32gui_struct.py new file mode 100644 index 0000000..7938f0e --- /dev/null +++ b/Lib/site-packages/win32/lib/win32gui_struct.py @@ -0,0 +1,729 @@ +# This is a work in progress - see Demos/win32gui_menu.py + +# win32gui_struct.py - helpers for working with various win32gui structures. +# As win32gui is "light-weight", it does not define objects for all possible +# win32 structures - in general, "buffer" objects are passed around - it is +# the callers responsibility to pack the buffer in the correct format. +# +# This module defines some helpers for the commonly used structures. +# +# In general, each structure has 3 functions: +# +# buffer, extras = PackSTRUCTURE(items, ...) +# item, ... = UnpackSTRUCTURE(buffer) +# buffer, extras = EmtpySTRUCTURE(...) +# +# 'extras' is always items that must be held along with the buffer, as the +# buffer refers to these object's memory. +# For structures that support a 'mask', this mask is hidden from the user - if +# 'None' is passed, the mask flag will not be set, or on return, None will +# be returned for the value if the mask is not set. +# +# NOTE: I considered making these structures look like real classes, and +# support 'attributes' etc - however, ctypes already has a good structure +# mechanism - I think it makes more sense to support ctype structures +# at the win32gui level, then there will be no need for this module at all. +# XXX - the above makes sense in terms of what is built and passed to +# win32gui (ie, the Pack* functions) - but doesn't make as much sense for +# the Unpack* functions, where the aim is user convenience. + +import sys +import win32gui +import win32con +import struct +import array +import commctrl +import pywintypes + +is64bit = "64 bit" in sys.version + +try: + from collections import namedtuple + def _MakeResult(names_str, values): + names = names_str.split() + nt = namedtuple(names[0], names[1:]) + return nt(*values) +except ImportError: + # no namedtuple support - just return the values as a normal tuple. + def _MakeResult(names_str, values): + return values + +_nmhdr_fmt = "PPi" +if is64bit: + # When the item past the NMHDR gets aligned (eg, when it is a struct) + # we need this many bytes padding. + _nmhdr_align_padding = "xxxx" +else: + _nmhdr_align_padding = "" + +# Encode a string suitable for passing in a win32gui related structure +# If win32gui is built with UNICODE defined (ie, py3k), then functions +# like InsertMenuItem are actually calling InsertMenuItemW etc, so all +# strings will need to be unicode. +if win32gui.UNICODE: + def _make_text_buffer(text): + # XXX - at this stage win32gui.UNICODE is only True in py3k, + # and in py3k is makes sense to reject bytes. + if not isinstance(text, str): + raise TypeError('MENUITEMINFO text must be unicode') + data = (text+'\0').encode("unicode-internal") + return array.array("b", data) + +else: + def _make_text_buffer(text): + if isinstance(text, str): + text = text.encode("mbcs") + return array.array("b", text+'\0') + +# make an 'empty' buffer, ready for filling with cch characters. +def _make_empty_text_buffer(cch): + return _make_text_buffer("\0" * cch) + +if sys.version_info < (3,0): + def _make_memory(ob): + return str(buffer(ob)) + + def _make_bytes(sval): + return sval +else: + def _make_memory(ob): + return bytes(memoryview(ob)) + + def _make_bytes(sval): + return sval.encode('ascii') + +# Generic WM_NOTIFY unpacking +def UnpackWMNOTIFY(lparam): + format = "PPi" + buf = win32gui.PyGetMemory(lparam, struct.calcsize(format)) + return _MakeResult("WMNOTIFY hwndFrom idFrom code", struct.unpack(format, buf)) + +def UnpackNMITEMACTIVATE(lparam): + format = _nmhdr_fmt + _nmhdr_align_padding + if is64bit: + # the struct module doesn't handle this correctly as some of the items + # are actually structs in structs, which get individually aligned. + format = format + "iiiiiiixxxxP" + else: + format = format + "iiiiiiiP" + buf = win32gui.PyMakeBuffer(struct.calcsize(format), lparam) + return _MakeResult("NMITEMACTIVATE hwndFrom idFrom code iItem iSubItem uNewState uOldState uChanged actionx actiony lParam", + struct.unpack(format, buf)) + +# MENUITEMINFO struct +# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/Resources/Menus/MenuReference/MenuStructures/MENUITEMINFO.asp +# We use the struct module to pack and unpack strings as MENUITEMINFO +# structures. We also have special handling for the 'fMask' item in that +# structure to avoid the caller needing to explicitly check validity +# (None is used if the mask excludes/should exclude the value) +_menuiteminfo_fmt = '5i5PiP' + +def PackMENUITEMINFO(fType=None, fState=None, wID=None, hSubMenu=None, + hbmpChecked=None, hbmpUnchecked=None, dwItemData=None, + text=None, hbmpItem=None, dwTypeData=None): + # 'extras' are objects the caller must keep a reference to (as their + # memory is used) for the lifetime of the INFO item. + extras = [] + # ack - dwItemData and dwTypeData were confused for a while... + assert dwItemData is None or dwTypeData is None, \ + "sorry - these were confused - you probably want dwItemData" + # if we are a long way past 209, then we can nuke the above... + if dwTypeData is not None: + import warnings + warnings.warn("PackMENUITEMINFO: please use dwItemData instead of dwTypeData") + if dwItemData is None: + dwItemData = dwTypeData or 0 + + fMask = 0 + if fType is None: fType = 0 + else: fMask |= win32con.MIIM_FTYPE + if fState is None: fState = 0 + else: fMask |= win32con.MIIM_STATE + if wID is None: wID = 0 + else: fMask |= win32con.MIIM_ID + if hSubMenu is None: hSubMenu = 0 + else: fMask |= win32con.MIIM_SUBMENU + if hbmpChecked is None: + assert hbmpUnchecked is None, \ + "neither or both checkmark bmps must be given" + hbmpChecked = hbmpUnchecked = 0 + else: + assert hbmpUnchecked is not None, \ + "neither or both checkmark bmps must be given" + fMask |= win32con.MIIM_CHECKMARKS + if dwItemData is None: dwItemData = 0 + else: fMask |= win32con.MIIM_DATA + if hbmpItem is None: hbmpItem = 0 + else: fMask |= win32con.MIIM_BITMAP + if text is not None: + fMask |= win32con.MIIM_STRING + str_buf = _make_text_buffer(text) + cch = len(text) + # We are taking address of strbuf - it must not die until windows + # has finished with our structure. + lptext = str_buf.buffer_info()[0] + extras.append(str_buf) + else: + lptext = 0 + cch = 0 + # Create the struct. + # 'P' format does not accept PyHANDLE's ! + item = struct.pack( + _menuiteminfo_fmt, + struct.calcsize(_menuiteminfo_fmt), # cbSize + fMask, + fType, + fState, + wID, + int(hSubMenu), + int(hbmpChecked), + int(hbmpUnchecked), + dwItemData, + lptext, + cch, + int(hbmpItem) + ) + # Now copy the string to a writable buffer, so that the result + # could be passed to a 'Get' function + return array.array("b", item), extras + +def UnpackMENUITEMINFO(s): + (cb, + fMask, + fType, + fState, + wID, + hSubMenu, + hbmpChecked, + hbmpUnchecked, + dwItemData, + lptext, + cch, + hbmpItem) = struct.unpack(_menuiteminfo_fmt, s) + assert cb==len(s) + if fMask & win32con.MIIM_FTYPE==0: fType = None + if fMask & win32con.MIIM_STATE==0: fState = None + if fMask & win32con.MIIM_ID==0: wID = None + if fMask & win32con.MIIM_SUBMENU==0: hSubMenu = None + if fMask & win32con.MIIM_CHECKMARKS==0: hbmpChecked = hbmpUnchecked = None + if fMask & win32con.MIIM_DATA==0: dwItemData = None + if fMask & win32con.MIIM_BITMAP==0: hbmpItem = None + if fMask & win32con.MIIM_STRING: + text = win32gui.PyGetString(lptext, cch) + else: + text = None + return _MakeResult("MENUITEMINFO fType fState wID hSubMenu hbmpChecked " + "hbmpUnchecked dwItemData text hbmpItem", + (fType, fState, wID, hSubMenu, hbmpChecked, hbmpUnchecked, \ + dwItemData, text, hbmpItem)) + +def EmptyMENUITEMINFO(mask = None, text_buf_size=512): + # text_buf_size is number of *characters* - not necessarily no of bytes. + extra = [] + if mask is None: + mask = win32con.MIIM_BITMAP | win32con.MIIM_CHECKMARKS | \ + win32con.MIIM_DATA | win32con.MIIM_FTYPE | \ + win32con.MIIM_ID | win32con.MIIM_STATE | \ + win32con.MIIM_STRING | win32con.MIIM_SUBMENU + # Note: No MIIM_TYPE - this screws win2k/98. + + if mask & win32con.MIIM_STRING: + text_buffer = _make_empty_text_buffer(text_buf_size) + extra.append(text_buffer) + text_addr, _ = text_buffer.buffer_info() + else: + text_addr = text_buf_size = 0 + + # Now copy the string to a writable buffer, so that the result + # could be passed to a 'Get' function + buf = struct.pack( + _menuiteminfo_fmt, + struct.calcsize(_menuiteminfo_fmt), # cbSize + mask, + 0, #fType, + 0, #fState, + 0, #wID, + 0, #hSubMenu, + 0, #hbmpChecked, + 0, #hbmpUnchecked, + 0, #dwItemData, + text_addr, + text_buf_size, + 0, #hbmpItem + ) + return array.array("b", buf), extra + +# MENUINFO struct +_menuinfo_fmt = 'iiiiPiP' + +def PackMENUINFO(dwStyle = None, cyMax = None, + hbrBack = None, dwContextHelpID = None, dwMenuData = None, + fMask = 0): + if dwStyle is None: dwStyle = 0 + else: fMask |= win32con.MIM_STYLE + if cyMax is None: cyMax = 0 + else: fMask |= win32con.MIM_MAXHEIGHT + if hbrBack is None: hbrBack = 0 + else: fMask |= win32con.MIM_BACKGROUND + if dwContextHelpID is None: dwContextHelpID = 0 + else: fMask |= win32con.MIM_HELPID + if dwMenuData is None: dwMenuData = 0 + else: fMask |= win32con.MIM_MENUDATA + # Create the struct. + item = struct.pack( + _menuinfo_fmt, + struct.calcsize(_menuinfo_fmt), # cbSize + fMask, + dwStyle, + cyMax, + hbrBack, + dwContextHelpID, + dwMenuData) + return array.array("b", item) + +def UnpackMENUINFO(s): + (cb, + fMask, + dwStyle, + cyMax, + hbrBack, + dwContextHelpID, + dwMenuData) = struct.unpack(_menuinfo_fmt, s) + assert cb==len(s) + if fMask & win32con.MIM_STYLE==0: dwStyle = None + if fMask & win32con.MIM_MAXHEIGHT==0: cyMax = None + if fMask & win32con.MIM_BACKGROUND==0: hbrBack = None + if fMask & win32con.MIM_HELPID==0: dwContextHelpID = None + if fMask & win32con.MIM_MENUDATA==0: dwMenuData = None + return _MakeResult("MENUINFO dwStyle cyMax hbrBack dwContextHelpID dwMenuData", + (dwStyle, cyMax, hbrBack, dwContextHelpID, dwMenuData)) + +def EmptyMENUINFO(mask = None): + if mask is None: + mask = win32con.MIM_STYLE | win32con.MIM_MAXHEIGHT| \ + win32con.MIM_BACKGROUND | win32con.MIM_HELPID | \ + win32con.MIM_MENUDATA + + buf = struct.pack( + _menuinfo_fmt, + struct.calcsize(_menuinfo_fmt), # cbSize + mask, + 0, #dwStyle + 0, #cyMax + 0, #hbrBack, + 0, #dwContextHelpID, + 0, #dwMenuData, + ) + return array.array("b", buf) + +########################################################################## +# +# Tree View structure support - TVITEM, TVINSERTSTRUCT and TVDISPINFO +# +########################################################################## + +# XXX - Note that the following implementation of TreeView structures is ripped +# XXX - from the SpamBayes project. It may not quite work correctly yet - I +# XXX - intend checking them later - but having them is better than not at all! + +_tvitem_fmt = "iPiiPiiiiP" +# Helpers for the ugly win32 structure packing/unpacking +# XXX - Note that functions using _GetMaskAndVal run 3x faster if they are +# 'inlined' into the function - see PackLVITEM. If the profiler points at +# _GetMaskAndVal(), you should nuke it (patches welcome once they have been +# tested) +def _GetMaskAndVal(val, default, mask, flag): + if val is None: + return mask, default + else: + if flag is not None: + mask |= flag + return mask, val + +def PackTVINSERTSTRUCT(parent, insertAfter, tvitem): + tvitem_buf, extra = PackTVITEM(*tvitem) + tvitem_buf = tvitem_buf.tostring() + format = "PP%ds" % len(tvitem_buf) + return struct.pack(format, parent, insertAfter, tvitem_buf), extra + +def PackTVITEM(hitem, state, stateMask, text, image, selimage, citems, param): + extra = [] # objects we must keep references to + mask = 0 + mask, hitem = _GetMaskAndVal(hitem, 0, mask, commctrl.TVIF_HANDLE) + mask, state = _GetMaskAndVal(state, 0, mask, commctrl.TVIF_STATE) + if not mask & commctrl.TVIF_STATE: + stateMask = 0 + mask, text = _GetMaskAndVal(text, None, mask, commctrl.TVIF_TEXT) + mask, image = _GetMaskAndVal(image, 0, mask, commctrl.TVIF_IMAGE) + mask, selimage = _GetMaskAndVal(selimage, 0, mask, commctrl.TVIF_SELECTEDIMAGE) + mask, citems = _GetMaskAndVal(citems, 0, mask, commctrl.TVIF_CHILDREN) + mask, param = _GetMaskAndVal(param, 0, mask, commctrl.TVIF_PARAM) + if text is None: + text_addr = text_len = 0 + else: + text_buffer = _make_text_buffer(text) + text_len = len(text) + extra.append(text_buffer) + text_addr, _ = text_buffer.buffer_info() + buf = struct.pack(_tvitem_fmt, + mask, hitem, + state, stateMask, + text_addr, text_len, # text + image, selimage, + citems, param) + return array.array("b", buf), extra + +# Make a new buffer suitable for querying hitem's attributes. +def EmptyTVITEM(hitem, mask = None, text_buf_size=512): + extra = [] # objects we must keep references to + if mask is None: + mask = commctrl.TVIF_HANDLE | commctrl.TVIF_STATE | commctrl.TVIF_TEXT | \ + commctrl.TVIF_IMAGE | commctrl.TVIF_SELECTEDIMAGE | \ + commctrl.TVIF_CHILDREN | commctrl.TVIF_PARAM + if mask & commctrl.TVIF_TEXT: + text_buffer = _make_empty_text_buffer(text_buf_size) + extra.append(text_buffer) + text_addr, _ = text_buffer.buffer_info() + else: + text_addr = text_buf_size = 0 + buf = struct.pack(_tvitem_fmt, + mask, hitem, + 0, 0, + text_addr, text_buf_size, # text + 0, 0, + 0, 0) + return array.array("b", buf), extra + +def UnpackTVITEM(buffer): + item_mask, item_hItem, item_state, item_stateMask, \ + item_textptr, item_cchText, item_image, item_selimage, \ + item_cChildren, item_param = struct.unpack(_tvitem_fmt, buffer) + # ensure only items listed by the mask are valid (except we assume the + # handle is always valid - some notifications (eg, TVN_ENDLABELEDIT) set a + # mask that doesn't include the handle, but the docs explicity say it is.) + if not (item_mask & commctrl.TVIF_TEXT): item_textptr = item_cchText = None + if not (item_mask & commctrl.TVIF_CHILDREN): item_cChildren = None + if not (item_mask & commctrl.TVIF_IMAGE): item_image = None + if not (item_mask & commctrl.TVIF_PARAM): item_param = None + if not (item_mask & commctrl.TVIF_SELECTEDIMAGE): item_selimage = None + if not (item_mask & commctrl.TVIF_STATE): item_state = item_stateMask = None + + if item_textptr: + text = win32gui.PyGetString(item_textptr) + else: + text = None + return _MakeResult("TVITEM item_hItem item_state item_stateMask " + "text item_image item_selimage item_cChildren item_param", + (item_hItem, item_state, item_stateMask, text, + item_image, item_selimage, item_cChildren, item_param)) + +# Unpack the lparm from a "TVNOTIFY" message +def UnpackTVNOTIFY(lparam): + item_size = struct.calcsize(_tvitem_fmt) + format = _nmhdr_fmt + _nmhdr_align_padding + if is64bit: + format = format + "ixxxx" + else: + format = format + "i" + format = format + "%ds%ds" % (item_size, item_size) + buf = win32gui.PyGetMemory(lparam, struct.calcsize(format)) + hwndFrom, id, code, action, buf_old, buf_new \ + = struct.unpack(format, buf) + item_old = UnpackTVITEM(buf_old) + item_new = UnpackTVITEM(buf_new) + return _MakeResult("TVNOTIFY hwndFrom id code action item_old item_new", + (hwndFrom, id, code, action, item_old, item_new)) + +def UnpackTVDISPINFO(lparam): + item_size = struct.calcsize(_tvitem_fmt) + format = "PPi%ds" % (item_size,) + buf = win32gui.PyGetMemory(lparam, struct.calcsize(format)) + hwndFrom, id, code, buf_item = struct.unpack(format, buf) + item = UnpackTVITEM(buf_item) + return _MakeResult("TVDISPINFO hwndFrom id code item", + (hwndFrom, id, code, item)) + +# +# List view items +_lvitem_fmt = "iiiiiPiiPi" + +def PackLVITEM(item=None, subItem=None, state=None, stateMask=None, text=None, image=None, param=None, indent=None): + extra = [] # objects we must keep references to + mask = 0 + # _GetMaskAndVal adds quite a bit of overhead to this function. + if item is None: item = 0 # No mask for item + if subItem is None: subItem = 0 # No mask for sibItem + if state is None: + state = 0 + stateMask = 0 + else: + mask |= commctrl.LVIF_STATE + if stateMask is None: stateMask = state + + if image is None: image = 0 + else: mask |= commctrl.LVIF_IMAGE + if param is None: param = 0 + else: mask |= commctrl.LVIF_PARAM + if indent is None: indent = 0 + else: mask |= commctrl.LVIF_INDENT + + if text is None: + text_addr = text_len = 0 + else: + mask |= commctrl.LVIF_TEXT + text_buffer = _make_text_buffer(text) + text_len = len(text) + extra.append(text_buffer) + text_addr, _ = text_buffer.buffer_info() + buf = struct.pack(_lvitem_fmt, + mask, item, subItem, + state, stateMask, + text_addr, text_len, # text + image, param, indent) + return array.array("b", buf), extra + +def UnpackLVITEM(buffer): + item_mask, item_item, item_subItem, \ + item_state, item_stateMask, \ + item_textptr, item_cchText, item_image, \ + item_param, item_indent = struct.unpack(_lvitem_fmt, buffer) + # ensure only items listed by the mask are valid + if not (item_mask & commctrl.LVIF_TEXT): item_textptr = item_cchText = None + if not (item_mask & commctrl.LVIF_IMAGE): item_image = None + if not (item_mask & commctrl.LVIF_PARAM): item_param = None + if not (item_mask & commctrl.LVIF_INDENT): item_indent = None + if not (item_mask & commctrl.LVIF_STATE): item_state = item_stateMask = None + + if item_textptr: + text = win32gui.PyGetString(item_textptr) + else: + text = None + return _MakeResult("LVITEM item_item item_subItem item_state " + "item_stateMask text item_image item_param item_indent", + (item_item, item_subItem, item_state, item_stateMask, + text, item_image, item_param, item_indent)) + +# Unpack an "LVNOTIFY" message +def UnpackLVDISPINFO(lparam): + item_size = struct.calcsize(_lvitem_fmt) + format = _nmhdr_fmt + _nmhdr_align_padding + ("%ds" % (item_size,)) + buf = win32gui.PyGetMemory(lparam, struct.calcsize(format)) + hwndFrom, id, code, buf_item = struct.unpack(format, buf) + item = UnpackLVITEM(buf_item) + return _MakeResult("LVDISPINFO hwndFrom id code item", + (hwndFrom, id, code, item)) + +def UnpackLVNOTIFY(lparam): + format = _nmhdr_fmt + _nmhdr_align_padding + "7i" + if is64bit: + format = format + "xxxx" # point needs padding. + format = format + "P" + buf = win32gui.PyGetMemory(lparam, struct.calcsize(format)) + hwndFrom, id, code, item, subitem, newstate, oldstate, \ + changed, pt_x, pt_y, lparam = struct.unpack(format, buf) + return _MakeResult("UnpackLVNOTIFY hwndFrom id code item subitem " + "newstate oldstate changed pt lparam", + (hwndFrom, id, code, item, subitem, newstate, oldstate, + changed, (pt_x, pt_y), lparam)) + + +# Make a new buffer suitable for querying an items attributes. +def EmptyLVITEM(item, subitem, mask = None, text_buf_size=512): + extra = [] # objects we must keep references to + if mask is None: + mask = commctrl.LVIF_IMAGE | commctrl.LVIF_INDENT | commctrl.LVIF_TEXT | \ + commctrl.LVIF_PARAM | commctrl.LVIF_STATE + if mask & commctrl.LVIF_TEXT: + text_buffer = _make_empty_text_buffer(text_buf_size) + extra.append(text_buffer) + text_addr, _ = text_buffer.buffer_info() + else: + text_addr = text_buf_size = 0 + buf = struct.pack(_lvitem_fmt, + mask, item, subitem, + 0, 0, + text_addr, text_buf_size, # text + 0, 0, 0) + return array.array("b", buf), extra + + +# List view column structure +_lvcolumn_fmt = "iiiPiiii" +def PackLVCOLUMN(fmt=None, cx=None, text=None, subItem=None, image=None, order=None): + extra = [] # objects we must keep references to + mask = 0 + mask, fmt = _GetMaskAndVal(fmt, 0, mask, commctrl.LVCF_FMT) + mask, cx = _GetMaskAndVal(cx, 0, mask, commctrl.LVCF_WIDTH) + mask, text = _GetMaskAndVal(text, None, mask, commctrl.LVCF_TEXT) + mask, subItem = _GetMaskAndVal(subItem, 0, mask, commctrl.LVCF_SUBITEM) + mask, image = _GetMaskAndVal(image, 0, mask, commctrl.LVCF_IMAGE) + mask, order= _GetMaskAndVal(order, 0, mask, commctrl.LVCF_ORDER) + if text is None: + text_addr = text_len = 0 + else: + text_buffer = _make_text_buffer(text) + extra.append(text_buffer) + text_addr, _ = text_buffer.buffer_info() + text_len = len(text) + buf = struct.pack(_lvcolumn_fmt, + mask, fmt, cx, + text_addr, text_len, # text + subItem, image, order) + return array.array("b", buf), extra + +def UnpackLVCOLUMN(lparam): + mask, fmt, cx, text_addr, text_size, subItem, image, order = \ + struct.unpack(_lvcolumn_fmt, lparam) + # ensure only items listed by the mask are valid + if not (mask & commctrl.LVCF_FMT): fmt = None + if not (mask & commctrl.LVCF_WIDTH): cx = None + if not (mask & commctrl.LVCF_TEXT): text_addr = text_size = None + if not (mask & commctrl.LVCF_SUBITEM): subItem = None + if not (mask & commctrl.LVCF_IMAGE): image = None + if not (mask & commctrl.LVCF_ORDER): order = None + if text_addr: + text = win32gui.PyGetString(text_addr) + else: + text = None + return _MakeResult("LVCOLUMN fmt cx text subItem image order", + (fmt, cx, text, subItem, image, order)) + + +# Make a new buffer suitable for querying an items attributes. +def EmptyLVCOLUMN(mask = None, text_buf_size=512): + extra = [] # objects we must keep references to + if mask is None: + mask = commctrl.LVCF_FMT | commctrl.LVCF_WIDTH | commctrl.LVCF_TEXT | \ + commctrl.LVCF_SUBITEM | commctrl.LVCF_IMAGE | commctrl.LVCF_ORDER + if mask & commctrl.LVCF_TEXT: + text_buffer = _make_empty_text_buffer(text_buf_size) + extra.append(text_buffer) + text_addr, _ = text_buffer.buffer_info() + else: + text_addr = text_buf_size = 0 + buf = struct.pack(_lvcolumn_fmt, + mask, 0, 0, + text_addr, text_buf_size, # text + 0, 0, 0) + return array.array("b", buf), extra + +# List view hit-test. +def PackLVHITTEST(pt): + format = "iiiii" + buf = struct.pack(format, + pt[0], pt[1], + 0, 0, 0) + return array.array("b", buf), None + +def UnpackLVHITTEST(buf): + format = "iiiii" + x, y, flags, item, subitem = struct.unpack(format, buf) + return _MakeResult("LVHITTEST pt flags item subitem", + ((x,y), flags, item, subitem)) + +def PackHDITEM(cxy = None, text = None, hbm = None, fmt = None, + param = None, image = None, order = None): + extra = [] # objects we must keep references to + mask = 0 + mask, cxy = _GetMaskAndVal(cxy, 0, mask, commctrl.HDI_HEIGHT) + mask, text = _GetMaskAndVal(text, None, mask, commctrl.LVCF_TEXT) + mask, hbm = _GetMaskAndVal(hbm, 0, mask, commctrl.HDI_BITMAP) + mask, fmt = _GetMaskAndVal(fmt, 0, mask, commctrl.HDI_FORMAT) + mask, param = _GetMaskAndVal(param, 0, mask, commctrl.HDI_LPARAM) + mask, image = _GetMaskAndVal(image, 0, mask, commctrl.HDI_IMAGE) + mask, order = _GetMaskAndVal(order, 0, mask, commctrl.HDI_ORDER) + + if text is None: + text_addr = text_len = 0 + else: + text_buffer = _make_text_buffer(text) + extra.append(text_buffer) + text_addr, _ = text_buffer.buffer_info() + text_len = len(text) + + format = "iiPPiiPiiii" + buf = struct.pack(format, + mask, cxy, text_addr, hbm, text_len, + fmt, param, image, order, 0, 0) + return array.array("b", buf), extra + +# Device notification stuff + +# Generic function for packing a DEV_BROADCAST_* structure - generally used +# by the other PackDEV_BROADCAST_* functions in this module. +def PackDEV_BROADCAST(devicetype, rest_fmt, rest_data, extra_data=_make_bytes('')): + # It seems a requirement is 4 byte alignment, even for the 'BYTE data[1]' + # field (eg, that would make DEV_BROADCAST_HANDLE 41 bytes, but we must + # be 44. + extra_data += _make_bytes('\0' * (4-len(extra_data)%4)) + format = "iii" + rest_fmt + full_size = struct.calcsize(format) + len(extra_data) + data = (full_size, devicetype, 0) + rest_data + return struct.pack(format, *data) + extra_data + +def PackDEV_BROADCAST_HANDLE(handle, hdevnotify=0, guid=_make_bytes("\0"*16), name_offset=0, data=_make_bytes("\0")): + return PackDEV_BROADCAST(win32con.DBT_DEVTYP_HANDLE, "PP16sl", + (int(handle), int(hdevnotify), _make_memory(guid), name_offset), + data) + +def PackDEV_BROADCAST_VOLUME(unitmask, flags): + return PackDEV_BROADCAST(win32con.DBT_DEVTYP_VOLUME, "II", + (unitmask, flags)) + +def PackDEV_BROADCAST_DEVICEINTERFACE(classguid, name=""): + if win32gui.UNICODE: + # This really means "is py3k?" - so not accepting bytes is OK + if not isinstance(name, str): + raise TypeError("Must provide unicode for the name") + name = name.encode('unicode-internal') + else: + # py2k was passed a unicode object - encode as mbcs. + if isinstance(name, str): + name = name.encode('mbcs') + + # 16 bytes for the IID followed by \0 term'd string. + rest_fmt = "16s%ds" % len(name) + # _make_memory(iid) hoops necessary to get the raw IID bytes. + rest_data = (_make_memory(pywintypes.IID(classguid)), name) + return PackDEV_BROADCAST(win32con.DBT_DEVTYP_DEVICEINTERFACE, rest_fmt, rest_data) + +# An object returned by UnpackDEV_BROADCAST. +class DEV_BROADCAST_INFO: + def __init__(self, devicetype, **kw): + self.devicetype = devicetype + self.__dict__.update(kw) + def __str__(self): + return "DEV_BROADCAST_INFO:" + str(self.__dict__) + +# Support for unpacking the 'lparam' +def UnpackDEV_BROADCAST(lparam): + if lparam == 0: + return None + hdr_format = "iii" + hdr_size = struct.calcsize(hdr_format) + hdr_buf = win32gui.PyGetMemory(lparam, hdr_size) + size, devtype, reserved = struct.unpack("iii", hdr_buf) + # Due to x64 alignment issues, we need to use the full format string over + # the entire buffer. ie, on x64: + # calcsize('iiiP') != calcsize('iii')+calcsize('P') + buf = win32gui.PyGetMemory(lparam, size) + + extra = x = {} + if devtype == win32con.DBT_DEVTYP_HANDLE: + # 2 handles, a GUID, a LONG and possibly an array following... + fmt = hdr_format + "PP16sl" + _, _, _, x['handle'], x['hdevnotify'], guid_bytes, x['nameoffset'] = \ + struct.unpack(fmt, buf[:struct.calcsize(fmt)]) + x['eventguid'] = pywintypes.IID(guid_bytes, True) + elif devtype == win32con.DBT_DEVTYP_DEVICEINTERFACE: + fmt = hdr_format + "16s" + _, _, _, guid_bytes = struct.unpack(fmt, buf[:struct.calcsize(fmt)]) + x['classguid'] = pywintypes.IID(guid_bytes, True) + x['name'] = win32gui.PyGetString(lparam + struct.calcsize(fmt)) + elif devtype == win32con.DBT_DEVTYP_VOLUME: + # int mask and flags + fmt = hdr_format + "II" + _, _, _, x['unitmask'], x['flags'] = struct.unpack(fmt, buf[:struct.calcsize(fmt)]) + else: + raise NotImplementedError("unknown device type %d" % (devtype,)) + return DEV_BROADCAST_INFO(devtype, **extra) diff --git a/Lib/site-packages/win32/lib/win32inetcon.py b/Lib/site-packages/win32/lib/win32inetcon.py new file mode 100644 index 0000000..51e3629 --- /dev/null +++ b/Lib/site-packages/win32/lib/win32inetcon.py @@ -0,0 +1,1103 @@ +# Generated by h2py from \mssdk\include\WinInet.h + +INTERNET_INVALID_PORT_NUMBER = 0 +INTERNET_DEFAULT_FTP_PORT = 21 +INTERNET_DEFAULT_GOPHER_PORT = 70 +INTERNET_DEFAULT_HTTP_PORT = 80 +INTERNET_DEFAULT_HTTPS_PORT = 443 +INTERNET_DEFAULT_SOCKS_PORT = 1080 +INTERNET_MAX_HOST_NAME_LENGTH = 256 +INTERNET_MAX_USER_NAME_LENGTH = 128 +INTERNET_MAX_PASSWORD_LENGTH = 128 +INTERNET_MAX_PORT_NUMBER_LENGTH = 5 +INTERNET_MAX_PORT_NUMBER_VALUE = 65535 +INTERNET_MAX_PATH_LENGTH = 2048 +INTERNET_MAX_SCHEME_LENGTH = 32 +INTERNET_KEEP_ALIVE_ENABLED = 1 +INTERNET_KEEP_ALIVE_DISABLED = 0 +INTERNET_REQFLAG_FROM_CACHE = 0x00000001 +INTERNET_REQFLAG_ASYNC = 0x00000002 +INTERNET_REQFLAG_VIA_PROXY = 0x00000004 +INTERNET_REQFLAG_NO_HEADERS = 0x00000008 +INTERNET_REQFLAG_PASSIVE = 0x00000010 +INTERNET_REQFLAG_CACHE_WRITE_DISABLED = 0x00000040 +INTERNET_REQFLAG_NET_TIMEOUT = 0x00000080 +INTERNET_FLAG_RELOAD = (-2147483648) +INTERNET_FLAG_RAW_DATA = 0x40000000 +INTERNET_FLAG_EXISTING_CONNECT = 0x20000000 +INTERNET_FLAG_ASYNC = 0x10000000 +INTERNET_FLAG_PASSIVE = 0x08000000 +INTERNET_FLAG_NO_CACHE_WRITE = 0x04000000 +INTERNET_FLAG_DONT_CACHE = INTERNET_FLAG_NO_CACHE_WRITE +INTERNET_FLAG_MAKE_PERSISTENT = 0x02000000 +INTERNET_FLAG_FROM_CACHE = 0x01000000 +INTERNET_FLAG_OFFLINE = INTERNET_FLAG_FROM_CACHE +INTERNET_FLAG_SECURE = 0x00800000 +INTERNET_FLAG_KEEP_CONNECTION = 0x00400000 +INTERNET_FLAG_NO_AUTO_REDIRECT = 0x00200000 +INTERNET_FLAG_READ_PREFETCH = 0x00100000 +INTERNET_FLAG_NO_COOKIES = 0x00080000 +INTERNET_FLAG_NO_AUTH = 0x00040000 +INTERNET_FLAG_RESTRICTED_ZONE = 0x00020000 +INTERNET_FLAG_CACHE_IF_NET_FAIL = 0x00010000 +INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP = 0x00008000 +INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS = 0x00004000 +INTERNET_FLAG_IGNORE_CERT_DATE_INVALID = 0x00002000 +INTERNET_FLAG_IGNORE_CERT_CN_INVALID = 0x00001000 +INTERNET_FLAG_RESYNCHRONIZE = 0x00000800 +INTERNET_FLAG_HYPERLINK = 0x00000400 +INTERNET_FLAG_NO_UI = 0x00000200 +INTERNET_FLAG_PRAGMA_NOCACHE = 0x00000100 +INTERNET_FLAG_CACHE_ASYNC = 0x00000080 +INTERNET_FLAG_FORMS_SUBMIT = 0x00000040 +INTERNET_FLAG_FWD_BACK = 0x00000020 +INTERNET_FLAG_NEED_FILE = 0x00000010 +INTERNET_FLAG_MUST_CACHE_REQUEST = INTERNET_FLAG_NEED_FILE +SECURITY_INTERNET_MASK = (INTERNET_FLAG_IGNORE_CERT_CN_INVALID | \ + INTERNET_FLAG_IGNORE_CERT_DATE_INVALID | \ + INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | \ + INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP ) +INTERNET_ERROR_MASK_INSERT_CDROM = 0x1 +INTERNET_ERROR_MASK_COMBINED_SEC_CERT = 0x2 +INTERNET_ERROR_MASK_NEED_MSN_SSPI_PKG = 0X4 +INTERNET_ERROR_MASK_LOGIN_FAILURE_DISPLAY_ENTITY_BODY = 0x8 +WININET_API_FLAG_ASYNC = 0x00000001 +WININET_API_FLAG_SYNC = 0x00000004 +WININET_API_FLAG_USE_CONTEXT = 0x00000008 +INTERNET_NO_CALLBACK = 0 +IDSI_FLAG_KEEP_ALIVE = 0x00000001 +IDSI_FLAG_SECURE = 0x00000002 +IDSI_FLAG_PROXY = 0x00000004 +IDSI_FLAG_TUNNEL = 0x00000008 +INTERNET_PER_CONN_FLAGS = 1 +INTERNET_PER_CONN_PROXY_SERVER = 2 +INTERNET_PER_CONN_PROXY_BYPASS = 3 +INTERNET_PER_CONN_AUTOCONFIG_URL = 4 +INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5 +INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL = 6 +INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS = 7 +INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME = 8 +INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL = 9 +PROXY_TYPE_DIRECT = 0x00000001 +PROXY_TYPE_PROXY = 0x00000002 +PROXY_TYPE_AUTO_PROXY_URL = 0x00000004 +PROXY_TYPE_AUTO_DETECT = 0x00000008 +AUTO_PROXY_FLAG_USER_SET = 0x00000001 +AUTO_PROXY_FLAG_ALWAYS_DETECT = 0x00000002 +AUTO_PROXY_FLAG_DETECTION_RUN = 0x00000004 +AUTO_PROXY_FLAG_MIGRATED = 0x00000008 +AUTO_PROXY_FLAG_DONT_CACHE_PROXY_RESULT = 0x00000010 +AUTO_PROXY_FLAG_CACHE_INIT_RUN = 0x00000020 +AUTO_PROXY_FLAG_DETECTION_SUSPECT = 0x00000040 +ISO_FORCE_DISCONNECTED = 0x00000001 +INTERNET_RFC1123_FORMAT = 0 +INTERNET_RFC1123_BUFSIZE = 30 +ICU_ESCAPE = (-2147483648) +ICU_USERNAME = 0x40000000 +ICU_NO_ENCODE = 0x20000000 +ICU_DECODE = 0x10000000 +ICU_NO_META = 0x08000000 +ICU_ENCODE_SPACES_ONLY = 0x04000000 +ICU_BROWSER_MODE = 0x02000000 +ICU_ENCODE_PERCENT = 0x00001000 +INTERNET_OPEN_TYPE_PRECONFIG = 0 +INTERNET_OPEN_TYPE_DIRECT = 1 +INTERNET_OPEN_TYPE_PROXY = 3 +INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY = 4 +PRE_CONFIG_INTERNET_ACCESS = INTERNET_OPEN_TYPE_PRECONFIG +LOCAL_INTERNET_ACCESS = INTERNET_OPEN_TYPE_DIRECT +CERN_PROXY_INTERNET_ACCESS = INTERNET_OPEN_TYPE_PROXY +INTERNET_SERVICE_FTP = 1 +INTERNET_SERVICE_GOPHER = 2 +INTERNET_SERVICE_HTTP = 3 +IRF_ASYNC = WININET_API_FLAG_ASYNC +IRF_SYNC = WININET_API_FLAG_SYNC +IRF_USE_CONTEXT = WININET_API_FLAG_USE_CONTEXT +IRF_NO_WAIT = 0x00000008 +ISO_GLOBAL = 0x00000001 +ISO_REGISTRY = 0x00000002 +ISO_VALID_FLAGS = (ISO_GLOBAL | ISO_REGISTRY) +INTERNET_OPTION_CALLBACK = 1 +INTERNET_OPTION_CONNECT_TIMEOUT = 2 +INTERNET_OPTION_CONNECT_RETRIES = 3 +INTERNET_OPTION_CONNECT_BACKOFF = 4 +INTERNET_OPTION_SEND_TIMEOUT = 5 +INTERNET_OPTION_CONTROL_SEND_TIMEOUT = INTERNET_OPTION_SEND_TIMEOUT +INTERNET_OPTION_RECEIVE_TIMEOUT = 6 +INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT = INTERNET_OPTION_RECEIVE_TIMEOUT +INTERNET_OPTION_DATA_SEND_TIMEOUT = 7 +INTERNET_OPTION_DATA_RECEIVE_TIMEOUT = 8 +INTERNET_OPTION_HANDLE_TYPE = 9 +INTERNET_OPTION_LISTEN_TIMEOUT = 11 +INTERNET_OPTION_READ_BUFFER_SIZE = 12 +INTERNET_OPTION_WRITE_BUFFER_SIZE = 13 +INTERNET_OPTION_ASYNC_ID = 15 +INTERNET_OPTION_ASYNC_PRIORITY = 16 +INTERNET_OPTION_PARENT_HANDLE = 21 +INTERNET_OPTION_KEEP_CONNECTION = 22 +INTERNET_OPTION_REQUEST_FLAGS = 23 +INTERNET_OPTION_EXTENDED_ERROR = 24 +INTERNET_OPTION_OFFLINE_MODE = 26 +INTERNET_OPTION_CACHE_STREAM_HANDLE = 27 +INTERNET_OPTION_USERNAME = 28 +INTERNET_OPTION_PASSWORD = 29 +INTERNET_OPTION_ASYNC = 30 +INTERNET_OPTION_SECURITY_FLAGS = 31 +INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT = 32 +INTERNET_OPTION_DATAFILE_NAME = 33 +INTERNET_OPTION_URL = 34 +INTERNET_OPTION_SECURITY_CERTIFICATE = 35 +INTERNET_OPTION_SECURITY_KEY_BITNESS = 36 +INTERNET_OPTION_REFRESH = 37 +INTERNET_OPTION_PROXY = 38 +INTERNET_OPTION_SETTINGS_CHANGED = 39 +INTERNET_OPTION_VERSION = 40 +INTERNET_OPTION_USER_AGENT = 41 +INTERNET_OPTION_END_BROWSER_SESSION = 42 +INTERNET_OPTION_PROXY_USERNAME = 43 +INTERNET_OPTION_PROXY_PASSWORD = 44 +INTERNET_OPTION_CONTEXT_VALUE = 45 +INTERNET_OPTION_CONNECT_LIMIT = 46 +INTERNET_OPTION_SECURITY_SELECT_CLIENT_CERT = 47 +INTERNET_OPTION_POLICY = 48 +INTERNET_OPTION_DISCONNECTED_TIMEOUT = 49 +INTERNET_OPTION_CONNECTED_STATE = 50 +INTERNET_OPTION_IDLE_STATE = 51 +INTERNET_OPTION_OFFLINE_SEMANTICS = 52 +INTERNET_OPTION_SECONDARY_CACHE_KEY = 53 +INTERNET_OPTION_CALLBACK_FILTER = 54 +INTERNET_OPTION_CONNECT_TIME = 55 +INTERNET_OPTION_SEND_THROUGHPUT = 56 +INTERNET_OPTION_RECEIVE_THROUGHPUT = 57 +INTERNET_OPTION_REQUEST_PRIORITY = 58 +INTERNET_OPTION_HTTP_VERSION = 59 +INTERNET_OPTION_RESET_URLCACHE_SESSION = 60 +INTERNET_OPTION_ERROR_MASK = 62 +INTERNET_OPTION_FROM_CACHE_TIMEOUT = 63 +INTERNET_OPTION_BYPASS_EDITED_ENTRY = 64 +INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO = 67 +INTERNET_OPTION_CODEPAGE = 68 +INTERNET_OPTION_CACHE_TIMESTAMPS = 69 +INTERNET_OPTION_DISABLE_AUTODIAL = 70 +INTERNET_OPTION_MAX_CONNS_PER_SERVER = 73 +INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER = 74 +INTERNET_OPTION_PER_CONNECTION_OPTION = 75 +INTERNET_OPTION_DIGEST_AUTH_UNLOAD = 76 +INTERNET_OPTION_IGNORE_OFFLINE = 77 +INTERNET_OPTION_IDENTITY = 78 +INTERNET_OPTION_REMOVE_IDENTITY = 79 +INTERNET_OPTION_ALTER_IDENTITY = 80 +INTERNET_OPTION_SUPPRESS_BEHAVIOR = 81 +INTERNET_OPTION_AUTODIAL_MODE = 82 +INTERNET_OPTION_AUTODIAL_CONNECTION = 83 +INTERNET_OPTION_CLIENT_CERT_CONTEXT = 84 +INTERNET_OPTION_AUTH_FLAGS = 85 +INTERNET_OPTION_COOKIES_3RD_PARTY = 86 +INTERNET_OPTION_DISABLE_PASSPORT_AUTH = 87 +INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY = 88 +INTERNET_OPTION_EXEMPT_CONNECTION_LIMIT = 89 +INTERNET_OPTION_ENABLE_PASSPORT_AUTH = 90 +INTERNET_OPTION_HIBERNATE_INACTIVE_WORKER_THREADS = 91 +INTERNET_OPTION_ACTIVATE_WORKER_THREADS = 92 +INTERNET_OPTION_RESTORE_WORKER_THREAD_DEFAULTS = 93 +INTERNET_OPTION_SOCKET_SEND_BUFFER_LENGTH = 94 +INTERNET_OPTION_PROXY_SETTINGS_CHANGED = 95 +INTERNET_FIRST_OPTION = INTERNET_OPTION_CALLBACK +INTERNET_LAST_OPTION = INTERNET_OPTION_PROXY_SETTINGS_CHANGED +INTERNET_PRIORITY_FOREGROUND = 1000 +INTERNET_HANDLE_TYPE_INTERNET = 1 +INTERNET_HANDLE_TYPE_CONNECT_FTP = 2 +INTERNET_HANDLE_TYPE_CONNECT_GOPHER = 3 +INTERNET_HANDLE_TYPE_CONNECT_HTTP = 4 +INTERNET_HANDLE_TYPE_FTP_FIND = 5 +INTERNET_HANDLE_TYPE_FTP_FIND_HTML = 6 +INTERNET_HANDLE_TYPE_FTP_FILE = 7 +INTERNET_HANDLE_TYPE_FTP_FILE_HTML = 8 +INTERNET_HANDLE_TYPE_GOPHER_FIND = 9 +INTERNET_HANDLE_TYPE_GOPHER_FIND_HTML = 10 +INTERNET_HANDLE_TYPE_GOPHER_FILE = 11 +INTERNET_HANDLE_TYPE_GOPHER_FILE_HTML = 12 +INTERNET_HANDLE_TYPE_HTTP_REQUEST = 13 +INTERNET_HANDLE_TYPE_FILE_REQUEST = 14 +AUTH_FLAG_DISABLE_NEGOTIATE = 0x00000001 +AUTH_FLAG_ENABLE_NEGOTIATE = 0x00000002 +SECURITY_FLAG_SECURE = 0x00000001 +SECURITY_FLAG_STRENGTH_WEAK = 0x10000000 +SECURITY_FLAG_STRENGTH_MEDIUM = 0x40000000 +SECURITY_FLAG_STRENGTH_STRONG = 0x20000000 +SECURITY_FLAG_UNKNOWNBIT = (-2147483648) +SECURITY_FLAG_FORTEZZA = 0x08000000 +SECURITY_FLAG_NORMALBITNESS = SECURITY_FLAG_STRENGTH_WEAK +SECURITY_FLAG_SSL = 0x00000002 +SECURITY_FLAG_SSL3 = 0x00000004 +SECURITY_FLAG_PCT = 0x00000008 +SECURITY_FLAG_PCT4 = 0x00000010 +SECURITY_FLAG_IETFSSL4 = 0x00000020 +SECURITY_FLAG_40BIT = SECURITY_FLAG_STRENGTH_WEAK +SECURITY_FLAG_128BIT = SECURITY_FLAG_STRENGTH_STRONG +SECURITY_FLAG_56BIT = SECURITY_FLAG_STRENGTH_MEDIUM +SECURITY_FLAG_IGNORE_REVOCATION = 0x00000080 +SECURITY_FLAG_IGNORE_UNKNOWN_CA = 0x00000100 +SECURITY_FLAG_IGNORE_WRONG_USAGE = 0x00000200 +SECURITY_FLAG_IGNORE_CERT_CN_INVALID = INTERNET_FLAG_IGNORE_CERT_CN_INVALID +SECURITY_FLAG_IGNORE_CERT_DATE_INVALID = INTERNET_FLAG_IGNORE_CERT_DATE_INVALID +SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTPS = INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS +SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTP = INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP +SECURITY_SET_MASK = (SECURITY_FLAG_IGNORE_REVOCATION |\ + SECURITY_FLAG_IGNORE_UNKNOWN_CA |\ + SECURITY_FLAG_IGNORE_CERT_CN_INVALID |\ + SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |\ + SECURITY_FLAG_IGNORE_WRONG_USAGE) +AUTODIAL_MODE_NEVER = 1 +AUTODIAL_MODE_ALWAYS = 2 +AUTODIAL_MODE_NO_NETWORK_PRESENT = 4 +INTERNET_STATUS_RESOLVING_NAME = 10 +INTERNET_STATUS_NAME_RESOLVED = 11 +INTERNET_STATUS_CONNECTING_TO_SERVER = 20 +INTERNET_STATUS_CONNECTED_TO_SERVER = 21 +INTERNET_STATUS_SENDING_REQUEST = 30 +INTERNET_STATUS_REQUEST_SENT = 31 +INTERNET_STATUS_RECEIVING_RESPONSE = 40 +INTERNET_STATUS_RESPONSE_RECEIVED = 41 +INTERNET_STATUS_CTL_RESPONSE_RECEIVED = 42 +INTERNET_STATUS_PREFETCH = 43 +INTERNET_STATUS_CLOSING_CONNECTION = 50 +INTERNET_STATUS_CONNECTION_CLOSED = 51 +INTERNET_STATUS_HANDLE_CREATED = 60 +INTERNET_STATUS_HANDLE_CLOSING = 70 +INTERNET_STATUS_DETECTING_PROXY = 80 +INTERNET_STATUS_REQUEST_COMPLETE = 100 +INTERNET_STATUS_REDIRECT = 110 +INTERNET_STATUS_INTERMEDIATE_RESPONSE = 120 +INTERNET_STATUS_USER_INPUT_REQUIRED = 140 +INTERNET_STATUS_STATE_CHANGE = 200 +INTERNET_STATUS_COOKIE_SENT = 320 +INTERNET_STATUS_COOKIE_RECEIVED = 321 +INTERNET_STATUS_PRIVACY_IMPACTED = 324 +INTERNET_STATUS_P3P_HEADER = 325 +INTERNET_STATUS_P3P_POLICYREF = 326 +INTERNET_STATUS_COOKIE_HISTORY = 327 +INTERNET_STATE_CONNECTED = 0x00000001 +INTERNET_STATE_DISCONNECTED = 0x00000002 +INTERNET_STATE_DISCONNECTED_BY_USER = 0x00000010 +INTERNET_STATE_IDLE = 0x00000100 +INTERNET_STATE_BUSY = 0x00000200 +FTP_TRANSFER_TYPE_UNKNOWN = 0x00000000 +FTP_TRANSFER_TYPE_ASCII = 0x00000001 +FTP_TRANSFER_TYPE_BINARY = 0x00000002 +FTP_TRANSFER_TYPE_MASK = (FTP_TRANSFER_TYPE_ASCII | FTP_TRANSFER_TYPE_BINARY) +MAX_GOPHER_DISPLAY_TEXT = 128 +MAX_GOPHER_SELECTOR_TEXT = 256 +MAX_GOPHER_HOST_NAME = INTERNET_MAX_HOST_NAME_LENGTH +MAX_GOPHER_LOCATOR_LENGTH = (1 \ + + MAX_GOPHER_DISPLAY_TEXT \ + + 1 \ + + MAX_GOPHER_SELECTOR_TEXT \ + + 1 \ + + MAX_GOPHER_HOST_NAME \ + + 1 \ + + INTERNET_MAX_PORT_NUMBER_LENGTH \ + + 1 \ + + 1 \ + + 2 \ + ) +GOPHER_TYPE_TEXT_FILE = 0x00000001 +GOPHER_TYPE_DIRECTORY = 0x00000002 +GOPHER_TYPE_CSO = 0x00000004 +GOPHER_TYPE_ERROR = 0x00000008 +GOPHER_TYPE_MAC_BINHEX = 0x00000010 +GOPHER_TYPE_DOS_ARCHIVE = 0x00000020 +GOPHER_TYPE_UNIX_UUENCODED = 0x00000040 +GOPHER_TYPE_INDEX_SERVER = 0x00000080 +GOPHER_TYPE_TELNET = 0x00000100 +GOPHER_TYPE_BINARY = 0x00000200 +GOPHER_TYPE_REDUNDANT = 0x00000400 +GOPHER_TYPE_TN3270 = 0x00000800 +GOPHER_TYPE_GIF = 0x00001000 +GOPHER_TYPE_IMAGE = 0x00002000 +GOPHER_TYPE_BITMAP = 0x00004000 +GOPHER_TYPE_MOVIE = 0x00008000 +GOPHER_TYPE_SOUND = 0x00010000 +GOPHER_TYPE_HTML = 0x00020000 +GOPHER_TYPE_PDF = 0x00040000 +GOPHER_TYPE_CALENDAR = 0x00080000 +GOPHER_TYPE_INLINE = 0x00100000 +GOPHER_TYPE_UNKNOWN = 0x20000000 +GOPHER_TYPE_ASK = 0x40000000 +GOPHER_TYPE_GOPHER_PLUS = (-2147483648) +GOPHER_TYPE_FILE_MASK = (GOPHER_TYPE_TEXT_FILE \ + | GOPHER_TYPE_MAC_BINHEX \ + | GOPHER_TYPE_DOS_ARCHIVE \ + | GOPHER_TYPE_UNIX_UUENCODED \ + | GOPHER_TYPE_BINARY \ + | GOPHER_TYPE_GIF \ + | GOPHER_TYPE_IMAGE \ + | GOPHER_TYPE_BITMAP \ + | GOPHER_TYPE_MOVIE \ + | GOPHER_TYPE_SOUND \ + | GOPHER_TYPE_HTML \ + | GOPHER_TYPE_PDF \ + | GOPHER_TYPE_CALENDAR \ + | GOPHER_TYPE_INLINE \ + ) +MAX_GOPHER_CATEGORY_NAME = 128 +MAX_GOPHER_ATTRIBUTE_NAME = 128 +MIN_GOPHER_ATTRIBUTE_LENGTH = 256 +GOPHER_ATTRIBUTE_ID_BASE = (-1412641792) +GOPHER_CATEGORY_ID_ALL = (GOPHER_ATTRIBUTE_ID_BASE + 1) +GOPHER_CATEGORY_ID_INFO = (GOPHER_ATTRIBUTE_ID_BASE + 2) +GOPHER_CATEGORY_ID_ADMIN = (GOPHER_ATTRIBUTE_ID_BASE + 3) +GOPHER_CATEGORY_ID_VIEWS = (GOPHER_ATTRIBUTE_ID_BASE + 4) +GOPHER_CATEGORY_ID_ABSTRACT = (GOPHER_ATTRIBUTE_ID_BASE + 5) +GOPHER_CATEGORY_ID_VERONICA = (GOPHER_ATTRIBUTE_ID_BASE + 6) +GOPHER_CATEGORY_ID_ASK = (GOPHER_ATTRIBUTE_ID_BASE + 7) +GOPHER_CATEGORY_ID_UNKNOWN = (GOPHER_ATTRIBUTE_ID_BASE + 8) +GOPHER_ATTRIBUTE_ID_ALL = (GOPHER_ATTRIBUTE_ID_BASE + 9) +GOPHER_ATTRIBUTE_ID_ADMIN = (GOPHER_ATTRIBUTE_ID_BASE + 10) +GOPHER_ATTRIBUTE_ID_MOD_DATE = (GOPHER_ATTRIBUTE_ID_BASE + 11) +GOPHER_ATTRIBUTE_ID_TTL = (GOPHER_ATTRIBUTE_ID_BASE + 12) +GOPHER_ATTRIBUTE_ID_SCORE = (GOPHER_ATTRIBUTE_ID_BASE + 13) +GOPHER_ATTRIBUTE_ID_RANGE = (GOPHER_ATTRIBUTE_ID_BASE + 14) +GOPHER_ATTRIBUTE_ID_SITE = (GOPHER_ATTRIBUTE_ID_BASE + 15) +GOPHER_ATTRIBUTE_ID_ORG = (GOPHER_ATTRIBUTE_ID_BASE + 16) +GOPHER_ATTRIBUTE_ID_LOCATION = (GOPHER_ATTRIBUTE_ID_BASE + 17) +GOPHER_ATTRIBUTE_ID_GEOG = (GOPHER_ATTRIBUTE_ID_BASE + 18) +GOPHER_ATTRIBUTE_ID_TIMEZONE = (GOPHER_ATTRIBUTE_ID_BASE + 19) +GOPHER_ATTRIBUTE_ID_PROVIDER = (GOPHER_ATTRIBUTE_ID_BASE + 20) +GOPHER_ATTRIBUTE_ID_VERSION = (GOPHER_ATTRIBUTE_ID_BASE + 21) +GOPHER_ATTRIBUTE_ID_ABSTRACT = (GOPHER_ATTRIBUTE_ID_BASE + 22) +GOPHER_ATTRIBUTE_ID_VIEW = (GOPHER_ATTRIBUTE_ID_BASE + 23) +GOPHER_ATTRIBUTE_ID_TREEWALK = (GOPHER_ATTRIBUTE_ID_BASE + 24) +GOPHER_ATTRIBUTE_ID_UNKNOWN = (GOPHER_ATTRIBUTE_ID_BASE + 25) +HTTP_MAJOR_VERSION = 1 +HTTP_MINOR_VERSION = 0 +HTTP_VERSIONA = "HTTP/1.0" +HTTP_VERSION = HTTP_VERSIONA +HTTP_QUERY_MIME_VERSION = 0 +HTTP_QUERY_CONTENT_TYPE = 1 +HTTP_QUERY_CONTENT_TRANSFER_ENCODING = 2 +HTTP_QUERY_CONTENT_ID = 3 +HTTP_QUERY_CONTENT_DESCRIPTION = 4 +HTTP_QUERY_CONTENT_LENGTH = 5 +HTTP_QUERY_CONTENT_LANGUAGE = 6 +HTTP_QUERY_ALLOW = 7 +HTTP_QUERY_PUBLIC = 8 +HTTP_QUERY_DATE = 9 +HTTP_QUERY_EXPIRES = 10 +HTTP_QUERY_LAST_MODIFIED = 11 +HTTP_QUERY_MESSAGE_ID = 12 +HTTP_QUERY_URI = 13 +HTTP_QUERY_DERIVED_FROM = 14 +HTTP_QUERY_COST = 15 +HTTP_QUERY_LINK = 16 +HTTP_QUERY_PRAGMA = 17 +HTTP_QUERY_VERSION = 18 +HTTP_QUERY_STATUS_CODE = 19 +HTTP_QUERY_STATUS_TEXT = 20 +HTTP_QUERY_RAW_HEADERS = 21 +HTTP_QUERY_RAW_HEADERS_CRLF = 22 +HTTP_QUERY_CONNECTION = 23 +HTTP_QUERY_ACCEPT = 24 +HTTP_QUERY_ACCEPT_CHARSET = 25 +HTTP_QUERY_ACCEPT_ENCODING = 26 +HTTP_QUERY_ACCEPT_LANGUAGE = 27 +HTTP_QUERY_AUTHORIZATION = 28 +HTTP_QUERY_CONTENT_ENCODING = 29 +HTTP_QUERY_FORWARDED = 30 +HTTP_QUERY_FROM = 31 +HTTP_QUERY_IF_MODIFIED_SINCE = 32 +HTTP_QUERY_LOCATION = 33 +HTTP_QUERY_ORIG_URI = 34 +HTTP_QUERY_REFERER = 35 +HTTP_QUERY_RETRY_AFTER = 36 +HTTP_QUERY_SERVER = 37 +HTTP_QUERY_TITLE = 38 +HTTP_QUERY_USER_AGENT = 39 +HTTP_QUERY_WWW_AUTHENTICATE = 40 +HTTP_QUERY_PROXY_AUTHENTICATE = 41 +HTTP_QUERY_ACCEPT_RANGES = 42 +HTTP_QUERY_SET_COOKIE = 43 +HTTP_QUERY_COOKIE = 44 +HTTP_QUERY_REQUEST_METHOD = 45 +HTTP_QUERY_REFRESH = 46 +HTTP_QUERY_CONTENT_DISPOSITION = 47 +HTTP_QUERY_AGE = 48 +HTTP_QUERY_CACHE_CONTROL = 49 +HTTP_QUERY_CONTENT_BASE = 50 +HTTP_QUERY_CONTENT_LOCATION = 51 +HTTP_QUERY_CONTENT_MD5 = 52 +HTTP_QUERY_CONTENT_RANGE = 53 +HTTP_QUERY_ETAG = 54 +HTTP_QUERY_HOST = 55 +HTTP_QUERY_IF_MATCH = 56 +HTTP_QUERY_IF_NONE_MATCH = 57 +HTTP_QUERY_IF_RANGE = 58 +HTTP_QUERY_IF_UNMODIFIED_SINCE = 59 +HTTP_QUERY_MAX_FORWARDS = 60 +HTTP_QUERY_PROXY_AUTHORIZATION = 61 +HTTP_QUERY_RANGE = 62 +HTTP_QUERY_TRANSFER_ENCODING = 63 +HTTP_QUERY_UPGRADE = 64 +HTTP_QUERY_VARY = 65 +HTTP_QUERY_VIA = 66 +HTTP_QUERY_WARNING = 67 +HTTP_QUERY_EXPECT = 68 +HTTP_QUERY_PROXY_CONNECTION = 69 +HTTP_QUERY_UNLESS_MODIFIED_SINCE = 70 +HTTP_QUERY_ECHO_REQUEST = 71 +HTTP_QUERY_ECHO_REPLY = 72 +HTTP_QUERY_ECHO_HEADERS = 73 +HTTP_QUERY_ECHO_HEADERS_CRLF = 74 +HTTP_QUERY_PROXY_SUPPORT = 75 +HTTP_QUERY_AUTHENTICATION_INFO = 76 +HTTP_QUERY_PASSPORT_URLS = 77 +HTTP_QUERY_PASSPORT_CONFIG = 78 +HTTP_QUERY_MAX = 78 +HTTP_QUERY_CUSTOM = 65535 +HTTP_QUERY_FLAG_REQUEST_HEADERS = (-2147483648) +HTTP_QUERY_FLAG_SYSTEMTIME = 0x40000000 +HTTP_QUERY_FLAG_NUMBER = 0x20000000 +HTTP_QUERY_FLAG_COALESCE = 0x10000000 +HTTP_QUERY_MODIFIER_FLAGS_MASK = (HTTP_QUERY_FLAG_REQUEST_HEADERS \ + | HTTP_QUERY_FLAG_SYSTEMTIME \ + | HTTP_QUERY_FLAG_NUMBER \ + | HTTP_QUERY_FLAG_COALESCE \ + ) +HTTP_QUERY_HEADER_MASK = (~HTTP_QUERY_MODIFIER_FLAGS_MASK) +HTTP_STATUS_CONTINUE = 100 +HTTP_STATUS_SWITCH_PROTOCOLS = 101 +HTTP_STATUS_OK = 200 +HTTP_STATUS_CREATED = 201 +HTTP_STATUS_ACCEPTED = 202 +HTTP_STATUS_PARTIAL = 203 +HTTP_STATUS_NO_CONTENT = 204 +HTTP_STATUS_RESET_CONTENT = 205 +HTTP_STATUS_PARTIAL_CONTENT = 206 +HTTP_STATUS_AMBIGUOUS = 300 +HTTP_STATUS_MOVED = 301 +HTTP_STATUS_REDIRECT = 302 +HTTP_STATUS_REDIRECT_METHOD = 303 +HTTP_STATUS_NOT_MODIFIED = 304 +HTTP_STATUS_USE_PROXY = 305 +HTTP_STATUS_REDIRECT_KEEP_VERB = 307 +HTTP_STATUS_BAD_REQUEST = 400 +HTTP_STATUS_DENIED = 401 +HTTP_STATUS_PAYMENT_REQ = 402 +HTTP_STATUS_FORBIDDEN = 403 +HTTP_STATUS_NOT_FOUND = 404 +HTTP_STATUS_BAD_METHOD = 405 +HTTP_STATUS_NONE_ACCEPTABLE = 406 +HTTP_STATUS_PROXY_AUTH_REQ = 407 +HTTP_STATUS_REQUEST_TIMEOUT = 408 +HTTP_STATUS_CONFLICT = 409 +HTTP_STATUS_GONE = 410 +HTTP_STATUS_LENGTH_REQUIRED = 411 +HTTP_STATUS_PRECOND_FAILED = 412 +HTTP_STATUS_REQUEST_TOO_LARGE = 413 +HTTP_STATUS_URI_TOO_LONG = 414 +HTTP_STATUS_UNSUPPORTED_MEDIA = 415 +HTTP_STATUS_RETRY_WITH = 449 +HTTP_STATUS_SERVER_ERROR = 500 +HTTP_STATUS_NOT_SUPPORTED = 501 +HTTP_STATUS_BAD_GATEWAY = 502 +HTTP_STATUS_SERVICE_UNAVAIL = 503 +HTTP_STATUS_GATEWAY_TIMEOUT = 504 +HTTP_STATUS_VERSION_NOT_SUP = 505 +HTTP_STATUS_FIRST = HTTP_STATUS_CONTINUE +HTTP_STATUS_LAST = HTTP_STATUS_VERSION_NOT_SUP +HTTP_ADDREQ_INDEX_MASK = 0x0000FFFF +HTTP_ADDREQ_FLAGS_MASK = (-65536) +HTTP_ADDREQ_FLAG_ADD_IF_NEW = 0x10000000 +HTTP_ADDREQ_FLAG_ADD = 0x20000000 +HTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA = 0x40000000 +HTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON = 0x01000000 +HTTP_ADDREQ_FLAG_COALESCE = HTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA +HTTP_ADDREQ_FLAG_REPLACE = (-2147483648) +HSR_ASYNC = WININET_API_FLAG_ASYNC +HSR_SYNC = WININET_API_FLAG_SYNC +HSR_USE_CONTEXT = WININET_API_FLAG_USE_CONTEXT +HSR_INITIATE = 0x00000008 +HSR_DOWNLOAD = 0x00000010 +HSR_CHUNKED = 0x00000020 +INTERNET_COOKIE_IS_SECURE = 0x01 +INTERNET_COOKIE_IS_SESSION = 0x02 +INTERNET_COOKIE_THIRD_PARTY = 0x10 +INTERNET_COOKIE_PROMPT_REQUIRED = 0x20 +INTERNET_COOKIE_EVALUATE_P3P = 0x40 +INTERNET_COOKIE_APPLY_P3P = 0x80 +INTERNET_COOKIE_P3P_ENABLED = 0x100 +INTERNET_COOKIE_IS_RESTRICTED = 0x200 +INTERNET_COOKIE_IE6 = 0x400 +INTERNET_COOKIE_IS_LEGACY = 0x800 +FLAG_ICC_FORCE_CONNECTION = 0x00000001 +FLAGS_ERROR_UI_FILTER_FOR_ERRORS = 0x01 +FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS = 0x02 +FLAGS_ERROR_UI_FLAGS_GENERATE_DATA = 0x04 +FLAGS_ERROR_UI_FLAGS_NO_UI = 0x08 +FLAGS_ERROR_UI_SERIALIZE_DIALOGS = 0x10 +INTERNET_ERROR_BASE = 12000 +ERROR_INTERNET_OUT_OF_HANDLES = (INTERNET_ERROR_BASE + 1) +ERROR_INTERNET_TIMEOUT = (INTERNET_ERROR_BASE + 2) +ERROR_INTERNET_EXTENDED_ERROR = (INTERNET_ERROR_BASE + 3) +ERROR_INTERNET_INTERNAL_ERROR = (INTERNET_ERROR_BASE + 4) +ERROR_INTERNET_INVALID_URL = (INTERNET_ERROR_BASE + 5) +ERROR_INTERNET_UNRECOGNIZED_SCHEME = (INTERNET_ERROR_BASE + 6) +ERROR_INTERNET_NAME_NOT_RESOLVED = (INTERNET_ERROR_BASE + 7) +ERROR_INTERNET_PROTOCOL_NOT_FOUND = (INTERNET_ERROR_BASE + 8) +ERROR_INTERNET_INVALID_OPTION = (INTERNET_ERROR_BASE + 9) +ERROR_INTERNET_BAD_OPTION_LENGTH = (INTERNET_ERROR_BASE + 10) +ERROR_INTERNET_OPTION_NOT_SETTABLE = (INTERNET_ERROR_BASE + 11) +ERROR_INTERNET_SHUTDOWN = (INTERNET_ERROR_BASE + 12) +ERROR_INTERNET_INCORRECT_USER_NAME = (INTERNET_ERROR_BASE + 13) +ERROR_INTERNET_INCORRECT_PASSWORD = (INTERNET_ERROR_BASE + 14) +ERROR_INTERNET_LOGIN_FAILURE = (INTERNET_ERROR_BASE + 15) +ERROR_INTERNET_INVALID_OPERATION = (INTERNET_ERROR_BASE + 16) +ERROR_INTERNET_OPERATION_CANCELLED = (INTERNET_ERROR_BASE + 17) +ERROR_INTERNET_INCORRECT_HANDLE_TYPE = (INTERNET_ERROR_BASE + 18) +ERROR_INTERNET_INCORRECT_HANDLE_STATE = (INTERNET_ERROR_BASE + 19) +ERROR_INTERNET_NOT_PROXY_REQUEST = (INTERNET_ERROR_BASE + 20) +ERROR_INTERNET_REGISTRY_VALUE_NOT_FOUND = (INTERNET_ERROR_BASE + 21) +ERROR_INTERNET_BAD_REGISTRY_PARAMETER = (INTERNET_ERROR_BASE + 22) +ERROR_INTERNET_NO_DIRECT_ACCESS = (INTERNET_ERROR_BASE + 23) +ERROR_INTERNET_NO_CONTEXT = (INTERNET_ERROR_BASE + 24) +ERROR_INTERNET_NO_CALLBACK = (INTERNET_ERROR_BASE + 25) +ERROR_INTERNET_REQUEST_PENDING = (INTERNET_ERROR_BASE + 26) +ERROR_INTERNET_INCORRECT_FORMAT = (INTERNET_ERROR_BASE + 27) +ERROR_INTERNET_ITEM_NOT_FOUND = (INTERNET_ERROR_BASE + 28) +ERROR_INTERNET_CANNOT_CONNECT = (INTERNET_ERROR_BASE + 29) +ERROR_INTERNET_CONNECTION_ABORTED = (INTERNET_ERROR_BASE + 30) +ERROR_INTERNET_CONNECTION_RESET = (INTERNET_ERROR_BASE + 31) +ERROR_INTERNET_FORCE_RETRY = (INTERNET_ERROR_BASE + 32) +ERROR_INTERNET_INVALID_PROXY_REQUEST = (INTERNET_ERROR_BASE + 33) +ERROR_INTERNET_NEED_UI = (INTERNET_ERROR_BASE + 34) +ERROR_INTERNET_HANDLE_EXISTS = (INTERNET_ERROR_BASE + 36) +ERROR_INTERNET_SEC_CERT_DATE_INVALID = (INTERNET_ERROR_BASE + 37) +ERROR_INTERNET_SEC_CERT_CN_INVALID = (INTERNET_ERROR_BASE + 38) +ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR = (INTERNET_ERROR_BASE + 39) +ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR = (INTERNET_ERROR_BASE + 40) +ERROR_INTERNET_MIXED_SECURITY = (INTERNET_ERROR_BASE + 41) +ERROR_INTERNET_CHG_POST_IS_NON_SECURE = (INTERNET_ERROR_BASE + 42) +ERROR_INTERNET_POST_IS_NON_SECURE = (INTERNET_ERROR_BASE + 43) +ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED = (INTERNET_ERROR_BASE + 44) +ERROR_INTERNET_INVALID_CA = (INTERNET_ERROR_BASE + 45) +ERROR_INTERNET_CLIENT_AUTH_NOT_SETUP = (INTERNET_ERROR_BASE + 46) +ERROR_INTERNET_ASYNC_THREAD_FAILED = (INTERNET_ERROR_BASE + 47) +ERROR_INTERNET_REDIRECT_SCHEME_CHANGE = (INTERNET_ERROR_BASE + 48) +ERROR_INTERNET_DIALOG_PENDING = (INTERNET_ERROR_BASE + 49) +ERROR_INTERNET_RETRY_DIALOG = (INTERNET_ERROR_BASE + 50) +ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR = (INTERNET_ERROR_BASE + 52) +ERROR_INTERNET_INSERT_CDROM = (INTERNET_ERROR_BASE + 53) +ERROR_INTERNET_FORTEZZA_LOGIN_NEEDED = (INTERNET_ERROR_BASE + 54) +ERROR_INTERNET_SEC_CERT_ERRORS = (INTERNET_ERROR_BASE + 55) +ERROR_INTERNET_SEC_CERT_NO_REV = (INTERNET_ERROR_BASE + 56) +ERROR_INTERNET_SEC_CERT_REV_FAILED = (INTERNET_ERROR_BASE + 57) +ERROR_FTP_TRANSFER_IN_PROGRESS = (INTERNET_ERROR_BASE + 110) +ERROR_FTP_DROPPED = (INTERNET_ERROR_BASE + 111) +ERROR_FTP_NO_PASSIVE_MODE = (INTERNET_ERROR_BASE + 112) +ERROR_GOPHER_PROTOCOL_ERROR = (INTERNET_ERROR_BASE + 130) +ERROR_GOPHER_NOT_FILE = (INTERNET_ERROR_BASE + 131) +ERROR_GOPHER_DATA_ERROR = (INTERNET_ERROR_BASE + 132) +ERROR_GOPHER_END_OF_DATA = (INTERNET_ERROR_BASE + 133) +ERROR_GOPHER_INVALID_LOCATOR = (INTERNET_ERROR_BASE + 134) +ERROR_GOPHER_INCORRECT_LOCATOR_TYPE = (INTERNET_ERROR_BASE + 135) +ERROR_GOPHER_NOT_GOPHER_PLUS = (INTERNET_ERROR_BASE + 136) +ERROR_GOPHER_ATTRIBUTE_NOT_FOUND = (INTERNET_ERROR_BASE + 137) +ERROR_GOPHER_UNKNOWN_LOCATOR = (INTERNET_ERROR_BASE + 138) +ERROR_HTTP_HEADER_NOT_FOUND = (INTERNET_ERROR_BASE + 150) +ERROR_HTTP_DOWNLEVEL_SERVER = (INTERNET_ERROR_BASE + 151) +ERROR_HTTP_INVALID_SERVER_RESPONSE = (INTERNET_ERROR_BASE + 152) +ERROR_HTTP_INVALID_HEADER = (INTERNET_ERROR_BASE + 153) +ERROR_HTTP_INVALID_QUERY_REQUEST = (INTERNET_ERROR_BASE + 154) +ERROR_HTTP_HEADER_ALREADY_EXISTS = (INTERNET_ERROR_BASE + 155) +ERROR_HTTP_REDIRECT_FAILED = (INTERNET_ERROR_BASE + 156) +ERROR_HTTP_NOT_REDIRECTED = (INTERNET_ERROR_BASE + 160) +ERROR_HTTP_COOKIE_NEEDS_CONFIRMATION = (INTERNET_ERROR_BASE + 161) +ERROR_HTTP_COOKIE_DECLINED = (INTERNET_ERROR_BASE + 162) +ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION = (INTERNET_ERROR_BASE + 168) +ERROR_INTERNET_SECURITY_CHANNEL_ERROR = (INTERNET_ERROR_BASE + 157) +ERROR_INTERNET_UNABLE_TO_CACHE_FILE = (INTERNET_ERROR_BASE + 158) +ERROR_INTERNET_TCPIP_NOT_INSTALLED = (INTERNET_ERROR_BASE + 159) +ERROR_INTERNET_DISCONNECTED = (INTERNET_ERROR_BASE + 163) +ERROR_INTERNET_SERVER_UNREACHABLE = (INTERNET_ERROR_BASE + 164) +ERROR_INTERNET_PROXY_SERVER_UNREACHABLE = (INTERNET_ERROR_BASE + 165) +ERROR_INTERNET_BAD_AUTO_PROXY_SCRIPT = (INTERNET_ERROR_BASE + 166) +ERROR_INTERNET_UNABLE_TO_DOWNLOAD_SCRIPT = (INTERNET_ERROR_BASE + 167) +ERROR_INTERNET_SEC_INVALID_CERT = (INTERNET_ERROR_BASE + 169) +ERROR_INTERNET_SEC_CERT_REVOKED = (INTERNET_ERROR_BASE + 170) +ERROR_INTERNET_FAILED_DUETOSECURITYCHECK = (INTERNET_ERROR_BASE + 171) +ERROR_INTERNET_NOT_INITIALIZED = (INTERNET_ERROR_BASE + 172) +ERROR_INTERNET_NEED_MSN_SSPI_PKG = (INTERNET_ERROR_BASE + 173) +ERROR_INTERNET_LOGIN_FAILURE_DISPLAY_ENTITY_BODY = (INTERNET_ERROR_BASE + 174) +INTERNET_ERROR_LAST = ERROR_INTERNET_LOGIN_FAILURE_DISPLAY_ENTITY_BODY +NORMAL_CACHE_ENTRY = 0x00000001 +STICKY_CACHE_ENTRY = 0x00000004 +EDITED_CACHE_ENTRY = 0x00000008 +TRACK_OFFLINE_CACHE_ENTRY = 0x00000010 +TRACK_ONLINE_CACHE_ENTRY = 0x00000020 +SPARSE_CACHE_ENTRY = 0x00010000 +COOKIE_CACHE_ENTRY = 0x00100000 +URLHISTORY_CACHE_ENTRY = 0x00200000 +URLCACHE_FIND_DEFAULT_FILTER = NORMAL_CACHE_ENTRY \ + | COOKIE_CACHE_ENTRY \ + | URLHISTORY_CACHE_ENTRY \ + | TRACK_OFFLINE_CACHE_ENTRY \ + | TRACK_ONLINE_CACHE_ENTRY \ + | STICKY_CACHE_ENTRY +CACHEGROUP_ATTRIBUTE_GET_ALL = (-1) +CACHEGROUP_ATTRIBUTE_BASIC = 0x00000001 +CACHEGROUP_ATTRIBUTE_FLAG = 0x00000002 +CACHEGROUP_ATTRIBUTE_TYPE = 0x00000004 +CACHEGROUP_ATTRIBUTE_QUOTA = 0x00000008 +CACHEGROUP_ATTRIBUTE_GROUPNAME = 0x00000010 +CACHEGROUP_ATTRIBUTE_STORAGE = 0x00000020 +CACHEGROUP_FLAG_NONPURGEABLE = 0x00000001 +CACHEGROUP_FLAG_GIDONLY = 0x00000004 +CACHEGROUP_FLAG_FLUSHURL_ONDELETE = 0x00000002 +CACHEGROUP_SEARCH_ALL = 0x00000000 +CACHEGROUP_SEARCH_BYURL = 0x00000001 +CACHEGROUP_TYPE_INVALID = 0x00000001 +CACHEGROUP_READWRITE_MASK = \ + CACHEGROUP_ATTRIBUTE_TYPE \ + | CACHEGROUP_ATTRIBUTE_QUOTA \ + | CACHEGROUP_ATTRIBUTE_GROUPNAME \ + | CACHEGROUP_ATTRIBUTE_STORAGE +GROUPNAME_MAX_LENGTH = 120 +GROUP_OWNER_STORAGE_SIZE = 4 +CACHE_ENTRY_ATTRIBUTE_FC = 0x00000004 +CACHE_ENTRY_HITRATE_FC = 0x00000010 +CACHE_ENTRY_MODTIME_FC = 0x00000040 +CACHE_ENTRY_EXPTIME_FC = 0x00000080 +CACHE_ENTRY_ACCTIME_FC = 0x00000100 +CACHE_ENTRY_SYNCTIME_FC = 0x00000200 +CACHE_ENTRY_HEADERINFO_FC = 0x00000400 +CACHE_ENTRY_EXEMPT_DELTA_FC = 0x00000800 +INTERNET_CACHE_GROUP_ADD = 0 +INTERNET_CACHE_GROUP_REMOVE = 1 +INTERNET_DIAL_FORCE_PROMPT = 0x2000 +INTERNET_DIAL_SHOW_OFFLINE = 0x4000 +INTERNET_DIAL_UNATTENDED = 0x8000 +INTERENT_GOONLINE_REFRESH = 0x00000001 +INTERENT_GOONLINE_MASK = 0x00000001 +INTERNET_AUTODIAL_FORCE_ONLINE = 1 +INTERNET_AUTODIAL_FORCE_UNATTENDED = 2 +INTERNET_AUTODIAL_FAILIFSECURITYCHECK = 4 +INTERNET_AUTODIAL_OVERRIDE_NET_PRESENT = 8 +INTERNET_AUTODIAL_FLAGS_MASK = (INTERNET_AUTODIAL_FORCE_ONLINE | INTERNET_AUTODIAL_FORCE_UNATTENDED | INTERNET_AUTODIAL_FAILIFSECURITYCHECK | INTERNET_AUTODIAL_OVERRIDE_NET_PRESENT) +PROXY_AUTO_DETECT_TYPE_DHCP = 1 +PROXY_AUTO_DETECT_TYPE_DNS_A = 2 +INTERNET_CONNECTION_MODEM = 0x01 +INTERNET_CONNECTION_LAN = 0x02 +INTERNET_CONNECTION_PROXY = 0x04 +INTERNET_CONNECTION_MODEM_BUSY = 0x08 +INTERNET_RAS_INSTALLED = 0x10 +INTERNET_CONNECTION_OFFLINE = 0x20 +INTERNET_CONNECTION_CONFIGURED = 0x40 +INTERNET_CUSTOMDIAL_CONNECT = 0 +INTERNET_CUSTOMDIAL_UNATTENDED = 1 +INTERNET_CUSTOMDIAL_DISCONNECT = 2 +INTERNET_CUSTOMDIAL_SHOWOFFLINE = 4 +INTERNET_CUSTOMDIAL_SAFE_FOR_UNATTENDED = 1 +INTERNET_CUSTOMDIAL_WILL_SUPPLY_STATE = 2 +INTERNET_CUSTOMDIAL_CAN_HANGUP = 4 +INTERNET_DIALSTATE_DISCONNECTED = 1 +INTERNET_IDENTITY_FLAG_PRIVATE_CACHE = 0x01 +INTERNET_IDENTITY_FLAG_SHARED_CACHE = 0x02 +INTERNET_IDENTITY_FLAG_CLEAR_DATA = 0x04 +INTERNET_IDENTITY_FLAG_CLEAR_COOKIES = 0x08 +INTERNET_IDENTITY_FLAG_CLEAR_HISTORY = 0x10 +INTERNET_IDENTITY_FLAG_CLEAR_CONTENT = 0x20 +INTERNET_SUPPRESS_RESET_ALL = 0x00 +INTERNET_SUPPRESS_COOKIE_POLICY = 0x01 +INTERNET_SUPPRESS_COOKIE_POLICY_RESET = 0x02 +PRIVACY_TEMPLATE_NO_COOKIES = 0 +PRIVACY_TEMPLATE_HIGH = 1 +PRIVACY_TEMPLATE_MEDIUM_HIGH = 2 +PRIVACY_TEMPLATE_MEDIUM = 3 +PRIVACY_TEMPLATE_MEDIUM_LOW = 4 +PRIVACY_TEMPLATE_LOW = 5 +PRIVACY_TEMPLATE_CUSTOM = 100 +PRIVACY_TEMPLATE_ADVANCED = 101 +PRIVACY_TEMPLATE_MAX = PRIVACY_TEMPLATE_LOW +PRIVACY_TYPE_FIRST_PARTY = 0 +PRIVACY_TYPE_THIRD_PARTY = 1 + +# Generated by h2py from winhttp.h +INTERNET_DEFAULT_PORT = 0 +INTERNET_DEFAULT_HTTP_PORT = 80 +INTERNET_DEFAULT_HTTPS_PORT = 443 +WINHTTP_FLAG_ASYNC = 0x10000000 +WINHTTP_FLAG_SECURE = 0x00800000 +WINHTTP_FLAG_ESCAPE_PERCENT = 0x00000004 +WINHTTP_FLAG_NULL_CODEPAGE = 0x00000008 +WINHTTP_FLAG_BYPASS_PROXY_CACHE = 0x00000100 +WINHTTP_FLAG_REFRESH = WINHTTP_FLAG_BYPASS_PROXY_CACHE +WINHTTP_FLAG_ESCAPE_DISABLE = 0x00000040 +WINHTTP_FLAG_ESCAPE_DISABLE_QUERY = 0x00000080 +SECURITY_FLAG_IGNORE_UNKNOWN_CA = 0x00000100 +SECURITY_FLAG_IGNORE_CERT_DATE_INVALID = 0x00002000 +SECURITY_FLAG_IGNORE_CERT_CN_INVALID = 0x00001000 +SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE = 0x00000200 +INTERNET_SCHEME_HTTP = (1) +INTERNET_SCHEME_HTTPS = (2) +WINHTTP_AUTOPROXY_AUTO_DETECT = 0x00000001 +WINHTTP_AUTOPROXY_CONFIG_URL = 0x00000002 +WINHTTP_AUTOPROXY_RUN_INPROCESS = 0x00010000 +WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY = 0x00020000 +WINHTTP_AUTO_DETECT_TYPE_DHCP = 0x00000001 +WINHTTP_AUTO_DETECT_TYPE_DNS_A = 0x00000002 +WINHTTP_TIME_FORMAT_BUFSIZE = 62 +ICU_NO_ENCODE = 0x20000000 +ICU_DECODE = 0x10000000 +ICU_NO_META = 0x08000000 +ICU_ENCODE_SPACES_ONLY = 0x04000000 +ICU_BROWSER_MODE = 0x02000000 +ICU_ENCODE_PERCENT = 0x00001000 +ICU_ESCAPE = (-2147483648) +ICU_ESCAPE_AUTHORITY = 0x00002000 +ICU_REJECT_USERPWD = 0x00004000 +WINHTTP_ACCESS_TYPE_DEFAULT_PROXY = 0 +WINHTTP_ACCESS_TYPE_NO_PROXY = 1 +WINHTTP_ACCESS_TYPE_NAMED_PROXY = 3 +WINHTTP_OPTION_CALLBACK = 1 +WINHTTP_OPTION_RESOLVE_TIMEOUT = 2 +WINHTTP_OPTION_CONNECT_TIMEOUT = 3 +WINHTTP_OPTION_CONNECT_RETRIES = 4 +WINHTTP_OPTION_SEND_TIMEOUT = 5 +WINHTTP_OPTION_RECEIVE_TIMEOUT = 6 +WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT = 7 +WINHTTP_OPTION_HANDLE_TYPE = 9 +WINHTTP_OPTION_READ_BUFFER_SIZE = 12 +WINHTTP_OPTION_WRITE_BUFFER_SIZE = 13 +WINHTTP_OPTION_PARENT_HANDLE = 21 +WINHTTP_OPTION_EXTENDED_ERROR = 24 +WINHTTP_OPTION_SECURITY_FLAGS = 31 +WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT = 32 +WINHTTP_OPTION_URL = 34 +WINHTTP_OPTION_SECURITY_KEY_BITNESS = 36 +WINHTTP_OPTION_PROXY = 38 +WINHTTP_OPTION_USER_AGENT = 41 +WINHTTP_OPTION_CONTEXT_VALUE = 45 +WINHTTP_OPTION_CLIENT_CERT_CONTEXT = 47 +WINHTTP_OPTION_REQUEST_PRIORITY = 58 +WINHTTP_OPTION_HTTP_VERSION = 59 +WINHTTP_OPTION_DISABLE_FEATURE = 63 +WINHTTP_OPTION_CODEPAGE = 68 +WINHTTP_OPTION_MAX_CONNS_PER_SERVER = 73 +WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER = 74 +WINHTTP_OPTION_AUTOLOGON_POLICY = 77 +WINHTTP_OPTION_SERVER_CERT_CONTEXT = 78 +WINHTTP_OPTION_ENABLE_FEATURE = 79 +WINHTTP_OPTION_WORKER_THREAD_COUNT = 80 +WINHTTP_OPTION_PASSPORT_COBRANDING_TEXT = 81 +WINHTTP_OPTION_PASSPORT_COBRANDING_URL = 82 +WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH = 83 +WINHTTP_OPTION_SECURE_PROTOCOLS = 84 +WINHTTP_OPTION_ENABLETRACING = 85 +WINHTTP_OPTION_PASSPORT_SIGN_OUT = 86 +WINHTTP_OPTION_PASSPORT_RETURN_URL = 87 +WINHTTP_OPTION_REDIRECT_POLICY = 88 +WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS = 89 +WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE = 90 +WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE = 91 +WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE = 92 +WINHTTP_OPTION_CONNECTION_INFO = 93 +WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST = 94 +WINHTTP_OPTION_SPN = 96 +WINHTTP_OPTION_GLOBAL_PROXY_CREDS = 97 +WINHTTP_OPTION_GLOBAL_SERVER_CREDS = 98 +WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT = 99 +WINHTTP_OPTION_REJECT_USERPWD_IN_URL = 100 +WINHTTP_OPTION_USE_GLOBAL_SERVER_CREDENTIALS = 101 +WINHTTP_LAST_OPTION = WINHTTP_OPTION_USE_GLOBAL_SERVER_CREDENTIALS +WINHTTP_OPTION_USERNAME = 0x1000 +WINHTTP_OPTION_PASSWORD = 0x1001 +WINHTTP_OPTION_PROXY_USERNAME = 0x1002 +WINHTTP_OPTION_PROXY_PASSWORD = 0x1003 +WINHTTP_CONNS_PER_SERVER_UNLIMITED = (-1) +WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM = 0 +WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW = 1 +WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH = 2 +WINHTTP_AUTOLOGON_SECURITY_LEVEL_DEFAULT = WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM +WINHTTP_OPTION_REDIRECT_POLICY_NEVER = 0 +WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP = 1 +WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS = 2 +WINHTTP_OPTION_REDIRECT_POLICY_LAST = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS +WINHTTP_OPTION_REDIRECT_POLICY_DEFAULT = WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP +WINHTTP_DISABLE_PASSPORT_AUTH = 0x00000000 +WINHTTP_ENABLE_PASSPORT_AUTH = 0x10000000 +WINHTTP_DISABLE_PASSPORT_KEYRING = 0x20000000 +WINHTTP_ENABLE_PASSPORT_KEYRING = 0x40000000 +WINHTTP_DISABLE_COOKIES = 0x00000001 +WINHTTP_DISABLE_REDIRECTS = 0x00000002 +WINHTTP_DISABLE_AUTHENTICATION = 0x00000004 +WINHTTP_DISABLE_KEEP_ALIVE = 0x00000008 +WINHTTP_ENABLE_SSL_REVOCATION = 0x00000001 +WINHTTP_ENABLE_SSL_REVERT_IMPERSONATION = 0x00000002 +WINHTTP_DISABLE_SPN_SERVER_PORT = 0x00000000 +WINHTTP_ENABLE_SPN_SERVER_PORT = 0x00000001 +WINHTTP_OPTION_SPN_MASK = WINHTTP_ENABLE_SPN_SERVER_PORT +WINHTTP_HANDLE_TYPE_SESSION = 1 +WINHTTP_HANDLE_TYPE_CONNECT = 2 +WINHTTP_HANDLE_TYPE_REQUEST = 3 +WINHTTP_AUTH_SCHEME_BASIC = 0x00000001 +WINHTTP_AUTH_SCHEME_NTLM = 0x00000002 +WINHTTP_AUTH_SCHEME_PASSPORT = 0x00000004 +WINHTTP_AUTH_SCHEME_DIGEST = 0x00000008 +WINHTTP_AUTH_SCHEME_NEGOTIATE = 0x00000010 +WINHTTP_AUTH_TARGET_SERVER = 0x00000000 +WINHTTP_AUTH_TARGET_PROXY = 0x00000001 +SECURITY_FLAG_SECURE = 0x00000001 +SECURITY_FLAG_STRENGTH_WEAK = 0x10000000 +SECURITY_FLAG_STRENGTH_MEDIUM = 0x40000000 +SECURITY_FLAG_STRENGTH_STRONG = 0x20000000 +WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED = 0x00000001 +WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT = 0x00000002 +WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED = 0x00000004 +WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA = 0x00000008 +WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID = 0x00000010 +WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID = 0x00000020 +WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE = 0x00000040 +WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR = (-2147483648) +WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 = 0x00000008 +WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 = 0x00000020 +WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 = 0x00000080 +WINHTTP_FLAG_SECURE_PROTOCOL_ALL = (WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 | \ + WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | \ + WINHTTP_FLAG_SECURE_PROTOCOL_TLS1) +WINHTTP_CALLBACK_STATUS_RESOLVING_NAME = 0x00000001 +WINHTTP_CALLBACK_STATUS_NAME_RESOLVED = 0x00000002 +WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER = 0x00000004 +WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER = 0x00000008 +WINHTTP_CALLBACK_STATUS_SENDING_REQUEST = 0x00000010 +WINHTTP_CALLBACK_STATUS_REQUEST_SENT = 0x00000020 +WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE = 0x00000040 +WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED = 0x00000080 +WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION = 0x00000100 +WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED = 0x00000200 +WINHTTP_CALLBACK_STATUS_HANDLE_CREATED = 0x00000400 +WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING = 0x00000800 +WINHTTP_CALLBACK_STATUS_DETECTING_PROXY = 0x00001000 +WINHTTP_CALLBACK_STATUS_REDIRECT = 0x00004000 +WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE = 0x00008000 +WINHTTP_CALLBACK_STATUS_SECURE_FAILURE = 0x00010000 +WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE = 0x00020000 +WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE = 0x00040000 +WINHTTP_CALLBACK_STATUS_READ_COMPLETE = 0x00080000 +WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE = 0x00100000 +WINHTTP_CALLBACK_STATUS_REQUEST_ERROR = 0x00200000 +WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE = 0x00400000 +API_RECEIVE_RESPONSE = (1) +API_QUERY_DATA_AVAILABLE = (2) +API_READ_DATA = (3) +API_WRITE_DATA = (4) +API_SEND_REQUEST = (5) +WINHTTP_CALLBACK_FLAG_RESOLVE_NAME = (WINHTTP_CALLBACK_STATUS_RESOLVING_NAME | WINHTTP_CALLBACK_STATUS_NAME_RESOLVED) +WINHTTP_CALLBACK_FLAG_CONNECT_TO_SERVER = (WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER | WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER) +WINHTTP_CALLBACK_FLAG_SEND_REQUEST = (WINHTTP_CALLBACK_STATUS_SENDING_REQUEST | WINHTTP_CALLBACK_STATUS_REQUEST_SENT) +WINHTTP_CALLBACK_FLAG_RECEIVE_RESPONSE = (WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE | WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED) +WINHTTP_CALLBACK_FLAG_CLOSE_CONNECTION = (WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION | WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED) +WINHTTP_CALLBACK_FLAG_HANDLES = (WINHTTP_CALLBACK_STATUS_HANDLE_CREATED | WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING) +WINHTTP_CALLBACK_FLAG_DETECTING_PROXY = WINHTTP_CALLBACK_STATUS_DETECTING_PROXY +WINHTTP_CALLBACK_FLAG_REDIRECT = WINHTTP_CALLBACK_STATUS_REDIRECT +WINHTTP_CALLBACK_FLAG_INTERMEDIATE_RESPONSE = WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE +WINHTTP_CALLBACK_FLAG_SECURE_FAILURE = WINHTTP_CALLBACK_STATUS_SECURE_FAILURE +WINHTTP_CALLBACK_FLAG_SENDREQUEST_COMPLETE = WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE +WINHTTP_CALLBACK_FLAG_HEADERS_AVAILABLE = WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE +WINHTTP_CALLBACK_FLAG_DATA_AVAILABLE = WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE +WINHTTP_CALLBACK_FLAG_READ_COMPLETE = WINHTTP_CALLBACK_STATUS_READ_COMPLETE +WINHTTP_CALLBACK_FLAG_WRITE_COMPLETE = WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE +WINHTTP_CALLBACK_FLAG_REQUEST_ERROR = WINHTTP_CALLBACK_STATUS_REQUEST_ERROR +WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS = (WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE \ + | WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE \ + | WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE \ + | WINHTTP_CALLBACK_STATUS_READ_COMPLETE \ + | WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE \ + | WINHTTP_CALLBACK_STATUS_REQUEST_ERROR) +WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS = (-1) +WINHTTP_QUERY_MIME_VERSION = 0 +WINHTTP_QUERY_CONTENT_TYPE = 1 +WINHTTP_QUERY_CONTENT_TRANSFER_ENCODING = 2 +WINHTTP_QUERY_CONTENT_ID = 3 +WINHTTP_QUERY_CONTENT_DESCRIPTION = 4 +WINHTTP_QUERY_CONTENT_LENGTH = 5 +WINHTTP_QUERY_CONTENT_LANGUAGE = 6 +WINHTTP_QUERY_ALLOW = 7 +WINHTTP_QUERY_PUBLIC = 8 +WINHTTP_QUERY_DATE = 9 +WINHTTP_QUERY_EXPIRES = 10 +WINHTTP_QUERY_LAST_MODIFIED = 11 +WINHTTP_QUERY_MESSAGE_ID = 12 +WINHTTP_QUERY_URI = 13 +WINHTTP_QUERY_DERIVED_FROM = 14 +WINHTTP_QUERY_COST = 15 +WINHTTP_QUERY_LINK = 16 +WINHTTP_QUERY_PRAGMA = 17 +WINHTTP_QUERY_VERSION = 18 +WINHTTP_QUERY_STATUS_CODE = 19 +WINHTTP_QUERY_STATUS_TEXT = 20 +WINHTTP_QUERY_RAW_HEADERS = 21 +WINHTTP_QUERY_RAW_HEADERS_CRLF = 22 +WINHTTP_QUERY_CONNECTION = 23 +WINHTTP_QUERY_ACCEPT = 24 +WINHTTP_QUERY_ACCEPT_CHARSET = 25 +WINHTTP_QUERY_ACCEPT_ENCODING = 26 +WINHTTP_QUERY_ACCEPT_LANGUAGE = 27 +WINHTTP_QUERY_AUTHORIZATION = 28 +WINHTTP_QUERY_CONTENT_ENCODING = 29 +WINHTTP_QUERY_FORWARDED = 30 +WINHTTP_QUERY_FROM = 31 +WINHTTP_QUERY_IF_MODIFIED_SINCE = 32 +WINHTTP_QUERY_LOCATION = 33 +WINHTTP_QUERY_ORIG_URI = 34 +WINHTTP_QUERY_REFERER = 35 +WINHTTP_QUERY_RETRY_AFTER = 36 +WINHTTP_QUERY_SERVER = 37 +WINHTTP_QUERY_TITLE = 38 +WINHTTP_QUERY_USER_AGENT = 39 +WINHTTP_QUERY_WWW_AUTHENTICATE = 40 +WINHTTP_QUERY_PROXY_AUTHENTICATE = 41 +WINHTTP_QUERY_ACCEPT_RANGES = 42 +WINHTTP_QUERY_SET_COOKIE = 43 +WINHTTP_QUERY_COOKIE = 44 +WINHTTP_QUERY_REQUEST_METHOD = 45 +WINHTTP_QUERY_REFRESH = 46 +WINHTTP_QUERY_CONTENT_DISPOSITION = 47 +WINHTTP_QUERY_AGE = 48 +WINHTTP_QUERY_CACHE_CONTROL = 49 +WINHTTP_QUERY_CONTENT_BASE = 50 +WINHTTP_QUERY_CONTENT_LOCATION = 51 +WINHTTP_QUERY_CONTENT_MD5 = 52 +WINHTTP_QUERY_CONTENT_RANGE = 53 +WINHTTP_QUERY_ETAG = 54 +WINHTTP_QUERY_HOST = 55 +WINHTTP_QUERY_IF_MATCH = 56 +WINHTTP_QUERY_IF_NONE_MATCH = 57 +WINHTTP_QUERY_IF_RANGE = 58 +WINHTTP_QUERY_IF_UNMODIFIED_SINCE = 59 +WINHTTP_QUERY_MAX_FORWARDS = 60 +WINHTTP_QUERY_PROXY_AUTHORIZATION = 61 +WINHTTP_QUERY_RANGE = 62 +WINHTTP_QUERY_TRANSFER_ENCODING = 63 +WINHTTP_QUERY_UPGRADE = 64 +WINHTTP_QUERY_VARY = 65 +WINHTTP_QUERY_VIA = 66 +WINHTTP_QUERY_WARNING = 67 +WINHTTP_QUERY_EXPECT = 68 +WINHTTP_QUERY_PROXY_CONNECTION = 69 +WINHTTP_QUERY_UNLESS_MODIFIED_SINCE = 70 +WINHTTP_QUERY_PROXY_SUPPORT = 75 +WINHTTP_QUERY_AUTHENTICATION_INFO = 76 +WINHTTP_QUERY_PASSPORT_URLS = 77 +WINHTTP_QUERY_PASSPORT_CONFIG = 78 +WINHTTP_QUERY_MAX = 78 +WINHTTP_QUERY_CUSTOM = 65535 +WINHTTP_QUERY_FLAG_REQUEST_HEADERS = (-2147483648) +WINHTTP_QUERY_FLAG_SYSTEMTIME = 0x40000000 +WINHTTP_QUERY_FLAG_NUMBER = 0x20000000 +HTTP_STATUS_CONTINUE = 100 +HTTP_STATUS_SWITCH_PROTOCOLS = 101 +HTTP_STATUS_OK = 200 +HTTP_STATUS_CREATED = 201 +HTTP_STATUS_ACCEPTED = 202 +HTTP_STATUS_PARTIAL = 203 +HTTP_STATUS_NO_CONTENT = 204 +HTTP_STATUS_RESET_CONTENT = 205 +HTTP_STATUS_PARTIAL_CONTENT = 206 +HTTP_STATUS_WEBDAV_MULTI_STATUS = 207 +HTTP_STATUS_AMBIGUOUS = 300 +HTTP_STATUS_MOVED = 301 +HTTP_STATUS_REDIRECT = 302 +HTTP_STATUS_REDIRECT_METHOD = 303 +HTTP_STATUS_NOT_MODIFIED = 304 +HTTP_STATUS_USE_PROXY = 305 +HTTP_STATUS_REDIRECT_KEEP_VERB = 307 +HTTP_STATUS_BAD_REQUEST = 400 +HTTP_STATUS_DENIED = 401 +HTTP_STATUS_PAYMENT_REQ = 402 +HTTP_STATUS_FORBIDDEN = 403 +HTTP_STATUS_NOT_FOUND = 404 +HTTP_STATUS_BAD_METHOD = 405 +HTTP_STATUS_NONE_ACCEPTABLE = 406 +HTTP_STATUS_PROXY_AUTH_REQ = 407 +HTTP_STATUS_REQUEST_TIMEOUT = 408 +HTTP_STATUS_CONFLICT = 409 +HTTP_STATUS_GONE = 410 +HTTP_STATUS_LENGTH_REQUIRED = 411 +HTTP_STATUS_PRECOND_FAILED = 412 +HTTP_STATUS_REQUEST_TOO_LARGE = 413 +HTTP_STATUS_URI_TOO_LONG = 414 +HTTP_STATUS_UNSUPPORTED_MEDIA = 415 +HTTP_STATUS_RETRY_WITH = 449 +HTTP_STATUS_SERVER_ERROR = 500 +HTTP_STATUS_NOT_SUPPORTED = 501 +HTTP_STATUS_BAD_GATEWAY = 502 +HTTP_STATUS_SERVICE_UNAVAIL = 503 +HTTP_STATUS_GATEWAY_TIMEOUT = 504 +HTTP_STATUS_VERSION_NOT_SUP = 505 +HTTP_STATUS_FIRST = HTTP_STATUS_CONTINUE +HTTP_STATUS_LAST = HTTP_STATUS_VERSION_NOT_SUP +WINHTTP_ADDREQ_INDEX_MASK = 0x0000FFFF +WINHTTP_ADDREQ_FLAGS_MASK = (-65536) +WINHTTP_ADDREQ_FLAG_ADD_IF_NEW = 0x10000000 +WINHTTP_ADDREQ_FLAG_ADD = 0x20000000 +WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA = 0x40000000 +WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON = 0x01000000 +WINHTTP_ADDREQ_FLAG_COALESCE = WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA +WINHTTP_ADDREQ_FLAG_REPLACE = (-2147483648) +WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH = 0 +WINHTTP_ERROR_BASE = 12000 +ERROR_WINHTTP_OUT_OF_HANDLES = (WINHTTP_ERROR_BASE + 1) +ERROR_WINHTTP_TIMEOUT = (WINHTTP_ERROR_BASE + 2) +ERROR_WINHTTP_INTERNAL_ERROR = (WINHTTP_ERROR_BASE + 4) +ERROR_WINHTTP_INVALID_URL = (WINHTTP_ERROR_BASE + 5) +ERROR_WINHTTP_UNRECOGNIZED_SCHEME = (WINHTTP_ERROR_BASE + 6) +ERROR_WINHTTP_NAME_NOT_RESOLVED = (WINHTTP_ERROR_BASE + 7) +ERROR_WINHTTP_INVALID_OPTION = (WINHTTP_ERROR_BASE + 9) +ERROR_WINHTTP_OPTION_NOT_SETTABLE = (WINHTTP_ERROR_BASE + 11) +ERROR_WINHTTP_SHUTDOWN = (WINHTTP_ERROR_BASE + 12) +ERROR_WINHTTP_LOGIN_FAILURE = (WINHTTP_ERROR_BASE + 15) +ERROR_WINHTTP_OPERATION_CANCELLED = (WINHTTP_ERROR_BASE + 17) +ERROR_WINHTTP_INCORRECT_HANDLE_TYPE = (WINHTTP_ERROR_BASE + 18) +ERROR_WINHTTP_INCORRECT_HANDLE_STATE = (WINHTTP_ERROR_BASE + 19) +ERROR_WINHTTP_CANNOT_CONNECT = (WINHTTP_ERROR_BASE + 29) +ERROR_WINHTTP_CONNECTION_ERROR = (WINHTTP_ERROR_BASE + 30) +ERROR_WINHTTP_RESEND_REQUEST = (WINHTTP_ERROR_BASE + 32) +ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED = (WINHTTP_ERROR_BASE + 44) +ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN = (WINHTTP_ERROR_BASE + 100) +ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND = (WINHTTP_ERROR_BASE + 101) +ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND = (WINHTTP_ERROR_BASE + 102) +ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN = (WINHTTP_ERROR_BASE + 103) +ERROR_WINHTTP_HEADER_NOT_FOUND = (WINHTTP_ERROR_BASE + 150) +ERROR_WINHTTP_INVALID_SERVER_RESPONSE = (WINHTTP_ERROR_BASE + 152) +ERROR_WINHTTP_INVALID_HEADER = (WINHTTP_ERROR_BASE + 153) +ERROR_WINHTTP_INVALID_QUERY_REQUEST = (WINHTTP_ERROR_BASE + 154) +ERROR_WINHTTP_HEADER_ALREADY_EXISTS = (WINHTTP_ERROR_BASE + 155) +ERROR_WINHTTP_REDIRECT_FAILED = (WINHTTP_ERROR_BASE + 156) +ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR = (WINHTTP_ERROR_BASE + 178) +ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT = (WINHTTP_ERROR_BASE + 166) +ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT = (WINHTTP_ERROR_BASE + 167) +ERROR_WINHTTP_NOT_INITIALIZED = (WINHTTP_ERROR_BASE + 172) +ERROR_WINHTTP_SECURE_FAILURE = (WINHTTP_ERROR_BASE + 175) +ERROR_WINHTTP_SECURE_CERT_DATE_INVALID = (WINHTTP_ERROR_BASE + 37) +ERROR_WINHTTP_SECURE_CERT_CN_INVALID = (WINHTTP_ERROR_BASE + 38) +ERROR_WINHTTP_SECURE_INVALID_CA = (WINHTTP_ERROR_BASE + 45) +ERROR_WINHTTP_SECURE_CERT_REV_FAILED = (WINHTTP_ERROR_BASE + 57) +ERROR_WINHTTP_SECURE_CHANNEL_ERROR = (WINHTTP_ERROR_BASE + 157) +ERROR_WINHTTP_SECURE_INVALID_CERT = (WINHTTP_ERROR_BASE + 169) +ERROR_WINHTTP_SECURE_CERT_REVOKED = (WINHTTP_ERROR_BASE + 170) +ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE = (WINHTTP_ERROR_BASE + 179) +ERROR_WINHTTP_AUTODETECTION_FAILED = (WINHTTP_ERROR_BASE + 180) +ERROR_WINHTTP_HEADER_COUNT_EXCEEDED = (WINHTTP_ERROR_BASE + 181) +ERROR_WINHTTP_HEADER_SIZE_OVERFLOW = (WINHTTP_ERROR_BASE + 182) +ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW = (WINHTTP_ERROR_BASE + 183) +ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW = (WINHTTP_ERROR_BASE + 184) +ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY = (WINHTTP_ERROR_BASE + 185) +ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY = (WINHTTP_ERROR_BASE + 186) +WINHTTP_ERROR_LAST = (WINHTTP_ERROR_BASE + 186) + +WINHTTP_NO_PROXY_NAME = None +WINHTTP_NO_PROXY_BYPASS = None +WINHTTP_NO_REFERER = None +WINHTTP_DEFAULT_ACCEPT_TYPES = None +WINHTTP_NO_ADDITIONAL_HEADERS = None +WINHTTP_NO_REQUEST_DATA = None diff --git a/Lib/site-packages/win32/lib/win32netcon.py b/Lib/site-packages/win32/lib/win32netcon.py new file mode 100644 index 0000000..568f472 --- /dev/null +++ b/Lib/site-packages/win32/lib/win32netcon.py @@ -0,0 +1,655 @@ +# Generated by h2py from lmaccess.h + +# Included from lmcons.h +CNLEN = 15 +LM20_CNLEN = 15 +DNLEN = CNLEN +LM20_DNLEN = LM20_CNLEN +UNCLEN = (CNLEN+2) +LM20_UNCLEN = (LM20_CNLEN+2) +NNLEN = 80 +LM20_NNLEN = 12 +RMLEN = (UNCLEN+1+NNLEN) +LM20_RMLEN = (LM20_UNCLEN+1+LM20_NNLEN) +SNLEN = 80 +LM20_SNLEN = 15 +STXTLEN = 256 +LM20_STXTLEN = 63 +PATHLEN = 256 +LM20_PATHLEN = 256 +DEVLEN = 80 +LM20_DEVLEN = 8 +EVLEN = 16 +UNLEN = 256 +LM20_UNLEN = 20 +GNLEN = UNLEN +LM20_GNLEN = LM20_UNLEN +PWLEN = 256 +LM20_PWLEN = 14 +SHPWLEN = 8 +CLTYPE_LEN = 12 +MAXCOMMENTSZ = 256 +LM20_MAXCOMMENTSZ = 48 +QNLEN = NNLEN +LM20_QNLEN = LM20_NNLEN +ALERTSZ = 128 +NETBIOS_NAME_LEN = 16 +CRYPT_KEY_LEN = 7 +CRYPT_TXT_LEN = 8 +ENCRYPTED_PWLEN = 16 +SESSION_PWLEN = 24 +SESSION_CRYPT_KLEN = 21 +PARMNUM_ALL = 0 +PARM_ERROR_NONE = 0 +PARMNUM_BASE_INFOLEVEL = 1000 +NULL = 0 +PLATFORM_ID_DOS = 300 +PLATFORM_ID_OS2 = 400 +PLATFORM_ID_NT = 500 +PLATFORM_ID_OSF = 600 +PLATFORM_ID_VMS = 700 +MAX_LANMAN_MESSAGE_ID = 5799 +UF_SCRIPT = 1 +UF_ACCOUNTDISABLE = 2 +UF_HOMEDIR_REQUIRED = 8 +UF_LOCKOUT = 16 +UF_PASSWD_NOTREQD = 32 +UF_PASSWD_CANT_CHANGE = 64 +UF_TEMP_DUPLICATE_ACCOUNT = 256 +UF_NORMAL_ACCOUNT = 512 +UF_INTERDOMAIN_TRUST_ACCOUNT = 2048 +UF_WORKSTATION_TRUST_ACCOUNT = 4096 +UF_SERVER_TRUST_ACCOUNT = 8192 +UF_MACHINE_ACCOUNT_MASK = ( UF_INTERDOMAIN_TRUST_ACCOUNT | \ + UF_WORKSTATION_TRUST_ACCOUNT | \ + UF_SERVER_TRUST_ACCOUNT ) +UF_ACCOUNT_TYPE_MASK = ( \ + UF_TEMP_DUPLICATE_ACCOUNT | \ + UF_NORMAL_ACCOUNT | \ + UF_INTERDOMAIN_TRUST_ACCOUNT | \ + UF_WORKSTATION_TRUST_ACCOUNT | \ + UF_SERVER_TRUST_ACCOUNT \ + ) +UF_DONT_EXPIRE_PASSWD = 65536 +UF_MNS_LOGON_ACCOUNT = 131072 +UF_SETTABLE_BITS = ( \ + UF_SCRIPT | \ + UF_ACCOUNTDISABLE | \ + UF_LOCKOUT | \ + UF_HOMEDIR_REQUIRED | \ + UF_PASSWD_NOTREQD | \ + UF_PASSWD_CANT_CHANGE | \ + UF_ACCOUNT_TYPE_MASK | \ + UF_DONT_EXPIRE_PASSWD | \ + UF_MNS_LOGON_ACCOUNT \ + ) +FILTER_TEMP_DUPLICATE_ACCOUNT = (1) +FILTER_NORMAL_ACCOUNT = (2) +FILTER_INTERDOMAIN_TRUST_ACCOUNT = (8) +FILTER_WORKSTATION_TRUST_ACCOUNT = (16) +FILTER_SERVER_TRUST_ACCOUNT = (32) +LG_INCLUDE_INDIRECT = (1) +AF_OP_PRINT = 1 +AF_OP_COMM = 2 +AF_OP_SERVER = 4 +AF_OP_ACCOUNTS = 8 +AF_SETTABLE_BITS = (AF_OP_PRINT | AF_OP_COMM | \ + AF_OP_SERVER | AF_OP_ACCOUNTS) +UAS_ROLE_STANDALONE = 0 +UAS_ROLE_MEMBER = 1 +UAS_ROLE_BACKUP = 2 +UAS_ROLE_PRIMARY = 3 +USER_NAME_PARMNUM = 1 +USER_PASSWORD_PARMNUM = 3 +USER_PASSWORD_AGE_PARMNUM = 4 +USER_PRIV_PARMNUM = 5 +USER_HOME_DIR_PARMNUM = 6 +USER_COMMENT_PARMNUM = 7 +USER_FLAGS_PARMNUM = 8 +USER_SCRIPT_PATH_PARMNUM = 9 +USER_AUTH_FLAGS_PARMNUM = 10 +USER_FULL_NAME_PARMNUM = 11 +USER_USR_COMMENT_PARMNUM = 12 +USER_PARMS_PARMNUM = 13 +USER_WORKSTATIONS_PARMNUM = 14 +USER_LAST_LOGON_PARMNUM = 15 +USER_LAST_LOGOFF_PARMNUM = 16 +USER_ACCT_EXPIRES_PARMNUM = 17 +USER_MAX_STORAGE_PARMNUM = 18 +USER_UNITS_PER_WEEK_PARMNUM = 19 +USER_LOGON_HOURS_PARMNUM = 20 +USER_PAD_PW_COUNT_PARMNUM = 21 +USER_NUM_LOGONS_PARMNUM = 22 +USER_LOGON_SERVER_PARMNUM = 23 +USER_COUNTRY_CODE_PARMNUM = 24 +USER_CODE_PAGE_PARMNUM = 25 +USER_PRIMARY_GROUP_PARMNUM = 51 +USER_PROFILE = 52 +USER_PROFILE_PARMNUM = 52 +USER_HOME_DIR_DRIVE_PARMNUM = 53 +USER_NAME_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_NAME_PARMNUM) +USER_PASSWORD_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_PASSWORD_PARMNUM) +USER_PASSWORD_AGE_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_PASSWORD_AGE_PARMNUM) +USER_PRIV_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_PRIV_PARMNUM) +USER_HOME_DIR_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_HOME_DIR_PARMNUM) +USER_COMMENT_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_COMMENT_PARMNUM) +USER_FLAGS_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_FLAGS_PARMNUM) +USER_SCRIPT_PATH_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_SCRIPT_PATH_PARMNUM) +USER_AUTH_FLAGS_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_AUTH_FLAGS_PARMNUM) +USER_FULL_NAME_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_FULL_NAME_PARMNUM) +USER_USR_COMMENT_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_USR_COMMENT_PARMNUM) +USER_PARMS_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_PARMS_PARMNUM) +USER_WORKSTATIONS_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_WORKSTATIONS_PARMNUM) +USER_LAST_LOGON_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_LAST_LOGON_PARMNUM) +USER_LAST_LOGOFF_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_LAST_LOGOFF_PARMNUM) +USER_ACCT_EXPIRES_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_ACCT_EXPIRES_PARMNUM) +USER_MAX_STORAGE_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_MAX_STORAGE_PARMNUM) +USER_UNITS_PER_WEEK_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_UNITS_PER_WEEK_PARMNUM) +USER_LOGON_HOURS_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_LOGON_HOURS_PARMNUM) +USER_PAD_PW_COUNT_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_PAD_PW_COUNT_PARMNUM) +USER_NUM_LOGONS_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_NUM_LOGONS_PARMNUM) +USER_LOGON_SERVER_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_LOGON_SERVER_PARMNUM) +USER_COUNTRY_CODE_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_COUNTRY_CODE_PARMNUM) +USER_CODE_PAGE_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_CODE_PAGE_PARMNUM) +USER_PRIMARY_GROUP_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_PRIMARY_GROUP_PARMNUM) +USER_HOME_DIR_DRIVE_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + USER_HOME_DIR_DRIVE_PARMNUM) +NULL_USERSETINFO_PASSWD = " " +UNITS_PER_DAY = 24 +UNITS_PER_WEEK = UNITS_PER_DAY * 7 +USER_PRIV_MASK = 3 +USER_PRIV_GUEST = 0 +USER_PRIV_USER = 1 +USER_PRIV_ADMIN = 2 +MAX_PASSWD_LEN = PWLEN +DEF_MIN_PWLEN = 6 +DEF_PWUNIQUENESS = 5 +DEF_MAX_PWHIST = 8 +DEF_MAX_BADPW = 0 +VALIDATED_LOGON = 0 +PASSWORD_EXPIRED = 2 +NON_VALIDATED_LOGON = 3 +VALID_LOGOFF = 1 +MODALS_MIN_PASSWD_LEN_PARMNUM = 1 +MODALS_MAX_PASSWD_AGE_PARMNUM = 2 +MODALS_MIN_PASSWD_AGE_PARMNUM = 3 +MODALS_FORCE_LOGOFF_PARMNUM = 4 +MODALS_PASSWD_HIST_LEN_PARMNUM = 5 +MODALS_ROLE_PARMNUM = 6 +MODALS_PRIMARY_PARMNUM = 7 +MODALS_DOMAIN_NAME_PARMNUM = 8 +MODALS_DOMAIN_ID_PARMNUM = 9 +MODALS_LOCKOUT_DURATION_PARMNUM = 10 +MODALS_LOCKOUT_OBSERVATION_WINDOW_PARMNUM = 11 +MODALS_LOCKOUT_THRESHOLD_PARMNUM = 12 +MODALS_MIN_PASSWD_LEN_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + MODALS_MIN_PASSWD_LEN_PARMNUM) +MODALS_MAX_PASSWD_AGE_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + MODALS_MAX_PASSWD_AGE_PARMNUM) +MODALS_MIN_PASSWD_AGE_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + MODALS_MIN_PASSWD_AGE_PARMNUM) +MODALS_FORCE_LOGOFF_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + MODALS_FORCE_LOGOFF_PARMNUM) +MODALS_PASSWD_HIST_LEN_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + MODALS_PASSWD_HIST_LEN_PARMNUM) +MODALS_ROLE_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + MODALS_ROLE_PARMNUM) +MODALS_PRIMARY_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + MODALS_PRIMARY_PARMNUM) +MODALS_DOMAIN_NAME_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + MODALS_DOMAIN_NAME_PARMNUM) +MODALS_DOMAIN_ID_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + MODALS_DOMAIN_ID_PARMNUM) +GROUPIDMASK = 32768 +GROUP_ALL_PARMNUM = 0 +GROUP_NAME_PARMNUM = 1 +GROUP_COMMENT_PARMNUM = 2 +GROUP_ATTRIBUTES_PARMNUM = 3 +GROUP_ALL_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + GROUP_ALL_PARMNUM) +GROUP_NAME_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + GROUP_NAME_PARMNUM) +GROUP_COMMENT_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + GROUP_COMMENT_PARMNUM) +GROUP_ATTRIBUTES_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + GROUP_ATTRIBUTES_PARMNUM) +LOCALGROUP_NAME_PARMNUM = 1 +LOCALGROUP_COMMENT_PARMNUM = 2 +MAXPERMENTRIES = 64 +ACCESS_NONE = 0 +ACCESS_READ = 1 +ACCESS_WRITE = 2 +ACCESS_CREATE = 4 +ACCESS_EXEC = 8 +ACCESS_DELETE = 16 +ACCESS_ATRIB = 32 +ACCESS_PERM = 64 +ACCESS_GROUP = 32768 +ACCESS_AUDIT = 1 +ACCESS_SUCCESS_OPEN = 16 +ACCESS_SUCCESS_WRITE = 32 +ACCESS_SUCCESS_DELETE = 64 +ACCESS_SUCCESS_ACL = 128 +ACCESS_SUCCESS_MASK = 240 +ACCESS_FAIL_OPEN = 256 +ACCESS_FAIL_WRITE = 512 +ACCESS_FAIL_DELETE = 1024 +ACCESS_FAIL_ACL = 2048 +ACCESS_FAIL_MASK = 3840 +ACCESS_FAIL_SHIFT = 4 +ACCESS_RESOURCE_NAME_PARMNUM = 1 +ACCESS_ATTR_PARMNUM = 2 +ACCESS_COUNT_PARMNUM = 3 +ACCESS_ACCESS_LIST_PARMNUM = 4 +ACCESS_RESOURCE_NAME_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + ACCESS_RESOURCE_NAME_PARMNUM) +ACCESS_ATTR_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + ACCESS_ATTR_PARMNUM) +ACCESS_COUNT_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + ACCESS_COUNT_PARMNUM) +ACCESS_ACCESS_LIST_INFOLEVEL = \ + (PARMNUM_BASE_INFOLEVEL + ACCESS_ACCESS_LIST_PARMNUM) +ACCESS_LETTERS = "RWCXDAP " +NETLOGON_CONTROL_QUERY = 1 +NETLOGON_CONTROL_REPLICATE = 2 +NETLOGON_CONTROL_SYNCHRONIZE = 3 +NETLOGON_CONTROL_PDC_REPLICATE = 4 +NETLOGON_CONTROL_REDISCOVER = 5 +NETLOGON_CONTROL_TC_QUERY = 6 +NETLOGON_CONTROL_TRANSPORT_NOTIFY = 7 +NETLOGON_CONTROL_FIND_USER = 8 +NETLOGON_CONTROL_UNLOAD_NETLOGON_DLL = 65531 +NETLOGON_CONTROL_BACKUP_CHANGE_LOG = 65532 +NETLOGON_CONTROL_TRUNCATE_LOG = 65533 +NETLOGON_CONTROL_SET_DBFLAG = 65534 +NETLOGON_CONTROL_BREAKPOINT = 65535 +NETLOGON_REPLICATION_NEEDED = 1 +NETLOGON_REPLICATION_IN_PROGRESS = 2 +NETLOGON_FULL_SYNC_REPLICATION = 4 +NETLOGON_REDO_NEEDED = 8 + +###################### +# Manual stuff + +TEXT=lambda x:x + +MAX_PREFERRED_LENGTH = -1 +PARM_ERROR_UNKNOWN = -1 +MESSAGE_FILENAME = TEXT("NETMSG") +OS2MSG_FILENAME = TEXT("BASE") +HELP_MSG_FILENAME = TEXT("NETH") +BACKUP_MSG_FILENAME = TEXT("BAK.MSG") +TIMEQ_FOREVER = -1 +USER_MAXSTORAGE_UNLIMITED = -1 +USER_NO_LOGOFF = -1 +DEF_MAX_PWAGE = TIMEQ_FOREVER +DEF_MIN_PWAGE = 0 +DEF_FORCE_LOGOFF = -1 +ONE_DAY = 1*24*3600 +GROUP_SPECIALGRP_USERS = "USERS" +GROUP_SPECIALGRP_ADMINS = "ADMINS" +GROUP_SPECIALGRP_GUESTS = "GUESTS" +GROUP_SPECIALGRP_LOCAL = "LOCAL" +ACCESS_ALL = ( ACCESS_READ | ACCESS_WRITE | ACCESS_CREATE | ACCESS_EXEC | ACCESS_DELETE | ACCESS_ATRIB | ACCESS_PERM ) + +# From lmserver.h +SV_PLATFORM_ID_OS2 = 400 +SV_PLATFORM_ID_NT = 500 +MAJOR_VERSION_MASK = 15 +SV_TYPE_WORKSTATION = 1 +SV_TYPE_SERVER = 2 +SV_TYPE_SQLSERVER = 4 +SV_TYPE_DOMAIN_CTRL = 8 +SV_TYPE_DOMAIN_BAKCTRL = 16 +SV_TYPE_TIME_SOURCE = 32 +SV_TYPE_AFP = 64 +SV_TYPE_NOVELL = 128 +SV_TYPE_DOMAIN_MEMBER = 256 +SV_TYPE_PRINTQ_SERVER = 512 +SV_TYPE_DIALIN_SERVER = 1024 +SV_TYPE_XENIX_SERVER = 2048 +SV_TYPE_SERVER_UNIX = SV_TYPE_XENIX_SERVER +SV_TYPE_NT = 4096 +SV_TYPE_WFW = 8192 +SV_TYPE_SERVER_MFPN = 16384 +SV_TYPE_SERVER_NT = 32768 +SV_TYPE_POTENTIAL_BROWSER = 65536 +SV_TYPE_BACKUP_BROWSER = 131072 +SV_TYPE_MASTER_BROWSER = 262144 +SV_TYPE_DOMAIN_MASTER = 524288 +SV_TYPE_SERVER_OSF = 1048576 +SV_TYPE_SERVER_VMS = 2097152 +SV_TYPE_WINDOWS = 4194304 +SV_TYPE_DFS = 8388608 +SV_TYPE_CLUSTER_NT = 16777216 +SV_TYPE_DCE = 268435456 +SV_TYPE_ALTERNATE_XPORT = 536870912 +SV_TYPE_LOCAL_LIST_ONLY = 1073741824 +SV_TYPE_DOMAIN_ENUM = -2147483648 +SV_TYPE_ALL = -1 +SV_NODISC = -1 +SV_USERSECURITY = 1 +SV_SHARESECURITY = 0 +SV_HIDDEN = 1 +SV_VISIBLE = 0 +SV_PLATFORM_ID_PARMNUM = 101 +SV_NAME_PARMNUM = 102 +SV_VERSION_MAJOR_PARMNUM = 103 +SV_VERSION_MINOR_PARMNUM = 104 +SV_TYPE_PARMNUM = 105 +SV_COMMENT_PARMNUM = 5 +SV_USERS_PARMNUM = 107 +SV_DISC_PARMNUM = 10 +SV_HIDDEN_PARMNUM = 16 +SV_ANNOUNCE_PARMNUM = 17 +SV_ANNDELTA_PARMNUM = 18 +SV_USERPATH_PARMNUM = 112 +SV_ULIST_MTIME_PARMNUM = 401 +SV_GLIST_MTIME_PARMNUM = 402 +SV_ALIST_MTIME_PARMNUM = 403 +SV_ALERTS_PARMNUM = 11 +SV_SECURITY_PARMNUM = 405 +SV_NUMADMIN_PARMNUM = 406 +SV_LANMASK_PARMNUM = 407 +SV_GUESTACC_PARMNUM = 408 +SV_CHDEVQ_PARMNUM = 410 +SV_CHDEVJOBS_PARMNUM = 411 +SV_CONNECTIONS_PARMNUM = 412 +SV_SHARES_PARMNUM = 413 +SV_OPENFILES_PARMNUM = 414 +SV_SESSREQS_PARMNUM = 417 +SV_ACTIVELOCKS_PARMNUM = 419 +SV_NUMREQBUF_PARMNUM = 420 +SV_NUMBIGBUF_PARMNUM = 422 +SV_NUMFILETASKS_PARMNUM = 423 +SV_ALERTSCHED_PARMNUM = 37 +SV_ERRORALERT_PARMNUM = 38 +SV_LOGONALERT_PARMNUM = 39 +SV_ACCESSALERT_PARMNUM = 40 +SV_DISKALERT_PARMNUM = 41 +SV_NETIOALERT_PARMNUM = 42 +SV_MAXAUDITSZ_PARMNUM = 43 +SV_SRVHEURISTICS_PARMNUM = 431 +SV_SESSOPENS_PARMNUM = 501 +SV_SESSVCS_PARMNUM = 502 +SV_OPENSEARCH_PARMNUM = 503 +SV_SIZREQBUF_PARMNUM = 504 +SV_INITWORKITEMS_PARMNUM = 505 +SV_MAXWORKITEMS_PARMNUM = 506 +SV_RAWWORKITEMS_PARMNUM = 507 +SV_IRPSTACKSIZE_PARMNUM = 508 +SV_MAXRAWBUFLEN_PARMNUM = 509 +SV_SESSUSERS_PARMNUM = 510 +SV_SESSCONNS_PARMNUM = 511 +SV_MAXNONPAGEDMEMORYUSAGE_PARMNUM = 512 +SV_MAXPAGEDMEMORYUSAGE_PARMNUM = 513 +SV_ENABLESOFTCOMPAT_PARMNUM = 514 +SV_ENABLEFORCEDLOGOFF_PARMNUM = 515 +SV_TIMESOURCE_PARMNUM = 516 +SV_ACCEPTDOWNLEVELAPIS_PARMNUM = 517 +SV_LMANNOUNCE_PARMNUM = 518 +SV_DOMAIN_PARMNUM = 519 +SV_MAXCOPYREADLEN_PARMNUM = 520 +SV_MAXCOPYWRITELEN_PARMNUM = 521 +SV_MINKEEPSEARCH_PARMNUM = 522 +SV_MAXKEEPSEARCH_PARMNUM = 523 +SV_MINKEEPCOMPLSEARCH_PARMNUM = 524 +SV_MAXKEEPCOMPLSEARCH_PARMNUM = 525 +SV_THREADCOUNTADD_PARMNUM = 526 +SV_NUMBLOCKTHREADS_PARMNUM = 527 +SV_SCAVTIMEOUT_PARMNUM = 528 +SV_MINRCVQUEUE_PARMNUM = 529 +SV_MINFREEWORKITEMS_PARMNUM = 530 +SV_XACTMEMSIZE_PARMNUM = 531 +SV_THREADPRIORITY_PARMNUM = 532 +SV_MAXMPXCT_PARMNUM = 533 +SV_OPLOCKBREAKWAIT_PARMNUM = 534 +SV_OPLOCKBREAKRESPONSEWAIT_PARMNUM = 535 +SV_ENABLEOPLOCKS_PARMNUM = 536 +SV_ENABLEOPLOCKFORCECLOSE_PARMNUM = 537 +SV_ENABLEFCBOPENS_PARMNUM = 538 +SV_ENABLERAW_PARMNUM = 539 +SV_ENABLESHAREDNETDRIVES_PARMNUM = 540 +SV_MINFREECONNECTIONS_PARMNUM = 541 +SV_MAXFREECONNECTIONS_PARMNUM = 542 +SV_INITSESSTABLE_PARMNUM = 543 +SV_INITCONNTABLE_PARMNUM = 544 +SV_INITFILETABLE_PARMNUM = 545 +SV_INITSEARCHTABLE_PARMNUM = 546 +SV_ALERTSCHEDULE_PARMNUM = 547 +SV_ERRORTHRESHOLD_PARMNUM = 548 +SV_NETWORKERRORTHRESHOLD_PARMNUM = 549 +SV_DISKSPACETHRESHOLD_PARMNUM = 550 +SV_MAXLINKDELAY_PARMNUM = 552 +SV_MINLINKTHROUGHPUT_PARMNUM = 553 +SV_LINKINFOVALIDTIME_PARMNUM = 554 +SV_SCAVQOSINFOUPDATETIME_PARMNUM = 555 +SV_MAXWORKITEMIDLETIME_PARMNUM = 556 +SV_MAXRAWWORKITEMS_PARMNUM = 557 +SV_PRODUCTTYPE_PARMNUM = 560 +SV_SERVERSIZE_PARMNUM = 561 +SV_CONNECTIONLESSAUTODISC_PARMNUM = 562 +SV_SHARINGVIOLATIONRETRIES_PARMNUM = 563 +SV_SHARINGVIOLATIONDELAY_PARMNUM = 564 +SV_MAXGLOBALOPENSEARCH_PARMNUM = 565 +SV_REMOVEDUPLICATESEARCHES_PARMNUM = 566 +SV_LOCKVIOLATIONRETRIES_PARMNUM = 567 +SV_LOCKVIOLATIONOFFSET_PARMNUM = 568 +SV_LOCKVIOLATIONDELAY_PARMNUM = 569 +SV_MDLREADSWITCHOVER_PARMNUM = 570 +SV_CACHEDOPENLIMIT_PARMNUM = 571 +SV_CRITICALTHREADS_PARMNUM = 572 +SV_RESTRICTNULLSESSACCESS_PARMNUM = 573 +SV_ENABLEWFW311DIRECTIPX_PARMNUM = 574 +SV_OTHERQUEUEAFFINITY_PARMNUM = 575 +SV_QUEUESAMPLESECS_PARMNUM = 576 +SV_BALANCECOUNT_PARMNUM = 577 +SV_PREFERREDAFFINITY_PARMNUM = 578 +SV_MAXFREERFCBS_PARMNUM = 579 +SV_MAXFREEMFCBS_PARMNUM = 580 +SV_MAXFREELFCBS_PARMNUM = 581 +SV_MAXFREEPAGEDPOOLCHUNKS_PARMNUM = 582 +SV_MINPAGEDPOOLCHUNKSIZE_PARMNUM = 583 +SV_MAXPAGEDPOOLCHUNKSIZE_PARMNUM = 584 +SV_SENDSFROMPREFERREDPROCESSOR_PARMNUM = 585 +SV_MAXTHREADSPERQUEUE_PARMNUM = 586 +SV_CACHEDDIRECTORYLIMIT_PARMNUM = 587 +SV_MAXCOPYLENGTH_PARMNUM = 588 +SV_ENABLEBULKTRANSFER_PARMNUM = 589 +SV_ENABLECOMPRESSION_PARMNUM = 590 +SV_AUTOSHAREWKS_PARMNUM = 591 +SV_AUTOSHARESERVER_PARMNUM = 592 +SV_ENABLESECURITYSIGNATURE_PARMNUM = 593 +SV_REQUIRESECURITYSIGNATURE_PARMNUM = 594 +SV_MINCLIENTBUFFERSIZE_PARMNUM = 595 +SV_CONNECTIONNOSESSIONSTIMEOUT_PARMNUM = 596 +SVI1_NUM_ELEMENTS = 5 +SVI2_NUM_ELEMENTS = 40 +SVI3_NUM_ELEMENTS = 44 +SW_AUTOPROF_LOAD_MASK = 1 +SW_AUTOPROF_SAVE_MASK = 2 +SV_MAX_SRV_HEUR_LEN = 32 +SV_USERS_PER_LICENSE = 5 +SVTI2_REMAP_PIPE_NAMES = 2 + +# Generated by h2py from lmshare.h +SHARE_NETNAME_PARMNUM = 1 +SHARE_TYPE_PARMNUM = 3 +SHARE_REMARK_PARMNUM = 4 +SHARE_PERMISSIONS_PARMNUM = 5 +SHARE_MAX_USES_PARMNUM = 6 +SHARE_CURRENT_USES_PARMNUM = 7 +SHARE_PATH_PARMNUM = 8 +SHARE_PASSWD_PARMNUM = 9 +SHARE_FILE_SD_PARMNUM = 501 +SHI1_NUM_ELEMENTS = 4 +SHI2_NUM_ELEMENTS = 10 +STYPE_DISKTREE = 0 +STYPE_PRINTQ = 1 +STYPE_DEVICE = 2 +STYPE_IPC = 3 +STYPE_SPECIAL = -2147483648 +SHI1005_FLAGS_DFS = 1 +SHI1005_FLAGS_DFS_ROOT = 2 +COW_PERMACHINE = 4 +COW_PERUSER = 8 +CSC_CACHEABLE = 16 +CSC_NOFLOWOPS = 32 +CSC_AUTO_INWARD = 64 +CSC_AUTO_OUTWARD = 128 +SHI1005_VALID_FLAGS_SET = ( CSC_CACHEABLE | \ + CSC_NOFLOWOPS | \ + CSC_AUTO_INWARD | \ + CSC_AUTO_OUTWARD| \ + COW_PERMACHINE | \ + COW_PERUSER ) +SHI1007_VALID_FLAGS_SET = SHI1005_VALID_FLAGS_SET +SESS_GUEST = 1 +SESS_NOENCRYPTION = 2 +SESI1_NUM_ELEMENTS = 8 +SESI2_NUM_ELEMENTS = 9 +PERM_FILE_READ = 1 +PERM_FILE_WRITE = 2 +PERM_FILE_CREATE = 4 + +# Generated by h2py from d:\mssdk\include\winnetwk.h +WNNC_NET_MSNET = 65536 +WNNC_NET_LANMAN = 131072 +WNNC_NET_NETWARE = 196608 +WNNC_NET_VINES = 262144 +WNNC_NET_10NET = 327680 +WNNC_NET_LOCUS = 393216 +WNNC_NET_SUN_PC_NFS = 458752 +WNNC_NET_LANSTEP = 524288 +WNNC_NET_9TILES = 589824 +WNNC_NET_LANTASTIC = 655360 +WNNC_NET_AS400 = 720896 +WNNC_NET_FTP_NFS = 786432 +WNNC_NET_PATHWORKS = 851968 +WNNC_NET_LIFENET = 917504 +WNNC_NET_POWERLAN = 983040 +WNNC_NET_BWNFS = 1048576 +WNNC_NET_COGENT = 1114112 +WNNC_NET_FARALLON = 1179648 +WNNC_NET_APPLETALK = 1245184 +WNNC_NET_INTERGRAPH = 1310720 +WNNC_NET_SYMFONET = 1376256 +WNNC_NET_CLEARCASE = 1441792 +WNNC_NET_FRONTIER = 1507328 +WNNC_NET_BMC = 1572864 +WNNC_NET_DCE = 1638400 +WNNC_NET_DECORB = 2097152 +WNNC_NET_PROTSTOR = 2162688 +WNNC_NET_FJ_REDIR = 2228224 +WNNC_NET_DISTINCT = 2293760 +WNNC_NET_TWINS = 2359296 +WNNC_NET_RDR2SAMPLE = 2424832 +RESOURCE_CONNECTED = 1 +RESOURCE_GLOBALNET = 2 +RESOURCE_REMEMBERED = 3 +RESOURCE_RECENT = 4 +RESOURCE_CONTEXT = 5 +RESOURCETYPE_ANY = 0 +RESOURCETYPE_DISK = 1 +RESOURCETYPE_PRINT = 2 +RESOURCETYPE_RESERVED = 8 +RESOURCETYPE_UNKNOWN = -1 +RESOURCEUSAGE_CONNECTABLE = 1 +RESOURCEUSAGE_CONTAINER = 2 +RESOURCEUSAGE_NOLOCALDEVICE = 4 +RESOURCEUSAGE_SIBLING = 8 +RESOURCEUSAGE_ATTACHED = 16 +RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED) +RESOURCEUSAGE_RESERVED = -2147483648 +RESOURCEDISPLAYTYPE_GENERIC = 0 +RESOURCEDISPLAYTYPE_DOMAIN = 1 +RESOURCEDISPLAYTYPE_SERVER = 2 +RESOURCEDISPLAYTYPE_SHARE = 3 +RESOURCEDISPLAYTYPE_FILE = 4 +RESOURCEDISPLAYTYPE_GROUP = 5 +RESOURCEDISPLAYTYPE_NETWORK = 6 +RESOURCEDISPLAYTYPE_ROOT = 7 +RESOURCEDISPLAYTYPE_SHAREADMIN = 8 +RESOURCEDISPLAYTYPE_DIRECTORY = 9 +RESOURCEDISPLAYTYPE_TREE = 10 +RESOURCEDISPLAYTYPE_NDSCONTAINER = 11 +NETPROPERTY_PERSISTENT = 1 +CONNECT_UPDATE_PROFILE = 1 +CONNECT_UPDATE_RECENT = 2 +CONNECT_TEMPORARY = 4 +CONNECT_INTERACTIVE = 8 +CONNECT_PROMPT = 16 +CONNECT_NEED_DRIVE = 32 +CONNECT_REFCOUNT = 64 +CONNECT_REDIRECT = 128 +CONNECT_LOCALDRIVE = 256 +CONNECT_CURRENT_MEDIA = 512 +CONNECT_DEFERRED = 1024 +CONNECT_RESERVED = -16777216 +CONNDLG_RO_PATH = 1 +CONNDLG_CONN_POINT = 2 +CONNDLG_USE_MRU = 4 +CONNDLG_HIDE_BOX = 8 +CONNDLG_PERSIST = 16 +CONNDLG_NOT_PERSIST = 32 +DISC_UPDATE_PROFILE = 1 +DISC_NO_FORCE = 64 +UNIVERSAL_NAME_INFO_LEVEL = 1 +REMOTE_NAME_INFO_LEVEL = 2 +WNFMT_MULTILINE = 1 +WNFMT_ABBREVIATED = 2 +WNFMT_INENUM = 16 +WNFMT_CONNECTION = 32 +NETINFO_DLL16 = 1 +NETINFO_DISKRED = 4 +NETINFO_PRINTERRED = 8 +RP_LOGON = 1 +RP_INIFILE = 2 +PP_DISPLAYERRORS = 1 +WNCON_FORNETCARD = 1 +WNCON_NOTROUTED = 2 +WNCON_SLOWLINK = 4 +WNCON_DYNAMIC = 8 + +## NETSETUP_NAME_TYPE, used with NetValidateName +NetSetupUnknown = 0 +NetSetupMachine = 1 +NetSetupWorkgroup = 2 +NetSetupDomain = 3 +NetSetupNonExistentDomain = 4 +NetSetupDnsMachine = 5 + +## NETSETUP_JOIN_STATUS, use with NetGetJoinInformation +NetSetupUnknownStatus = 0 +NetSetupUnjoined = 1 +NetSetupWorkgroupName = 2 +NetSetupDomainName = 3 + +NetValidateAuthentication = 1 +NetValidatePasswordChange = 2 +NetValidatePasswordReset = 3 diff --git a/Lib/site-packages/win32/lib/win32pdhquery.py b/Lib/site-packages/win32/lib/win32pdhquery.py new file mode 100644 index 0000000..054e275 --- /dev/null +++ b/Lib/site-packages/win32/lib/win32pdhquery.py @@ -0,0 +1,515 @@ +''' +Performance Data Helper (PDH) Query Classes + +Wrapper classes for end-users and high-level access to the PDH query +mechanisms. PDH is a win32-specific mechanism for accessing the +performance data made available by the system. The Python for Windows +PDH module does not implement the "Registry" interface, implementing +the more straightforward Query-based mechanism. + +The basic idea of a PDH Query is an object which can query the system +about the status of any number of "counters." The counters are paths +to a particular piece of performance data. For instance, the path +'\\Memory\\Available Bytes' describes just about exactly what it says +it does, the amount of free memory on the default computer expressed +in Bytes. These paths can be considerably more complex than this, +but part of the point of this wrapper module is to hide that +complexity from the end-user/programmer. + +EXAMPLE: A more complex Path + '\\\\RAISTLIN\\PhysicalDisk(_Total)\\Avg. Disk Bytes/Read' + Raistlin --> Computer Name + PhysicalDisk --> Object Name + _Total --> The particular Instance (in this case, all instances, i.e. all drives) + Avg. Disk Bytes/Read --> The piece of data being monitored. + +EXAMPLE: Collecting Data with a Query + As an example, the following code implements a logger which allows the + user to choose what counters they would like to log, and logs those + counters for 30 seconds, at two-second intervals. + + query = Query() + query.addcounterbybrowsing() + query.collectdatafor(30,2) + + The data is now stored in a list of lists as: + query.curresults + + The counters(paths) which were used to collect the data are: + query.curpaths + + You can use the win32pdh.ParseCounterPath(path) utility function + to turn the paths into more easily read values for your task, or + write the data to a file, or do whatever you want with it. + +OTHER NOTABLE METHODS: + query.collectdatawhile(period) # start a logging thread for collecting data + query.collectdatawhile_stop() # signal the logging thread to stop logging + query.collectdata() # run the query only once + query.addperfcounter(object, counter, machine=None) # add a standard performance counter + query.addinstcounter(object, counter,machine=None,objtype = 'Process',volatile=1,format = win32pdh.PDH_FMT_LONG) # add a possibly volatile counter + +### Known bugs and limitations ### +Due to a problem with threading under the PythonWin interpreter, there +will be no data logged if the PythonWin window is not the foreground +application. Workaround: scripts using threading should be run in the +python.exe interpreter. + +The volatile-counter handlers are possibly buggy, they haven't been +tested to any extent. The wrapper Query makes it safe to pass invalid +paths (a -1 will be returned, or the Query will be totally ignored, +depending on the missing element), so you should be able to work around +the error by including all possible paths and filtering out the -1's. + +There is no way I know of to stop a thread which is currently sleeping, +so you have to wait until the thread in collectdatawhile is activated +again. This might become a problem in situations where the collection +period is multiple minutes (or hours, or whatever). + +Should make the win32pdh.ParseCounter function available to the Query +classes as a method or something similar, so that it can be accessed +by programmes that have just picked up an instance from somewhere. + +Should explicitly mention where QueryErrors can be raised, and create a +full test set to see if there are any uncaught win32api.error's still +hanging around. + +When using the python.exe interpreter, the addcounterbybrowsing- +generated browser window is often hidden behind other windows. No known +workaround other than Alt-tabing to reach the browser window. + +### Other References ### +The win32pdhutil module (which should be in the %pythonroot%/win32/lib +directory) provides quick-and-dirty utilities for one-off access to +variables from the PDH. Almost everything in that module can be done +with a Query object, but it provides task-oriented functions for a +number of common one-off tasks. + +If you can access the MS Developers Network Library, you can find +information about the PDH API as MS describes it. For a background article, +try: +http://msdn.microsoft.com/library/en-us/dnperfmo/html/msdn_pdhlib.asp + +The reference guide for the PDH API was last spotted at: +http://msdn.microsoft.com/library/en-us/perfmon/base/using_the_pdh_interface.asp + + +In general the Python version of the API is just a wrapper around the +Query-based version of this API (as far as I can see), so you can learn what +you need to from there. From what I understand, the MSDN Online +resources are available for the price of signing up for them. I can't +guarantee how long that's supposed to last. (Or anything for that +matter). +http://premium.microsoft.com/isapi/devonly/prodinfo/msdnprod/msdnlib.idc?theURL=/msdn/library/sdkdoc/perfdata_4982.htm + +The eventual plan is for my (Mike Fletcher's) Starship account to include +a section on NT Administration, and the Query is the first project +in this plan. There should be an article describing the creation of +a simple logger there, but the example above is 90% of the work of +that project, so don't sweat it if you don't find anything there. +(currently the account hasn't been set up). +http://starship.skyport.net/crew/mcfletch/ + +If you need to contact me immediately, (why I can't imagine), you can +email me at mcfletch@golden.net, or just post your question to the +Python newsgroup with a catchy subject line. +news:comp.lang.python + +### Other Stuff ### +The Query classes are by Mike Fletcher, with the working code +being corruptions of Mark Hammonds win32pdhutil module. + +Use at your own risk, no warranties, no guarantees, no assurances, +if you use it, you accept the risk of using it, etceteras. + +''' +# Feb 12, 98 - MH added "rawaddcounter" so caller can get exception details. + +import win32pdh, win32api,time, _thread,copy + +class BaseQuery: + ''' + Provides wrapped access to the Performance Data Helper query + objects, generally you should use the child class Query + unless you have need of doing weird things :) + + This class supports two major working paradigms. In the first, + you open the query, and run it as many times as you need, closing + the query when you're done with it. This is suitable for static + queries (ones where processes being monitored don't disappear). + + In the second, you allow the query to be opened each time and + closed afterward. This causes the base query object to be + destroyed after each call. Suitable for dynamic queries (ones + which watch processes which might be closed while watching.) + ''' + def __init__(self,paths=None): + ''' + The PDH Query object is initialised with a single, optional + list argument, that must be properly formatted PDH Counter + paths. Generally this list will only be provided by the class + when it is being unpickled (removed from storage). Normal + use is to call the class with no arguments and use the various + addcounter functions (particularly, for end user's, the use of + addcounterbybrowsing is the most common approach) You might + want to provide the list directly if you want to hard-code the + elements with which your query deals (and thereby avoid the + overhead of unpickling the class). + ''' + self.counters = [] + if paths: + self.paths = paths + else: + self.paths = [] + self._base = None + self.active = 0 + self.curpaths = [] + def addcounterbybrowsing(self, flags = win32pdh.PERF_DETAIL_WIZARD, windowtitle="Python Browser"): + ''' + Adds possibly multiple paths to the paths attribute of the query, + does this by calling the standard counter browsing dialogue. Within + this dialogue, find the counter you want to log, and click: Add, + repeat for every path you want to log, then click on close. The + paths are appended to the non-volatile paths list for this class, + subclasses may create a function which parses the paths and decides + (via heuristics) whether to add the path to the volatile or non-volatile + path list. + e.g.: + query.addcounter() + ''' + win32pdh.BrowseCounters(None,0, self.paths.append, flags, windowtitle) + def rawaddcounter(self,object, counter, instance = None, inum=-1, machine=None): + ''' + Adds a single counter path, without catching any exceptions. + + See addcounter for details. + ''' + path = win32pdh.MakeCounterPath( (machine,object,instance, None, inum,counter) ) + self.paths.append(path) + + def addcounter(self,object, counter, instance = None, inum=-1, machine=None): + ''' + Adds a single counter path to the paths attribute. Normally + this will be called by a child class' speciality functions, + rather than being called directly by the user. (Though it isn't + hard to call manually, since almost everything is given a default) + This method is only functional when the query is closed (or hasn't + yet been opened). This is to prevent conflict in multi-threaded + query applications). + e.g.: + query.addcounter('Memory','Available Bytes') + ''' + if not self.active: + try: + self.rawaddcounter(object, counter, instance, inum, machine) + return 0 + except win32api.error: + return -1 + else: + return -1 + + def open(self): + ''' + Build the base query object for this wrapper, + then add all of the counters required for the query. + Raise a QueryError if we can't complete the functions. + If we are already open, then do nothing. + ''' + if not self.active: # to prevent having multiple open queries + # curpaths are made accessible here because of the possibility of volatile paths + # which may be dynamically altered by subclasses. + self.curpaths = copy.copy(self.paths) + try: + base = win32pdh.OpenQuery() + for path in self.paths: + try: + self.counters.append(win32pdh.AddCounter(base, path)) + except win32api.error: # we passed a bad path + self.counters.append(0) + pass + self._base = base + self.active = 1 + return 0 # open succeeded + except: # if we encounter any errors, kill the Query + try: + self.killbase(base) + except NameError: # failed in creating query + pass + self.active = 0 + self.curpaths = [] + raise QueryError(self) + return 1 # already open + + def killbase(self,base=None): + ''' + ### This is not a public method + Mission critical function to kill the win32pdh objects held + by this object. User's should generally use the close method + instead of this method, in case a sub-class has overridden + close to provide some special functionality. + ''' + # Kill Pythonic references to the objects in this object's namespace + self._base = None + counters = self.counters + self.counters = [] + # we don't kill the curpaths for convenience, this allows the + # user to close a query and still access the last paths + self.active = 0 + # Now call the delete functions on all of the objects + try: + map(win32pdh.RemoveCounter,counters) + except: + pass + try: + win32pdh.CloseQuery(base) + except: + pass + del(counters) + del(base) + def close(self): + ''' + Makes certain that the underlying query object has been closed, + and that all counters have been removed from it. This is + important for reference counting. + You should only need to call close if you have previously called + open. The collectdata methods all can handle opening and + closing the query. Calling close multiple times is acceptable. + ''' + try: + self.killbase(self._base) + except AttributeError: + self.killbase() + __del__ = close + def collectdata(self,format = win32pdh.PDH_FMT_LONG): + ''' + Returns the formatted current values for the Query + ''' + if self._base: # we are currently open, don't change this + return self.collectdataslave(format) + else: # need to open and then close the _base, should be used by one-offs and elements tracking application instances + self.open() # will raise QueryError if couldn't open the query + temp = self.collectdataslave(format) + self.close() # will always close + return temp + def collectdataslave(self,format = win32pdh.PDH_FMT_LONG): + ''' + ### Not a public method + Called only when the Query is known to be open, runs over + the whole set of counters, appending results to the temp, + returns the values as a list. + ''' + try: + win32pdh.CollectQueryData(self._base) + temp = [] + for counter in self.counters: + ok = 0 + try: + if counter: + temp.append(win32pdh.GetFormattedCounterValue(counter, format)[1]) + ok = 1 + except win32api.error: + pass + if not ok: + temp.append(-1) # a better way to signal failure??? + return temp + except win32api.error: # will happen if, for instance, no counters are part of the query and we attempt to collect data for it. + return [-1] * len(self.counters) + # pickle functions + def __getinitargs__(self): + ''' + ### Not a public method + ''' + return (self.paths,) + +class Query(BaseQuery): + ''' + Performance Data Helper(PDH) Query object: + + Provides a wrapper around the native PDH query object which + allows for query reuse, query storage, and general maintenance + functions (adding counter paths in various ways being the most + obvious ones). + ''' + def __init__(self,*args,**namedargs): + ''' + The PDH Query object is initialised with a single, optional + list argument, that must be properly formatted PDH Counter + paths. Generally this list will only be provided by the class + when it is being unpickled (removed from storage). Normal + use is to call the class with no arguments and use the various + addcounter functions (particularly, for end user's, the use of + addcounterbybrowsing is the most common approach) You might + want to provide the list directly if you want to hard-code the + elements with which your query deals (and thereby avoid the + overhead of unpickling the class). + ''' + self.volatilecounters = [] + BaseQuery.__init__(*(self,)+args, **namedargs) + def addperfcounter(self, object, counter, machine=None): + ''' + A "Performance Counter" is a stable, known, common counter, + such as Memory, or Processor. The use of addperfcounter by + end-users is deprecated, since the use of + addcounterbybrowsing is considerably more flexible and general. + It is provided here to allow the easy development of scripts + which need to access variables so common we know them by name + (such as Memory|Available Bytes), and to provide symmetry with + the add inst counter method. + usage: + query.addperfcounter('Memory', 'Available Bytes') + It is just as easy to access addcounter directly, the following + has an identicle effect. + query.addcounter('Memory', 'Available Bytes') + ''' + BaseQuery.addcounter(self, object=object, counter=counter, machine=machine) + def addinstcounter(self, object, counter,machine=None,objtype = 'Process',volatile=1,format = win32pdh.PDH_FMT_LONG): + ''' + The purpose of using an instcounter is to track particular + instances of a counter object (e.g. a single processor, a single + running copy of a process). For instance, to track all python.exe + instances, you would need merely to ask: + query.addinstcounter('python','Virtual Bytes') + You can find the names of the objects and their available counters + by doing an addcounterbybrowsing() call on a query object (or by + looking in performance monitor's add dialog.) + + Beyond merely rearranging the call arguments to make more sense, + if the volatile flag is true, the instcounters also recalculate + the paths of the available instances on every call to open the + query. + ''' + if volatile: + self.volatilecounters.append((object,counter,machine,objtype,format)) + else: + self.paths[len(self.paths):] = self.getinstpaths(object,counter,machine,objtype,format) + + def getinstpaths(self,object,counter,machine=None,objtype='Process',format = win32pdh.PDH_FMT_LONG): + ''' + ### Not an end-user function + Calculate the paths for an instance object. Should alter + to allow processing for lists of object-counter pairs. + ''' + items, instances = win32pdh.EnumObjectItems(None,None,objtype, -1) + # find out how many instances of this element we have... + instances.sort() + try: + cur = instances.index(object) + except ValueError: + return [] # no instances of this object + temp = [object] + try: + while instances[cur+1] == object: + temp.append(object) + cur = cur+1 + except IndexError: # if we went over the end + pass + paths = [] + for ind in range(len(temp)): + # can this raise an error? + paths.append(win32pdh.MakeCounterPath( (machine,'Process',object,None,ind,counter) ) ) + return paths # should also return the number of elements for naming purposes + + def open(self,*args,**namedargs): + ''' + Explicitly open a query: + When you are needing to make multiple calls to the same query, + it is most efficient to open the query, run all of the calls, + then close the query, instead of having the collectdata method + automatically open and close the query each time it runs. + There are currently no arguments to open. + ''' + # do all the normal opening stuff, self._base is now the query object + BaseQuery.open(*(self,)+args, **namedargs) + # should rewrite getinstpaths to take a single tuple + paths = [] + for tup in self.volatilecounters: + paths[len(paths):] = self.getinstpaths(*tup) + for path in paths: + try: + self.counters.append(win32pdh.AddCounter(self._base, path)) + self.curpaths.append(path) # if we fail on the line above, this path won't be in the table or the counters + except win32api.error: + pass # again, what to do with a malformed path??? + def collectdatafor(self, totalperiod, period=1): + ''' + Non-threaded collection of performance data: + This method allows you to specify the total period for which you would + like to run the Query, and the time interval between individual + runs. The collected data is stored in query.curresults at the + _end_ of the run. The pathnames for the query are stored in + query.curpaths. + e.g.: + query.collectdatafor(30,2) + Will collect data for 30seconds at 2 second intervals + ''' + tempresults = [] + try: + self.open() + for ind in range(totalperiod/period): + tempresults.append(self.collectdata()) + time.sleep(period) + self.curresults = tempresults + finally: + self.close() + def collectdatawhile(self, period=1): + ''' + Threaded collection of performance data: + This method sets up a simple semaphor system for signalling + when you would like to start and stop a threaded data collection + method. The collection runs every period seconds until the + semaphor attribute is set to a non-true value (which normally + should be done by calling query.collectdatawhile_stop() .) + e.g.: + query.collectdatawhile(2) + # starts the query running, returns control to the caller immediately + # is collecting data every two seconds. + # do whatever you want to do while the thread runs, then call: + query.collectdatawhile_stop() + # when you want to deal with the data. It is generally a good idea + # to sleep for period seconds yourself, since the query will not copy + # the required data until the next iteration: + time.sleep(2) + # now you can access the data from the attributes of the query + query.curresults + query.curpaths + ''' + self.collectdatawhile_active = 1 + _thread.start_new_thread(self.collectdatawhile_slave,(period,)) + def collectdatawhile_stop(self): + ''' + Signals the collectdatawhile slave thread to stop collecting data + on the next logging iteration. + ''' + self.collectdatawhile_active = 0 + def collectdatawhile_slave(self, period): + ''' + ### Not a public function + Does the threaded work of collecting the data and storing it + in an attribute of the class. + ''' + tempresults = [] + try: + self.open() # also sets active, so can't be changed. + while self.collectdatawhile_active: + tempresults.append(self.collectdata()) + time.sleep(period) + self.curresults = tempresults + finally: + self.close() + + # pickle functions + def __getinitargs__(self): + return (self.paths,) + def __getstate__(self): + return self.volatilecounters + def __setstate__(self, volatilecounters): + self.volatilecounters = volatilecounters + + +class QueryError: + def __init__(self, query): + self.query = query + def __repr__(self): + return ''%repr(self.query) + __str__ = __repr__ + diff --git a/Lib/site-packages/win32/lib/win32pdhutil.py b/Lib/site-packages/win32/lib/win32pdhutil.py new file mode 100644 index 0000000..7f5af8b --- /dev/null +++ b/Lib/site-packages/win32/lib/win32pdhutil.py @@ -0,0 +1,168 @@ +"""Utilities for the win32 Performance Data Helper module + +Example: + To get a single bit of data: + >>> import win32pdhutil + >>> win32pdhutil.GetPerformanceAttributes("Memory", "Available Bytes") + 6053888 + >>> win32pdhutil.FindPerformanceAttributesByName("python", counter="Virtual Bytes") + [22278144] + + First example returns data which is not associated with any specific instance. + + The second example reads data for a specific instance - hence the list return - + it would return one result for each instance of Python running. + + In general, it can be tricky finding exactly the "name" of the data you wish to query. + Although you can use (None,None,(eg)"Memory", -1) to do this, + the easiest way is often to simply use PerfMon to find out the names. +""" + +import win32pdh, time + +error = win32pdh.error + +# Handle some localization issues. +# see http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/Q287/1/59.asp&NoWebContent=1 +# Build a map of english_counter_name: counter_id +counter_english_map = {} + +def find_pdh_counter_localized_name(english_name, machine_name = None): + if not counter_english_map: + import win32api, win32con + counter_reg_value = win32api.RegQueryValueEx(win32con.HKEY_PERFORMANCE_DATA, + "Counter 009") + counter_list = counter_reg_value[0] + for i in range(0, len(counter_list) - 1, 2): + try: + counter_id = int(counter_list[i]) + except ValueError: + continue + counter_english_map[counter_list[i+1].lower()] = counter_id + return win32pdh.LookupPerfNameByIndex(machine_name, counter_english_map[english_name.lower()]) + +def GetPerformanceAttributes(object, counter, instance = None, inum=-1, + format = win32pdh.PDH_FMT_LONG, machine=None): + # NOTE: Many counters require 2 samples to give accurate results, + # including "% Processor Time" (as by definition, at any instant, a + # thread's CPU usage is either 0 or 100). To read counters like this, + # you should copy this function, but keep the counter open, and call + # CollectQueryData() each time you need to know. + # See http://support.microsoft.com/default.aspx?scid=kb;EN-US;q262938 + # and http://msdn.microsoft.com/library/en-us/dnperfmo/html/perfmonpt2.asp + # My older explanation for this was that the "AddCounter" process forced + # the CPU to 100%, but the above makes more sense :) + path = win32pdh.MakeCounterPath( (machine,object,instance, None, inum,counter) ) + hq = win32pdh.OpenQuery() + try: + hc = win32pdh.AddCounter(hq, path) + try: + win32pdh.CollectQueryData(hq) + type, val = win32pdh.GetFormattedCounterValue(hc, format) + return val + finally: + win32pdh.RemoveCounter(hc) + finally: + win32pdh.CloseQuery(hq) + +def FindPerformanceAttributesByName(instanceName, object = None, + counter = None, + format = win32pdh.PDH_FMT_LONG, + machine = None, bRefresh=0): + """Find peformance attributes by (case insensitive) instance name. + + Given a process name, return a list with the requested attributes. + Most useful for returning a tuple of PIDs given a process name. + """ + if object is None: object = find_pdh_counter_localized_name("Process", machine) + if counter is None: counter = find_pdh_counter_localized_name("ID Process", machine) + if bRefresh: # PDH docs say this is how you do a refresh. + win32pdh.EnumObjects(None, machine, 0, 1) + instanceName = instanceName.lower() + items, instances = win32pdh.EnumObjectItems(None,None,object, -1) + # Track multiple instances. + instance_dict = {} + for instance in instances: + try: + instance_dict[instance] = instance_dict[instance] + 1 + except KeyError: + instance_dict[instance] = 0 + + ret = [] + for instance, max_instances in instance_dict.items(): + for inum in range(max_instances+1): + if instance.lower() == instanceName: + ret.append(GetPerformanceAttributes(object, counter, + instance, inum, format, + machine)) + return ret + +def ShowAllProcesses(): + object = find_pdh_counter_localized_name("Process") + items, instances = win32pdh.EnumObjectItems(None,None,object, + win32pdh.PERF_DETAIL_WIZARD) + # Need to track multiple instances of the same name. + instance_dict = {} + for instance in instances: + try: + instance_dict[instance] = instance_dict[instance] + 1 + except KeyError: + instance_dict[instance] = 0 + + # Bit of a hack to get useful info. + items = [find_pdh_counter_localized_name("ID Process")] + items[:5] + print("Process Name", ",".join(items)) + for instance, max_instances in instance_dict.items(): + for inum in range(max_instances+1): + hq = win32pdh.OpenQuery() + hcs = [] + for item in items: + path = win32pdh.MakeCounterPath( (None,object,instance, + None, inum, item) ) + hcs.append(win32pdh.AddCounter(hq, path)) + win32pdh.CollectQueryData(hq) + # as per http://support.microsoft.com/default.aspx?scid=kb;EN-US;q262938, some "%" based + # counters need two collections + time.sleep(0.01) + win32pdh.CollectQueryData(hq) + print("%-15s\t" % (instance[:15]), end=' ') + for hc in hcs: + type, val = win32pdh.GetFormattedCounterValue(hc, win32pdh.PDH_FMT_LONG) + print("%5d" % (val), end=' ') + win32pdh.RemoveCounter(hc) + print() + win32pdh.CloseQuery(hq) + +# NOTE: This BrowseCallback doesn't seem to work on Vista for markh. +# XXX - look at why!? +# Some counters on Vista require elevation, and callback would previously +# clear exceptions without printing them. +def BrowseCallBackDemo(counters): + ## BrowseCounters can now return multiple counter paths + for counter in counters: + machine, object, instance, parentInstance, index, counterName = \ + win32pdh.ParseCounterPath(counter) + + result = GetPerformanceAttributes(object, counterName, instance, index, + win32pdh.PDH_FMT_DOUBLE, machine) + print("Value of '%s' is" % counter, result) + print("Added '%s' on object '%s' (machine %s), instance %s(%d)-parent of %s" \ + % (counterName, object, machine, instance, index, parentInstance)) + return 0 + +def browse(callback = BrowseCallBackDemo, title="Python Browser", + level=win32pdh.PERF_DETAIL_WIZARD): + win32pdh.BrowseCounters(None,0, callback, level, title, ReturnMultiple=True) + +if __name__=='__main__': + ShowAllProcesses() + # Show how to get a couple of attributes by name. + counter = find_pdh_counter_localized_name("Virtual Bytes") + print("Virtual Bytes = ", FindPerformanceAttributesByName("python", + counter=counter)) + print("Available Bytes = ", GetPerformanceAttributes( + find_pdh_counter_localized_name("Memory"), + find_pdh_counter_localized_name("Available Bytes"))) + # And a browser. + print("Browsing for counters...") + browse() diff --git a/Lib/site-packages/win32/lib/win32rcparser.py b/Lib/site-packages/win32/lib/win32rcparser.py new file mode 100644 index 0000000..d484670 --- /dev/null +++ b/Lib/site-packages/win32/lib/win32rcparser.py @@ -0,0 +1,602 @@ +# Windows dialog .RC file parser, by Adam Walker. + +# This module was adapted from the spambayes project, and is Copyright +# 2003/2004 The Python Software Foundation and is covered by the Python +# Software Foundation license. +""" +This is a parser for Windows .rc files, which are text files which define +dialogs and other Windows UI resources. +""" +__author__="Adam Walker" +__version__="0.11" + +import sys, os, shlex, stat +import pprint +import win32con +import commctrl + +_controlMap = {"DEFPUSHBUTTON":0x80, + "PUSHBUTTON":0x80, + "Button":0x80, + "GROUPBOX":0x80, + "Static":0x82, + "CTEXT":0x82, + "RTEXT":0x82, + "LTEXT":0x82, + "LISTBOX":0x83, + "SCROLLBAR":0x84, + "COMBOBOX":0x85, + "EDITTEXT":0x81, + "ICON":0x82, + "RICHEDIT":"RichEdit20A" + } + +# These are "default styles" for certain controls - ie, Visual Studio assumes +# the styles will be applied, and emits a "NOT {STYLE_NAME}" if it is to be +# disabled. These defaults have been determined by experimentation, so may +# not be completely accurate (most notably, some styles and/or control-types +# may be missing. +_addDefaults = {"EDITTEXT":win32con.WS_BORDER | win32con.WS_TABSTOP, + "GROUPBOX":win32con.BS_GROUPBOX, + "LTEXT":win32con.SS_LEFT, + "DEFPUSHBUTTON":win32con.BS_DEFPUSHBUTTON | win32con.WS_TABSTOP, + "PUSHBUTTON": win32con.WS_TABSTOP, + "CTEXT":win32con.SS_CENTER, + "RTEXT":win32con.SS_RIGHT, + "ICON":win32con.SS_ICON, + "LISTBOX":win32con.LBS_NOTIFY, + } + +defaultControlStyle = win32con.WS_CHILD | win32con.WS_VISIBLE +defaultControlStyleEx = 0 + +class DialogDef: + name = "" + id = 0 + style = 0 + styleEx = None + caption = "" + font = "MS Sans Serif" + fontSize = 8 + x = 0 + y = 0 + w = 0 + h = 0 + template = None + def __init__(self, n, i): + self.name = n + self.id = i + self.styles = [] + self.stylesEx = [] + self.controls = [] + #print "dialog def for ",self.name, self.id + def createDialogTemplate(self): + t = None + self.template = [[self.caption, + (self.x,self.y,self.w,self.h), + self.style, self.styleEx, + (self.fontSize, self.font)] + ] + # Add the controls + for control in self.controls: + self.template.append(control.createDialogTemplate()) + return self.template + +class ControlDef: + id = "" + controlType = "" + subType = "" + idNum = 0 + style = defaultControlStyle + styleEx = defaultControlStyleEx + label = "" + x = 0 + y = 0 + w = 0 + h = 0 + def __init__(self): + self.styles = [] + self.stylesEx = [] + def toString(self): + s = "" + return s + def createDialogTemplate(self): + ct = self.controlType + if "CONTROL"==ct: + ct = self.subType + if ct in _controlMap: + ct = _controlMap[ct] + t = [ct, self.label, self.idNum, (self.x, self.y, self.w, self.h), self.style, self.styleEx] + #print t + return t + +class StringDef: + def __init__(self, id, idNum, value): + self.id = id + self.idNum = idNum + self.value = value + + def __repr__(self): + return "StringDef(%r, %r, %r)" % (self.id, self.idNum, self.value) + +class RCParser: + next_id = 1001 + dialogs = {} + _dialogs = {} + debugEnabled = False + token = "" + + def __init__(self): + self.ungot = False + self.ids = {"IDC_STATIC": -1} + self.names = {-1:"IDC_STATIC"} + self.bitmaps = {} + self.stringTable = {} + self.icons = {} + + def debug(self, *args): + if self.debugEnabled: + print(args) + + def getToken(self): + if self.ungot: + self.ungot = False + self.debug("getToken returns (ungot):", self.token) + return self.token + self.token = self.lex.get_token() + self.debug("getToken returns:", self.token) + if self.token=="": + self.token = None + return self.token + + def ungetToken(self): + self.ungot = True + + def getCheckToken(self, expected): + tok = self.getToken() + assert tok == expected, "Expected token '%s', but got token '%s'!" % (expected, tok) + return tok + + def getCommaToken(self): + return self.getCheckToken(",") + + # Return the *current* token as a number, only consuming a token + # if it is the negative-sign. + def currentNumberToken(self): + mult = 1 + if self.token=='-': + mult = -1 + self.getToken() + return int(self.token) * mult + + # Return the *current* token as a string literal (ie, self.token will be a + # quote. consumes all tokens until the end of the string + def currentQuotedString(self): + # Handle quoted strings - pity shlex doesn't handle it. + assert self.token.startswith('"'), self.token + bits = [self.token] + while 1: + tok = self.getToken() + if not tok.startswith('"'): + self.ungetToken() + break + bits.append(tok) + sval = "".join(bits)[1:-1] # Remove end quotes. + # Fixup quotes in the body, and all (some?) quoted characters back + # to their raw value. + for i, o in ('""', '"'), ("\\r", "\r"), ("\\n", "\n"), ("\\t", "\t"): + sval = sval.replace(i, o) + return sval + + def load(self, rcstream): + """ + RCParser.loadDialogs(rcFileName) -> None + Load the dialog information into the parser. Dialog Definations can then be accessed + using the "dialogs" dictionary member (name->DialogDef). The "ids" member contains the dictionary of id->name. + The "names" member contains the dictionary of name->id + """ + self.open(rcstream) + self.getToken() + while self.token!=None: + self.parse() + self.getToken() + + def open(self, rcstream): + self.lex = shlex.shlex(rcstream) + self.lex.commenters = "//#" + + def parseH(self, file): + lex = shlex.shlex(file) + lex.commenters = "//" + token = " " + while token is not None: + token = lex.get_token() + if token == "" or token is None: + token = None + else: + if token=='define': + n = lex.get_token() + i = int(lex.get_token()) + self.ids[n] = i + if i in self.names: + # Dupe ID really isn't a problem - most consumers + # want to go from name->id, and this is OK. + # It means you can't go from id->name though. + pass + # ignore AppStudio special ones + #if not n.startswith("_APS_"): + # print "Duplicate id",i,"for",n,"is", self.names[i] + else: + self.names[i] = n + if self.next_id<=i: + self.next_id = i+1 + + def parse(self): + noid_parsers = { + "STRINGTABLE": self.parse_stringtable, + } + + id_parsers = { + "DIALOG" : self.parse_dialog, + "DIALOGEX": self.parse_dialog, +# "TEXTINCLUDE": self.parse_textinclude, + "BITMAP": self.parse_bitmap, + "ICON": self.parse_icon, + } + deep = 0 + base_token = self.token + rp = noid_parsers.get(base_token) + if rp is not None: + rp() + else: + # Not something we parse that isn't prefixed by an ID + # See if it is an ID prefixed item - if it is, our token + # is the resource ID. + resource_id = self.token + self.getToken() + if self.token is None: + return + + if "BEGIN" == self.token: + # A 'BEGIN' for a structure we don't understand - skip to the + # matching 'END' + deep = 1 + while deep!=0 and self.token is not None: + self.getToken() + self.debug("Zooming over", self.token) + if "BEGIN" == self.token: + deep += 1 + elif "END" == self.token: + deep -= 1 + else: + rp = id_parsers.get(self.token) + if rp is not None: + self.debug("Dispatching '%s'" % (self.token,)) + rp(resource_id) + else: + # We don't know what the resource type is, but we + # have already consumed the next, which can cause problems, + # so push it back. + self.debug("Skipping top-level '%s'" % base_token) + self.ungetToken() + + def addId(self, id_name): + if id_name in self.ids: + id = self.ids[id_name] + else: + # IDOK, IDCANCEL etc are special - if a real resource has this value + for n in ["IDOK","IDCANCEL","IDYES","IDNO", "IDABORT"]: + if id_name == n: + v = getattr(win32con, n) + self.ids[n] = v + self.names[v] = n + return v + id = self.next_id + self.next_id += 1 + self.ids[id_name] = id + self.names[id] = id_name + return id + + def lang(self): + while self.token[0:4]=="LANG" or self.token[0:7]=="SUBLANG" or self.token==',': + self.getToken(); + + def parse_textinclude(self, res_id): + while self.getToken() != "BEGIN": + pass + while 1: + if self.token == "END": + break + s = self.getToken() + + def parse_stringtable(self): + while self.getToken() != "BEGIN": + pass + while 1: + self.getToken() + if self.token == "END": + break + sid = self.token + self.getToken() + sd = StringDef(sid, self.addId(sid), self.currentQuotedString()) + self.stringTable[sid] = sd + + def parse_bitmap(self, name): + return self.parse_bitmap_or_icon(name, self.bitmaps) + + def parse_icon(self, name): + return self.parse_bitmap_or_icon(name, self.icons) + + def parse_bitmap_or_icon(self, name, dic): + self.getToken() + while not self.token.startswith('"'): + self.getToken() + bmf = self.token[1:-1] # quotes + dic[name] = bmf + + def parse_dialog(self, name): + dlg = DialogDef(name,self.addId(name)) + assert len(dlg.controls)==0 + self._dialogs[name] = dlg + extras = [] + self.getToken() + while not self.token.isdigit(): + self.debug("extra", self.token) + extras.append(self.token) + self.getToken() + dlg.x = int(self.token) + self.getCommaToken() + self.getToken() # number + dlg.y = int(self.token) + self.getCommaToken() + self.getToken() # number + dlg.w = int(self.token) + self.getCommaToken() + self.getToken() # number + dlg.h = int(self.token) + self.getToken() + while not (self.token==None or self.token=="" or self.token=="END"): + if self.token=="STYLE": + self.dialogStyle(dlg) + elif self.token=="EXSTYLE": + self.dialogExStyle(dlg) + elif self.token=="CAPTION": + self.dialogCaption(dlg) + elif self.token=="FONT": + self.dialogFont(dlg) + elif self.token=="BEGIN": + self.controls(dlg) + else: + break + self.dialogs[name] = dlg.createDialogTemplate() + + def dialogStyle(self, dlg): + dlg.style, dlg.styles = self.styles( [], win32con.DS_SETFONT) + def dialogExStyle(self, dlg): + self.getToken() + dlg.styleEx, dlg.stylesEx = self.styles( [], 0) + + def styles(self, defaults, defaultStyle): + list = defaults + style = defaultStyle + + if "STYLE"==self.token: + self.getToken() + i = 0 + Not = False + while ((i%2==1 and ("|"==self.token or "NOT"==self.token)) or (i%2==0)) and not self.token==None: + Not = False; + if "NOT"==self.token: + Not = True + self.getToken() + i += 1 + if self.token!="|": + if self.token in win32con.__dict__: + value = getattr(win32con,self.token) + else: + if self.token in commctrl.__dict__: + value = getattr(commctrl,self.token) + else: + value = 0 + if Not: + list.append("NOT "+self.token) + self.debug("styles add Not",self.token, value) + style &= ~value + else: + list.append(self.token) + self.debug("styles add", self.token, value) + style |= value + self.getToken() + self.debug("style is ",style) + + return style, list + + def dialogCaption(self, dlg): + if "CAPTION"==self.token: + self.getToken() + self.token = self.token[1:-1] + self.debug("Caption is:",self.token) + dlg.caption = self.token + self.getToken() + def dialogFont(self, dlg): + if "FONT"==self.token: + self.getToken() + dlg.fontSize = int(self.token) + self.getCommaToken() + self.getToken() # Font name + dlg.font = self.token[1:-1] # it's quoted + self.getToken() + while "BEGIN"!=self.token: + self.getToken() + def controls(self, dlg): + if self.token=="BEGIN": self.getToken() + # All controls look vaguely like: + # TYPE [text, ] Control_id, l, t, r, b [, style] + # .rc parser documents all control types as: + # CHECKBOX, COMBOBOX, CONTROL, CTEXT, DEFPUSHBUTTON, EDITTEXT, GROUPBOX, + # ICON, LISTBOX, LTEXT, PUSHBUTTON, RADIOBUTTON, RTEXT, SCROLLBAR + without_text = ["EDITTEXT", "COMBOBOX", "LISTBOX", "SCROLLBAR"] + while self.token!="END": + control = ControlDef() + control.controlType = self.token; + self.getToken() + if control.controlType not in without_text: + if self.token[0:1]=='"': + control.label = self.currentQuotedString() + # Some funny controls, like icons and picture controls use + # the "window text" as extra resource ID (ie, the ID of the + # icon itself). This may be either a literal, or an ID string. + elif self.token=="-" or self.token.isdigit(): + control.label = str(self.currentNumberToken()) + else: + # An ID - use the numeric equiv. + control.label = str(self.addId(self.token)) + self.getCommaToken() + self.getToken() + # Control IDs may be "names" or literal ints + if self.token=="-" or self.token.isdigit(): + control.id = self.currentNumberToken() + control.idNum = control.id + else: + # name of an ID + control.id = self.token + control.idNum = self.addId(control.id) + self.getCommaToken() + + if control.controlType == "CONTROL": + self.getToken() + control.subType = self.token[1:-1] + thisDefaultStyle = defaultControlStyle | \ + _addDefaults.get(control.subType, 0) + # Styles + self.getCommaToken() + self.getToken() + control.style, control.styles = self.styles([], thisDefaultStyle) + else: + thisDefaultStyle = defaultControlStyle | \ + _addDefaults.get(control.controlType, 0) + # incase no style is specified. + control.style = thisDefaultStyle + # Rect + control.x = int(self.getToken()) + self.getCommaToken() + control.y = int(self.getToken()) + self.getCommaToken() + control.w = int(self.getToken()) + self.getCommaToken() + self.getToken() + control.h = int(self.token) + self.getToken() + if self.token==",": + self.getToken() + control.style, control.styles = self.styles([], thisDefaultStyle) + if self.token==",": + self.getToken() + control.styleEx, control.stylesEx = self.styles([], defaultControlStyleEx) + #print control.toString() + dlg.controls.append(control) + +def ParseStreams(rc_file, h_file): + rcp = RCParser() + if h_file: + rcp.parseH(h_file) + try: + rcp.load(rc_file) + except: + lex = getattr(rcp, "lex", None) + if lex: + print("ERROR parsing dialogs at line", lex.lineno) + print("Next 10 tokens are:") + for i in range(10): + print(lex.get_token(), end=' ') + print() + raise + return rcp + +def Parse(rc_name, h_name = None): + if h_name: + h_file = open(h_name, "rU") + else: + # See if same basename as the .rc + h_name = rc_name[:-2]+"h" + try: + h_file = open(h_name, "rU") + except IOError: + # See if MSVC default of 'resource.h' in the same dir. + h_name = os.path.join(os.path.dirname(rc_name), "resource.h") + try: + h_file = open(h_name, "rU") + except IOError: + # .h files are optional anyway + h_file = None + rc_file = open(rc_name, "rU") + try: + return ParseStreams(rc_file, h_file) + finally: + if h_file is not None: + h_file.close() + rc_file.close() + return rcp + +def GenerateFrozenResource(rc_name, output_name, h_name = None): + """Converts an .rc windows resource source file into a python source file + with the same basic public interface as the rest of this module. + Particularly useful for py2exe or other 'freeze' type solutions, + where a frozen .py file can be used inplace of a real .rc file. + """ + rcp = Parse(rc_name, h_name) + in_stat = os.stat(rc_name) + + out = open(output_name, "wt") + out.write("#%s\n" % output_name) + out.write("#This is a generated file. Please edit %s instead.\n" % rc_name) + out.write("__version__=%r\n" % __version__) + out.write("_rc_size_=%d\n_rc_mtime_=%d\n" % (in_stat[stat.ST_SIZE], in_stat[stat.ST_MTIME])) + + out.write("class StringDef:\n") + out.write("\tdef __init__(self, id, idNum, value):\n") + out.write("\t\tself.id = id\n") + out.write("\t\tself.idNum = idNum\n") + out.write("\t\tself.value = value\n") + out.write("\tdef __repr__(self):\n") + out.write("\t\treturn \"StringDef(%r, %r, %r)\" % (self.id, self.idNum, self.value)\n") + + out.write("class FakeParser:\n") + + for name in "dialogs", "ids", "names", "bitmaps", "icons", "stringTable": + out.write("\t%s = \\\n" % (name,)) + pprint.pprint(getattr(rcp, name), out) + out.write("\n") + + out.write("def Parse(s):\n") + out.write("\treturn FakeParser()\n") + out.close() + +if __name__=='__main__': + if len(sys.argv) <= 1: + print(__doc__) + print() + print("See test_win32rcparser.py, and the win32rcparser directory (both") + print("in the test suite) for an example of this module's usage.") + else: + import pprint + filename = sys.argv[1] + if "-v" in sys.argv: + RCParser.debugEnabled = 1 + print("Dumping all resources in '%s'" % filename) + resources = Parse(filename) + for id, ddef in resources.dialogs.items(): + print("Dialog %s (%d controls)" % (id, len(ddef))) + pprint.pprint(ddef) + print() + for id, sdef in resources.stringTable.items(): + print("String %s=%r" % (id, sdef.value)) + print() + for id, sdef in resources.bitmaps.items(): + print("Bitmap %s=%r" % (id, sdef)) + print() + for id, sdef in resources.icons.items(): + print("Icon %s=%r" % (id, sdef)) + print() diff --git a/Lib/site-packages/win32/lib/win32serviceutil.py b/Lib/site-packages/win32/lib/win32serviceutil.py new file mode 100644 index 0000000..71af02d --- /dev/null +++ b/Lib/site-packages/win32/lib/win32serviceutil.py @@ -0,0 +1,839 @@ +# General purpose service utilities, both for standard Python scripts, +# and for for Python programs which run as services... +# +# Note that most utility functions here will raise win32api.error's +# (which is == win32service.error, pywintypes.error, etc) +# when things go wrong - eg, not enough permissions to hit the +# registry etc. + +import win32service, win32api, win32con, winerror +import sys, pywintypes, os, warnings +error = RuntimeError + +def LocatePythonServiceExe(exeName = None): + if not exeName and hasattr(sys, "frozen"): + # If py2exe etc calls this with no exeName, default is current exe. + return sys.executable + + # Try and find the specified EXE somewhere. If specifically registered, + # use it. Otherwise look down sys.path, and the global PATH environment. + if exeName is None: + if os.path.splitext(win32service.__file__)[0].endswith("_d"): + exeName = "PythonService_d.exe" + else: + exeName = "PythonService.exe" + # See if it exists as specified + if os.path.isfile(exeName): return win32api.GetFullPathName(exeName) + baseName = os.path.splitext(os.path.basename(exeName))[0] + try: + exeName = win32api.RegQueryValue(win32con.HKEY_LOCAL_MACHINE, + "Software\\Python\\%s\\%s" % (baseName, sys.winver)) + if os.path.isfile(exeName): + return exeName + raise RuntimeError("The executable '%s' is registered as the Python " \ + "service exe, but it does not exist as specified" \ + % exeName) + except win32api.error: + # OK - not there - lets go a-searchin' + for path in [sys.prefix] + sys.path: + look = os.path.join(path, exeName) + if os.path.isfile(look): + return win32api.GetFullPathName(look) + # Try the global Path. + try: + return win32api.SearchPath(None, exeName)[0] + except win32api.error: + msg = "%s is not correctly registered\nPlease locate and run %s, and it will self-register\nThen run this service registration process again." % (exeName, exeName) + raise error(msg) + +def _GetServiceShortName(longName): + # looks up a services name + # from the display name + # Thanks to Andy McKay for this code. + access = win32con.KEY_READ | win32con.KEY_ENUMERATE_SUB_KEYS | win32con.KEY_QUERY_VALUE + hkey = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services", 0, access) + num = win32api.RegQueryInfoKey(hkey)[0] + longName = longName.lower() + # loop through number of subkeys + for x in range(0, num): + # find service name, open subkey + svc = win32api.RegEnumKey(hkey, x) + skey = win32api.RegOpenKey(hkey, svc, 0, access) + try: + # find display name + thisName = str(win32api.RegQueryValueEx(skey, "DisplayName")[0]) + if thisName.lower() == longName: + return svc + except win32api.error: + # in case there is no key called DisplayName + pass + return None + +# Open a service given either it's long or short name. +def SmartOpenService(hscm, name, access): + try: + return win32service.OpenService(hscm, name, access) + except win32api.error as details: + if details.winerror not in [winerror.ERROR_SERVICE_DOES_NOT_EXIST, + winerror.ERROR_INVALID_NAME]: + raise + name = win32service.GetServiceKeyName(hscm, name) + return win32service.OpenService(hscm, name, access) + +def LocateSpecificServiceExe(serviceName): + # Given the name of a specific service, return the .EXE name _it_ uses + # (which may or may not be the Python Service EXE + hkey = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\%s" % (serviceName), 0, win32con.KEY_ALL_ACCESS) + try: + return win32api.RegQueryValueEx(hkey, "ImagePath")[0] + finally: + hkey.Close() + +def InstallPerfmonForService(serviceName, iniName, dllName = None): + # If no DLL name, look it up in the INI file name + if not dllName: # May be empty string! + dllName = win32api.GetProfileVal("Python", "dll", "", iniName) + # Still not found - look for the standard one in the same dir as win32service.pyd + if not dllName: + try: + tryName = os.path.join(os.path.split(win32service.__file__)[0], "perfmondata.dll") + if os.path.isfile(tryName): + dllName = tryName + except AttributeError: + # Frozen app? - anyway, can't find it! + pass + if not dllName: + raise ValueError("The name of the performance DLL must be available") + dllName = win32api.GetFullPathName(dllName) + # Now setup all the required "Performance" entries. + hkey = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\%s" % (serviceName), 0, win32con.KEY_ALL_ACCESS) + try: + subKey = win32api.RegCreateKey(hkey, "Performance") + try: + win32api.RegSetValueEx(subKey, "Library", 0, win32con.REG_SZ, dllName) + win32api.RegSetValueEx(subKey, "Open", 0, win32con.REG_SZ, "OpenPerformanceData") + win32api.RegSetValueEx(subKey, "Close", 0, win32con.REG_SZ, "ClosePerformanceData") + win32api.RegSetValueEx(subKey, "Collect", 0, win32con.REG_SZ, "CollectPerformanceData") + finally: + win32api.RegCloseKey(subKey) + finally: + win32api.RegCloseKey(hkey) + # Now do the "Lodctr" thang... + + try: + import perfmon + path, fname = os.path.split(iniName) + oldPath = os.getcwd() + if path: + os.chdir(path) + try: + perfmon.LoadPerfCounterTextStrings("python.exe " + fname) + finally: + os.chdir(oldPath) + except win32api.error as details: + print("The service was installed OK, but the performance monitor") + print("data could not be loaded.", details) + +def _GetCommandLine(exeName, exeArgs): + if exeArgs is not None: + return exeName + " " + exeArgs + else: + return exeName + +def InstallService(pythonClassString, serviceName, displayName, startType = None, errorControl = None, bRunInteractive = 0, serviceDeps = None, userName = None, password = None, exeName = None, perfMonIni = None, perfMonDll = None, exeArgs = None, + description = None, delayedstart = None): + # Handle the default arguments. + if startType is None: + startType = win32service.SERVICE_DEMAND_START + serviceType = win32service.SERVICE_WIN32_OWN_PROCESS + if bRunInteractive: + serviceType = serviceType | win32service.SERVICE_INTERACTIVE_PROCESS + if errorControl is None: + errorControl = win32service.SERVICE_ERROR_NORMAL + + exeName = '"%s"' % LocatePythonServiceExe(exeName) # None here means use default PythonService.exe + commandLine = _GetCommandLine(exeName, exeArgs) + hscm = win32service.OpenSCManager(None,None,win32service.SC_MANAGER_ALL_ACCESS) + try: + hs = win32service.CreateService(hscm, + serviceName, + displayName, + win32service.SERVICE_ALL_ACCESS, # desired access + serviceType, # service type + startType, + errorControl, # error control type + commandLine, + None, + 0, + serviceDeps, + userName, + password) + if description is not None: + try: + win32service.ChangeServiceConfig2(hs,win32service.SERVICE_CONFIG_DESCRIPTION,description) + except NotImplementedError: + pass ## ChangeServiceConfig2 and description do not exist on NT + if delayedstart is not None: + try: + win32service.ChangeServiceConfig2(hs,win32service.SERVICE_CONFIG_DELAYED_AUTO_START_INFO, delayedstart) + except (win32service.error, NotImplementedError): + ## delayed start only exists on Vista and later - warn only when trying to set delayed to True + if delayedstart: + warnings.warn('Delayed Start not available on this system') + win32service.CloseServiceHandle(hs) + finally: + win32service.CloseServiceHandle(hscm) + InstallPythonClassString(pythonClassString, serviceName) + # If I have performance monitor info to install, do that. + if perfMonIni is not None: + InstallPerfmonForService(serviceName, perfMonIni, perfMonDll) + +def ChangeServiceConfig(pythonClassString, serviceName, startType = None, errorControl = None, bRunInteractive = 0, + serviceDeps = None, userName = None, password = None, + exeName = None, displayName = None, perfMonIni = None, perfMonDll = None, + exeArgs = None, description = None, delayedstart = None): + # Before doing anything, remove any perfmon counters. + try: + import perfmon + perfmon.UnloadPerfCounterTextStrings("python.exe "+serviceName) + except (ImportError, win32api.error): + pass + + # The EXE location may have changed + exeName = '"%s"' % LocatePythonServiceExe(exeName) + + # Handle the default arguments. + if startType is None: startType = win32service.SERVICE_NO_CHANGE + if errorControl is None: errorControl = win32service.SERVICE_NO_CHANGE + + hscm = win32service.OpenSCManager(None,None,win32service.SC_MANAGER_ALL_ACCESS) + serviceType = win32service.SERVICE_WIN32_OWN_PROCESS + if bRunInteractive: + serviceType = serviceType | win32service.SERVICE_INTERACTIVE_PROCESS + commandLine = _GetCommandLine(exeName, exeArgs) + try: + hs = SmartOpenService(hscm, serviceName, win32service.SERVICE_ALL_ACCESS) + try: + + win32service.ChangeServiceConfig(hs, + serviceType, # service type + startType, + errorControl, # error control type + commandLine, + None, + 0, + serviceDeps, + userName, + password, + displayName) + if description is not None: + try: + win32service.ChangeServiceConfig2(hs,win32service.SERVICE_CONFIG_DESCRIPTION,description) + except NotImplementedError: + pass ## ChangeServiceConfig2 and description do not exist on NT + if delayedstart is not None: + try: + win32service.ChangeServiceConfig2(hs,win32service.SERVICE_CONFIG_DELAYED_AUTO_START_INFO, delayedstart) + except (win32service.error, NotImplementedError): + ## Delayed start only exists on Vista and later. On Nt, will raise NotImplementedError since ChangeServiceConfig2 + ## doensn't exist. On Win2k and XP, will fail with ERROR_INVALID_LEVEL + ## Warn only if trying to set delayed to True + if delayedstart: + warnings.warn('Delayed Start not available on this system') + finally: + win32service.CloseServiceHandle(hs) + finally: + win32service.CloseServiceHandle(hscm) + InstallPythonClassString(pythonClassString, serviceName) + # If I have performance monitor info to install, do that. + if perfMonIni is not None: + InstallPerfmonForService(serviceName, perfMonIni, perfMonDll) + +def InstallPythonClassString(pythonClassString, serviceName): + # Now setup our Python specific entries. + if pythonClassString: + key = win32api.RegCreateKey(win32con.HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\%s\\PythonClass" % serviceName) + try: + win32api.RegSetValue(key, None, win32con.REG_SZ, pythonClassString); + finally: + win32api.RegCloseKey(key) + +# Utility functions for Services, to allow persistant properties. +def SetServiceCustomOption(serviceName, option, value): + try: + serviceName = serviceName._svc_name_ + except AttributeError: + pass + key = win32api.RegCreateKey(win32con.HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\%s\\Parameters" % serviceName) + try: + if type(value)==type(0): + win32api.RegSetValueEx(key, option, 0, win32con.REG_DWORD, value); + else: + win32api.RegSetValueEx(key, option, 0, win32con.REG_SZ, value); + finally: + win32api.RegCloseKey(key) + +def GetServiceCustomOption(serviceName, option, defaultValue = None): + # First param may also be a service class/instance. + # This allows services to pass "self" + try: + serviceName = serviceName._svc_name_ + except AttributeError: + pass + key = win32api.RegCreateKey(win32con.HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\%s\\Parameters" % serviceName) + try: + try: + return win32api.RegQueryValueEx(key, option)[0] + except win32api.error: # No value. + return defaultValue + finally: + win32api.RegCloseKey(key) + + +def RemoveService(serviceName): + try: + import perfmon + perfmon.UnloadPerfCounterTextStrings("python.exe "+serviceName) + except (ImportError, win32api.error): + pass + + hscm = win32service.OpenSCManager(None,None,win32service.SC_MANAGER_ALL_ACCESS) + try: + hs = SmartOpenService(hscm, serviceName, win32service.SERVICE_ALL_ACCESS) + win32service.DeleteService(hs) + win32service.CloseServiceHandle(hs) + finally: + win32service.CloseServiceHandle(hscm) + + import win32evtlogutil + try: + win32evtlogutil.RemoveSourceFromRegistry(serviceName) + except win32api.error: + pass + +def ControlService(serviceName, code, machine = None): + hscm = win32service.OpenSCManager(machine,None,win32service.SC_MANAGER_ALL_ACCESS) + try: + + hs = SmartOpenService(hscm, serviceName, win32service.SERVICE_ALL_ACCESS) + try: + status = win32service.ControlService(hs, code) + finally: + win32service.CloseServiceHandle(hs) + finally: + win32service.CloseServiceHandle(hscm) + return status + +def __FindSvcDeps(findName): + if type(findName) is pywintypes.UnicodeType: findName = str(findName) + dict = {} + k = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services") + num = 0 + while 1: + try: + svc = win32api.RegEnumKey(k, num) + except win32api.error: + break + num = num + 1 + sk = win32api.RegOpenKey(k, svc) + try: + deps, typ = win32api.RegQueryValueEx(sk, "DependOnService") + except win32api.error: + deps = () + for dep in deps: + dep = dep.lower() + dep_on = dict.get(dep, []) + dep_on.append(svc) + dict[dep]=dep_on + + return __ResolveDeps(findName, dict) + + +def __ResolveDeps(findName, dict): + items = dict.get(findName.lower(), []) + retList = [] + for svc in items: + retList.insert(0, svc) + retList = __ResolveDeps(svc, dict) + retList + return retList + +def WaitForServiceStatus(serviceName, status, waitSecs, machine=None): + """Waits for the service to return the specified status. You + should have already requested the service to enter that state""" + for i in range(waitSecs*4): + now_status = QueryServiceStatus(serviceName, machine)[1] + if now_status == status: + break + win32api.Sleep(250) + else: + raise pywintypes.error(winerror.ERROR_SERVICE_REQUEST_TIMEOUT, "QueryServiceStatus", win32api.FormatMessage(winerror.ERROR_SERVICE_REQUEST_TIMEOUT)[:-2]) + +def __StopServiceWithTimeout(hs, waitSecs = 30): + try: + status = win32service.ControlService(hs, win32service.SERVICE_CONTROL_STOP) + except pywintypes.error as exc: + if exc.winerror!=winerror.ERROR_SERVICE_NOT_ACTIVE: + raise + for i in range(waitSecs): + status = win32service.QueryServiceStatus(hs) + if status[1] == win32service.SERVICE_STOPPED: + break + win32api.Sleep(1000) + else: + raise pywintypes.error(winerror.ERROR_SERVICE_REQUEST_TIMEOUT, "ControlService", win32api.FormatMessage(winerror.ERROR_SERVICE_REQUEST_TIMEOUT)[:-2]) + + +def StopServiceWithDeps(serviceName, machine = None, waitSecs = 30): + # Stop a service recursively looking for dependant services + hscm = win32service.OpenSCManager(machine,None,win32service.SC_MANAGER_ALL_ACCESS) + try: + deps = __FindSvcDeps(serviceName) + for dep in deps: + hs = win32service.OpenService(hscm, dep, win32service.SERVICE_ALL_ACCESS) + try: + __StopServiceWithTimeout(hs, waitSecs) + finally: + win32service.CloseServiceHandle(hs) + # Now my service! + hs = win32service.OpenService(hscm, serviceName, win32service.SERVICE_ALL_ACCESS) + try: + __StopServiceWithTimeout(hs, waitSecs) + finally: + win32service.CloseServiceHandle(hs) + + finally: + win32service.CloseServiceHandle(hscm) + + +def StopService(serviceName, machine = None): + return ControlService(serviceName, win32service.SERVICE_CONTROL_STOP, machine) + +def StartService(serviceName, args = None, machine = None): + hscm = win32service.OpenSCManager(machine,None,win32service.SC_MANAGER_ALL_ACCESS) + try: + + hs = SmartOpenService(hscm, serviceName, win32service.SERVICE_ALL_ACCESS) + try: + win32service.StartService(hs, args) + finally: + win32service.CloseServiceHandle(hs) + finally: + win32service.CloseServiceHandle(hscm) + +def RestartService(serviceName, args = None, waitSeconds = 30, machine = None): + "Stop the service, and then start it again (with some tolerance for allowing it to stop.)" + try: + StopService(serviceName, machine) + except pywintypes.error as exc: + # Allow only "service not running" error + if exc.winerror!=winerror.ERROR_SERVICE_NOT_ACTIVE: + raise + # Give it a few goes, as the service may take time to stop + for i in range(waitSeconds): + try: + StartService(serviceName, args, machine) + break + except pywintypes.error as exc: + if exc.winerror!=winerror.ERROR_SERVICE_ALREADY_RUNNING: + raise + win32api.Sleep(1000) + else: + print("Gave up waiting for the old service to stop!") + +def _DebugCtrlHandler(evt): + if evt in (win32con.CTRL_C_EVENT, win32con.CTRL_BREAK_EVENT): + assert g_debugService + print("Stopping debug service.") + g_debugService.SvcStop() + return True + return False + +def DebugService(cls, argv = []): + # Run a service in "debug" mode. Re-implements what pythonservice.exe + # does when it sees a "-debug" param. + # Currently only used by "frozen" (ie, py2exe) programs (but later may + # end up being used for all services should we ever remove + # pythonservice.exe) + import servicemanager + global g_debugService + + print("Debugging service %s - press Ctrl+C to stop." % (cls._svc_name_,)) + servicemanager.Debugging(True) + servicemanager.PrepareToHostSingle(cls) + g_debugService = cls(argv) + # Setup a ctrl+c handler to simulate a "stop" + win32api.SetConsoleCtrlHandler(_DebugCtrlHandler, True) + try: + g_debugService.SvcRun() + finally: + win32api.SetConsoleCtrlHandler(_DebugCtrlHandler, False) + servicemanager.Debugging(False) + g_debugService = None + +def GetServiceClassString(cls, argv = None): + if argv is None: + argv = sys.argv + import pickle + modName = pickle.whichmodule(cls, cls.__name__) + if modName == '__main__': + try: + fname = win32api.GetFullPathName(argv[0]) + path = os.path.split(fname)[0] + # Eaaaahhhh - sometimes this will be a short filename, which causes + # problems with 1.5.1 and the silly filename case rule. + # Get the long name + fname = os.path.join(path, win32api.FindFiles(fname)[0][8]) + except win32api.error: + raise error("Could not resolve the path name '%s' to a full path" % (argv[0])) + modName = os.path.splitext(fname)[0] + return modName + "." + cls.__name__ + +def QueryServiceStatus(serviceName, machine=None): + hscm = win32service.OpenSCManager(machine,None,win32service.SC_MANAGER_CONNECT) + try: + + hs = SmartOpenService(hscm, serviceName, win32service.SERVICE_QUERY_STATUS) + try: + status = win32service.QueryServiceStatus(hs) + finally: + win32service.CloseServiceHandle(hs) + finally: + win32service.CloseServiceHandle(hscm) + return status + +def usage(): + try: + fname = os.path.split(sys.argv[0])[1] + except: + fname = sys.argv[0] + print("Usage: '%s [options] install|update|remove|start [...]|stop|restart [...]|debug [...]'" % fname) + print("Options for 'install' and 'update' commands only:") + print(" --username domain\\username : The Username the service is to run under") + print(" --password password : The password for the username") + print(" --startup [manual|auto|disabled|delayed] : How the service starts, default = manual") + print(" --interactive : Allow the service to interact with the desktop.") + print(" --perfmonini file: .ini file to use for registering performance monitor data") + print(" --perfmondll file: .dll file to use when querying the service for") + print(" performance data, default = perfmondata.dll") + print("Options for 'start' and 'stop' commands only:") + print(" --wait seconds: Wait for the service to actually start or stop.") + print(" If you specify --wait with the 'stop' option, the service") + print(" and all dependent services will be stopped, each waiting") + print(" the specified period.") + sys.exit(1) + +def HandleCommandLine(cls, serviceClassString = None, argv = None, customInstallOptions = "", customOptionHandler = None): + """Utility function allowing services to process the command line. + + Allows standard commands such as 'start', 'stop', 'debug', 'install' etc. + + Install supports 'standard' command line options prefixed with '--', such as + --username, --password, etc. In addition, + the function allows custom command line options to be handled by the calling function. + """ + err = 0 + + if argv is None: argv = sys.argv + + if len(argv)<=1: + usage() + + serviceName = cls._svc_name_ + serviceDisplayName = cls._svc_display_name_ + if serviceClassString is None: + serviceClassString = GetServiceClassString(cls) + + # Pull apart the command line + import getopt + try: + opts, args = getopt.getopt(argv[1:], customInstallOptions,["password=","username=","startup=","perfmonini=", "perfmondll=", "interactive", "wait="]) + except getopt.error as details: + print(details) + usage() + userName = None + password = None + perfMonIni = perfMonDll = None + startup = None + delayedstart = None + interactive = None + waitSecs = 0 + for opt, val in opts: + if opt=='--username': + userName = val + elif opt=='--password': + password = val + elif opt=='--perfmonini': + perfMonIni = val + elif opt=='--perfmondll': + perfMonDll = val + elif opt=='--interactive': + interactive = 1 + elif opt=='--startup': + map = {"manual": win32service.SERVICE_DEMAND_START, + "auto" : win32service.SERVICE_AUTO_START, + "delayed": win32service.SERVICE_AUTO_START, ## ChangeServiceConfig2 called later + "disabled": win32service.SERVICE_DISABLED} + try: + startup = map[val.lower()] + except KeyError: + print("'%s' is not a valid startup option" % val) + if val.lower() == "delayed": + delayedstart = True + elif val.lower() == "auto": + delayedstart = False + ## else no change + elif opt=='--wait': + try: + waitSecs = int(val) + except ValueError: + print("--wait must specify an integer number of seconds.") + usage() + + arg=args[0] + knownArg = 0 + # First we process all arguments which pass additional args on + if arg=="start": + knownArg = 1 + print("Starting service %s" % (serviceName)) + try: + StartService(serviceName, args[1:]) + if waitSecs: + WaitForServiceStatus(serviceName, win32service.SERVICE_RUNNING, waitSecs) + except win32service.error as exc: + print("Error starting service: %s" % exc.strerror) + err = exc.winerror + + elif arg=="restart": + knownArg = 1 + print("Restarting service %s" % (serviceName)) + RestartService(serviceName, args[1:]) + if waitSecs: + WaitForServiceStatus(serviceName, win32service.SERVICE_RUNNING, waitSecs) + + elif arg=="debug": + knownArg = 1 + if not hasattr(sys, "frozen"): + # non-frozen services use pythonservice.exe which handles a + # -debug option + svcArgs = " ".join(args[1:]) + try: + exeName = LocateSpecificServiceExe(serviceName) + except win32api.error as exc: + if exc.winerror == winerror.ERROR_FILE_NOT_FOUND: + print("The service does not appear to be installed.") + print("Please install the service before debugging it.") + sys.exit(1) + raise + try: + os.system("%s -debug %s %s" % (exeName, serviceName, svcArgs)) + # ^C is used to kill the debug service. Sometimes Python also gets + # interrupted - ignore it... + except KeyboardInterrupt: + pass + else: + # py2exe services don't use pythonservice - so we simulate + # debugging here. + DebugService(cls, args) + + if not knownArg and len(args)!=1: + usage() # the rest of the cmds don't take addn args + + if arg=="install": + knownArg = 1 + try: + serviceDeps = cls._svc_deps_ + except AttributeError: + serviceDeps = None + try: + exeName = cls._exe_name_ + except AttributeError: + exeName = None # Default to PythonService.exe + try: + exeArgs = cls._exe_args_ + except AttributeError: + exeArgs = None + try: + description = cls._svc_description_ + except AttributeError: + description = None + print("Installing service %s" % (serviceName,)) + # Note that we install the service before calling the custom option + # handler, so if the custom handler fails, we have an installed service (from NT's POV) + # but is unlikely to work, as the Python code controlling it failed. Therefore + # we remove the service if the first bit works, but the second doesnt! + try: + InstallService(serviceClassString, serviceName, serviceDisplayName, serviceDeps = serviceDeps, startType=startup, bRunInteractive=interactive, userName=userName,password=password, exeName=exeName, perfMonIni=perfMonIni,perfMonDll=perfMonDll,exeArgs=exeArgs, + description=description, delayedstart=delayedstart) + if customOptionHandler: + customOptionHandler(*(opts,)) + print("Service installed") + except win32service.error as exc: + if exc.winerror==winerror.ERROR_SERVICE_EXISTS: + arg = "update" # Fall through to the "update" param! + else: + print("Error installing service: %s (%d)" % (exc.strerror, exc.winerror)) + err = exc.winerror + except ValueError as msg: # Can be raised by custom option handler. + print("Error installing service: %s" % str(msg)) + err = -1 + # xxx - maybe I should remove after _any_ failed install - however, + # xxx - it may be useful to help debug to leave the service as it failed. + # xxx - We really _must_ remove as per the comments above... + # As we failed here, remove the service, so the next installation + # attempt works. + try: + RemoveService(serviceName) + except win32api.error: + print("Warning - could not remove the partially installed service.") + + if arg == "update": + knownArg = 1 + try: + serviceDeps = cls._svc_deps_ + except AttributeError: + serviceDeps = None + try: + exeName = cls._exe_name_ + except AttributeError: + exeName = None # Default to PythonService.exe + try: + exeArgs = cls._exe_args_ + except AttributeError: + exeArgs = None + try: + description=cls._svc_description_ + except AttributeError: + description=None + print("Changing service configuration") + try: + ChangeServiceConfig(serviceClassString, serviceName, serviceDeps = serviceDeps, startType=startup, bRunInteractive=interactive, userName=userName,password=password, exeName=exeName, displayName = serviceDisplayName, perfMonIni=perfMonIni,perfMonDll=perfMonDll,exeArgs=exeArgs, + description=description, delayedstart=delayedstart) + if customOptionHandler: + customOptionHandler(*(opts,)) + print("Service updated") + except win32service.error as exc: + print("Error changing service configuration: %s (%d)" % (exc.strerror,exc.winerror)) + err = exc.winerror + + elif arg=="remove": + knownArg = 1 + print("Removing service %s" % (serviceName)) + try: + RemoveService(serviceName) + print("Service removed") + except win32service.error as exc: + print("Error removing service: %s (%d)" % (exc.strerror,exc.winerror)) + err = exc.winerror + elif arg=="stop": + knownArg = 1 + print("Stopping service %s" % (serviceName)) + try: + if waitSecs: + StopServiceWithDeps(serviceName, waitSecs = waitSecs) + else: + StopService(serviceName) + except win32service.error as exc: + print("Error stopping service: %s (%d)" % (exc.strerror,exc.winerror)) + err = exc.winerror + if not knownArg: + err = -1 + print("Unknown command - '%s'" % arg) + usage() + return err + +# +# Useful base class to build services from. +# +class ServiceFramework: + # Required Attributes: + # _svc_name_ = The service name + # _svc_display_name_ = The service display name + + # Optional Attributes: + _svc_deps_ = None # sequence of service names on which this depends + _exe_name_ = None # Default to PythonService.exe + _exe_args_ = None # Default to no arguments + _svc_description_ = None # Only exists on Windows 2000 or later, ignored on windows NT + + def __init__(self, args): + import servicemanager + self.ssh = servicemanager.RegisterServiceCtrlHandler(args[0], self.ServiceCtrlHandlerEx, True) + servicemanager.SetEventSourceName(self._svc_name_) + self.checkPoint = 0 + + def GetAcceptedControls(self): + # Setup the service controls we accept based on our attributes. Note + # that if you need to handle controls via SvcOther[Ex](), you must + # override this. + accepted = 0 + if hasattr(self, "SvcStop"): accepted = accepted | win32service.SERVICE_ACCEPT_STOP + if hasattr(self, "SvcPause") and hasattr(self, "SvcContinue"): + accepted = accepted | win32service.SERVICE_ACCEPT_PAUSE_CONTINUE + if hasattr(self, "SvcShutdown"): accepted = accepted | win32service.SERVICE_ACCEPT_SHUTDOWN + return accepted + + def ReportServiceStatus(self, serviceStatus, waitHint = 5000, win32ExitCode = 0, svcExitCode = 0): + if self.ssh is None: # Debugging! + return + if serviceStatus == win32service.SERVICE_START_PENDING: + accepted = 0 + else: + accepted = self.GetAcceptedControls() + + if serviceStatus in [win32service.SERVICE_RUNNING, win32service.SERVICE_STOPPED]: + checkPoint = 0 + else: + self.checkPoint = self.checkPoint + 1 + checkPoint = self.checkPoint + + # Now report the status to the control manager + status = (win32service.SERVICE_WIN32_OWN_PROCESS, + serviceStatus, + accepted, # dwControlsAccepted, + win32ExitCode, # dwWin32ExitCode; + svcExitCode, # dwServiceSpecificExitCode; + checkPoint, # dwCheckPoint; + waitHint) + win32service.SetServiceStatus( self.ssh, status) + + def SvcInterrogate(self): + # Assume we are running, and everyone is happy. + self.ReportServiceStatus(win32service.SERVICE_RUNNING) + + def SvcOther(self, control): + try: + print("Unknown control status - %d" % control) + except IOError: + # services may not have a valid stdout! + pass + + def ServiceCtrlHandler(self, control): + return self.ServiceCtrlHandlerEx(control, 0, None) + + # The 'Ex' functions, which take additional params + def SvcOtherEx(self, control, event_type, data): + # The default here is to call self.SvcOther as that is the old behaviour. + # If you want to take advantage of the extra data, override this method + return self.SvcOther(control) + + def ServiceCtrlHandlerEx(self, control, event_type, data): + if control==win32service.SERVICE_CONTROL_STOP: + return self.SvcStop() + elif control==win32service.SERVICE_CONTROL_PAUSE: + return self.SvcPause() + elif control==win32service.SERVICE_CONTROL_CONTINUE: + return self.SvcContinue() + elif control==win32service.SERVICE_CONTROL_INTERROGATE: + return self.SvcInterrogate() + elif control==win32service.SERVICE_CONTROL_SHUTDOWN: + return self.SvcShutdown() + else: + return self.SvcOtherEx(control, event_type, data) + + def SvcRun(self): + self.ReportServiceStatus(win32service.SERVICE_RUNNING) + self.SvcDoRun() + # Once SvcDoRun terminates, the service has stopped. + # We tell the SCM the service is still stopping - the C framework + # will automatically tell the SCM it has stopped when this returns. + self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) diff --git a/Lib/site-packages/win32/lib/win32timezone.py b/Lib/site-packages/win32/lib/win32timezone.py new file mode 100644 index 0000000..d2b64f9 --- /dev/null +++ b/Lib/site-packages/win32/lib/win32timezone.py @@ -0,0 +1,975 @@ +# -*- coding: UTF-8 -*- + +""" +win32timezone: + Module for handling datetime.tzinfo time zones using the windows +registry for time zone information. The time zone names are dependent +on the registry entries defined by the operating system. + + This module may be tested using the doctest module. + + Written by Jason R. Coombs (jaraco@jaraco.com). + Copyright © 2003-2012. + All Rights Reserved. + + This module is licenced for use in Mark Hammond's pywin32 +library under the same terms as the pywin32 library. + + To use this time zone module with the datetime module, simply pass +the TimeZoneInfo object to the datetime constructor. For example, + +>>> import win32timezone, datetime +>>> assert 'Mountain Standard Time' in win32timezone.TimeZoneInfo.get_sorted_time_zone_names() +>>> MST = win32timezone.TimeZoneInfo('Mountain Standard Time') +>>> now = datetime.datetime.now(MST) + + The now object is now a time-zone aware object, and daylight savings- +aware methods may be called on it. + +>>> now.utcoffset() in (datetime.timedelta(-1, 61200), datetime.timedelta(-1, 64800)) +True + +(note that the result of utcoffset call will be different based on when now was +generated, unless standard time is always used) + +>>> now = datetime.datetime.now(TimeZoneInfo('Mountain Standard Time', True)) +>>> now.utcoffset() +datetime.timedelta(-1, 61200) + +>>> aug2 = datetime.datetime(2003, 8, 2, tzinfo = MST) +>>> tuple(aug2.utctimetuple()) +(2003, 8, 2, 6, 0, 0, 5, 214, 0) +>>> nov2 = datetime.datetime(2003, 11, 25, tzinfo = MST) +>>> tuple(nov2.utctimetuple()) +(2003, 11, 25, 7, 0, 0, 1, 329, 0) + +To convert from one timezone to another, just use the astimezone method. + +>>> aug2.isoformat() +'2003-08-02T00:00:00-06:00' +>>> aug2est = aug2.astimezone(win32timezone.TimeZoneInfo('Eastern Standard Time')) +>>> aug2est.isoformat() +'2003-08-02T02:00:00-04:00' + +calling the displayName member will return the display name as set in the +registry. + +>>> est = win32timezone.TimeZoneInfo('Eastern Standard Time') +>>> str(est.displayName) +'(UTC-05:00) Eastern Time (US & Canada)' + +>>> gmt = win32timezone.TimeZoneInfo('GMT Standard Time', True) +>>> str(gmt.displayName) +'(UTC) Dublin, Edinburgh, Lisbon, London' + +To get the complete list of available time zone keys, +>>> zones = win32timezone.TimeZoneInfo.get_all_time_zones() + +If you want to get them in an order that's sorted longitudinally +>>> zones = win32timezone.TimeZoneInfo.get_sorted_time_zones() + +TimeZoneInfo now supports being pickled and comparison +>>> import pickle +>>> tz = win32timezone.TimeZoneInfo('China Standard Time') +>>> tz == pickle.loads(pickle.dumps(tz)) +True + +It's possible to construct a TimeZoneInfo from a TimeZoneDescription +including the currently-defined zone. +>>> tz = win32timezone.TimeZoneInfo(TimeZoneDefinition.current()) +>>> tz == pickle.loads(pickle.dumps(tz)) +True + +>>> aest = win32timezone.TimeZoneInfo('AUS Eastern Standard Time') +>>> est = win32timezone.TimeZoneInfo('E. Australia Standard Time') +>>> dt = datetime.datetime(2006, 11, 11, 1, 0, 0, tzinfo = aest) +>>> estdt = dt.astimezone(est) +>>> estdt.strftime('%Y-%m-%d %H:%M:%S') +'2006-11-11 00:00:00' + +>>> dt = datetime.datetime(2007, 1, 12, 1, 0, 0, tzinfo = aest) +>>> estdt = dt.astimezone(est) +>>> estdt.strftime('%Y-%m-%d %H:%M:%S') +'2007-01-12 00:00:00' + +>>> dt = datetime.datetime(2007, 6, 13, 1, 0, 0, tzinfo = aest) +>>> estdt = dt.astimezone(est) +>>> estdt.strftime('%Y-%m-%d %H:%M:%S') +'2007-06-13 01:00:00' + +Microsoft now has a patch for handling time zones in 2007 (see +http://support.microsoft.com/gp/cp_dst) + +As a result, patched systems will give an incorrect result for +dates prior to the designated year except for Vista and its +successors, which have dynamic time zone support. +>>> nov2_pre_change = datetime.datetime(2003, 11, 2, tzinfo = MST) +>>> old_response = (2003, 11, 2, 7, 0, 0, 6, 306, 0) +>>> incorrect_patch_response = (2003, 11, 2, 6, 0, 0, 6, 306, 0) +>>> pre_response = nov2_pre_change.utctimetuple() +>>> pre_response in (old_response, incorrect_patch_response) +True + +Furthermore, unpatched systems pre-Vista will give an incorrect +result for dates after 2007. +>>> nov2_post_change = datetime.datetime(2007, 11, 2, tzinfo = MST) +>>> incorrect_unpatched_response = (2007, 11, 2, 7, 0, 0, 4, 306, 0) +>>> new_response = (2007, 11, 2, 6, 0, 0, 4, 306, 0) +>>> post_response = nov2_post_change.utctimetuple() +>>> post_response in (new_response, incorrect_unpatched_response) +True + + +There is a function you can call to get some capabilities of the time +zone data. +>>> caps = GetTZCapabilities() +>>> isinstance(caps, dict) +True +>>> 'MissingTZPatch' in caps +True +>>> 'DynamicTZSupport' in caps +True + +>>> both_dates_correct = (pre_response == old_response and post_response == new_response) +>>> old_dates_wrong = (pre_response == incorrect_patch_response) +>>> new_dates_wrong = (post_response == incorrect_unpatched_response) + +>>> caps['DynamicTZSupport'] == both_dates_correct +True + +>>> (not caps['DynamicTZSupport'] and caps['MissingTZPatch']) == new_dates_wrong +True + +>>> (not caps['DynamicTZSupport'] and not caps['MissingTZPatch']) == old_dates_wrong +True + +This test helps ensure language support for unicode characters +>>> x = TIME_ZONE_INFORMATION(0, u'français') + + +Test conversion from one time zone to another at a DST boundary +=============================================================== + +>>> tz_hi = TimeZoneInfo('Hawaiian Standard Time') +>>> tz_pac = TimeZoneInfo('Pacific Standard Time') +>>> time_before = datetime.datetime(2011, 11, 5, 15, 59, 59, tzinfo=tz_hi) +>>> tz_hi.utcoffset(time_before) +datetime.timedelta(-1, 50400) +>>> tz_hi.dst(time_before) +datetime.timedelta(0) + +Hawaii doesn't need dynamic TZ info +>>> getattr(tz_hi, 'dynamicInfo', None) + +Here's a time that gave some trouble as reported in #3523104 +because one minute later, the equivalent UTC time changes from DST +in the U.S. +>>> dt_hi = datetime.datetime(2011, 11, 5, 15, 59, 59, 0, tzinfo=tz_hi) +>>> dt_hi.timetuple() +time.struct_time(tm_year=2011, tm_mon=11, tm_mday=5, tm_hour=15, tm_min=59, tm_sec=59, tm_wday=5, tm_yday=309, tm_isdst=0) +>>> dt_hi.utctimetuple() +time.struct_time(tm_year=2011, tm_mon=11, tm_mday=6, tm_hour=1, tm_min=59, tm_sec=59, tm_wday=6, tm_yday=310, tm_isdst=0) + +Convert the time to pacific time. +>>> dt_pac = dt_hi.astimezone(tz_pac) +>>> dt_pac.timetuple() +time.struct_time(tm_year=2011, tm_mon=11, tm_mday=5, tm_hour=18, tm_min=59, tm_sec=59, tm_wday=5, tm_yday=309, tm_isdst=1) + +Notice that the UTC time is almost 2am. +>>> dt_pac.utctimetuple() +time.struct_time(tm_year=2011, tm_mon=11, tm_mday=6, tm_hour=1, tm_min=59, tm_sec=59, tm_wday=6, tm_yday=310, tm_isdst=0) + +Now do the same tests one minute later in Hawaii. +>>> time_after = datetime.datetime(2011, 11, 5, 16, 0, 0, 0, tzinfo=tz_hi) +>>> tz_hi.utcoffset(time_after) +datetime.timedelta(-1, 50400) +>>> tz_hi.dst(time_before) +datetime.timedelta(0) + +>>> dt_hi = datetime.datetime(2011, 11, 5, 16, 0, 0, 0, tzinfo=tz_hi) +>>> print dt_hi.timetuple() +time.struct_time(tm_year=2011, tm_mon=11, tm_mday=5, tm_hour=16, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=309, tm_isdst=0) +>>> print dt_hi.utctimetuple() +time.struct_time(tm_year=2011, tm_mon=11, tm_mday=6, tm_hour=2, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=310, tm_isdst=0) + +According to the docs, this is what astimezone does. +>>> utc = (dt_hi - dt_hi.utcoffset()).replace(tzinfo=tz_pac) +>>> utc +datetime.datetime(2011, 11, 6, 2, 0, tzinfo=TimeZoneInfo('Pacific Standard Time')) +>>> tz_pac.fromutc(utc) == dt_hi.astimezone(tz_pac) +True +>>> tz_pac.fromutc(utc) +datetime.datetime(2011, 11, 5, 19, 0, tzinfo=TimeZoneInfo('Pacific Standard Time')) + +Make sure the converted time is correct. +>>> dt_pac = dt_hi.astimezone(tz_pac) +>>> dt_pac.timetuple() +time.struct_time(tm_year=2011, tm_mon=11, tm_mday=5, tm_hour=19, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=309, tm_isdst=1) +>>> dt_pac.utctimetuple() +time.struct_time(tm_year=2011, tm_mon=11, tm_mday=6, tm_hour=2, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=310, tm_isdst=0) + +Check some internal methods +>>> tz_pac._getStandardBias(datetime.datetime(2011, 1, 1)) +datetime.timedelta(0, 28800) +>>> tz_pac._getDaylightBias(datetime.datetime(2011, 1, 1)) +datetime.timedelta(0, 25200) + +Test the offsets +>>> offset = tz_pac.utcoffset(datetime.datetime(2011, 11, 6, 2, 0)) +>>> offset == datetime.timedelta(hours=-8) +True +>>> dst_offset = tz_pac.dst(datetime.datetime(2011, 11, 6, 2, 0) + offset) +>>> dst_offset == datetime.timedelta(hours=1) +True +>>> (offset + dst_offset) == datetime.timedelta(hours=-7) +True + + +Test offsets that occur right at the DST changeover +>>> datetime.datetime.utcfromtimestamp(1320570000).replace( +... tzinfo=TimeZoneInfo.utc()).astimezone(tz_pac) +datetime.datetime(2011, 11, 6, 1, 0, tzinfo=TimeZoneInfo('Pacific Standard Time')) + +""" +from __future__ import generators + +__author__ = 'Jason R. Coombs ' + +import winreg +import struct +import datetime +import win32api +import re +import operator +import warnings +from itertools import count + +import logging +log = logging.getLogger(__file__) + +# A couple of objects for working with objects as if they were native C-type +# structures. +class _SimpleStruct(object): + _fields_ = None # must be overridden by subclasses + def __init__(self, *args, **kw): + for i, (name, typ) in enumerate(self._fields_): + def_arg = None + if i < len(args): + def_arg = args[i] + if name in kw: + def_arg = kw[name] + if def_arg is not None: + if not isinstance(def_arg, tuple): + def_arg = (def_arg,) + else: + def_arg = () + if len(def_arg)==1 and isinstance(def_arg[0], typ): + # already an object of this type. + # XXX - should copy.copy??? + def_val = def_arg[0] + else: + def_val = typ(*def_arg) + setattr(self, name, def_val) + + def field_names(self): + return [f[0] for f in self._fields_] + + def __eq__(self, other): + if not hasattr(other, "_fields_"): + return False + if self._fields_ != other._fields_: + return False + for name, _ in self._fields_: + if getattr(self, name) != getattr(other, name): + return False + return True + + def __ne__(self, other): + return not self.__eq__(other) + +class SYSTEMTIME(_SimpleStruct): + _fields_ = [ + ('year', int), + ('month', int), + ('day_of_week', int), + ('day', int), + ('hour', int), + ('minute', int), + ('second', int), + ('millisecond', int), + ] + +class TIME_ZONE_INFORMATION(_SimpleStruct): + _fields_ = [ + ('bias', int), + ('standard_name', str), + ('standard_start', SYSTEMTIME), + ('standard_bias', int), + ('daylight_name', str), + ('daylight_start', SYSTEMTIME), + ('daylight_bias', int), + ] + +class DYNAMIC_TIME_ZONE_INFORMATION(_SimpleStruct): + _fields_ = TIME_ZONE_INFORMATION._fields_ + [ + ('key_name', str), + ('dynamic_daylight_time_disabled', bool), + ] + + +class TimeZoneDefinition(DYNAMIC_TIME_ZONE_INFORMATION): + """ + A time zone definition class based on the win32 + DYNAMIC_TIME_ZONE_INFORMATION structure. + + Describes a bias against UTC (bias), and two dates at which a separate + additional bias applies (standard_bias and daylight_bias). + """ + + def __init__(self, *args, **kwargs): + """ + Try to construct a TimeZoneDefinition from + a) [DYNAMIC_]TIME_ZONE_INFORMATION args + b) another TimeZoneDefinition + c) a byte structure (using _from_bytes) + """ + try: + super(TimeZoneDefinition, self).__init__(*args, **kwargs) + return + except (TypeError, ValueError): + pass + + try: + self.__init_from_other(*args, **kwargs) + return + except TypeError: + pass + + try: + self.__init_from_bytes(*args, **kwargs) + return + except TypeError: + pass + + raise TypeError("Invalid arguments for %s" % self.__class__) + + def __init_from_bytes(self, bytes, standard_name='', daylight_name='', key_name='', daylight_disabled=False): + format = '3l8h8h' + components = struct.unpack(format, bytes) + bias, standard_bias, daylight_bias = components[:3] + standard_start = SYSTEMTIME(*components[3:11]) + daylight_start = SYSTEMTIME(*components[11:19]) + super(TimeZoneDefinition, self).__init__(bias, + standard_name, standard_start, standard_bias, + daylight_name, daylight_start, daylight_bias, + key_name, daylight_disabled,) + + def __init_from_other(self, other): + if not isinstance(other, TIME_ZONE_INFORMATION): + raise TypeError("Not a TIME_ZONE_INFORMATION") + for name in other.field_names(): + # explicitly get the value from the underlying structure + value = super(TimeZoneDefinition, other).__getattribute__(other, name) + setattr(self, name, value) + # consider instead of the loop above just copying the memory directly + #size = max(ctypes.sizeof(DYNAMIC_TIME_ZONE_INFO), ctypes.sizeof(other)) + #ctypes.memmove(ctypes.addressof(self), other, size) + + def __getattribute__(self, attr): + value = super(TimeZoneDefinition, self).__getattribute__(attr) + if 'bias' in attr: + make_minute_timedelta = lambda m: datetime.timedelta(minutes = m) + value = make_minute_timedelta(value) + return value + + @classmethod + def current(class_): + "Windows Platform SDK GetTimeZoneInformation" + code, tzi = win32api.GetTimeZoneInformation(True) + return code, class_(*tzi) + + def set(self): + tzi = tuple(getattr(self, n) for n, t in self._fields_) + win32api.SetTimeZoneInformation(tzi) + + def copy(self): + # XXX - this is no longer a copy! + return self.__class__(self) + + def locate_daylight_start(self, year): + return self._locate_day(year, self.daylight_start) + + def locate_standard_start(self, year): + return self._locate_day(year, self.standard_start) + + @staticmethod + def _locate_day(year, cutoff): + """ + Takes a SYSTEMTIME object, such as retrieved from a TIME_ZONE_INFORMATION + structure or call to GetTimeZoneInformation and interprets it based on the given + year to identify the actual day. + + This method is necessary because the SYSTEMTIME structure refers to a day by its + day of the week and week of the month (e.g. 4th saturday in March). + + >>> SATURDAY = 6 + >>> MARCH = 3 + >>> st = SYSTEMTIME(2000, MARCH, SATURDAY, 4, 0, 0, 0, 0) + + # according to my calendar, the 4th Saturday in March in 2009 was the 28th + >>> expected_date = datetime.datetime(2009, 3, 28) + >>> TimeZoneDefinition._locate_day(2009, st) == expected_date + True + """ + # MS stores Sunday as 0, Python datetime stores Monday as zero + target_weekday = (cutoff.day_of_week + 6) % 7 + # For SYSTEMTIMEs relating to time zone inforamtion, cutoff.day + # is the week of the month + week_of_month = cutoff.day + # so the following is the first day of that week + day = (week_of_month - 1) * 7 + 1 + result = datetime.datetime(year, cutoff.month, day, + cutoff.hour, cutoff.minute, cutoff.second, cutoff.millisecond) + # now the result is the correct week, but not necessarily the correct day of the week + days_to_go = (target_weekday - result.weekday()) % 7 + result += datetime.timedelta(days_to_go) + # if we selected a day in the month following the target month, + # move back a week or two. + # This is necessary because Microsoft defines the fifth week in a month + # to be the last week in a month and adding the time delta might have + # pushed the result into the next month. + while result.month == cutoff.month + 1: + result -= datetime.timedelta(weeks = 1) + return result + +class TimeZoneInfo(datetime.tzinfo): + """ + Main class for handling Windows time zones. + Usage: + TimeZoneInfo(