[pywin32-checkins] /hgroot/pywin32/pywin32: Add IEnumShellItems, and allow PyIShell...
OLD project page for the Python extensions for Windows
Brought to you by:
mhammond
From: <pyw...@li...> - 2012-07-29 04:09:58
|
changeset 8031b6d1b4dd in /hgroot/pywin32/pywin32 details: http://pywin32.hg.sourceforge.net/hgweb/pywin32/pywin32/hgroot/pywin32/pywin32?cmd=changeset;node=8031b6d1b4dd summary: Add IEnumShellItems, and allow PyIShellItemArray to act as an iterator thru it diffstat: com/win32com/src/extensions/PyIDataObject.cpp | 11 +- com/win32com/src/include/PyIDataObject.h | 2 +- com/win32comext/shell/src/PyIEnumShellItems.cpp | 270 +++++++++++++++++++++++ com/win32comext/shell/src/PyIEnumShellItems.h | 51 ++++ com/win32comext/shell/src/PyIExplorerCommand.cpp | 6 +- com/win32comext/shell/src/PyIShellFolder.cpp | 4 +- com/win32comext/shell/src/PyIShellFolder2.cpp | 2 +- com/win32comext/shell/src/PyIShellItem.cpp | 2 +- com/win32comext/shell/src/PyIShellItemArray.cpp | 96 ++++---- com/win32comext/shell/src/PyIShellItemArray.h | 2 +- com/win32comext/shell/src/shell.cpp | 50 ++-- com/win32comext/shell/src/shell_pch.h | 2 - setup.py | 1 + win32/src/PyWinTypes.h | 6 +- 14 files changed, 414 insertions(+), 91 deletions(-) diffs (truncated from 855 to 300 lines): diff -r 06fd2a416c94 -r 8031b6d1b4dd com/win32com/src/extensions/PyIDataObject.cpp --- a/com/win32com/src/extensions/PyIDataObject.cpp Thu Jul 26 11:01:58 2012 -0400 +++ b/com/win32com/src/extensions/PyIDataObject.cpp Sun Jul 29 00:05:52 2012 -0400 @@ -299,11 +299,13 @@ return PyCom_PyObjectFromIUnknown(ppenumAdvise, IID_IEnumSTATDATA, FALSE); } -// @object PyIDataObject|Description of the interface +// @object PyIDataObject|Used to transfer data in various formats throughout the shell +// @comm Can be enumerated to return a series of <o PyFORMATETC> describing the formats +// that the object can render. static struct PyMethodDef PyIDataObject_methods[] = { { "GetData", PyIDataObject::GetData, 1 }, // @pymeth GetData|Retrieves data from the object in specified format - { "GetDataHere", PyIDataObject::GetDataHere, 1 }, // @pymeth GetDataHere|Retunrs a copy of the object's data in specified format + { "GetDataHere", PyIDataObject::GetDataHere, 1 }, // @pymeth GetDataHere|Returns a copy of the object's data in specified format { "QueryGetData", PyIDataObject::QueryGetData, 1 }, // @pymeth QueryGetData|Checks if the object supports returning data in a particular format { "GetCanonicalFormatEtc", PyIDataObject::GetCanonicalFormatEtc, 1 }, // @pymeth GetCanonicalFormatEtc|Transforms a FORMATECT data description into a general format that the object supports { "SetData", PyIDataObject::SetData, 1 }, // @pymeth SetData|Sets the data that the object will return. @@ -314,11 +316,12 @@ { NULL } }; -PyComTypeObject PyIDataObject::type("PyIDataObject", +PyComEnumProviderTypeObject PyIDataObject::type("PyIDataObject", &PyIUnknown::type, sizeof(PyIDataObject), PyIDataObject_methods, - GET_PYCOM_CTOR(PyIDataObject)); + GET_PYCOM_CTOR(PyIDataObject), + "EnumFormatEtc"); // --------------------------------------------------- // // Gateway Implementation diff -r 06fd2a416c94 -r 8031b6d1b4dd com/win32com/src/include/PyIDataObject.h --- a/com/win32com/src/include/PyIDataObject.h Thu Jul 26 11:01:58 2012 -0400 +++ b/com/win32com/src/include/PyIDataObject.h Sun Jul 29 00:05:52 2012 -0400 @@ -9,7 +9,7 @@ public: MAKE_PYCOM_CTOR(PyIDataObject); static IDataObject *GetI(PyObject *self); - static PyComTypeObject type; + static PyComEnumProviderTypeObject type; // The Python methods static PyObject *GetData(PyObject *self, PyObject *args); diff -r 06fd2a416c94 -r 8031b6d1b4dd com/win32comext/shell/src/PyIEnumShellItems.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/com/win32comext/shell/src/PyIEnumShellItems.cpp Sun Jul 29 00:05:52 2012 -0400 @@ -0,0 +1,270 @@ +// This file implements the IEnumShellItems Interface and Gateway for Python. +// Generated by makegw.py + +#include "shell_pch.h" +#include "PyIEnumShellItems.h" + +// @doc - This file contains autoduck documentation + +// --------------------------------------------------- +// +// Interface Implementation + +PyIEnumShellItems::PyIEnumShellItems(IUnknown *pdisp): + PyIUnknown(pdisp) +{ + ob_type = &type; +} + +PyIEnumShellItems::~PyIEnumShellItems() +{ +} + +/* static */ IEnumShellItems *PyIEnumShellItems::GetI(PyObject *self) +{ + return (IEnumShellItems *)PyIUnknown::GetI(self); +} + +// @pymethod (o <PyIShellItem>,...)|PyIEnumShellItems|Next|Retrieves a specified number of items in the enumeration sequence. +PyObject *PyIEnumShellItems::Next(PyObject *self, PyObject *args) +{ + long celt = 1; + // @pyparm int|num|1|Number of items to retrieve. + if ( !PyArg_ParseTuple(args, "|l:Next", &celt) ) + return NULL; + + IEnumShellItems *pIEShellItems = GetI(self); + if ( pIEShellItems == NULL ) + return NULL; + + IShellItem **rgVar = new IShellItem *[celt]; + if ( rgVar == NULL ) { + PyErr_SetString(PyExc_MemoryError, "allocating result ShellItemss"); + return NULL; + } + + int i; +/* for ( i = celt; i--; ) + // *** possibly init each structure element??? +*/ + + ULONG celtFetched = 0; + PY_INTERFACE_PRECALL; + HRESULT hr = pIEShellItems->Next(celt, rgVar, &celtFetched); + PY_INTERFACE_POSTCALL; + if ( HRESULT_CODE(hr) != ERROR_NO_MORE_ITEMS && FAILED(hr) ) + { + delete [] rgVar; + return PyCom_BuildPyException(hr,pIEShellItems, IID_IEnumShellItems); + } + + PyObject *result = PyTuple_New(celtFetched); + if ( result != NULL ) + { + for ( i = celtFetched; i--; ) + { + PyObject *ob = PyCom_PyObjectFromIUnknown(rgVar[i], IID_IShellItem, FALSE); + if ( ob == NULL ) + { + Py_DECREF(result); + result = NULL; + break; + } + PyTuple_SET_ITEM(result, i, ob); + } + } + /* ??? Could leak some of the returned interfaces if conversion fails, but how to tell + which ones have already been released when result is DECREF'd ? + Maybe always AddRef and always Release when done ??? + */ + if (result == NULL) + for ( i = celtFetched; i--; ) + rgVar[1]->Release(); + + delete [] rgVar; + return result; +} + +// @pymethod |PyIEnumShellItems|Skip|Skips over the next specified elementes. +PyObject *PyIEnumShellItems::Skip(PyObject *self, PyObject *args) +{ + long celt; + if ( !PyArg_ParseTuple(args, "l:Skip", &celt) ) + return NULL; + + IEnumShellItems *pIEShellItems = GetI(self); + if ( pIEShellItems == NULL ) + return NULL; + + PY_INTERFACE_PRECALL; + HRESULT hr = pIEShellItems->Skip(celt); + PY_INTERFACE_POSTCALL; + if ( FAILED(hr) ) + return PyCom_BuildPyException(hr, pIEShellItems, IID_IEnumShellItems); + + Py_INCREF(Py_None); + return Py_None; +} + +// @pymethod |PyIEnumShellItems|Reset|Resets the enumeration sequence to the beginning. +PyObject *PyIEnumShellItems::Reset(PyObject *self, PyObject *args) +{ + if ( !PyArg_ParseTuple(args, ":Reset") ) + return NULL; + + IEnumShellItems *pIEShellItems = GetI(self); + if ( pIEShellItems == NULL ) + return NULL; + + PY_INTERFACE_PRECALL; + HRESULT hr = pIEShellItems->Reset(); + PY_INTERFACE_POSTCALL; + if ( FAILED(hr) ) + return PyCom_BuildPyException(hr, pIEShellItems, IID_IEnumShellItems); + + Py_INCREF(Py_None); + return Py_None; +} + +// @pymethod <o PyIEnumShellItems>|PyIEnumShellItems|Clone|Creates another enumerator that contains the same enumeration state as the current one +PyObject *PyIEnumShellItems::Clone(PyObject *self, PyObject *args) +{ + if ( !PyArg_ParseTuple(args, ":Clone") ) + return NULL; + + IEnumShellItems *pIEShellItems = GetI(self); + if ( pIEShellItems == NULL ) + return NULL; + + IEnumShellItems *pClone; + PY_INTERFACE_PRECALL; + HRESULT hr = pIEShellItems->Clone(&pClone); + PY_INTERFACE_POSTCALL; + if ( FAILED(hr) ) + return PyCom_BuildPyException(hr, pIEShellItems, IID_IEnumShellItems); + + return PyCom_PyObjectFromIUnknown(pClone, IID_IEnumShellItems, FALSE); +} + +// @object PyIEnumShellItems|A Python interface to IEnumShellItems +static struct PyMethodDef PyIEnumShellItems_methods[] = +{ + { "Next", PyIEnumShellItems::Next, 1 }, // @pymeth Next|Retrieves a specified number of items in the enumeration sequence. + { "Skip", PyIEnumShellItems::Skip, 1 }, // @pymeth Skip|Skips over the next specified elementes. + { "Reset", PyIEnumShellItems::Reset, 1 }, // @pymeth Reset|Resets the enumeration sequence to the beginning. + { "Clone", PyIEnumShellItems::Clone, 1 }, // @pymeth Clone|Creates another enumerator that contains the same enumeration state as the current one. + { NULL } +}; + +PyComEnumTypeObject PyIEnumShellItems::type("PyIEnumShellItems", + &PyIUnknown::type, + sizeof(PyIEnumShellItems), + PyIEnumShellItems_methods, + GET_PYCOM_CTOR(PyIEnumShellItems)); + +// --------------------------------------------------- +// +// Gateway Implementation +STDMETHODIMP PyGEnumShellItems::Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ IShellItem __RPC_FAR * __RPC_FAR *rgVar, + /* [out] */ ULONG __RPC_FAR *pCeltFetched) +{ + PY_GATEWAY_METHOD; + PyObject *result; + HRESULT hr = InvokeViaPolicy("Next", &result, "i", celt); + if ( FAILED(hr) ) + return hr; + + if ( !PySequence_Check(result) ) + goto error; + int len; + len = PyObject_Length(result); + if ( len == -1 ) + goto error; + if ( len > (int)celt) + len = celt; + + if ( pCeltFetched ) + *pCeltFetched = len; + + int i; + for ( i = 0; i < len; ++i ) + { + PyObject *ob = PySequence_GetItem(result, i); + if ( ob == NULL ) + goto error; + + if ( !PyCom_InterfaceFromPyObject(ob, IID_IShellItem, (void **)&rgVar[i], FALSE) ) + { + Py_DECREF(result); + return PyCom_SetCOMErrorFromPyException(IID_IEnumShellItems); + } + } + + Py_DECREF(result); + + return len < (int)celt ? S_FALSE : S_OK; + + error: + PyErr_Clear(); // just in case + Py_DECREF(result); + return PyCom_SetCOMErrorFromSimple(E_FAIL, IID_IEnumShellItems, "Next() did not return a sequence of objects"); +} + +STDMETHODIMP PyGEnumShellItems::Skip( + /* [in] */ ULONG celt) +{ + PY_GATEWAY_METHOD; + return InvokeViaPolicy("Skip", NULL, "i", celt); +} + +STDMETHODIMP PyGEnumShellItems::Reset(void) +{ + PY_GATEWAY_METHOD; + return InvokeViaPolicy("Reset"); +} + +STDMETHODIMP PyGEnumShellItems::Clone( + /* [out] */ IEnumShellItems __RPC_FAR *__RPC_FAR *ppEnum) +{ + PY_GATEWAY_METHOD; + PyObject * result; + HRESULT hr = InvokeViaPolicy("Clone", &result); + if ( FAILED(hr) ) + return hr; + + /* + ** Make sure we have the right kind of object: we should have some kind + ** of IUnknown subclass wrapped into a PyIUnknown instance. + */ + if ( !PyIBase::is_object(result, &PyIUnknown::type) ) + { + /* the wrong kind of object was returned to us */ + Py_DECREF(result); + return PyCom_SetCOMErrorFromSimple(E_FAIL, IID_IEnumShellItems); + } + + /* + ** Get the IUnknown out of the thing. note that the Python ob maintains + ** a reference, so we don't have to explicitly AddRef() here. |