Ejemplo n.º 1
0
// @pymethod |PyIOleObject|GetExtent|Description of GetExtent.
PyObject *PyIOleObject::GetExtent(PyObject *self, PyObject *args)
{
	IOleObject *pIOO = GetI(self);
	if ( pIOO == NULL )
		return NULL;
	// @pyparm int|dwDrawAspect||Description for dwDrawAspect
	// @pyparm (int, int)|size||Size limit for the object. 
	DWORD dwDrawAspect;
	if ( !PyArg_ParseTuple(args, "i:GetExtent", &dwDrawAspect) )
		return NULL;
	HRESULT hr;
	SIZEL sizel;
	PY_INTERFACE_PRECALL;

	hr = pIOO->GetExtent( dwDrawAspect, &sizel );

	PY_INTERFACE_POSTCALL;

	if ( FAILED(hr) )
		return OleSetOleError(hr);
	return Py_BuildValue("ll", sizel.cx, sizel.cy);

}
Ejemplo n.º 2
0
// @pymethod str, <o WIN32_FIND_DATA>|PyIShellLink|GetPath|Retrieves the target path and file name of a shell link object
// @comm The AlternateFileName (8.3) member of WIN32_FIND_DATA does not return information
PyObject *PyIShellLink::GetPath(PyObject *self, PyObject *args)
{
	IShellLink *pISL = GetI(self);
	if ( pISL == NULL )
		return NULL;
	WIN32_FIND_DATA fd;
	// @pyparm int|fFlags||One of the following values:
	// @flagh Value|Description
	// @flag SLGP_SHORTPATH|Retrieves the standard short (8.3 format) file name.  
	// @flag SLGP_UNCPRIORITY|Retrieves the Universal Naming Convention (UNC) path name of the file.  
	// @flag SLGP_RAWPATH|Retrieves the raw path name. A raw path is something that might not exist and may include environment variables that need to be expanded. 
	// @pyparm int|cchMaxPath|_MAX_PATH|Number of characters to allocate for returned filename
	int cchMaxPath = _MAX_PATH;
	DWORD fFlags;
	if ( !PyArg_ParseTuple(args, "l|i:GetPath", &fFlags, &cchMaxPath) )
		return NULL;
	HRESULT hr;
	TCHAR *pszFile = (TCHAR *)malloc(cchMaxPath * sizeof(TCHAR));
	if (pszFile==NULL) {
		PyErr_SetString(PyExc_MemoryError, "allocating string buffer");
		return NULL;
	}
	ZeroMemory(&fd, sizeof(fd));
	PY_INTERFACE_PRECALL;
	hr = pISL->GetPath( pszFile, cchMaxPath, &fd, fFlags );
	PY_INTERFACE_POSTCALL;

	if ( FAILED(hr) ) {
		free(pszFile);
		return OleSetOleError(hr);
	}
	PyObject *ret = Py_BuildValue("NN",
		PyWinObject_FromTCHAR(pszFile),
		PyObject_FromWIN32_FIND_DATA(&fd));
	free(pszFile);
	return ret;
}
Ejemplo n.º 3
0
// @object PySSortOrderSet|An object describing a SortOrderSet.
// @pyparm ( <o PySSortOrderItem>, ...)|sortItems||The items to sort by
// @pyparm int|cCategories|0|
// @pyparm int|cExpanded|0|
BOOL PyMAPIObject_AsSSortOrderSet(PyObject *obsos, SSortOrderSet **ppsos, BOOL bNoneOK /*= TRUE */)
{
    if (obsos==Py_None) {
        if (bNoneOK) {
            *ppsos = NULL;
            return TRUE;
        } else {
            PyErr_SetString(PyExc_ValueError, "None is not a valid SSortOrderSet in this context");
            return FALSE;
        }
    } else {
        ULONG cCategories=0, cExpanded=0;
        PyObject *obSorts;
        if (!PyArg_ParseTuple(obsos, "O|ll", &obSorts, &cCategories, &cExpanded)) {
            PyErr_Clear();
            PyErr_SetString(PyExc_TypeError, "A SortOrder object must be tuple of (sequence, cCategories=0, cExpanded=0)");
            return FALSE;
        }
        if (!PySequence_Check(obSorts)) {
            PyErr_SetString(PyExc_TypeError, "The first object must be a sequence");
            return FALSE;
        }
        ULONG numSorts = PySequence_Length(obSorts);
        HRESULT hr;
        if (S_OK != (hr=MAPIAllocateBuffer(sizeof(SSortOrderSet) + (sizeof(SSortOrder) * numSorts), (void **)ppsos))) {
            OleSetOleError(hr);
            return FALSE;
        }
        BOOL ok = TRUE;
        (*ppsos)->cSorts = numSorts;
        (*ppsos)->cCategories = cCategories;
        (*ppsos)->cExpanded = cExpanded;
        ok = ok && PyMAPIObject_BuildSSortOrderSet(obSorts, *ppsos);
        if (!ok) MAPIFreeBuffer(*ppsos);
        return ok;
    }
}
Ejemplo n.º 4
0
// @pymethod |PyIShellLink|SetIDList|Sets the target of the link using an item id list
PyObject *PyIShellLink::SetIDList(PyObject *self, PyObject *args)
{
	IShellLink *pISL = GetI(self);
	if ( pISL == NULL )
		return NULL;
	LPITEMIDLIST pidl;
	PyObject *obpidl;
	// @pyparm <o PyIDL>|pidl||Absolute item id list that identifies the target
	if ( !PyArg_ParseTuple(args, "O:SetIDList", &obpidl) )
		return NULL;
	if (!PyObject_AsPIDL( obpidl, &pidl ))
		return NULL;
	HRESULT hr;
	PY_INTERFACE_PRECALL;
	hr = pISL->SetIDList( pidl );
	PY_INTERFACE_POSTCALL;

	PyObject_FreePIDL(pidl);

	if ( FAILED(hr) )
		return OleSetOleError(hr);
	Py_INCREF(Py_None);
	return Py_None;
}
Ejemplo n.º 5
0
// @pymethod |PyIShellLink|SetArguments|Sets the command-line arguments associated with a shell link object.
PyObject *PyIShellLink::SetArguments(PyObject *self, PyObject *args)
{
	IShellLink *pISL = GetI(self);
	if ( pISL == NULL )
		return NULL;
	PyObject *obArgs;
	// @pyparm str|args||The new arguments.
	if ( !PyArg_ParseTuple(args, "O:SetArguments", &obArgs) )
		return NULL;
	TCHAR *pszArgs;
	if (!PyWinObject_AsTCHAR(obArgs, &pszArgs))
		return NULL;
	HRESULT hr;
	PY_INTERFACE_PRECALL;
	hr = pISL->SetArguments( pszArgs );
	PY_INTERFACE_POSTCALL;
	PyWinObject_FreeTCHAR(pszArgs);

	if ( FAILED(hr) )
		return OleSetOleError(hr);
	Py_INCREF(Py_None);
	return Py_None;

}
Ejemplo n.º 6
0
// @pymethod |PyIShellLink|SetWorkingDirectory|Sets the working directory for the link.
PyObject *PyIShellLink::SetWorkingDirectory(PyObject *self, PyObject *args)
{
	IShellLink *pISL = GetI(self);
	if ( pISL == NULL )
		return NULL;
	PyObject *obName;
	// @pyparm str|Dir||The working directory for the link
	if ( !PyArg_ParseTuple(args, "O:SetWorkingDirectory", &obName) )
		return NULL;
	TCHAR *pszName;
	if (!PyWinObject_AsTCHAR(obName, &pszName))
		return NULL;
	HRESULT hr;
	PY_INTERFACE_PRECALL;
	hr = pISL->SetWorkingDirectory( pszName );
	PY_INTERFACE_POSTCALL;
	PyWinObject_FreeTCHAR(pszName);

	if ( FAILED(hr) )
		return OleSetOleError(hr);
	Py_INCREF(Py_None);
	return Py_None;

}
// @pymethod |PyIRemoteDebugApplicationEvents|OnConnectDebugger|Description of OnConnectDebugger.
PyObject *PyIRemoteDebugApplicationEvents::OnConnectDebugger(PyObject *self, PyObject *args)
{
	IRemoteDebugApplicationEvents *pIRDAE = GetI(self);
	if ( pIRDAE == NULL )
		return NULL;
	// @pyparm <o PyIApplicationDebugger>|pad||Description for pad
	PyObject *obpad;
	IApplicationDebugger *pad;
	if ( !PyArg_ParseTuple(args, "O:OnConnectDebugger", &obpad) )
		return NULL;
	BOOL bPythonIsHappy = TRUE;
	if (!PyCom_InterfaceFromPyInstanceOrObject(obpad, IID_IApplicationDebugger, (void **)&pad, FALSE /* bNoneOK */))
		 bPythonIsHappy = FALSE;
	if (!bPythonIsHappy) return NULL;
	PY_INTERFACE_PRECALL;
	HRESULT hr = pIRDAE->OnConnectDebugger( pad );
	pad->Release();
	PY_INTERFACE_POSTCALL;
	if ( FAILED(hr) )
		return OleSetOleError(hr);
	Py_INCREF(Py_None);
	return Py_None;

}
// @pymethod |PyIRemoteDebugApplicationEvents|OnDestroyThread|Description of OnDestroyThread.
PyObject *PyIRemoteDebugApplicationEvents::OnDestroyThread(PyObject *self, PyObject *args)
{
	IRemoteDebugApplicationEvents *pIRDAE = GetI(self);
	if ( pIRDAE == NULL )
		return NULL;
	// @pyparm <o PyIRemoteDebugApplicationThread>|prdat||Description for prdat
	PyObject *obprdat;
	IRemoteDebugApplicationThread *prdat;
	if ( !PyArg_ParseTuple(args, "O:OnDestroyThread", &obprdat) )
		return NULL;
	BOOL bPythonIsHappy = TRUE;
	if (!PyCom_InterfaceFromPyInstanceOrObject(obprdat, IID_IRemoteDebugApplicationThread, (void **)&prdat, FALSE /* bNoneOK */))
		 bPythonIsHappy = FALSE;
	if (!bPythonIsHappy) return NULL;
	PY_INTERFACE_PRECALL;
	HRESULT hr = pIRDAE->OnDestroyThread( prdat );
	prdat->Release();
	PY_INTERFACE_POSTCALL;
	if ( FAILED(hr) )
		return OleSetOleError(hr);
	Py_INCREF(Py_None);
	return Py_None;

}
Ejemplo n.º 9
0
// @pymethod |PyIOleObject|GetClipboardData|Description of GetClipboardData.
PyObject *PyIOleObject::GetClipboardData(PyObject *self, PyObject *args)
{
	IOleObject *pIOO = GetI(self);
	if ( pIOO == NULL )
		return NULL;
	// @pyparm int|dwReserved||Description for dwReserved
	DWORD dwReserved;
	IDataObject * ppDataObject;
	if ( !PyArg_ParseTuple(args, "i:GetClipboardData", &dwReserved) )
		return NULL;
	HRESULT hr;
	PY_INTERFACE_PRECALL;
	hr = pIOO->GetClipboardData( dwReserved, &ppDataObject );
	PY_INTERFACE_POSTCALL;

	if ( FAILED(hr) )
		return OleSetOleError(hr);
	PyObject *obppDataObject;

	obppDataObject = PyCom_PyObjectFromIUnknown(ppDataObject, IID_IDataObject, FALSE);
	PyObject *pyretval = Py_BuildValue("O", obppDataObject);
	Py_XDECREF(obppDataObject);
	return pyretval;
}
Ejemplo n.º 10
0
// @pymethod |PyIShellLink|SetIDList|Sets the list of item identifiers for a shell link object.
PyObject *PyIShellLink::SetIDList(PyObject *self, PyObject *args)
{
	IShellLink *pISL = GetI(self);
	if ( pISL == NULL )
		return NULL;
	LPITEMIDLIST pidl;
	PyObject *obpidl;
	if ( !PyArg_ParseTuple(args, "O:SetIDList", &obpidl) )
		return NULL;
	BOOL bPythonIsHappy = TRUE;
	if (bPythonIsHappy && !PyObject_AsPIDL( obpidl, &pidl )) bPythonIsHappy = FALSE;
	if (!bPythonIsHappy) return NULL;
	HRESULT hr;
	PY_INTERFACE_PRECALL;
	hr = pISL->SetIDList( pidl );
	PY_INTERFACE_POSTCALL;

	PyObject_FreePIDL(pidl);

	if ( FAILED(hr) )
		return OleSetOleError(hr);
	Py_INCREF(Py_None);
	return Py_None;
}
Ejemplo n.º 11
0
// @object PyMAPINAMEIDArray|A sequence (<o PyIID>, string/int) objects
BOOL PyMAPIObject_AsMAPINAMEIDArray(PyObject *ob, MAPINAMEID ***pppNameId, ULONG *pNumIds, BOOL bNoneOK /*= FALSE*/ )
{
    if (bNoneOK && ob==Py_None) {
        *pppNameId = NULL;
        *pNumIds = 0;
        return TRUE;
    }
    PyErr_Clear();
    ULONG len = (ULONG)PySequence_Length(ob);
    if (PyErr_Occurred()) {
        PyErr_Clear();
        PyErr_SetString(PyExc_TypeError, "MAPINAMEID array list be a sequence of tuples");
        return FALSE;
    }
    MAPINAMEID **ppNew = NULL;
    MAPINAMEID *prgIds = NULL;
    IID *pIIDs = NULL;
    HRESULT hr = MAPIAllocateBuffer(len * sizeof(MAPINAMEID *), (void **)&ppNew);
    if (SUCCEEDED(hr)) hr = MAPIAllocateMore(len * sizeof(MAPINAMEID), ppNew, (void **)&prgIds);
    if (SUCCEEDED(hr)) hr = MAPIAllocateMore(len * sizeof(IID), ppNew, (void **)&pIIDs);
    if (FAILED(hr)) {
        MAPIFreeBuffer(ppNew);
        OleSetOleError(hr);
        return FALSE;
    }
    for (ULONG i=0; i<len; i++) {
        ppNew[i] = prgIds+i;
        MAPINAMEID *pNew = prgIds+i;
        PyObject *obIID, *obPropId;
        PyObject *pMe = PySequence_GetItem(ob, i);
        if (pMe==NULL) {
            goto loop_error;
        }
        if (!PyArg_ParseTuple(pMe, "OO", &obIID, &obPropId )) {
            PyErr_Clear();
            PyErr_SetString(PyExc_TypeError, "MAPINAMEIDArray must be a sequence of (iid, string/int) tuples");
            goto loop_error;
        }

        pNew->lpguid = pIIDs+i;
        BSTR bstrVal;
        if (!PyWinObject_AsIID(obIID, pIIDs+i))
            goto loop_error;
        if (PyInt_Check(obPropId)) {
            pNew->ulKind = MNID_ID;
            pNew->Kind.lID = PyInt_AsLong(obPropId);
        } else if (PyWinObject_AsBstr(obPropId, &bstrVal)) {
            // Make a copy of the string
            pNew->ulKind = MNID_STRING;
            DWORD strLen = SysStringLen(bstrVal);
            hr = MAPIAllocateMore(sizeof(WCHAR) * (strLen+1), ppNew, (void **)&pNew->Kind.lpwstrName);
            if (FAILED(hr)) {
                PyWinObject_FreeBstr(bstrVal);
                OleSetOleError(hr);
                goto loop_error;
            }
            wcsncpy(pNew->Kind.lpwstrName, bstrVal, strLen+1);
            PyWinObject_FreeBstr(bstrVal);
        } else {
            PyErr_SetString(PyExc_TypeError, "The type of property ID is invalid - must be string/unicode or int");
            goto loop_error;
        }
        Py_DECREF(pMe);
        continue;
loop_error:
        Py_XDECREF(pMe);
        MAPIFreeBuffer(ppNew);
        return NULL;
    }
    *pppNameId = ppNew;
    *pNumIds = len;
    return TRUE;
}
Ejemplo n.º 12
0
// @object PySRowSet|A sequence of <o PySRow> objects, as passed to many MAPI functions.
BOOL PyMAPIObject_AsSRowSet(PyObject *obSeq, SRowSet **ppResult, BOOL bNoneOK)
{
    if (ppResult==NULL || obSeq==NULL)
        return FALSE;
    if (obSeq==NULL) return FALSE;
    *ppResult=NULL;
    if (obSeq==Py_None) {
        if (bNoneOK)
            return TRUE;
        PyErr_SetString(PyExc_ValueError, "None is not a valid SRowSet/ADRLIST in this context");
        return FALSE;
    }
    PyObject *rowObject = NULL;
    PyObject *propObject = NULL;
    BOOL rc = FALSE;
    HRESULT hr;
    ULONG i;
    DWORD allocSize;

    int seqLen = PySequence_Length(obSeq);

    if (seqLen==-1) {
        PyErr_SetString(PyExc_TypeError, "ADRLIST/SRowSet items must be a sequence");
        goto done;
    }

    allocSize = sizeof(SRowSet) + (sizeof(SRow) * seqLen);
    if (S_OK != (hr=MAPIAllocateBuffer(allocSize, (void **)ppResult))) {
        OleSetOleError(hr);
        goto done;
    }
    ZeroMemory(*ppResult, allocSize); // so cleanup works correctly.
    (*ppResult)->cRows = seqLen;

    for (i=0; i<(ULONG)seqLen; i++) {
        rowObject = PySequence_GetItem(obSeq, i);
        if (rowObject==NULL)
            goto done;
        // myob is expected to represent an SRow structure.  This is really an array
        // of property values.
        SRow *pRow = (*ppResult)->aRow+i;
        pRow->cValues = PySequence_Length(rowObject);
        if (pRow->cValues==-1)
            goto done;

        if (pRow->cValues==0)
            pRow->lpProps = NULL;
        else {
            allocSize = sizeof(SPropValue) * pRow->cValues;
            hr = MAPIAllocateBuffer(allocSize, (void **)&pRow->lpProps);
            if (FAILED(hr)) {
                OleSetOleError(hr);
                goto done;
            }
            for (ULONG j=0; j<pRow->cValues; j++) {
                propObject = PySequence_GetItem(rowObject, j);
                if (propObject==NULL)
                    goto done;
                if (!PyMAPIObject_AsSPropValue(propObject, pRow->lpProps+j, *ppResult))
                    goto done;
                Py_DECREF(propObject);
                propObject = NULL; // important for cleanup
            }
        }
        Py_DECREF(rowObject);
        rowObject = NULL; // important for cleanup
    }
    rc = TRUE;
done:
    if (!rc && (*ppResult)) {
        PyMAPIObject_FreeSRowSet(*ppResult);
    }
    Py_XDECREF(propObject);
    Py_XDECREF(rowObject);
    return rc;
}
Ejemplo n.º 13
0
// @object PySPropValue|A MAPI property value.  Property values can either be passed from
// python into MAPI functions, or returned from MAPI functions to Python.
BOOL PyMAPIObject_AsSPropValue(PyObject *Valob, SPropValue *pv, void *pAllocMoreLinkBlock)
{
    PyObject *ob;
    // @pyparm int|propType||The type of the MAPI property
    // @pyparm object|value||The property value
    if (!PyArg_ParseTuple(Valob, "lO:SPropValue item", &pv->ulPropTag, &ob )) {
        PyErr_Clear();
        PyErr_SetString(PyExc_TypeError, "An SPropValue item must be a tuple of (integer, object)");
        return NULL;
    }
    BOOL ok = TRUE;
    unsigned int i;
    PyErr_Clear();
    // @comm The parameters can be one of the following pairs of values.
    // @flagh propType|value
    switch (PROP_TYPE(pv->ulPropTag)) {
    // @flag PT_I2|An integer
    case PT_I2:	//		case PT_SHORT:
        pv->Value.i = (int)PyInt_AsLong(ob);
        break;
    // @flag PT_MV_I2|A sequence of integers
    case PT_MV_I2:
        MAKE_MV(short int, pAllocMoreLinkBlock, pv->Value.MVi.lpi, pv->Value.MVi.cValues, PyInt_AsLong)
    // @flag PT_I4|An integer
    case PT_I4: //		case PT_LONG:
        pv->Value.l = PyInt_AsLong(ob);
        break;
    // @flag PT_MV_I4|A sequence of integers
    case PT_MV_I4:
        MAKE_MV(long, pAllocMoreLinkBlock, pv->Value.MVl.lpl, pv->Value.MVl.cValues, PyInt_AsLong)
    // @flag PT_R4|A float
    case PT_R4: //		case PT_FLOAT:
        pv->Value.flt = (float)PyFloat_AsDouble(ob);
        break;
    // @flag PT_MV_R4|A sequence of floats
    case PT_MV_R4:
        MAKE_MV(float, pAllocMoreLinkBlock, pv->Value.MVflt.lpflt, pv->Value.MVflt.cValues, PyFloat_AsDouble)
    // @flag PT_R8|A float
    case PT_R8: //		case PT_DOUBLE:
        pv->Value.dbl = PyFloat_AsDouble(ob);
        break;
    // @flag PT_MV_R8|A sequence of floats
    case PT_MV_R8:
        MAKE_MV(double, pAllocMoreLinkBlock, pv->Value.MVdbl.lpdbl, pv->Value.MVdbl.cValues, PyFloat_AsDouble)
    // @flag PT_BOOLEAN|A boolean value (or an int)
    case PT_BOOLEAN:
        pv->Value.b = PyInt_AsLong(ob) ? VARIANT_TRUE : VARIANT_FALSE;
        break;

    /*
    		case PT_CURRENCY:
    			p->Value.cur ??
    			break;

    */
    // @flag PT_APPTIME|A <o PyTime> object
    case PT_APPTIME :
        ok = PyWinObject_AsDATE(ob, &pv->Value.at);
        break;

    // @flag PT_MV_APPTIME|An sequence of <o PyTime> object
    case PT_MV_APPTIME:
        MAKEB_MV(double, pAllocMoreLinkBlock, pv->Value.MVat.lpat, pv->Value.MVat.cValues, PyWinObject_AsDATE)

    // @flag PT_SYSTIME|A <o PyTime> object
    case PT_SYSTIME:
        ok = PyWinObject_AsFILETIME(ob, &pv->Value.ft);
        break;

    // @flag PT_MV_APPTIME|An sequence of <o PyTime> object
    case PT_MV_SYSTIME:
        MAKEB_MV(FILETIME, pAllocMoreLinkBlock, pv->Value.MVft.lpft, pv->Value.MVft.cValues, PyWinObject_AsFILETIME)

    // @flag PT_STRING8|A string or <o PyUnicode>
    case PT_STRING8:
    {   // Copy into new MAPI memory block
        DWORD bufLen;
        char *str;
        ok = PyWinObject_AsString(ob, &str, FALSE, &bufLen);
        if (ok) {
            bufLen++;
            HRESULT hr = MAPIAllocateMore(bufLen, pAllocMoreLinkBlock, (void **)&pv->Value.lpszA);
            if (S_OK!=hr) {
                OleSetOleError(hr);
                ok = FALSE;
            } else {
                memcpy(pv->Value.lpszA, str, bufLen-sizeof(char));
                // Null terminate
                memcpy(((char *)pv->Value.lpszA)+(bufLen-sizeof(char)),"\0", sizeof(char));
            }
        }
        PyWinObject_FreeString(str);
        break;
    }

    // @flag PT_STRING8|A sequence of string or <o PyUnicode> objects.
    case PT_MV_STRING8:
        ok = AllocMVBuffer( ob, sizeof(char *), pAllocMoreLinkBlock, (void **)&pv->Value.MVszA.lppszA, &pv->Value.MVszA.cValues);
        if (!ok) break;
        for (i=0; ok && !PyErr_Occurred() && i<pv->Value.MVszA.cValues; i++) {
            PyObject *obmv=PySequence_GetItem(ob,i);
            if (obmv==NULL) break;

            DWORD bufLen;
            char *str;
            ok = PyWinObject_AsString(obmv, &str, FALSE, &bufLen);
            if (ok) {
                bufLen++;
                HRESULT hr = MAPIAllocateMore(bufLen, pAllocMoreLinkBlock, (void **)&pv->Value.MVszA.lppszA[i]);
                if (S_OK!=hr) {
                    OleSetOleError(hr);
                    ok = FALSE;
                } else {
                    memcpy(pv->Value.MVszA.lppszA[i], str, bufLen-sizeof(char));
                    // Null terminate
                    memcpy(((char *)pv->Value.MVszA.lppszA[i])+(bufLen-sizeof(char)),"\0", sizeof(char));
                }
            }
            PyWinObject_FreeString(str);
            Py_DECREF(obmv);
        }
        break;

    // @flag PT_UNICODE|A string or <o PyUnicode>
    case PT_UNICODE:
    {   // Bit of a hack - need to copy into MAPI block.
        BSTR wstr = NULL;
        ok = PyWinObject_AsBstr(ob, &wstr, FALSE);
        if (ok) {
            DWORD bufSize = sizeof(WCHAR) * (SysStringLen(wstr)+1);
            HRESULT hr = MAPIAllocateMore(bufSize, pAllocMoreLinkBlock, (void **)&pv->Value.lpszW);
            if (S_OK!=hr) {
                OleSetOleError(hr);
                ok = FALSE;
            } else {
                memcpy(pv->Value.lpszW, wstr, bufSize-2);
                // Null terminate
                memcpy(((char *)pv->Value.lpszW)+(bufSize-2),"\0\0", 2);
            }
        }
        SysFreeString(wstr);
        break;
    }

    // @flag PT_MV_UNICODE|A sequence of string or <o PyUnicode>
    case PT_MV_UNICODE:
        ok = AllocMVBuffer( ob, sizeof(char *), pAllocMoreLinkBlock, (void **)&pv->Value.MVszW.lppszW, &pv->Value.MVszW.cValues);
        if (!ok) break;
        for (i=0; ok && !PyErr_Occurred() && i<pv->Value.MVszW.cValues; i++) {
            PyObject *obmv=PySequence_GetItem(ob,i);
            if (obmv==NULL) break;

            BSTR wstr = NULL;
            ok = PyWinObject_AsBstr(obmv, &wstr, FALSE);
            if (ok) {
                DWORD bufSize = sizeof(WCHAR) * (SysStringLen(wstr)+1);
                HRESULT hr = MAPIAllocateMore(bufSize, pAllocMoreLinkBlock, (void **)&pv->Value.MVszW.lppszW[i]);
                if (S_OK!=hr) {
                    OleSetOleError(hr);
                    ok = FALSE;
                } else {
                    memcpy(pv->Value.MVszW.lppszW[i], wstr, bufSize-2);
                    // Null terminate
                    memcpy(((char *)pv->Value.MVszW.lppszW[i])+(bufSize-2),"\0\0", 2);
                }
            }
            SysFreeString(wstr);
            Py_DECREF(obmv);
        }
        break;

    // @flag PT_BINARY|A string containing binary data
    case PT_BINARY:
        pv->Value.bin.lpb = (unsigned char *)PyString_AsString(ob);
        pv->Value.bin.cb = PyString_Size(ob);
        break;

    // @flag PT_MV_BINARY|A sequence of strings containing binary data
    case PT_MV_BINARY:
        ok = AllocMVBuffer( ob, sizeof(SBinary), pAllocMoreLinkBlock, (void **)&pv->Value.MVbin.lpbin, &pv->Value.MVbin.cValues);
        for (i=0; !PyErr_Occurred() && i<pv->Value.MVbin.cValues; i++) {
            PyObject *obmv=PySequence_GetItem(ob,i);
            if (obmv==NULL) break;
            pv->Value.MVbin.lpbin[i].lpb = (unsigned char *)PyString_AsString(ob);
            pv->Value.MVbin.lpbin[i].cb = PyString_Size(ob);
            Py_DECREF(obmv);
        }
        break;

    // @flag PT_CLSID|A <o PyIID>
    case PT_CLSID:
    {
        HRESULT hr = MAPIAllocateMore(sizeof(CLSID), pAllocMoreLinkBlock, (void **)&pv->Value.lpguid);
        if (S_OK != hr) {
            OleSetOleError(hr);
            ok = FALSE;
        } else
            ok = PyWinObject_AsIID(ob, pv->Value.lpguid);
        break;
    }

    // @flag PT_MV_CLSID|A sequence of <o PyIID> objects
    case PT_MV_CLSID:
        MAKEB_MV(CLSID, pAllocMoreLinkBlock, pv->Value.MVguid.lpguid, pv->Value.MVguid.cValues, PyWinObject_AsIID)

    // @flag PT_I8|A <o PyLARGE_INTEGER>
    case PT_I8:
//		case PT_LONGLONG:
        ok = PyWinObject_AsLARGE_INTEGER(ob, &pv->Value.li);
        break;

    // @flag PT_MV_I8|A sequence of <o PyLARGE_INTEGER>
    case PT_MV_I8:
        MAKEB_MV(LARGE_INTEGER, pAllocMoreLinkBlock, pv->Value.MVli.lpli, pv->Value.MVli.cValues, PyWinObject_AsLARGE_INTEGER)

    // @flag PT_ERROR|An integer error code.
    case PT_ERROR:
        pv->Value.err = (SCODE)PyInt_AsLong(ob);
        break;

    // @flag PT_NULL|Anything!
    case PT_NULL:
        pv->Value.x = 0;
        break;

    default: {
        char buf[128];
        sprintf(buf, "Unsupported MAPI property type 0x%X", PROP_TYPE(pv->ulPropTag));
        PyErr_SetString(PyExc_TypeError, buf);
        ok = FALSE;
    }
    }
    ok = (ok && !PyErr_Occurred());
    return ok;
}