Commits

Jason Scheirer committed fdd0298

Import of 0.5.1

  • Participants
  • Parent commits 400d273

Comments (0)

Files changed (159)

-2007-01-11  Thomas Heller  <theller@python.net>
-
-	* comtypes codegenerator: Do not hardcode pointer and VARIANT size
-	and alignment.  This fixes code generation issues on 64-bit
-	Windows.
-
-	* comtypes.automation: Fix size of VARIANT definition for 64-bit
-	Windows.
-
-2007-01-10  Thomas Heller  <theller@python.net>
-
-	* (Re-)Added comtypes.__version__ again, and set it to "0.3.2".
-
-	* Removed assert statements about sizeof() and alingment() of
-	generated Structure subclasses for portability to 64-bit Windows.
-
-	* Iterating over COM collections retrived the _NewEnum property
-	twice.
-	
-	* Cleaned up the codegeneration.  Generated modules now have a
-	'typelib_path' variable that points to the type library used to
-	generate them, 'CoClass' subclasses have '_typelib_path_' which is
-	used for registration.
-
-2007-01-02  Thomas Heller  <theller@python.net>
-
-	* comtypes\client\_generate.py: Make sure that generated modules
-	have a __file__ attribute, even if gen_dir is None.  The filename
-	part of the __file__ attribute is '<memory>' in this case.
-
-2006-12-20  Thomas Heller  <theller@python.net>
-
-	* comtypes.client.GetModule now recreates the Python module
-	automatically if the type library file timestamp is newer than the
-	module.  The actual code for GetModule now lives in a separate
-	module comtypes.client._generate, but the GetModule symbol is
-	still exposed from comtypes.client.
-
-	* COM method implementations are now found doing case insensitive
-	lookup if the interfaces "_case_insensitivity_" attribute is True.
-
-	* Some memory leaks with BSTR have been fixed.
-
-2006-12-13  Thomas Heller  <theller@python.net>
-
-	* Fix the case insensitivity for COM interfaces (client-side only,
-	so far): If the Python interface class has a "_case_insensitive_"
-	attribute which is True, access of methods and properties is case
-	insensitive.
-
-	By default, this attribute is set to True in interfaces generated
-	from type libraries, because type libraries generally don't
-	preserve the casing of identifiers from IDL interface definitions.
-
-2006-12-06  Thomas Heller  <theller@python.net>
-
-	* Fix comtypes.test.test_typeinfo to work when either IE6 or IE7
-	is installed.
-
-	* comtypes.hresult: Add MAKE_HRESULT and HRESULT_FROM_WIN32
-	functions which return HRESULT values.
-
-	* Receive events from the event interface plus all the super
-	interfaces.
-
-	* When a NULL IDispatch pointer is received as an [out] parameter,
-	return None instead of the NULL pointer.
-
-	* Changed the way COM is shut down.  No longer a need to call the
-	possibly expensive (or dangerous?) _is_com_initialized.
-
-2006-11-15  Thomas Heller  <theller@python.net>
-
-	* comtypes.client._events.GetEvents: Catch the exception when
-	IProvideClassInfo::GetGUID fails, and try the next strategy for
-	finding the outgoing interface.
-
-	* comtypes now has a __version__ attribute.  This is set to
-	"0.3.1".  Added test command to the setup script.
-
-	* New function comtypes.client.ShowEvents(source, interface=None).
-	This function is useful for debugging; it connects the source
-	object to a special event receiver that will first print out all
-	the event names, and later print out the events as they occur.
-
-2006-08-04  Thomas Heller  <theller@python.net>
-
-	* Fixed quite some tests to work or be skipped on Windows CE.
-
-	* comtypes\typesinfo.py: Added ICreateTypeLib2 interface, and
-	changed the CreateTypeLib function to return a pointer to that
-	interface.
-
-	* Added a COM server for testing to the comtypes.test package,
-	plus tests for it.  There are still several memory leaks in
-	comtypes, as the tests show.
-	
-2006-08-03  Thomas Heller  <theller@python.net>
-
-	* comtypes\server\register.py: For localserver, the wrong script
-	was registered when the class was not in a toplevel module.
-
-2006-08-02  Thomas Heller  <theller@python.net>
-
-	* Version number changed to 0.3.0, added 'comtypes.server' package
-	to the setup script.
-
-	* Merged in a LOT of changes from the upstream version.
-	For details see the svn commit messages.
-
-	The most prominent changes are:
-
-	- The strings returned by ITypeInfo::GetDocumentation() do not
-	contain NUL characters any more (some buggy typelibs contain them)
-
-	- comtypes.client.GetEvents returns a 'connection object', which
-	will UnAdvise the connection when deleted.  In other words, you
-	must keep the return value of the GetEvents call as long as you
-	want to reveive events.
-
-	- Pointer to COM interface pointer instances __setitem__ method manages
-	the COM refcount correctly.
-
-	- Changes in the COM shutdown code: maybe the win32com way of
-	never calling CoUninitialize() is the best compromise ;-), but I
-	have not yet given up.
-	
-2006-07-11  Thomas Heller  <theller@python.net>
-
-	* Imported comtypes 0.2.1 into the python.org svn repository.
-
-2006-04-25  Thomas Heller  <theller@python.net>
-
-	* Released version 0.2.1 (svn revision 8).
-
-2006-03-07  Thomas Heller  <theller@python.net>
-
-	* Imported comtypes from the ctypes CVS repository into the
-	comtypes SVN repository.
-
-2006-03-03  Thomas Heller  <theller@python.net>
-
-	* (Repository): Move the code generator modules into the
-	comtypes.tools package.  Should be refactored later - most
-	important is now that it works again.
-
-2006-02-11  Thomas Heller  <theller@python.net>
-
-	* Merged in lots of changes from the upstream version.  Started
-	localserver support.
-
-2005-10-20  Thomas Heller  <theller@python.net>
-
-	* comtypes\__init__.py: Add logging for easier debugging.  Add
-	COINIT_... flags.  Use the value of sys.coinit_flags (when
-	defined) in the call to CoInitializeEx, this allows to use
-	multithreaded appartments.
-
-	Clean up the lifetime management of implemented COM objects.  Make
-	COM attribute access case insensitive (has a large impact on the
-	performance, unfortunately).
-
-	Move the COMObject definition in a separate module
-	comtypes\_comobject.py.
-
-	* comtypes\tools\codegenerator.py: Don't generate dispid() for
-	non-dispatch based interfaces.
-	
-	* comtypes\client\__init__.py: Add logging for easier debugging.
-
-	* comtypes\persist.py: Remove dispid() from non-dispatch based
-	interfaces. Correct the Read method. Hack around the
-	POINTER(c_wchar) <-> c_wchar_p problem.
-
-2005-10-11  Thomas Heller  <theller@python.net>
-
-	* comtypes\client\__init__.py: Renamed CreateModule() into
-	GetModule().  Removed the 'modulename' parameter from all the
-	function calls - the typelib wrapper alias name is now taken from
-	the typelib library name.  Suggestions from Bruce Dodson.
-
-2005-09-29  Thomas Heller  <theller@python.net>
-
-	* comtypes\GUID.py: Rename the GUID.progid() classmethod into
-	GUID.as_progid().
-
-2005-09-02  Thomas Heller  <theller@python.net>
-
-	* comtypes\client\__init__.py: Can now receive events from custom,
-	non-dispatch interfaces.
+2008-08-07  Thomas Heller  <theller@python.net>
+
+	* Bump version number to 0.5.1
+
+	* comtypes\tools\codegenerator.py: Change the order of the
+	interfaces in the _com_interfaces_ and _outgoing_interfaces_ list
+	so that the default interface is the first one.  This fixes the
+	bug that GetEvents() and ShowEvents() sometimes did use the wrong
+	event interface.
+
+2008-08-06  Thomas Heller  <theller@python.net>
+
+	* The repository was moved from python.org to sourceforge.net.
+	The svn trunk URL is now:
+	https://comtypes.svn.sourceforge.net/svnroot/comtypes/trunk
+
+	The script that extracted the repository is in
+	admin/extract_comtypes_repo. The repository structure and the
+	revision numbers have changed; the last revision on python.org is
+	rev 65336, this was imported as revision rev 355.
+
+2008-07-18  Thomas Heller  <theller@python.net>
+
+	* comtypes\test\find_memleak.py: Windows CE does not have
+	GetProcessMemoryInfo; disable the find_memleak function because it
+	cannot work.
+
+	* comtypes\client\_generate.py, comtypes\typeinfo.py: Windows CE
+	doesn't have QueryPathOfRegTypeLib - try to emulate it.  Also it
+	doesn't use tha PATH environment variable; use a hardcoded search
+	path for type libraries.
+
+	* comtypes\test\runtests.py: Define a main() function.
+
+2008-05-29  Thomas Heller  <theller@python.net>
+
+	* Improved the [in, out] parameter workaround.  These parameters
+	are now optional.  Removed the special codegeneration for [in,
+	out] parameters in IEnumXXX.Next methods.  Added test.
+
+2008-05-16  Thomas Heller  <theller@python.net>
+
+	* Provide a workaround for a bug in ctypes. This allows methods
+	using [in, out] parameters to correctly convert native Python
+	values.
+
+	* comtypes/tools/tlbparser.py: When GetRefTypeInfo(hreftype)
+	fails, emit a warning and generate a fake type instead.
+
+2008-05-07  Thomas Heller  <theller@python.net>
+
+	* Fixed the definition of VARIANT.empty and VARIANT.null; the
+	values were swapped.
+	https://sourceforge.net/tracker/?func=detail&atid=692940&aid=1959722&group_id=115265
+
+2008-04-25  Thomas Heller  <theller@python.net>
+
+	* Replace logger.info() calls with logger.debug() since it is more
+	appropriate.
+
+	In comtypes.server.connectionpoints, when a event notification
+	fails with an error indicating that the event sink is no longer
+	present, close the connection and log a warning.
+
+	The __repr__ of VARIANT changed again to make it a little bit shorter.
+
+	VARIANT instances of VT_BREF are NOT unpacked when the .value
+	attribute as accessed. The value instead can be got or set by
+	indexing, so the api is the same as for pointer instances:
+
+	  print byref_var[0]
+	  byref_var[0] = value
+
+
+2008-04-17  Thomas Heller  <theller@python.net>
+
+	* More changes merged from upstream svn 26400, add support for
+	implementing (non-dual) dispinterfaces (work in progress).
+
+	* Merge in a lot of changes from the private upstream repository
+	26394; mainly much better support for implementing comtypes
+	servers.
+
+2008-04-09  Thomas Heller  <theller@python.net>
+
+	* Bump version number to 0.4.3a
+
+	* Released version comtypes 0.4.2.
+
+	* comtypes.util: New module, containing the byref_at() and
+	cast_field() helper functions.
+
+2008-04-07  Thomas Heller  <theller@python.net>
+
+	* Fix the codegenerator to handle all kinds of IEnumXXX::Next
+	method signatures; the second and third parameters may be [out] or
+	[in, out].
+
+2008-03-07  Thomas Heller  <theller@python.net>
+
+	* Implemented support for SAFEARRAYs containing com interface
+	pointers.
+
+2008-03-04  Thomas Heller  <theller@python.net>
+
+	* Add comtypes.client.gen_dir to comtypes.gen.__path__ so that the
+	codegenerator can import its generated module(s).
+
+2008-02-08  Thomas Heller  <theller@python.net>
+
+	* Hacked support for 'open array' [out] parameters in COM methods.
+	These are arrays that have both size_is() and length_is() in IDL.
+	See the comments in comtypes\tools\codegenerator.py, search for
+	'OPENARRAY'.
+
+2008-02-06  Thomas Heller  <theller@python.net>
+
+	* The badly named comtypes.client.wrap function was renamed into
+	comtypes.client.GetBestInterface.  For backwards compatibility the
+	old name stays as an alias.
+	
+	* Replaced the comtypes.messageloop.add_filter(filter) function
+	with comtypes-messageloop.insert_filter(index, filter).  This
+	allows to specify the order in which the filters are applied.
+
+	* Added a workaround for the buggy _ctypes.COMError in Python 2.5
+	and 2.51.
+
+2007-12-19  Thomas Heller  <theller@python.net>
+
+	* Bump version number to 0.4.2.
+
+	* Special methods (__iter__ and so on) did not work on
+	dispinterfaces, because the __map_case__ dictionary was not
+	populated.
+
+2007-11-23  Thomas Heller  <theller@python.net>
+
+	* Released version comtypes 0.4.1.
+
+	* Add a PumpEvents(timeout) function to comtypes.client.  This
+	function calls the win32 CoWaitForMultipleHandles() function which
+	will wait in a way compatible with all types of apartments;
+	additionally this function can be interrupted with Control+C.
+
+2007-11-21  Thomas Heller  <theller@python.net>
+
+	* comtypes\__init__.py: Add docstrings to special methods.  Make
+	named_property a data descriptor by providing a __set__ method
+	(which will raise AttributeError when called).
+
+2007-11-15  Thomas Heller  <theller@python.net>
+
+	* comtypes\__init__.py: Fix bound_named_property.__setitem__ so
+	that COM properties can be set that require zero or more than one
+	arguments.
+
+	* comtypes\__init__.py:  Restructure the code that extend the COM
+	interface subclasses with __len__, __call__, __getitem__, and
+	__iter__ methods.  This is done with the comtypes.partial module,
+	and apparently had strange behaviour when the code is run under a
+	debugger.
+
+2007-11-07  Thomas Heller  <theller@python.net>
+
+	* Changed version number to 0.4.1.
+
+	* Add an post-install script that will (after confirmation) remove
+	the comtypes\gen directory containing the generated modules.
+
+2007-11-02  Thomas Heller  <theller@python.net>
+
+	* Bump version number to 0.4.0.
+	Released version 0.4.0.
+
+	* In _wrap_coclass, attach a __clsid attribute to the returned
+	object. This allows, for example, to find outgoing interfaces when
+	a CoClass is returned from a COM method call.
+
+2007-10-26  Thomas Heller  <theller@python.net>
+
+	* Implemented property get, put, and putref with arguments
+	in comtypes.client.dynamic.
+
+	* When a COM property has both propput and propputref accessor
+	methods, the Python property fset methods determines the type of
+	the argument.
+
+	If the argument is a COM interface pointer, or a VARIANT
+	containing one, then propputref is called, otherwise proput is
+	called to set the property.
+
+	* Allow the creation of SAFEARRAY(UDT) types even if the UDT has
+	no _recordinfo_.  Creating instances of these types will fail
+	however since no IRecordInfo pointer can be created.  This change
+	allows to import typelib wrappers that have UDTs without guids.
+
+2007-10-24  Thomas Heller  <theller@python.net>
+
+	* When a COM property has a 'propputref' but no 'propput' accessor
+	method, use the former in the same way as a 'propput' would work.
+	When both 'propputref' and 'propput' are present, raise a
+	TypeError because we cannot handle this case for now.
+
+	* Fixed infinit recursion error in __getattr__ implementation.
+	
+	* comtypes.dynamic._Dispatch now implements a __setattr__ methods
+	that will call to Invoke() with DISPATCH_PROPERTYPUT or
+	DISPATCH_PROPERTYPUTREF.
+	
+	* Handle DISPATCH_PROPERTYPUTREF in IDispatch.Invoke
+	implementation.
+
+	* comtypes.dynamic._Dispatch objects can now be used as VARIANT
+	value.
+
+2007-10-22  Thomas Heller  <theller@python.net>
+
+	* The repr of a COM pointer instance now includes the pointer
+	value for easier debugging.
+
+2007-10-17  Thomas Heller  <theller@python.net>
+
+	* Disable the VT_UNKNOWN and VT_DISPATCH safearray codes, they do
+	not work yet.
+
+	* More multidimensional safearray tests, bug fixes.
+	
+	* Speed up the unpacking of 1- and 2-dimensional safearrays.
+	
+	* Lots of refatoring of the new SAFEARRAY code; added a docstring
+	to the public function comtypes.safearray._midlSAFEARRAY.
+
+	* For easier debugging, the repr of a VARIANT instance now
+	contains the vartype.
+
+2007-10-16  Thomas Heller  <theller@python.net>
+
+	* Changed version number to 0.3.4.
+	
+	* Mega-patch: Completely rewritten safearray support.  SAFERARRAYs
+	are now automatically converted to Python tuples when they are
+	received as [out] parameters in COM methods, and sequences are
+	accepted as SAFEARRAY [in] parameters.  Multidimensional safearray
+	support still has to be added.
+
+	* VARIANTs can now also contain SAFEARRAYs.  VARIANTs containing
+	SAFEARRAYs with a typecode other than VT_VARIANT, Python
+	array.array instances can be used.
+
+	* Added a comtypes.messageloop module that contains a simple
+	messageloop which allows to add and remove custom filter functions.
+
+	* Removed the comtypes.client.PumpWaitingMessages function.
+
+	* Fixed the codegenerator so that it handles unnamed method
+	parameters.
+
+2007-10-04  Thomas Heller  <theller@python.net>
+
+	* Several refactorings and a small bugfix from the upstream
+	repository.
+
+	* In the comtypes\gen\... type library wrappers, the code
+	generator now creates a commented out template that shows an
+	implementation for each interface it wraps.
+
+2007-10-02  Thomas Heller  <theller@python.net>
+
+	* comtypes.safearray.UnpackSafeArray can now unpack SAFEARRAYs
+	that containt UDT (user defined data types).  Patch by Rimon Barr,
+	testcase by me.
+
+2007-09-14  Thomas Heller  <theller@python.net>
+
+	* Released version 0.3.3.
+
+2007-09-12  Thomas Heller  <theller@python.net>
+
+	* Bump version number to 0.3.3.
+
+2007-09-03  Thomas Heller  <theller@python.net>
+
+	* Add the partial module, which allows the usual class statement
+	syntax to attach methods to already existing classes.
+
+	* Use partial in comtypes.automation to attach methods to
+	POINTER(VARIANT).
+
+
+2007-08-24  Thomas Heller  <theller@python.net>
+
+	* Added a custom outgoing interface to TestComServer.idl.
+	Implemented IConnectionPointContainer in TestComServer.py.
+
+	* comtypes.server.automation: Fix the IProvideClassInfo2.GetGUID
+	implementation.
+
+	* comtypes.client: Fix ShowEvents(): COM methods must return a
+	HRESULT value, not None.  Fix several NameErrors in the
+	PumpWaitingMessages function.
+	
+2007-08-14  Thomas Heller  <theller@python.net>
+
+	* comtypes\tools\codegenerator.py: Generate the needed imports
+	when COM defaultvalues are used in parameter lists.
+
+2007-08-10  Thomas Heller  <theller@python.net>
+
+	* Add comtypes.client.PumpWaitingMessages() helper funtion.  May
+	be used to dispatch COM events in single threaded appartments.
+
+2007-08-09  Thomas Heller  <theller@python.net>
+
+	* Added the IRecordInfo interface to comtypes.typeinfo.
+
+	* If UDTs (structures or unions) in a typelib have a GUID defined,
+	add a _recordinfo_ attribute to the generated code.  This allows
+	to call GetRecordInfoFromGuids(*_recordinfo_) to get an
+	IRecordInfo pointer.
+
+	* Released comtypes-0.3.2
+
+2007-08-08  Thomas Heller  <theller@python.net>
+
+	* Add better support for dynamic dispatch, comtypes.CoUninitialize
+	function.  Patch from Belyaev Dmitry.
+
+2007-03-23  Thomas Heller  <theller@python.net>
+
+	* Fixed: TextWrap did destroy the generated code when very long
+	symbol names used were in the type library.
+
+	* The IEnumVARIANT.Next(celt) method can now be called with
+	celt != 1.  It will return a list of items then; this allows to get
+	more objects at a time.
+
+2007-03-22  Thomas Heller  <theller@python.net>
+
+	* In comtypes.hresult, add the hex HRESULT values in comments for
+	reference.
+
+	* In comtypes.errorinfo.ReportError, use the supplied hresult
+	value.
+
+	* Improved _NewEnum client-side handling.
+
+	* When a relative pathname to a type library is passed to
+	comtypes.client.GetModule(), the pathname is now interpreted
+	relative to the __file__ of the caller if this pathname actually
+	exists in the filesystem.
+
+	* Fixed several memory leaks and other problems in the BSTR
+	implementation.  The previous change that requires ctypes version
+	1.0.2 was backed out again because it was the wrong approach.
+	
+2007-01-25  Thomas Heller  <theller@python.net>
+
+	NOTE: This comment is no longer true, see above.
+	* Removed unneeded methods from comtypes.BSTR.  The resource
+	management is handled by ctypes; this requires ctypes version
+	1.0.2 to correctly release BSTR resources.
+
+2007-01-19  Thomas Heller  <theller@python.net>
+
+	* The comtypes.test package is now self contained, it does no
+	longer depend on ctypes.test which may not be available.
+
+2007-01-16  Thomas Heller  <theller@python.net>
+
+	* comtypes.tools.tlbparser: Sort interface methods by VTable order
+	(there are typeinfos that list the methods in a different order).
+
+2007-01-11  Thomas Heller  <theller@python.net>
+
+	* comtypes codegenerator: Do not hardcode pointer and VARIANT size
+	and alignment.  This fixes code generation issues on 64-bit
+	Windows.
+
+	* comtypes.automation: Fix size of VARIANT definition for 64-bit
+	Windows.
+
+2007-01-10  Thomas Heller  <theller@python.net>
+
+	* (Re-)Added comtypes.__version__ again, and set it to "0.3.2".
+
+	* Removed assert statements about sizeof() and alingment() of
+	generated Structure subclasses for portability to 64-bit Windows.
+
+	* Iterating over COM collections retrived the _NewEnum property
+	twice.
+	
+	* Cleaned up the codegeneration.  Generated modules now have a
+	'typelib_path' variable that points to the type library used to
+	generate them, 'CoClass' subclasses have '_typelib_path_' which is
+	used for registration.
+
+2007-01-02  Thomas Heller  <theller@python.net>
+
+	* comtypes\client\_generate.py: Make sure that generated modules
+	have a __file__ attribute, even if gen_dir is None.  The filename
+	part of the __file__ attribute is '<memory>' in this case.
+
+2006-12-20  Thomas Heller  <theller@python.net>
+
+	* comtypes.client.GetModule now recreates the Python module
+	automatically if the type library file timestamp is newer than the
+	module.  The actual code for GetModule now lives in a separate
+	module comtypes.client._generate, but the GetModule symbol is
+	still exposed from comtypes.client.
+
+	* COM method implementations are now found doing case insensitive
+	lookup if the interfaces "_case_insensitivity_" attribute is True.
+
+	* Some memory leaks with BSTR have been fixed.
+
+2006-12-13  Thomas Heller  <theller@python.net>
+
+	* Fix the case insensitivity for COM interfaces (client-side only,
+	so far): If the Python interface class has a "_case_insensitive_"
+	attribute which is True, access of methods and properties is case
+	insensitive.
+
+	By default, this attribute is set to True in interfaces generated
+	from type libraries, because type libraries generally don't
+	preserve the casing of identifiers from IDL interface definitions.
+
+2006-12-06  Thomas Heller  <theller@python.net>
+
+	* Fix comtypes.test.test_typeinfo to work when either IE6 or IE7
+	is installed.
+
+	* comtypes.hresult: Add MAKE_HRESULT and HRESULT_FROM_WIN32
+	functions which return HRESULT values.
+
+	* Receive events from the event interface plus all the super
+	interfaces.
+
+	* When a NULL IDispatch pointer is received as an [out] parameter,
+	return None instead of the NULL pointer.
+
+	* Changed the way COM is shut down.  No longer a need to call the
+	possibly expensive (or dangerous?) _is_com_initialized.
+
+2006-11-15  Thomas Heller  <theller@python.net>
+
+	* comtypes.client._events.GetEvents: Catch the exception when
+	IProvideClassInfo::GetGUID fails, and try the next strategy for
+	finding the outgoing interface.
+
+	* comtypes now has a __version__ attribute.  This is set to
+	"0.3.1".  Added test command to the setup script.
+
+	* New function comtypes.client.ShowEvents(source, interface=None).
+	This function is useful for debugging; it connects the source
+	object to a special event receiver that will first print out all
+	the event names, and later print out the events as they occur.
+
+2006-08-04  Thomas Heller  <theller@python.net>
+
+	* Fixed quite some tests to work or be skipped on Windows CE.
+
+	* comtypes\typesinfo.py: Added ICreateTypeLib2 interface, and
+	changed the CreateTypeLib function to return a pointer to that
+	interface.
+
+	* Added a COM server for testing to the comtypes.test package,
+	plus tests for it.  There are still several memory leaks in
+	comtypes, as the tests show.
+	
+2006-08-03  Thomas Heller  <theller@python.net>
+
+	* comtypes\server\register.py: For localserver, the wrong script
+	was registered when the class was not in a toplevel module.
+
+2006-08-02  Thomas Heller  <theller@python.net>
+
+	* Version number changed to 0.3.0, added 'comtypes.server' package
+	to the setup script.
+
+	* Merged in a LOT of changes from the upstream version.
+	For details see the svn commit messages.
+
+	The most prominent changes are:
+
+	- The strings returned by ITypeInfo::GetDocumentation() do not
+	contain NUL characters any more (some buggy typelibs contain them)
+
+	- comtypes.client.GetEvents returns a 'connection object', which
+	will UnAdvise the connection when deleted.  In other words, you
+	must keep the return value of the GetEvents call as long as you
+	want to reveive events.
+
+	- Pointer to COM interface pointer instances __setitem__ method manages
+	the COM refcount correctly.
+
+	- Changes in the COM shutdown code: maybe the win32com way of
+	never calling CoUninitialize() is the best compromise ;-), but I
+	have not yet given up.
+	
+2006-07-11  Thomas Heller  <theller@python.net>
+
+	* Imported comtypes 0.2.1 into the python.org svn repository.
+
+2006-04-25  Thomas Heller  <theller@python.net>
+
+	* Released version 0.2.1 (svn revision 8).
+
+2006-03-07  Thomas Heller  <theller@python.net>
+
+	* Imported comtypes from the ctypes CVS repository into the
+	comtypes SVN repository.
+
+2006-03-03  Thomas Heller  <theller@python.net>
+
+	* (Repository): Move the code generator modules into the
+	comtypes.tools package.  Should be refactored later - most
+	important is now that it works again.
+
+2006-02-11  Thomas Heller  <theller@python.net>
+
+	* Merged in lots of changes from the upstream version.  Started
+	localserver support.
+
+2005-10-20  Thomas Heller  <theller@python.net>
+
+	* comtypes\__init__.py: Add logging for easier debugging.  Add
+	COINIT_... flags.  Use the value of sys.coinit_flags (when
+	defined) in the call to CoInitializeEx, this allows to use
+	multithreaded appartments.
+
+	Clean up the lifetime management of implemented COM objects.  Make
+	COM attribute access case insensitive (has a large impact on the
+	performance, unfortunately).
+
+	Move the COMObject definition in a separate module
+	comtypes\_comobject.py.
+
+	* comtypes\tools\codegenerator.py: Don't generate dispid() for
+	non-dispatch based interfaces.
+	
+	* comtypes\client\__init__.py: Add logging for easier debugging.
+
+	* comtypes\persist.py: Remove dispid() from non-dispatch based
+	interfaces. Correct the Read method. Hack around the
+	POINTER(c_wchar) <-> c_wchar_p problem.
+
+2005-10-11  Thomas Heller  <theller@python.net>
+
+	* comtypes\client\__init__.py: Renamed CreateModule() into
+	GetModule().  Removed the 'modulename' parameter from all the
+	function calls - the typelib wrapper alias name is now taken from
+	the typelib library name.  Suggestions from Bruce Dodson.
+
+2005-09-29  Thomas Heller  <theller@python.net>
+
+	* comtypes\GUID.py: Rename the GUID.progid() classmethod into
+	GUID.as_progid().
+
+2005-09-02  Thomas Heller  <theller@python.net>
+
+	* comtypes\client\__init__.py: Can now receive events from custom,
+	non-dispatch interfaces.
-
-To be written.
-==============
-
-comtypes - Python COM package, based on the ctypes FFI library.
-
-comtypes allows to define, call, and implement custom COM interfaces
-in pure Python.
-
-author="Thomas Heller"
-author_email="theller@ctypes.org"
-license="MIT License"
-url="http://starship.python.net/crew/theller/comtypes/"
-
-
-'Development Status :: 4 - Beta'
-##'Development Status :: 5 - Production/Stable'
-'Intended Audience :: Developers'
-'License :: OSI Approved :: MIT License'
-'Operating System :: Microsoft :: Windows'
-'Operating System :: Microsoft :: Windows CE'
-'Programming Language :: Python'
-'Topic :: Software Development :: Libraries :: Python Modules'
-
-
-Bugs
-====
-
-Windows:
-
-    test_comserver.py, TestLocalServer.test_get_typeinfo() fails with
-    an access violation.  No idea why.
-
-    There are memory leaks, run the tests with -umemleaks to see them.
-
-Windows CE:
-
-    6 tests still fail. One because the CoGetObject function is not
-    found (it seems not to exist), the others because
-    SafeArrayCreateVectorEx does not exist on CE.
+
+comtypes
+========
+
+comtypes - Pure Python COM package, based on the ctypes FFI library.
+
+comtypes allows to define, call, and implement custom COM interfaces
+in pure Python.  It works on Windows, 64-bit Windows, and Windows CE.
+
+author="Thomas Heller"
+author_email="theller@ctypes.org"
+license="MIT License"
+url="http://starship.python.net/crew/theller/comtypes/"
+
+
+'Development Status :: 4 - Beta'
+##'Development Status :: 5 - Production/Stable'
+'Intended Audience :: Developers'
+'License :: OSI Approved :: MIT License'
+'Operating System :: Microsoft :: Windows'
+'Operating System :: Microsoft :: Windows CE'
+'Programming Language :: Python'
+'Topic :: Software Development :: Libraries :: Python Modules'
+
+
+comtypes TODO-list
+==================
+
+Bugs
+----
+
+Events handlers for office applications (Word, Excel) are called with
+the arguments in reverse order.
+
+In test_comserver.py, TestLocalServer.test_get_typeinfo() fails with
+an access violation.  No idea why.
+
+With Python 2.6, there are two failures in the test suite.  The same errors
+occur with Python2.5 and Python 2.4 if ctypes-1.1 is used, so it seems to be
+a ctypes bug:
+  Traceback (most recent call last):
+    File "c:\sf\comtypes\comtypes\test\test_sapi.py", line 21, in test
+      engine.AudioOutputStream = stream
+  AttributeError: can't set attribute
+
+  Traceback (most recent call last):
+    File "c:\sf\comtypes\comtypes\test\test_propputref.py", line 13, in test
+      d.Item["object"] = s
+    File "c:\sf\comtypes\comtypes\__init__.py", line 750, in __setitem__
+      self.setter(self.im_inst, index, value)
+  COMError: (-2147352573, 'Mitglied nicht gefunden.', (None, None, None, 0, None))
+
+Features planned
+----------------
+
+The comtypes\gen directory may be unwritable for the current user. See
+http://sourceforge.net/tracker/index.php?func=detail&aid=2014775&group_id=115265&atid=692942
+
+Improve dynamic dispatch support, based on patches provided by Michael
+Curran.  See
+http://article.gmane.org/gmane.comp.python.comtypes.user/199
+
+Provide a .cab file for easy installation on Windows CE.

File admin/extract-comtypes-repo

+#!/bin/sh
+
+# This script extracts the comtypes repository from the svn.python.org repository.
+
+if test ! -d mirror
+then {
+	svnadmin create mirror
+	cat <<'EOF' > mirror/hooks/pre-revprop-change
+#!/bin/sh
+USER="$3"
+
+if [ "$USER" = "svnsync" ]; then exit 0; fi
+
+echo "Only the svnsync user can change revprops" >&2
+exit 1
+EOF
+
+	chmod +x mirror/hooks/pre-revprop-change
+	svnsync init --username svnsync file://`pwd`/mirror http://svn.python.org/projects/
+}
+fi
+
+svnsync sync file://`pwd`/mirror
+
+if test ! -f svn.python.org-dumpfile
+then {
+    echo "Dumping svn.python.org SVN repository mirror, this may take an hour or so."
+    svnadmin dump ./mirror -r 40000:HEAD > svn.python.org-dumpfile
+} fi
+
+if test ! -f ctypes-dumpfile
+then {
+    rm -fr comtypes-dumpfile
+    echo "Filtering ctypes out of the svn.python.org SVN repository dumpfile, this may take some minutes."
+    # It is important that we use svndumpfilter first to create a smaller dumpfile (5 GB reduced to 120 MB),
+    # otherwise svndumpfilter2 below will run out of memory.
+    cat svn.python.org-dumpfile | svndumpfilter include ctypes >ctypes-dumpfile
+} fi
+
+if test ! -f comtypes-dumpfile
+then {
+    rm -fr comtypes-repo
+    echo "Filtering comtypes out of the ctypes dumpfile, this may take some minutes."
+    # We include ctypes/trunk/comtypes, ctypes/branches/comtypes*, ctypes/tags/comtypes*
+    # Then we strip off the ctypes/ prefix, and rewrite 'trunk/comtypes' into 'trunk'
+    cat ctypes-dumpfile | ./svndumpfilter2 --drop-empty-revs --renumber-revs ./mirror ctypes/trunk/comtypes ctypes/branches/comtypes* ctypes/tags/comtypes* | sed "s/-path: ctypes\//-path: /g" | sed "s/-path: trunk\/comtypes/-path: trunk/g" >comtypes-dumpfile
+} fi
+
+if test ! -d comtypes-repo
+then {
+    svnadmin create comtypes-repo
+    svn mkdir file://`pwd`/comtypes-repo/branches -m "Create initial structure"
+    svn mkdir file://`pwd`/comtypes-repo/tags -m "Create initial structure"
+    svnadmin load comtypes-repo < comtypes-dumpfile
+} fi
+
+# Create the dumpfile
+svnadmin dump ./comtypes-repo | bzip2 > sfimportcomtypes.bz2
+# and test it.
+svnadmin create ./new-comtypes-repo
+bzcat sfimportcomtypes.bz2 | svnadmin load ./new-comtypes-repo

File admin/svndumpfilter2

+#!/usr/bin/env python
+
+## Simon Thatam's svndumpfilter2 from
+##  http://svn.tartarus.org/svn-tools/svndumpfilter2, rev 8055.
+
+# Utility to filter a dump file of a Subversion repository to
+# produce a dump file describing only specified subdirectories of
+# the tree contained in the original one. This is similar in
+# concept to the official tool `svndumpfilter', but it's able to
+# cope with revisions which copy files into the area of interest
+# from outside it (in which situation a Node-copyfrom won't be
+# valid in the output dump file). However, in order to support
+# this, svndumpfilter2 requires access via `svnlook' to the
+# original repository from which the input dump file was produced.
+#
+# Usage:
+#
+#     svndumpfilter [options] source-repository regexp [regexp...]
+#
+# This command expects to receive a Subversion dump file on
+# standard input, which must correspond to the Subversion
+# repository pointed to by the first argument. It outputs a
+# filtered dump file on standard output.
+#
+# `source-repository': The first argument must be a pathname to a
+# _local_ Subversion repository. That is, it isn't a Subversion URL
+# (beginning with http:// or svn:// or anything else like that);
+# it's a simple local pathname (absolute or relative). A simple
+# test to see if it's a valid pathname is to pass it as an argument
+# to `svnlook tree'. If that succeeds, it's also a valid first
+# argument to svndumpfilter2.
+#
+# `regexp': The remaining arguments are used to select directory
+# names from the top level of the repository's internal directory
+# tree. Any directory matching any of the regexps will be
+# considered `interesting' and copied into the output dump file;
+# any directory not matching will not. Matching is performed at the
+# top level only: it is not currently possible to selectively
+# include a subset of second-level directories with a common
+# parent.
+#
+# Options include:
+#
+# `--drop-empty-revs': Exclude empty revisions from the output.
+#
+# `--renumber-revs': Generated sequential revision numbers in the
+# filtered output.  This may help work around issues with certain
+# versions of 'svnadmin load'.
+#
+# For example, this command...
+#
+#     svndumpfilter2 /home/svnadmin/myrepos foo bar baz quu+x
+#
+# ... will read a dump file on standard input, and output one on
+# standard output which contains only the subdirectories `foo',
+# `bar', `baz', `quux', `quuux', `quuuux', etc.
+#
+# You will probably usually want to use svndumpfilter2 in
+# conjunction with the production of the dump file in the first
+# place, like this:
+#
+#     svnadmin dump /home/svnadmin/myrepos | \
+#         svndumpfilter2 /home/svnadmin/myrepos foo bar baz quu+x > msv.dump
+
+import sys
+import os
+import re
+import string
+import types
+import md5
+from optparse import OptionParser
+
+# Quoting function which should render any string impervious to
+# POSIX shell metacharacter expansion.
+def quote(word):
+    return "'" + string.replace(word, "'", "'\\''") + "'"
+
+# First, the sensible way to deal with a pathname is to split it
+# into pieces at the slashes and thereafter treat it as a list.
+def splitpath(s):
+    list = string.split(s, "/")
+    # Simplest way to remove all empty elements!
+    try:
+	while 1:
+	    list.remove("")
+    except ValueError:
+	pass
+    return list
+
+def joinpath(list, prefix=""):
+    return prefix + string.join(list, "/")
+
+def cleanpath(s):
+    return joinpath(splitpath(s))
+
+def catpath(path1, path2, prefix=""):
+    return joinpath(splitpath(path1) + splitpath(path2), prefix)
+
+# Decide whether a pathname is interesting or not.
+class InterestingPaths:
+    def __init__(self, args):
+	self.res = []
+	for a in args:
+	    self.res.append(re.compile(a))
+    def interesting(self, path):
+	path = cleanpath(path)
+	if path == '':
+	    # It's possible that the path may have no elements at
+	    # all, in which case we can't match on its first
+	    # element. This generally occurs when svn properties
+	    # are being changed on the root of the repository; we
+	    # consider those to be always interesting and never
+	    # filter them out.
+	    return 1
+	for r in self.res:
+	    if r.match(path):
+		return 1
+	return 0
+
+# A class and some functions to handle a single lump of
+# RFC822-ish-headers-plus-data read from an SVN dump file.
+
+class Lump:
+    def __init__(self):
+	self.hdrlist = []
+	self.hdrdict = {}
+	self.prop = ""
+	self.text = ""
+	self.extant = 1
+	self.props = [[], {}]
+    def sethdr(self, key, val):
+	if not self.hdrdict.has_key(key):
+	    self.hdrlist.append(key)
+	self.hdrdict[key] = val
+    def delhdr(self, key):
+	if self.hdrdict.has_key(key):
+	    del self.hdrdict[key]
+	    self.hdrlist.remove(key)
+    def propparse(self):
+	index = 0
+	while 1:
+	    if self.prop[index:index+2] == "K ":
+		wantval = 1
+	    elif self.prop[index:index+2] == "D ":
+		wantval = 0
+	    elif self.prop[index:index+9] == "PROPS-END":
+		break
+	    else:
+		raise "Unrecognised record in props section"
+	    nlpos = string.find(self.prop, "\n", index)
+	    assert nlpos > 0
+	    namelen = string.atoi(self.prop[index+2:nlpos])
+	    assert self.prop[nlpos+1+namelen] == "\n"
+	    name = self.prop[nlpos+1:nlpos+1+namelen]
+	    index = nlpos+2+namelen
+	    if wantval:
+		assert self.prop[index:index+2] == "V "
+		nlpos = string.find(self.prop, "\n", index)
+		assert nlpos > 0
+		proplen = string.atoi(self.prop[index+2:nlpos])
+		assert self.prop[nlpos+1+proplen] == "\n"
+		prop = self.prop[nlpos+1:nlpos+1+proplen]
+		index = nlpos+2+proplen
+	    else:
+		prop = None
+	    self.props[0].append(name)
+	    self.props[1][name] = prop
+    def setprop(self, key, val):
+	if not self.props[1].has_key(key):
+	    self.props[0].append(key)
+	self.props[1][key] = val
+    def delprop(self, key):
+	if self.props[1].has_key(key):
+	    del self.props[1][key]
+	    self.props[0].remove(key)
+    def correct_headers(self, revmap):
+	# First reconstitute the properties block.
+	self.prop = ""
+	if len(self.props[0]) > 0:
+	    for key in self.props[0]:
+		val = self.props[1][key]
+		if val == None:
+		    self.prop = self.prop + "D %d" % len(key) + "\n" + key + "\n"
+		else:
+		    self.prop = self.prop + "K %d" % len(key) + "\n" + key + "\n"
+		    self.prop = self.prop + "V %d" % len(val) + "\n" + val + "\n"
+	    self.prop = self.prop + "PROPS-END\n"
+	# Now fix up the content length headers.
+	if len(self.prop) > 0:
+	    self.sethdr("Prop-content-length", str(len(self.prop)))
+	else:
+	    self.delhdr("Prop-content-length")
+	# Only fiddle with the md5 if we're not doing a delta.
+	if self.hdrdict.get("Text-delta", "false") != "true":
+	    if len(self.text) > 0:
+		self.sethdr("Text-content-length", str(len(self.text)))
+		m = md5.new()
+		m.update(self.text)
+		self.sethdr("Text-content-md5", m.hexdigest())
+	    else:
+		self.delhdr("Text-content-length")
+		self.delhdr("Text-content-md5")
+	if len(self.prop) > 0 or len(self.text) > 0:
+	    self.sethdr("Content-length", str(len(self.prop)+len(self.text)))
+	else:
+	    self.delhdr("Content-length")
+	# Adjust the revision numbers as needed.
+	for header in ["Revision-number", "Node-copyfrom-rev"]:
+	    if self.hdrdict.has_key(header):
+		old_val = int(self.hdrdict[header])
+		new_val = revmap[old_val]
+		self.sethdr(header, str(new_val))
+
+def read_rfc822_headers(f):
+    ret = Lump()
+    while 1:
+	s = f.readline()
+	if s == "":
+	    return None # end of file
+	if s == "\n":
+	    if len(ret.hdrlist) > 0:
+		break # newline after headers ends them
+	    else:
+		continue # newline before headers is simply ignored
+	if s[-1:] == "\n": s = s[:-1]
+	colon = string.find(s, ":")
+	assert colon > 0
+	assert s[colon:colon+2] == ": "
+	key = s[:colon]
+	val = s[colon+2:]
+	ret.sethdr(key, val)
+    return ret
+
+def read_lump(f):
+    lump = read_rfc822_headers(f)
+    if lump == None:
+	return None
+    pcl = string.atoi(lump.hdrdict.get("Prop-content-length", "0"))
+    tcl = string.atoi(lump.hdrdict.get("Text-content-length", "0"))
+    if pcl > 0:
+	lump.prop = f.read(pcl)
+	lump.propparse()
+    if tcl > 0:
+	lump.text = f.read(tcl)
+    return lump
+
+def write_lump(f, lump, revmap):
+    if not lump.extant:
+	return
+    lump.correct_headers(revmap)
+    for key in lump.hdrlist:
+	val = lump.hdrdict[key]
+	f.write(key + ": " + val + "\n")
+    f.write("\n")
+    f.write(lump.prop)
+    f.write(lump.text)
+    if lump.hdrdict.has_key("Prop-content-length") or \
+    lump.hdrdict.has_key("Text-content-length") or \
+    lump.hdrdict.has_key("Content-length"):
+	f.write("\n")
+
+# Higher-level class that makes use of the above to filter dump
+# file fragments a whole revision at a time.
+
+class Filter:
+    def __init__(self, paths):
+	self.revisions = {}
+	self.paths = paths
+
+    def tweak(self, revhdr, contents):
+	contents2 = []
+	for lump in contents:
+	    action = lump.hdrdict["Node-action"]
+	    path = lump.hdrdict["Node-path"]
+
+	    if not self.paths.interesting(path):
+		continue # boooring
+
+	    need = 1 # we need to do something about this lump
+
+	    if action == "add":
+		if lump.hdrdict.has_key("Node-copyfrom-path"):
+		    srcrev = string.atoi(lump.hdrdict["Node-copyfrom-rev"])
+		    srcpath = lump.hdrdict["Node-copyfrom-path"]
+		    if not self.paths.interesting(srcpath):
+			# Copy from a boring path to an interesting
+			# one, meaning we must use svnlook to
+			# extract the subtree and convert it into
+			# lumps.
+			treecmd = "svnlook tree -r%d %s %s" % \
+			(srcrev, quote(repos), quote(srcpath))
+			tree = os.popen(treecmd, "r")
+			pathcomponents = []
+			while 1:
+			    treeline = tree.readline()
+			    if treeline == "": break
+			    if treeline[-1:] == "\n": treeline = treeline[:-1]
+			    subdir = 0
+			    while treeline[-1:] == "/":
+				subdir = 1
+				treeline = treeline[:-1]
+			    depth = 0
+			    while treeline[:1] == " ":
+				depth = depth + 1
+				treeline = treeline[1:]
+			    pathcomponents[depth:] = [treeline]
+			    thissrcpath = string.join([srcpath] + pathcomponents[1:], "/")
+			    thisdstpath = string.join([path] + pathcomponents[1:], "/")
+			    newlump = Lump()
+			    newlump.sethdr("Node-path", thisdstpath)
+			    newlump.sethdr("Node-action", "add")
+			    props = os.popen("svnlook pl -r%d %s %s" % \
+			    (srcrev, quote(repos), quote(thissrcpath)), "r")
+			    while 1:
+				propname = props.readline()
+				if propname == "": break
+				if propname[-1:] == "\n": propname = propname[:-1]
+				while propname[:1] == " ": propname = propname[1:]
+				propf = os.popen("svnlook pg -r%d %s %s %s" % \
+				(srcrev, quote(repos), quote(propname), quote(thissrcpath)), "r")
+				proptext = propf.read()
+				propf.close()
+				newlump.setprop(propname, proptext)
+			    props.close()
+			    if subdir:
+				newlump.sethdr("Node-kind", "dir")
+			    else:
+				newlump.sethdr("Node-kind", "file")
+				f = os.popen("svnlook cat -r%d %s %s" % \
+				(srcrev, quote(repos), quote(thissrcpath)), "r")
+				newlump.text = f.read()
+				f.close()
+			    contents2.append(newlump)
+			tree.close()
+			if len(lump.text) > 0:
+			    # This was a copyfrom _plus_ some sort of
+			    # delta or new contents, which means that
+			    # having done the copy we now also need a
+			    # change record providing the new contents.
+			    lump.sethdr("Node-action", "change")
+			    lump.delhdr("Node-copyfrom-rev")
+			    lump.delhdr("Node-copyfrom-path")
+			else:
+			    need = 0 # we have now done something
+	    if need:
+		contents2.append(lump)
+
+	# Change the contents array.
+	contents[:] = contents2
+
+	# If we've just removed everything in this revision, leave
+	# out some revision properties as well.
+	if (len(contents) == 0):
+	    revhdr.delprop("svn:log")
+	    revhdr.delprop("svn:author")
+	    revhdr.delprop("svn:date")
+
+fr = sys.stdin
+fw = sys.stdout
+
+# Parse our command-line arguments.
+parser = OptionParser(usage="Usage: %prog [options] src-repo regexp...")
+parser.add_option("--drop-empty-revs", action="store_true",
+                  dest="drop_empty_revs", default=False,
+                  help="filter empty revisions from the dump")
+parser.add_option("--renumber-revs", action="store_true",
+                  dest="renumber_revs", default=False,
+                  help="renumber remaining revisions")
+(options, args) = parser.parse_args()
+if len(args) < 2:
+    print >>sys.stderr, sys.argv[0] + ": Too few arguments."
+    print >>sys.stderr, parser.usage
+    sys.exit(2)
+
+repos = args[0]
+paths = InterestingPaths(args[1:])
+
+# We use this table to map input revisions to output revisions.
+revmap = {}
+
+# Pass the dump-file header through unchanged.
+lump = read_lump(fr)
+while not lump.hdrdict.has_key("Revision-number"):
+    write_lump(fw, lump, revmap)
+    lump = read_lump(fr)
+
+revhdr = lump
+
+filt = Filter(paths)
+
+current_output_rev = 0
+while revhdr != None:
+    # Read revision header.
+    assert revhdr.hdrdict.has_key("Revision-number")
+    contents = []
+    # Read revision contents.
+    while 1:
+	lump = read_lump(fr)
+	if lump == None or lump.hdrdict.has_key("Revision-number"):
+	    newrevhdr = lump
+	    break
+	contents.append(lump)
+
+    # Alter the contents of the revision.
+    filt.tweak(revhdr, contents)
+
+    # Determine whether we should output this revision.  We only
+    # update the current_output_rev if we're actually going to write
+    # something.
+    should_write = (len(contents) > 0 or not options.drop_empty_revs)
+    if should_write:
+	current_output_rev += 1
+
+    # Update our revmap with information about this revision.  Note that
+    # if this revision won't be written, current_output_rev still points
+    # to the last version we dumped.
+    input_rev = int(revhdr.hdrdict["Revision-number"])
+    if options.renumber_revs:
+	revmap[input_rev] = current_output_rev
+    else:
+	revmap[input_rev] = input_rev        
+
+    # Write out this revision, if that's what we've decided to do.
+    if should_write:
+	write_lump(fw, revhdr, revmap)
+	for lump in contents:
+	    write_lump(fw, lump, revmap)
+
+    # And loop round again.
+    revhdr = newrevhdr
+
+fr.close()
+fw.close()

File build/lib/comtypes/GUID.py

+from ctypes import *
+
+BYTE = c_byte
+WORD = c_ushort
+DWORD = c_ulong
+
+_ole32 = oledll.ole32
+
+_StringFromCLSID = _ole32.StringFromCLSID
+_CoTaskMemFree = _ole32.CoTaskMemFree
+_ProgIDFromCLSID = _ole32.ProgIDFromCLSID
+_CLSIDFromString = _ole32.CLSIDFromString
+_CLSIDFromProgID = _ole32.CLSIDFromProgID
+_CoCreateGuid = _ole32.CoCreateGuid
+
+# Note: Comparing GUID instances by comparing their buffers
+# is slightly faster than using ole32.IsEqualGUID.
+
+class GUID(Structure):
+    _fields_ = [("Data1", DWORD),
+                ("Data2", WORD),
+                ("Data3", WORD),
+                ("Data4", BYTE * 8)]
+
+    def __init__(self, name=None):
+        if name is not None:
+            _CLSIDFromString(unicode(name), byref(self))
+
+    def __repr__(self):
+        return u'GUID("%s")' % unicode(self)
+
+    def __unicode__(self):
+        p = c_wchar_p()
+        _StringFromCLSID(byref(self), byref(p))
+        result = p.value
+        _CoTaskMemFree(p)
+        return result
+    __str__ = __unicode__
+
+    def __cmp__(self, other):
+        if isinstance(other, GUID):
+            return cmp(buffer(self), buffer(other))
+        return -1
+
+    def __nonzero__(self):
+        return str(buffer(self)) != "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+
+    def __eq__(self, other):
+        return isinstance(other, GUID) and \
+               buffer(self) == buffer(other)
+
+    def __hash__(self):
+        # We make GUID instances hashable, although they are mutable.
+        return hash(buffer(self))
+
+    def copy(self):
+        return GUID(unicode(self))
+
+    def from_progid(cls, progid):
+        """Get guid from progid, ...
+        """
+        if hasattr(progid, "_reg_clsid_"):
+            progid = progid._reg_clsid_
+        if isinstance(progid, cls):
+            return progid
+        elif isinstance(progid, basestring):
+            if progid.startswith("{"):
+                return cls(progid)
+            inst = cls()
+            _CLSIDFromProgID(unicode(progid), byref(inst))
+            return inst
+        else:
+            raise TypeError("Cannot construct guid from %r" % progid)
+    from_progid = classmethod(from_progid)
+
+    def as_progid(self):
+        "Convert a GUID into a progid"
+        progid = c_wchar_p()
+        _ProgIDFromCLSID(byref(self), byref(progid))
+        result = progid.value
+        _CoTaskMemFree(progid)
+        return result
+
+    def create_new(cls):
+        "Create a brand new guid"
+        guid = cls()
+        _CoCreateGuid(byref(guid))
+        return guid
+    create_new = classmethod(create_new)
+
+__all__ = ["GUID"]

File build/lib/comtypes/__init__.py

+import new, types, sys, os
+
+__version__ = "0.3.2"
+
+from ctypes import *
+from _ctypes import COMError
+
+import logging
+logger = logging.getLogger(__name__)
+
+##class IDLWarning(UserWarning):
+##    "Warn about questionable type information"
+
+from comtypes.GUID import GUID
+_GUID = GUID
+IID = GUID
+DWORD = c_ulong
+
+wireHWND = c_ulong
+
+################################################################
+# About COM apartments:
+# http://blogs.msdn.com/larryosterman/archive/2004/04/28/122240.aspx
+################################################################
+
+################################################################
+# Where should the __ctypes_from_param__ story go?
+# And what would be the 'correct' name for that method?
+################################################################
+# constants for object creation
+CLSCTX_INPROC_SERVER = 1
+CLSCTX_INPROC_HANDLER = 2
+CLSCTX_LOCAL_SERVER = 4
+
+CLSCTX_INPROC = 3
+CLSCTX_SERVER = 5
+CLSCTX_ALL = 7
+
+CLSCTX_INPROC_SERVER16 = 8
+CLSCTX_REMOTE_SERVER = 16
+CLSCTX_INPROC_HANDLER16 = 32
+CLSCTX_RESERVED1 = 64
+CLSCTX_RESERVED2 = 128
+CLSCTX_RESERVED3 = 256
+CLSCTX_RESERVED4 = 512
+CLSCTX_NO_CODE_DOWNLOAD = 1024
+CLSCTX_RESERVED5 = 2048
+CLSCTX_NO_CUSTOM_MARSHAL = 4096
+CLSCTX_ENABLE_CODE_DOWNLOAD = 8192
+CLSCTX_NO_FAILURE_LOG = 16384
+CLSCTX_DISABLE_AAA = 32768
+CLSCTX_ENABLE_AAA = 65536
+CLSCTX_FROM_DEFAULT_CONTEXT = 131072
+
+tagCLSCTX = c_int # enum
+CLSCTX = tagCLSCTX
+
+################################################################
+# Initialization and shutdown
+_ole32 = oledll.ole32
+
+COINIT_MULTITHREADED     = 0x0
+COINIT_APARTMENTTHREADED = 0x2
+COINIT_DISABLE_OLE1DDE   = 0x4
+COINIT_SPEED_OVER_MEMORY = 0x8
+
+def CoInitialize():
+    return CoInitializeEx(COINIT_APARTMENTTHREADED)
+
+def CoInitializeEx(flags=None):
+    if flags is None:
+        if os.name == "ce":
+            flags = getattr(sys, "coinit_flags", COINIT_MULTITHREADED)
+        else:
+            flags = getattr(sys, "coinit_flags", COINIT_APARTMENTTHREADED)
+    logger.debug("CoInitializeEx(None, %s)", flags)
+    _ole32.CoInitializeEx(None, flags)
+
+# COM is initialized automatically for the thread that imports this module
+# for the first time.  sys.coinit_flags is passed as parameter to CoInitializeEx,
+# if defined, otherwise COINIT_APARTMENTTHREADED is used.
+# A shutdown function is registered with atexit, so that CoUninitialize is
+# called when Python is shut down.
+CoInitializeEx()
+
+def shutdown(func=_ole32.CoUninitialize,
+             _debug=logger.debug):
+    # Make sure no COM pointers stay in exception frames.
+    sys.exc_clear()
+    # Sometimes, CoUnititialize, running at Python shutdown,
+    # raises an exception.  We suppress this when __debug__ is
+    # False.
+    _debug("Calling CoUnititialize()")
+    if __debug__:
+        func()
+    else:
+        try: func()
+        except WindowsError: pass
+    # Set the flag which means that calling obj.Release() is no longer
+    # needed.
+    _cominterface_meta._com_shutting_down = True
+    _debug("CoUnititialize() done.")
+
+import atexit
+atexit.register(shutdown)
+del shutdown
+
+################################################################
+# global registries.
+
+# allows to find interface classes by guid strings (iid)
+com_interface_registry = {}
+
+# allows to find coclasses by guid strings (clsid)
+com_coclass_registry = {}
+
+################################################################
+# The metaclasses...
+
+class _cominterface_meta(type):
+    """Metaclass for COM interfaces.  Automatically creates high level
+    methods from COMMETHOD lists.
+    """
+
+    # This flag is set to True by the atexit handler which calls
+    # CoUnititialize.
+    _com_shutting_down = False
+
+    # Creates also a POINTER type for the newly created class.
+    def __new__(self, name, bases, namespace):
+        methods = namespace.pop("_methods_", None)
+        dispmethods = namespace.pop("_disp_methods_", None)
+        cls = type.__new__(self, name, bases, namespace)
+
+        if methods is not None:
+            cls._methods_ = methods
+        if dispmethods is not None:
+            cls._disp_methods_ = dispmethods
+
+        # If we sublass a COM interface, for example:
+        #
+        # class IDispatch(IUnknown):
+        #     ....
+        #
+        # then we need to make sure that POINTER(IDispatch) is a
+        # subclass of POINTER(IUnknown) because of the way ctypes
+        # typechecks work.
+        if bases == (object,):
+            _ptr_bases = (cls, _compointer_base)
+        else:
+            _ptr_bases = (cls, POINTER(bases[0]))
+
+        # The following function will be used as POINTER(<cominterface>).from_param.
+        #
+        # It fixes the problem when there are multiple python interface types
+        # wrapping the same COM interface.  This could happen because some interfaces
+        # are contained in multiple typelibs.
+        #
+        # It also allows to pass a CoClass instance to an api
+        # expecting a COM interface.
+        def from_param(klass, value):
+            """Convert 'value' into a COM pointer to the interface.
+
+            This method accepts a COM pointer, or a CoClass instance
+            which is QueryInterface()d."""
+            if value is None:
+                return None
+            if isinstance(value, klass):
+                return value
+            # multiple python interface types for the same COM interface.
+            # Do we need more checks here?
+            if klass._iid_ == getattr(value, "_iid_", None):
+                return value
+            # Accept an CoClass instance which exposes the interface required.
+            try:
+                table = value._com_pointers_
+            except AttributeError:
+                pass
+            else:
+                try:
+                    # a kind of QueryInterface
+                    return table[klass._iid_]
+                except KeyError:
+                    raise TypeError("Interface %s not supported" % klass._iid_)
+            return value.QueryInterface(cls)
+
+        # case insensitive attributes for COM methods and properties
+        def __getattr__(self, name):
+            """Implement case insensitive access to methods and properties"""
+            try:
+                name = self.__map_case__[name.lower()]
+            except KeyError:
+                raise AttributeError(name)
+            else:
+                return getattr(self, name)
+
+        # __setattr__ is pretty heavy-weight, because it is called for
+        # EVERY attribute assignment.  Settings a non-com attribute
+        # through this function takes 8.6 usec, while without this
+        # function it takes 0.7 sec - 12 times slower.
+        #
+        # How much faster would this be if implemented in C?
+        def __setattr__(self, name, value):
+            """Implement case insensitive access to methods and properties"""
+            object.__setattr__(self,
+                               self.__map_case__.get(name.lower(), name),
+                               value)
+            
+        namespace = {"from_param": classmethod(from_param),
+                     "__com_interface__": cls,
+                     "_needs_com_addref_": None}
+
+        if cls._case_insensitive_:
+            namespace["__setattr__"] = __setattr__
+            namespace["__getattr__"] = __getattr__
+
+        # The interface 'cls' is used as a mixin.
+        p = type(_compointer_base)("POINTER(%s)" % cls.__name__,
+                                   _ptr_bases,
+                                   namespace)
+        from ctypes import _pointer_type_cache
+        _pointer_type_cache[cls] = p
+
+        def comptr_setitem(self, index, value):
+            # We override the __setitem__ method of the
+            # POINTER(POINTER(interface)) type, so that the COM
+            # reference count is managed correctly.
+            #
+            # This is so that we can implement COM methods that have to
+            # return COM pointers more easily and consistent.  Instead of
+            # using CopyComPointer in the method implementation, we can
+            # simply do:
+            #
+            # def GetTypeInfo(self, this, ..., pptinfo):
+            #     if not pptinfo: return E_POINTER
+            #     pptinfo[0] = a_com_interface_pointer
+            #     return S_OK
+            if index != 0:
+                raise IndexError("Invalid index %s, must be 0" % index)
+            from _ctypes import CopyComPointer
+            CopyComPointer(value, self)
+        POINTER(p).__setitem__ = comptr_setitem
+
+        return cls
+
+    def __setattr__(self, name, value):
+        if name == "_methods_":
+            self._make_methods(value)
+        elif name == "_disp_methods_":
+            self._make_dispmethods(value)
+        type.__setattr__(self, name, value)
+
+    def _make_case_insensitive(self):
+        # The __map_case__ dictionary maps lower case names to the
+        # names in the original spelling to enable case insensitive
+        # method and attribute access.
+        try:
+            self.__dict__["__map_case__"]
+        except KeyError:
+            d = {}
+            d.update(getattr(self, "__map_case__", {}))
+            self.__map_case__ = d
+
+    def _make_dispmethods(self, methods):
+        if self._case_insensitive_:
+            self._make_case_insensitive()
+
+        # create dispinterface methods and properties on the interface 'self'
+        properties = {}
+        for m in methods:
+            what, name, idlflags, restype, argspec = m
+
+            # argspec is a sequence of tuples, each tuple is:
+            # ([paramflags], type, name)
+            try:
+                memid = [x for x in idlflags if isinstance(x, int)][0]
+            except IndexError:
+                raise TypeError, "no dispid found in idlflags"
+            if what == "DISPPROPERTY": # DISPPROPERTY
+                assert not argspec # XXX does not yet work for properties with parameters
+                accessor = self._disp_property(memid, idlflags)
+                setattr(self, name, accessor)
+            elif what == "DISPMETHOD": # DISPMETHOD
+                # argspec is a tuple of (idlflags, type, name[,
+                # defval]) items.
+                method = self._disp_method(memid, name, idlflags, restype, argspec)
+## not in 2.3                method.__name__ = name
+                if 'propget' in idlflags:
+                    nargs = len(argspec)
+                    properties.setdefault((name, nargs), [None, None])[0] = method
+                elif 'propput' in idlflags:
+                    nargs = len(argspec)-1
+                    properties.setdefault((name, nargs), [None, None])[1] = method
+                else:
+                    setattr(self, name, method)
+        for (name, nargs), methods in properties.items():
+            if nargs:
+                setattr(self, name, named_property(*methods))
+            else:
+                assert len(methods) <= 2
+                setattr(self, name, property(*methods))
+
+    # Some ideas, (not only) related to disp_methods:
+    #
+    # Should the functions/methods we create have restype and/or
+    # argtypes attributes?
+
+    def _disp_method(self, memid, name, idlflags, restype, argspec):
+        if 'propget' in idlflags:
+            def getfunc(obj, *args, **kw):
+                return self.Invoke(obj, memid, _invkind=2, *args, **kw) # DISPATCH_PROPERTYGET
+            return getfunc
+        elif 'propput' in idlflags:
+            def putfunc(obj, *args, **kw):
+                return self.Invoke(obj, memid, _invkind=4, *args, **kw) # DISPATCH_PROPERTYPUT
+            return putfunc
+        # a first attempt to make use of the restype.  Still, support
+        # for named arguments and default argument values should be
+        # added.
+        if hasattr(restype, "__com_interface__"):
+            interface = restype.__com_interface__
+            def func(s, *args, **kw):
+                result = self.Invoke(s, memid, _invkind=1, *args, **kw)
+                return result.QueryInterface(interface)
+        else:
+            def func(obj, *args, **kw):
+                return self.Invoke(obj, memid, _invkind=1, *args, **kw) # DISPATCH_METHOD
+        return func
+
+    def _disp_property(self, memid, idlflags):
+        # XXX doc string missing in property
+        def _get(obj):
+            return obj.Invoke(memid, _invkind=2) # DISPATCH_PROPERTYGET
+        if "readonly" in idlflags:
+            return property(_get)
+        def _set(obj, value):
+            return obj.Invoke(memid, value, _invkind=4) # DISPATCH_PROPERTYPUT
+        return property(_get, _set)
+
+    def __get_baseinterface_methodcount(self):
+        "Return the number of com methods in the base interfaces"
+        try:
+            return sum([len(itf.__dict__["_methods_"])
+                        for itf in self.mro()[1:-1]])
+        except KeyError, (name,):
+            if name == "_methods_":
+                raise TypeError, "baseinterface '%s' has no _methods_" % itf.__name__
+            raise
+
+    def _make_methods(self, methods):
+        if self._case_insensitive_:
+            self._make_case_insensitive()
+
+        # we insist on an _iid_ in THIS class!
+        try:
+            iid = self.__dict__["_iid_"]
+        except KeyError:
+            raise AttributeError, "this class must define an _iid_"
+        else:
+            iid = str(iid)
+##            if iid in com_interface_registry:
+##                # Warn when multiple interfaces are defined with identical iids.
+##                # This would also trigger if we reload() a module that contains
+##                # interface types, so suppress the warning in this case.
+##                other = com_interface_registry[iid]
+##                if self.__name__ != other.__name__ or self.__module__ != other.__module__:
+##                    text = "Multiple interface defn: %s, %s" % \
+##                           (self, other)
+##                    warnings.warn(text, UserWarning)
+            com_interface_registry[iid] = self
+            del iid
+        vtbl_offset = self.__get_baseinterface_methodcount()
+
+        properties = {}
+
+        # create private low level, and public high level methods
+        for i, item in enumerate(methods):
+            restype, name, argtypes, paramflags, idlflags, doc = item
+            # the function prototype
+            prototype = WINFUNCTYPE(restype, *argtypes)
+
+            # a low level unbound method calling the com method.
+            # attach it with a private name (__com_AddRef, for example),
+            # so that custom method implementations can call it.
+
+            # If the method returns a HRESULT, we pass the interface iid,
+            # so that we can request error info for the interface.
+            if restype == HRESULT:
+##                print "%s.%s" % (self.__name__, name)
+                raw_func = prototype(i + vtbl_offset, name, None, self._iid_)
+                func = prototype(i + vtbl_offset, name, paramflags, self._iid_)
+            else:
+                raw_func = prototype(i + vtbl_offset, name, None, None)
+                func = prototype(i + vtbl_offset, name, paramflags, None)
+            setattr(self,
+                    "_%s__com_%s" % (self.__name__, name),
+                    new.instancemethod(raw_func, None, self))
+            # 'func' is a high level function calling the COM method
+            func.__doc__ = doc
+            func.__name__ = name # for pyhelp
+            # make it an unbound method.  Remember, 'self' is a type here.
+            mth = new.instancemethod(func, None, self)
+
+            # is it a property set or property get?
+            is_prop = False
+
+            # XXX Hm.  What, when paramflags is None?
+            # Or does have '0' values?
+            # Seems we loose then, at least for properties...
+
+            # The following code assumes that the docstrings for
+            # propget and propput are identical.
+            if "propget" in idlflags:
+                assert name.startswith("_get_")
+                nargs = len([flags for flags in paramflags
+                             if flags[0] & 7 in (0, 1)])
+                # XXX or should we do this?
+                # nargs = len([flags for flags in paramflags
+                #             if (flags[0] & 1) or (flags[0] == 0)])
+                propname = name[len("_get_"):]
+                properties.setdefault((propname, doc, nargs), [None, None])[0] = func
+                is_prop = True
+            elif "propput" in idlflags:
+                assert name.startswith("_set_")
+                nargs = len([flags for flags in paramflags
+                              if flags[0] & 7 in (0, 1)]) - 1
+                propname = name[len("_set_"):]
+                properties.setdefault((propname, doc, nargs), [None, None])[1] = func
+                is_prop = True
+
+            # We install the method in the class, except when it's a
+            # property accessor.  And we make sure we don't overwrite
+            # a property that's already present in the class.
+            if not is_prop:
+                if hasattr(self, name):
+                    setattr(self, "_" + name, mth)
+                else:
+                    setattr(self, name, mth)
+
+            # COM is case insensitive.
+            #
+            # For a method, this is the real name.  For a property,
+            # this is the name WITHOUT the _set_ or _get_ prefix.
+            if self._case_insensitive_:
+                self.__map_case__[name.lower()] = name
+
+        # create public properties / attribute accessors
+        for (name, doc, nargs), methods in properties.items():
+            if nargs == 0:
+                prop = property(*methods + [None, doc])
+            else:
+                # Hm, must be a descriptor where the __get__ method
+                # returns a bound object having __getitem__ and
+                # __setitem__ methods.
+                prop = named_property(*methods + [doc])
+            # Again, we should not overwrite class attributes that are
+            # already present.
+            if hasattr(self, name):
+                setattr(self, "_" + name, prop)
+            else:
+                setattr(self, name, prop)
+
+            # COM is case insensitive
+            if self._case_insensitive_:
+                self.__map_case__[name.lower()] = name
+
+
+################################################################
+# helper classes for COM propget / propput
+# Should they be implemented in C for speed?
+
+class bound_named_property(object):
+    def __init__(self, getter, setter, im_inst):
+        self.im_inst = im_inst
+        self.getter = getter
+        self.setter = setter
+
+    def __getitem__(self, index):
+        if self.getter is None:
+            raise TypeError("unsubscriptable object")
+        return self.getter(self.im_inst, index)
+
+    def __call__(self, *args):
+        if self.getter is None:
+            raise TypeError("object is nor callable")
+        return self.getter(self.im_inst, *args)
+
+    def __setitem__(self, index, value):
+        if self.setter is None:
+            raise TypeError("object does not support item assignment")
+        self.setter(self.im_inst, index, value)
+
+class named_property(object):
+    def __init__(self, getter, setter, doc=None):
+        self.getter = getter
+        self.setter = setter
+        self.doc = doc
+
+    def __get__(self, im_inst, im_class=None):
+        if im_inst is None:
+            return self
+        return bound_named_property(self.getter, self.setter, im_inst)
+
+################################################################
+
+class _compointer_meta(type(c_void_p), _cominterface_meta):