1*c2c66affSColin Finck /* 2*c2c66affSColin Finck * Property functions 3*c2c66affSColin Finck * 4*c2c66affSColin Finck * Copyright 2004 Jon Griffiths 5*c2c66affSColin Finck * 6*c2c66affSColin Finck * This library is free software; you can redistribute it and/or 7*c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public 8*c2c66affSColin Finck * License as published by the Free Software Foundation; either 9*c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version. 10*c2c66affSColin Finck * 11*c2c66affSColin Finck * This library is distributed in the hope that it will be useful, 12*c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14*c2c66affSColin Finck * Lesser General Public License for more details. 15*c2c66affSColin Finck * 16*c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public 17*c2c66affSColin Finck * License along with this library; if not, write to the Free Software 18*c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19*c2c66affSColin Finck */ 20*c2c66affSColin Finck 21*c2c66affSColin Finck #include "precomp.h" 22*c2c66affSColin Finck 23*c2c66affSColin Finck #include <wine/list.h> 24*c2c66affSColin Finck 25*c2c66affSColin Finck BOOL WINAPI FBadRglpszA(LPSTR*,ULONG); 26*c2c66affSColin Finck 27*c2c66affSColin Finck /* Internal: Check if a property value array is invalid */ 28*c2c66affSColin Finck static inline ULONG PROP_BadArray(LPSPropValue lpProp, size_t elemSize) 29*c2c66affSColin Finck { 30*c2c66affSColin Finck return IsBadReadPtr(lpProp->Value.MVi.lpi, lpProp->Value.MVi.cValues * elemSize); 31*c2c66affSColin Finck } 32*c2c66affSColin Finck 33*c2c66affSColin Finck /************************************************************************* 34*c2c66affSColin Finck * PropCopyMore@16 (MAPI32.76) 35*c2c66affSColin Finck * 36*c2c66affSColin Finck * Copy a property value. 37*c2c66affSColin Finck * 38*c2c66affSColin Finck * PARAMS 39*c2c66affSColin Finck * lpDest [O] Destination for the copied value 40*c2c66affSColin Finck * lpSrc [I] Property value to copy to lpDest 41*c2c66affSColin Finck * lpMore [I] Linked memory allocation function (pass MAPIAllocateMore()) 42*c2c66affSColin Finck * lpOrig [I] Original allocation to which memory will be linked 43*c2c66affSColin Finck * 44*c2c66affSColin Finck * RETURNS 45*c2c66affSColin Finck * Success: S_OK. lpDest contains a deep copy of lpSrc. 46*c2c66affSColin Finck * Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid, 47*c2c66affSColin Finck * MAPI_E_NOT_ENOUGH_MEMORY, if memory allocation fails. 48*c2c66affSColin Finck * 49*c2c66affSColin Finck * NOTES 50*c2c66affSColin Finck * Any elements within the property returned should not be individually 51*c2c66affSColin Finck * freed, as they will be freed when lpOrig is. 52*c2c66affSColin Finck */ 53*c2c66affSColin Finck SCODE WINAPI PropCopyMore(LPSPropValue lpDest, LPSPropValue lpSrc, 54*c2c66affSColin Finck ALLOCATEMORE *lpMore, LPVOID lpOrig) 55*c2c66affSColin Finck { 56*c2c66affSColin Finck ULONG ulLen, i; 57*c2c66affSColin Finck SCODE scode = S_OK; 58*c2c66affSColin Finck 59*c2c66affSColin Finck TRACE("(%p,%p,%p,%p)\n", lpDest, lpSrc, lpMore, lpOrig); 60*c2c66affSColin Finck 61*c2c66affSColin Finck if (!lpDest || IsBadWritePtr(lpDest, sizeof(SPropValue)) || 62*c2c66affSColin Finck FBadProp(lpSrc) || !lpMore) 63*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 64*c2c66affSColin Finck 65*c2c66affSColin Finck /* Shallow copy first, this is sufficient for properties without pointers */ 66*c2c66affSColin Finck *lpDest = *lpSrc; 67*c2c66affSColin Finck 68*c2c66affSColin Finck switch (PROP_TYPE(lpSrc->ulPropTag)) 69*c2c66affSColin Finck { 70*c2c66affSColin Finck case PT_CLSID: 71*c2c66affSColin Finck scode = lpMore(sizeof(GUID), lpOrig, (LPVOID*)&lpDest->Value.lpguid); 72*c2c66affSColin Finck if (SUCCEEDED(scode)) 73*c2c66affSColin Finck *lpDest->Value.lpguid = *lpSrc->Value.lpguid; 74*c2c66affSColin Finck break; 75*c2c66affSColin Finck case PT_STRING8: 76*c2c66affSColin Finck ulLen = lstrlenA(lpSrc->Value.lpszA) + 1u; 77*c2c66affSColin Finck scode = lpMore(ulLen, lpOrig, (LPVOID*)&lpDest->Value.lpszA); 78*c2c66affSColin Finck if (SUCCEEDED(scode)) 79*c2c66affSColin Finck memcpy(lpDest->Value.lpszA, lpSrc->Value.lpszA, ulLen); 80*c2c66affSColin Finck break; 81*c2c66affSColin Finck case PT_UNICODE: 82*c2c66affSColin Finck ulLen = (strlenW(lpSrc->Value.lpszW) + 1u) * sizeof(WCHAR); 83*c2c66affSColin Finck scode = lpMore(ulLen, lpOrig, (LPVOID*)&lpDest->Value.lpszW); 84*c2c66affSColin Finck if (SUCCEEDED(scode)) 85*c2c66affSColin Finck memcpy(lpDest->Value.lpszW, lpSrc->Value.lpszW, ulLen); 86*c2c66affSColin Finck break; 87*c2c66affSColin Finck case PT_BINARY: 88*c2c66affSColin Finck scode = lpMore(lpSrc->Value.bin.cb, lpOrig, (LPVOID*)&lpDest->Value.bin.lpb); 89*c2c66affSColin Finck if (SUCCEEDED(scode)) 90*c2c66affSColin Finck memcpy(lpDest->Value.bin.lpb, lpSrc->Value.bin.lpb, lpSrc->Value.bin.cb); 91*c2c66affSColin Finck break; 92*c2c66affSColin Finck default: 93*c2c66affSColin Finck if (lpSrc->ulPropTag & MV_FLAG) 94*c2c66affSColin Finck { 95*c2c66affSColin Finck ulLen = UlPropSize(lpSrc); 96*c2c66affSColin Finck 97*c2c66affSColin Finck if (PROP_TYPE(lpSrc->ulPropTag) == PT_MV_STRING8 || 98*c2c66affSColin Finck PROP_TYPE(lpSrc->ulPropTag) == PT_MV_UNICODE) 99*c2c66affSColin Finck { 100*c2c66affSColin Finck /* UlPropSize doesn't account for the string pointers */ 101*c2c66affSColin Finck ulLen += lpSrc->Value.MVszA.cValues * sizeof(char*); 102*c2c66affSColin Finck } 103*c2c66affSColin Finck else if (PROP_TYPE(lpSrc->ulPropTag) == PT_MV_BINARY) 104*c2c66affSColin Finck { 105*c2c66affSColin Finck /* UlPropSize doesn't account for the SBinary structs */ 106*c2c66affSColin Finck ulLen += lpSrc->Value.MVbin.cValues * sizeof(SBinary); 107*c2c66affSColin Finck } 108*c2c66affSColin Finck 109*c2c66affSColin Finck lpDest->Value.MVi.cValues = lpSrc->Value.MVi.cValues; 110*c2c66affSColin Finck scode = lpMore(ulLen, lpOrig, (LPVOID*)&lpDest->Value.MVi.lpi); 111*c2c66affSColin Finck if (FAILED(scode)) 112*c2c66affSColin Finck break; 113*c2c66affSColin Finck 114*c2c66affSColin Finck /* Note that we could allocate the memory for each value in a 115*c2c66affSColin Finck * multi-value property separately, however if an allocation failed 116*c2c66affSColin Finck * we would be left with a bunch of allocated memory, which (while 117*c2c66affSColin Finck * not really leaked) is unusable until lpOrig is freed. So for 118*c2c66affSColin Finck * strings and binary arrays we make a single allocation for all 119*c2c66affSColin Finck * of the data. This is consistent since individual elements can't 120*c2c66affSColin Finck * be freed anyway. 121*c2c66affSColin Finck */ 122*c2c66affSColin Finck 123*c2c66affSColin Finck switch (PROP_TYPE(lpSrc->ulPropTag)) 124*c2c66affSColin Finck { 125*c2c66affSColin Finck case PT_MV_STRING8: 126*c2c66affSColin Finck { 127*c2c66affSColin Finck char *lpNextStr = (char*)(lpDest->Value.MVszA.lppszA + 128*c2c66affSColin Finck lpDest->Value.MVszA.cValues); 129*c2c66affSColin Finck 130*c2c66affSColin Finck for (i = 0; i < lpSrc->Value.MVszA.cValues; i++) 131*c2c66affSColin Finck { 132*c2c66affSColin Finck ULONG ulStrLen = lstrlenA(lpSrc->Value.MVszA.lppszA[i]) + 1u; 133*c2c66affSColin Finck 134*c2c66affSColin Finck lpDest->Value.MVszA.lppszA[i] = lpNextStr; 135*c2c66affSColin Finck memcpy(lpNextStr, lpSrc->Value.MVszA.lppszA[i], ulStrLen); 136*c2c66affSColin Finck lpNextStr += ulStrLen; 137*c2c66affSColin Finck } 138*c2c66affSColin Finck break; 139*c2c66affSColin Finck } 140*c2c66affSColin Finck case PT_MV_UNICODE: 141*c2c66affSColin Finck { 142*c2c66affSColin Finck WCHAR *lpNextStr = (WCHAR*)(lpDest->Value.MVszW.lppszW + 143*c2c66affSColin Finck lpDest->Value.MVszW.cValues); 144*c2c66affSColin Finck 145*c2c66affSColin Finck for (i = 0; i < lpSrc->Value.MVszW.cValues; i++) 146*c2c66affSColin Finck { 147*c2c66affSColin Finck ULONG ulStrLen = strlenW(lpSrc->Value.MVszW.lppszW[i]) + 1u; 148*c2c66affSColin Finck 149*c2c66affSColin Finck lpDest->Value.MVszW.lppszW[i] = lpNextStr; 150*c2c66affSColin Finck memcpy(lpNextStr, lpSrc->Value.MVszW.lppszW[i], ulStrLen * sizeof(WCHAR)); 151*c2c66affSColin Finck lpNextStr += ulStrLen; 152*c2c66affSColin Finck } 153*c2c66affSColin Finck break; 154*c2c66affSColin Finck } 155*c2c66affSColin Finck case PT_MV_BINARY: 156*c2c66affSColin Finck { 157*c2c66affSColin Finck LPBYTE lpNext = (LPBYTE)(lpDest->Value.MVbin.lpbin + 158*c2c66affSColin Finck lpDest->Value.MVbin.cValues); 159*c2c66affSColin Finck 160*c2c66affSColin Finck for (i = 0; i < lpSrc->Value.MVszW.cValues; i++) 161*c2c66affSColin Finck { 162*c2c66affSColin Finck lpDest->Value.MVbin.lpbin[i].cb = lpSrc->Value.MVbin.lpbin[i].cb; 163*c2c66affSColin Finck lpDest->Value.MVbin.lpbin[i].lpb = lpNext; 164*c2c66affSColin Finck memcpy(lpNext, lpSrc->Value.MVbin.lpbin[i].lpb, lpDest->Value.MVbin.lpbin[i].cb); 165*c2c66affSColin Finck lpNext += lpDest->Value.MVbin.lpbin[i].cb; 166*c2c66affSColin Finck } 167*c2c66affSColin Finck break; 168*c2c66affSColin Finck } 169*c2c66affSColin Finck default: 170*c2c66affSColin Finck /* No embedded pointers, just copy the data over */ 171*c2c66affSColin Finck memcpy(lpDest->Value.MVi.lpi, lpSrc->Value.MVi.lpi, ulLen); 172*c2c66affSColin Finck break; 173*c2c66affSColin Finck } 174*c2c66affSColin Finck break; 175*c2c66affSColin Finck } 176*c2c66affSColin Finck } 177*c2c66affSColin Finck return scode; 178*c2c66affSColin Finck } 179*c2c66affSColin Finck 180*c2c66affSColin Finck /************************************************************************* 181*c2c66affSColin Finck * UlPropSize@4 (MAPI32.77) 182*c2c66affSColin Finck * 183*c2c66affSColin Finck * Determine the size of a property in bytes. 184*c2c66affSColin Finck * 185*c2c66affSColin Finck * PARAMS 186*c2c66affSColin Finck * lpProp [I] Property to determine the size of 187*c2c66affSColin Finck * 188*c2c66affSColin Finck * RETURNS 189*c2c66affSColin Finck * Success: The size of the value in lpProp. 190*c2c66affSColin Finck * Failure: 0, if a multi-value (array) property is invalid or the type of lpProp 191*c2c66affSColin Finck * is unknown. 192*c2c66affSColin Finck * 193*c2c66affSColin Finck * NOTES 194*c2c66affSColin Finck * - The size returned does not include the size of the SPropValue struct 195*c2c66affSColin Finck * or the size of the array of pointers for multi-valued properties that 196*c2c66affSColin Finck * contain pointers (such as PT_MV_STRING8 or PT-MV_UNICODE). 197*c2c66affSColin Finck * - MSDN incorrectly states that this function returns MAPI_E_CALL_FAILED if 198*c2c66affSColin Finck * lpProp is invalid. In reality no checking is performed and this function 199*c2c66affSColin Finck * will crash if passed an invalid property, or return 0 if the property 200*c2c66affSColin Finck * type is PT_OBJECT or is unknown. 201*c2c66affSColin Finck */ 202*c2c66affSColin Finck ULONG WINAPI UlPropSize(LPSPropValue lpProp) 203*c2c66affSColin Finck { 204*c2c66affSColin Finck ULONG ulRet = 1u, i; 205*c2c66affSColin Finck 206*c2c66affSColin Finck TRACE("(%p)\n", lpProp); 207*c2c66affSColin Finck 208*c2c66affSColin Finck switch (PROP_TYPE(lpProp->ulPropTag)) 209*c2c66affSColin Finck { 210*c2c66affSColin Finck case PT_MV_I2: ulRet = lpProp->Value.MVi.cValues; 211*c2c66affSColin Finck /* fall through */ 212*c2c66affSColin Finck case PT_BOOLEAN: 213*c2c66affSColin Finck case PT_I2: ulRet *= sizeof(USHORT); 214*c2c66affSColin Finck break; 215*c2c66affSColin Finck case PT_MV_I4: ulRet = lpProp->Value.MVl.cValues; 216*c2c66affSColin Finck /* fall through */ 217*c2c66affSColin Finck case PT_ERROR: 218*c2c66affSColin Finck case PT_I4: ulRet *= sizeof(LONG); 219*c2c66affSColin Finck break; 220*c2c66affSColin Finck case PT_MV_I8: ulRet = lpProp->Value.MVli.cValues; 221*c2c66affSColin Finck /* fall through */ 222*c2c66affSColin Finck case PT_I8: ulRet *= sizeof(LONG64); 223*c2c66affSColin Finck break; 224*c2c66affSColin Finck case PT_MV_R4: ulRet = lpProp->Value.MVflt.cValues; 225*c2c66affSColin Finck /* fall through */ 226*c2c66affSColin Finck case PT_R4: ulRet *= sizeof(float); 227*c2c66affSColin Finck break; 228*c2c66affSColin Finck case PT_MV_APPTIME: 229*c2c66affSColin Finck case PT_MV_R8: ulRet = lpProp->Value.MVdbl.cValues; 230*c2c66affSColin Finck /* fall through */ 231*c2c66affSColin Finck case PT_APPTIME: 232*c2c66affSColin Finck case PT_R8: ulRet *= sizeof(double); 233*c2c66affSColin Finck break; 234*c2c66affSColin Finck case PT_MV_CURRENCY: ulRet = lpProp->Value.MVcur.cValues; 235*c2c66affSColin Finck /* fall through */ 236*c2c66affSColin Finck case PT_CURRENCY: ulRet *= sizeof(CY); 237*c2c66affSColin Finck break; 238*c2c66affSColin Finck case PT_MV_SYSTIME: ulRet = lpProp->Value.MVft.cValues; 239*c2c66affSColin Finck /* fall through */ 240*c2c66affSColin Finck case PT_SYSTIME: ulRet *= sizeof(FILETIME); 241*c2c66affSColin Finck break; 242*c2c66affSColin Finck case PT_MV_CLSID: ulRet = lpProp->Value.MVguid.cValues; 243*c2c66affSColin Finck /* fall through */ 244*c2c66affSColin Finck case PT_CLSID: ulRet *= sizeof(GUID); 245*c2c66affSColin Finck break; 246*c2c66affSColin Finck case PT_MV_STRING8: ulRet = 0u; 247*c2c66affSColin Finck for (i = 0; i < lpProp->Value.MVszA.cValues; i++) 248*c2c66affSColin Finck ulRet += (lstrlenA(lpProp->Value.MVszA.lppszA[i]) + 1u); 249*c2c66affSColin Finck break; 250*c2c66affSColin Finck case PT_STRING8: ulRet = lstrlenA(lpProp->Value.lpszA) + 1u; 251*c2c66affSColin Finck break; 252*c2c66affSColin Finck case PT_MV_UNICODE: ulRet = 0u; 253*c2c66affSColin Finck for (i = 0; i < lpProp->Value.MVszW.cValues; i++) 254*c2c66affSColin Finck ulRet += (strlenW(lpProp->Value.MVszW.lppszW[i]) + 1u); 255*c2c66affSColin Finck ulRet *= sizeof(WCHAR); 256*c2c66affSColin Finck break; 257*c2c66affSColin Finck case PT_UNICODE: ulRet = (lstrlenW(lpProp->Value.lpszW) + 1u) * sizeof(WCHAR); 258*c2c66affSColin Finck break; 259*c2c66affSColin Finck case PT_MV_BINARY: ulRet = 0u; 260*c2c66affSColin Finck for (i = 0; i < lpProp->Value.MVbin.cValues; i++) 261*c2c66affSColin Finck ulRet += lpProp->Value.MVbin.lpbin[i].cb; 262*c2c66affSColin Finck break; 263*c2c66affSColin Finck case PT_BINARY: ulRet = lpProp->Value.bin.cb; 264*c2c66affSColin Finck break; 265*c2c66affSColin Finck case PT_OBJECT: 266*c2c66affSColin Finck default: ulRet = 0u; 267*c2c66affSColin Finck break; 268*c2c66affSColin Finck } 269*c2c66affSColin Finck 270*c2c66affSColin Finck return ulRet; 271*c2c66affSColin Finck } 272*c2c66affSColin Finck 273*c2c66affSColin Finck /************************************************************************* 274*c2c66affSColin Finck * FPropContainsProp@12 (MAPI32.78) 275*c2c66affSColin Finck * 276*c2c66affSColin Finck * Find a property with a given property tag in a property array. 277*c2c66affSColin Finck * 278*c2c66affSColin Finck * PARAMS 279*c2c66affSColin Finck * lpHaystack [I] Property to match to 280*c2c66affSColin Finck * lpNeedle [I] Property to find in lpHaystack 281*c2c66affSColin Finck * ulFuzzy [I] Flags controlling match type and strictness (FL_* flags from "mapidefs.h") 282*c2c66affSColin Finck * 283*c2c66affSColin Finck * RETURNS 284*c2c66affSColin Finck * TRUE, if lpNeedle matches lpHaystack according to the criteria of ulFuzzy. 285*c2c66affSColin Finck * 286*c2c66affSColin Finck * NOTES 287*c2c66affSColin Finck * Only property types of PT_STRING8 and PT_BINARY are handled by this function. 288*c2c66affSColin Finck */ 289*c2c66affSColin Finck BOOL WINAPI FPropContainsProp(LPSPropValue lpHaystack, LPSPropValue lpNeedle, ULONG ulFuzzy) 290*c2c66affSColin Finck { 291*c2c66affSColin Finck TRACE("(%p,%p,0x%08x)\n", lpHaystack, lpNeedle, ulFuzzy); 292*c2c66affSColin Finck 293*c2c66affSColin Finck if (FBadProp(lpHaystack) || FBadProp(lpNeedle) || 294*c2c66affSColin Finck PROP_TYPE(lpHaystack->ulPropTag) != PROP_TYPE(lpNeedle->ulPropTag)) 295*c2c66affSColin Finck return FALSE; 296*c2c66affSColin Finck 297*c2c66affSColin Finck /* FIXME: Do later versions support Unicode as well? */ 298*c2c66affSColin Finck 299*c2c66affSColin Finck if (PROP_TYPE(lpHaystack->ulPropTag) == PT_STRING8) 300*c2c66affSColin Finck { 301*c2c66affSColin Finck DWORD dwFlags = 0, dwNeedleLen, dwHaystackLen; 302*c2c66affSColin Finck 303*c2c66affSColin Finck if (ulFuzzy & FL_IGNORECASE) 304*c2c66affSColin Finck dwFlags |= NORM_IGNORECASE; 305*c2c66affSColin Finck if (ulFuzzy & FL_IGNORENONSPACE) 306*c2c66affSColin Finck dwFlags |= NORM_IGNORENONSPACE; 307*c2c66affSColin Finck if (ulFuzzy & FL_LOOSE) 308*c2c66affSColin Finck dwFlags |= (NORM_IGNORECASE|NORM_IGNORENONSPACE|NORM_IGNORESYMBOLS); 309*c2c66affSColin Finck 310*c2c66affSColin Finck dwNeedleLen = lstrlenA(lpNeedle->Value.lpszA); 311*c2c66affSColin Finck dwHaystackLen = lstrlenA(lpHaystack->Value.lpszA); 312*c2c66affSColin Finck 313*c2c66affSColin Finck if ((ulFuzzy & (FL_SUBSTRING|FL_PREFIX)) == FL_PREFIX) 314*c2c66affSColin Finck { 315*c2c66affSColin Finck if (dwNeedleLen <= dwHaystackLen && 316*c2c66affSColin Finck CompareStringA(LOCALE_USER_DEFAULT, dwFlags, 317*c2c66affSColin Finck lpHaystack->Value.lpszA, dwNeedleLen, 318*c2c66affSColin Finck lpNeedle->Value.lpszA, dwNeedleLen) == CSTR_EQUAL) 319*c2c66affSColin Finck return TRUE; /* needle is a prefix of haystack */ 320*c2c66affSColin Finck } 321*c2c66affSColin Finck else if ((ulFuzzy & (FL_SUBSTRING|FL_PREFIX)) == FL_SUBSTRING) 322*c2c66affSColin Finck { 323*c2c66affSColin Finck LPSTR (WINAPI *pStrChrFn)(LPCSTR,WORD) = StrChrA; 324*c2c66affSColin Finck LPSTR lpStr = lpHaystack->Value.lpszA; 325*c2c66affSColin Finck 326*c2c66affSColin Finck if (dwFlags & NORM_IGNORECASE) 327*c2c66affSColin Finck pStrChrFn = StrChrIA; 328*c2c66affSColin Finck 329*c2c66affSColin Finck while ((lpStr = pStrChrFn(lpStr, *lpNeedle->Value.lpszA)) != NULL) 330*c2c66affSColin Finck { 331*c2c66affSColin Finck dwHaystackLen -= (lpStr - lpHaystack->Value.lpszA); 332*c2c66affSColin Finck if (dwNeedleLen <= dwHaystackLen && 333*c2c66affSColin Finck CompareStringA(LOCALE_USER_DEFAULT, dwFlags, 334*c2c66affSColin Finck lpStr, dwNeedleLen, 335*c2c66affSColin Finck lpNeedle->Value.lpszA, dwNeedleLen) == CSTR_EQUAL) 336*c2c66affSColin Finck return TRUE; /* needle is a substring of haystack */ 337*c2c66affSColin Finck lpStr++; 338*c2c66affSColin Finck } 339*c2c66affSColin Finck } 340*c2c66affSColin Finck else if (CompareStringA(LOCALE_USER_DEFAULT, dwFlags, 341*c2c66affSColin Finck lpHaystack->Value.lpszA, dwHaystackLen, 342*c2c66affSColin Finck lpNeedle->Value.lpszA, dwNeedleLen) == CSTR_EQUAL) 343*c2c66affSColin Finck return TRUE; /* full string match */ 344*c2c66affSColin Finck } 345*c2c66affSColin Finck else if (PROP_TYPE(lpHaystack->ulPropTag) == PT_BINARY) 346*c2c66affSColin Finck { 347*c2c66affSColin Finck if ((ulFuzzy & (FL_SUBSTRING|FL_PREFIX)) == FL_PREFIX) 348*c2c66affSColin Finck { 349*c2c66affSColin Finck if (lpNeedle->Value.bin.cb <= lpHaystack->Value.bin.cb && 350*c2c66affSColin Finck !memcmp(lpNeedle->Value.bin.lpb, lpHaystack->Value.bin.lpb, 351*c2c66affSColin Finck lpNeedle->Value.bin.cb)) 352*c2c66affSColin Finck return TRUE; /* needle is a prefix of haystack */ 353*c2c66affSColin Finck } 354*c2c66affSColin Finck else if ((ulFuzzy & (FL_SUBSTRING|FL_PREFIX)) == FL_SUBSTRING) 355*c2c66affSColin Finck { 356*c2c66affSColin Finck ULONG ulLen = lpHaystack->Value.bin.cb; 357*c2c66affSColin Finck LPBYTE lpb = lpHaystack->Value.bin.lpb; 358*c2c66affSColin Finck 359*c2c66affSColin Finck while ((lpb = memchr(lpb, *lpNeedle->Value.bin.lpb, ulLen)) != NULL) 360*c2c66affSColin Finck { 361*c2c66affSColin Finck ulLen = lpHaystack->Value.bin.cb - (lpb - lpHaystack->Value.bin.lpb); 362*c2c66affSColin Finck if (lpNeedle->Value.bin.cb <= ulLen && 363*c2c66affSColin Finck !memcmp(lpNeedle->Value.bin.lpb, lpb, lpNeedle->Value.bin.cb)) 364*c2c66affSColin Finck return TRUE; /* needle is a substring of haystack */ 365*c2c66affSColin Finck lpb++; 366*c2c66affSColin Finck } 367*c2c66affSColin Finck } 368*c2c66affSColin Finck else if (!LPropCompareProp(lpHaystack, lpNeedle)) 369*c2c66affSColin Finck return TRUE; /* needle is an exact match with haystack */ 370*c2c66affSColin Finck 371*c2c66affSColin Finck } 372*c2c66affSColin Finck return FALSE; 373*c2c66affSColin Finck } 374*c2c66affSColin Finck 375*c2c66affSColin Finck /************************************************************************* 376*c2c66affSColin Finck * FPropCompareProp@12 (MAPI32.79) 377*c2c66affSColin Finck * 378*c2c66affSColin Finck * Compare two properties. 379*c2c66affSColin Finck * 380*c2c66affSColin Finck * PARAMS 381*c2c66affSColin Finck * lpPropLeft [I] Left hand property to compare to lpPropRight 382*c2c66affSColin Finck * ulOp [I] Comparison operator (RELOP_* enum from "mapidefs.h") 383*c2c66affSColin Finck * lpPropRight [I] Right hand property to compare to lpPropLeft 384*c2c66affSColin Finck * 385*c2c66affSColin Finck * RETURNS 386*c2c66affSColin Finck * TRUE, if the comparison is true, FALSE otherwise. 387*c2c66affSColin Finck */ 388*c2c66affSColin Finck BOOL WINAPI FPropCompareProp(LPSPropValue lpPropLeft, ULONG ulOp, LPSPropValue lpPropRight) 389*c2c66affSColin Finck { 390*c2c66affSColin Finck LONG iCmp; 391*c2c66affSColin Finck 392*c2c66affSColin Finck TRACE("(%p,%d,%p)\n", lpPropLeft, ulOp, lpPropRight); 393*c2c66affSColin Finck 394*c2c66affSColin Finck if (ulOp > RELOP_RE || FBadProp(lpPropLeft) || FBadProp(lpPropRight)) 395*c2c66affSColin Finck return FALSE; 396*c2c66affSColin Finck 397*c2c66affSColin Finck if (ulOp == RELOP_RE) 398*c2c66affSColin Finck { 399*c2c66affSColin Finck FIXME("Comparison operator RELOP_RE not yet implemented!\n"); 400*c2c66affSColin Finck return FALSE; 401*c2c66affSColin Finck } 402*c2c66affSColin Finck 403*c2c66affSColin Finck iCmp = LPropCompareProp(lpPropLeft, lpPropRight); 404*c2c66affSColin Finck 405*c2c66affSColin Finck switch (ulOp) 406*c2c66affSColin Finck { 407*c2c66affSColin Finck case RELOP_LT: return iCmp < 0; 408*c2c66affSColin Finck case RELOP_LE: return iCmp <= 0; 409*c2c66affSColin Finck case RELOP_GT: return iCmp > 0; 410*c2c66affSColin Finck case RELOP_GE: return iCmp >= 0; 411*c2c66affSColin Finck case RELOP_EQ: return iCmp == 0; 412*c2c66affSColin Finck case RELOP_NE: return iCmp != 0; 413*c2c66affSColin Finck } 414*c2c66affSColin Finck return FALSE; 415*c2c66affSColin Finck } 416*c2c66affSColin Finck 417*c2c66affSColin Finck /************************************************************************* 418*c2c66affSColin Finck * LPropCompareProp@8 (MAPI32.80) 419*c2c66affSColin Finck * 420*c2c66affSColin Finck * Compare two properties. 421*c2c66affSColin Finck * 422*c2c66affSColin Finck * PARAMS 423*c2c66affSColin Finck * lpPropLeft [I] Left hand property to compare to lpPropRight 424*c2c66affSColin Finck * lpPropRight [I] Right hand property to compare to lpPropLeft 425*c2c66affSColin Finck * 426*c2c66affSColin Finck * RETURNS 427*c2c66affSColin Finck * An integer less than, equal to or greater than 0, indicating that 428*c2c66affSColin Finck * lpszStr is less than, the same, or greater than lpszComp. 429*c2c66affSColin Finck */ 430*c2c66affSColin Finck LONG WINAPI LPropCompareProp(LPSPropValue lpPropLeft, LPSPropValue lpPropRight) 431*c2c66affSColin Finck { 432*c2c66affSColin Finck LONG iRet; 433*c2c66affSColin Finck 434*c2c66affSColin Finck TRACE("(%p->0x%08x,%p->0x%08x)\n", lpPropLeft, lpPropLeft->ulPropTag, 435*c2c66affSColin Finck lpPropRight, lpPropRight->ulPropTag); 436*c2c66affSColin Finck 437*c2c66affSColin Finck /* If the properties are not the same, sort by property type */ 438*c2c66affSColin Finck if (PROP_TYPE(lpPropLeft->ulPropTag) != PROP_TYPE(lpPropRight->ulPropTag)) 439*c2c66affSColin Finck return (LONG)PROP_TYPE(lpPropLeft->ulPropTag) - (LONG)PROP_TYPE(lpPropRight->ulPropTag); 440*c2c66affSColin Finck 441*c2c66affSColin Finck switch (PROP_TYPE(lpPropLeft->ulPropTag)) 442*c2c66affSColin Finck { 443*c2c66affSColin Finck case PT_UNSPECIFIED: 444*c2c66affSColin Finck case PT_NULL: 445*c2c66affSColin Finck return 0; /* NULLs are equal */ 446*c2c66affSColin Finck case PT_I2: 447*c2c66affSColin Finck return lpPropLeft->Value.i - lpPropRight->Value.i; 448*c2c66affSColin Finck case PT_I4: 449*c2c66affSColin Finck return lpPropLeft->Value.l - lpPropRight->Value.l; 450*c2c66affSColin Finck case PT_I8: 451*c2c66affSColin Finck if (lpPropLeft->Value.li.QuadPart > lpPropRight->Value.li.QuadPart) 452*c2c66affSColin Finck return 1; 453*c2c66affSColin Finck if (lpPropLeft->Value.li.QuadPart == lpPropRight->Value.li.QuadPart) 454*c2c66affSColin Finck return 0; 455*c2c66affSColin Finck return -1; 456*c2c66affSColin Finck case PT_R4: 457*c2c66affSColin Finck if (lpPropLeft->Value.flt > lpPropRight->Value.flt) 458*c2c66affSColin Finck return 1; 459*c2c66affSColin Finck if (lpPropLeft->Value.flt == lpPropRight->Value.flt) 460*c2c66affSColin Finck return 0; 461*c2c66affSColin Finck return -1; 462*c2c66affSColin Finck case PT_APPTIME: 463*c2c66affSColin Finck case PT_R8: 464*c2c66affSColin Finck if (lpPropLeft->Value.dbl > lpPropRight->Value.dbl) 465*c2c66affSColin Finck return 1; 466*c2c66affSColin Finck if (lpPropLeft->Value.dbl == lpPropRight->Value.dbl) 467*c2c66affSColin Finck return 0; 468*c2c66affSColin Finck return -1; 469*c2c66affSColin Finck case PT_CURRENCY: 470*c2c66affSColin Finck if (lpPropLeft->Value.cur.int64 > lpPropRight->Value.cur.int64) 471*c2c66affSColin Finck return 1; 472*c2c66affSColin Finck if (lpPropLeft->Value.cur.int64 == lpPropRight->Value.cur.int64) 473*c2c66affSColin Finck return 0; 474*c2c66affSColin Finck return -1; 475*c2c66affSColin Finck case PT_SYSTIME: 476*c2c66affSColin Finck return CompareFileTime(&lpPropLeft->Value.ft, &lpPropRight->Value.ft); 477*c2c66affSColin Finck case PT_BOOLEAN: 478*c2c66affSColin Finck return (lpPropLeft->Value.b ? 1 : 0) - (lpPropRight->Value.b ? 1 : 0); 479*c2c66affSColin Finck case PT_BINARY: 480*c2c66affSColin Finck if (lpPropLeft->Value.bin.cb == lpPropRight->Value.bin.cb) 481*c2c66affSColin Finck iRet = memcmp(lpPropLeft->Value.bin.lpb, lpPropRight->Value.bin.lpb, 482*c2c66affSColin Finck lpPropLeft->Value.bin.cb); 483*c2c66affSColin Finck else 484*c2c66affSColin Finck { 485*c2c66affSColin Finck iRet = memcmp(lpPropLeft->Value.bin.lpb, lpPropRight->Value.bin.lpb, 486*c2c66affSColin Finck min(lpPropLeft->Value.bin.cb, lpPropRight->Value.bin.cb)); 487*c2c66affSColin Finck 488*c2c66affSColin Finck if (!iRet) 489*c2c66affSColin Finck iRet = lpPropLeft->Value.bin.cb - lpPropRight->Value.bin.cb; 490*c2c66affSColin Finck } 491*c2c66affSColin Finck return iRet; 492*c2c66affSColin Finck case PT_STRING8: 493*c2c66affSColin Finck return lstrcmpA(lpPropLeft->Value.lpszA, lpPropRight->Value.lpszA); 494*c2c66affSColin Finck case PT_UNICODE: 495*c2c66affSColin Finck return strcmpW(lpPropLeft->Value.lpszW, lpPropRight->Value.lpszW); 496*c2c66affSColin Finck case PT_ERROR: 497*c2c66affSColin Finck if (lpPropLeft->Value.err > lpPropRight->Value.err) 498*c2c66affSColin Finck return 1; 499*c2c66affSColin Finck if (lpPropLeft->Value.err == lpPropRight->Value.err) 500*c2c66affSColin Finck return 0; 501*c2c66affSColin Finck return -1; 502*c2c66affSColin Finck case PT_CLSID: 503*c2c66affSColin Finck return memcmp(lpPropLeft->Value.lpguid, lpPropRight->Value.lpguid, 504*c2c66affSColin Finck sizeof(GUID)); 505*c2c66affSColin Finck } 506*c2c66affSColin Finck FIXME("Unhandled property type %d\n", PROP_TYPE(lpPropLeft->ulPropTag)); 507*c2c66affSColin Finck return 0; 508*c2c66affSColin Finck } 509*c2c66affSColin Finck 510*c2c66affSColin Finck /************************************************************************* 511*c2c66affSColin Finck * HrGetOneProp@8 (MAPI32.135) 512*c2c66affSColin Finck * 513*c2c66affSColin Finck * Get a property value from an IMAPIProp object. 514*c2c66affSColin Finck * 515*c2c66affSColin Finck * PARAMS 516*c2c66affSColin Finck * lpIProp [I] IMAPIProp object to get the property value in 517*c2c66affSColin Finck * ulPropTag [I] Property tag of the property to get 518*c2c66affSColin Finck * lppProp [O] Destination for the returned property 519*c2c66affSColin Finck * 520*c2c66affSColin Finck * RETURNS 521*c2c66affSColin Finck * Success: S_OK. *lppProp contains the property value requested. 522*c2c66affSColin Finck * Failure: MAPI_E_NOT_FOUND, if no property value has the tag given by ulPropTag. 523*c2c66affSColin Finck */ 524*c2c66affSColin Finck HRESULT WINAPI HrGetOneProp(LPMAPIPROP lpIProp, ULONG ulPropTag, LPSPropValue *lppProp) 525*c2c66affSColin Finck { 526*c2c66affSColin Finck SPropTagArray pta; 527*c2c66affSColin Finck ULONG ulCount; 528*c2c66affSColin Finck HRESULT hRet; 529*c2c66affSColin Finck 530*c2c66affSColin Finck TRACE("(%p,%d,%p)\n", lpIProp, ulPropTag, lppProp); 531*c2c66affSColin Finck 532*c2c66affSColin Finck pta.cValues = 1u; 533*c2c66affSColin Finck pta.aulPropTag[0] = ulPropTag; 534*c2c66affSColin Finck hRet = IMAPIProp_GetProps(lpIProp, &pta, 0u, &ulCount, lppProp); 535*c2c66affSColin Finck if (hRet == MAPI_W_ERRORS_RETURNED) 536*c2c66affSColin Finck { 537*c2c66affSColin Finck MAPIFreeBuffer(*lppProp); 538*c2c66affSColin Finck *lppProp = NULL; 539*c2c66affSColin Finck hRet = MAPI_E_NOT_FOUND; 540*c2c66affSColin Finck } 541*c2c66affSColin Finck return hRet; 542*c2c66affSColin Finck } 543*c2c66affSColin Finck 544*c2c66affSColin Finck /************************************************************************* 545*c2c66affSColin Finck * HrSetOneProp@8 (MAPI32.136) 546*c2c66affSColin Finck * 547*c2c66affSColin Finck * Set a property value in an IMAPIProp object. 548*c2c66affSColin Finck * 549*c2c66affSColin Finck * PARAMS 550*c2c66affSColin Finck * lpIProp [I] IMAPIProp object to set the property value in 551*c2c66affSColin Finck * lpProp [I] Property value to set 552*c2c66affSColin Finck * 553*c2c66affSColin Finck * RETURNS 554*c2c66affSColin Finck * Success: S_OK. The value in lpProp is set in lpIProp. 555*c2c66affSColin Finck * Failure: An error result from IMAPIProp_SetProps(). 556*c2c66affSColin Finck */ 557*c2c66affSColin Finck HRESULT WINAPI HrSetOneProp(LPMAPIPROP lpIProp, LPSPropValue lpProp) 558*c2c66affSColin Finck { 559*c2c66affSColin Finck TRACE("(%p,%p)\n", lpIProp, lpProp); 560*c2c66affSColin Finck 561*c2c66affSColin Finck return IMAPIProp_SetProps(lpIProp, 1u, lpProp, NULL); 562*c2c66affSColin Finck } 563*c2c66affSColin Finck 564*c2c66affSColin Finck /************************************************************************* 565*c2c66affSColin Finck * FPropExists@8 (MAPI32.137) 566*c2c66affSColin Finck * 567*c2c66affSColin Finck * Find a property with a given property tag in an IMAPIProp object. 568*c2c66affSColin Finck * 569*c2c66affSColin Finck * PARAMS 570*c2c66affSColin Finck * lpIProp [I] IMAPIProp object to find the property tag in 571*c2c66affSColin Finck * ulPropTag [I] Property tag to find 572*c2c66affSColin Finck * 573*c2c66affSColin Finck * RETURNS 574*c2c66affSColin Finck * TRUE, if ulPropTag matches a property held in lpIProp, 575*c2c66affSColin Finck * FALSE, otherwise. 576*c2c66affSColin Finck * 577*c2c66affSColin Finck * NOTES 578*c2c66affSColin Finck * if ulPropTag has a property type of PT_UNSPECIFIED, then only the property 579*c2c66affSColin Finck * Ids need to match for a successful match to occur. 580*c2c66affSColin Finck */ 581*c2c66affSColin Finck BOOL WINAPI FPropExists(LPMAPIPROP lpIProp, ULONG ulPropTag) 582*c2c66affSColin Finck { 583*c2c66affSColin Finck BOOL bRet = FALSE; 584*c2c66affSColin Finck 585*c2c66affSColin Finck TRACE("(%p,%d)\n", lpIProp, ulPropTag); 586*c2c66affSColin Finck 587*c2c66affSColin Finck if (lpIProp) 588*c2c66affSColin Finck { 589*c2c66affSColin Finck LPSPropTagArray lpTags; 590*c2c66affSColin Finck ULONG i; 591*c2c66affSColin Finck 592*c2c66affSColin Finck if (FAILED(IMAPIProp_GetPropList(lpIProp, 0u, &lpTags))) 593*c2c66affSColin Finck return FALSE; 594*c2c66affSColin Finck 595*c2c66affSColin Finck for (i = 0; i < lpTags->cValues; i++) 596*c2c66affSColin Finck { 597*c2c66affSColin Finck if (!FBadPropTag(lpTags->aulPropTag[i]) && 598*c2c66affSColin Finck (lpTags->aulPropTag[i] == ulPropTag || 599*c2c66affSColin Finck (PROP_TYPE(ulPropTag) == PT_UNSPECIFIED && 600*c2c66affSColin Finck PROP_ID(lpTags->aulPropTag[i]) == lpTags->aulPropTag[i]))) 601*c2c66affSColin Finck { 602*c2c66affSColin Finck bRet = TRUE; 603*c2c66affSColin Finck break; 604*c2c66affSColin Finck } 605*c2c66affSColin Finck } 606*c2c66affSColin Finck MAPIFreeBuffer(lpTags); 607*c2c66affSColin Finck } 608*c2c66affSColin Finck return bRet; 609*c2c66affSColin Finck } 610*c2c66affSColin Finck 611*c2c66affSColin Finck /************************************************************************* 612*c2c66affSColin Finck * PpropFindProp@12 (MAPI32.138) 613*c2c66affSColin Finck * 614*c2c66affSColin Finck * Find a property with a given property tag in a property array. 615*c2c66affSColin Finck * 616*c2c66affSColin Finck * PARAMS 617*c2c66affSColin Finck * lpProps [I] Property array to search 618*c2c66affSColin Finck * cValues [I] Number of properties in lpProps 619*c2c66affSColin Finck * ulPropTag [I] Property tag to find 620*c2c66affSColin Finck * 621*c2c66affSColin Finck * RETURNS 622*c2c66affSColin Finck * A pointer to the matching property, or NULL if none was found. 623*c2c66affSColin Finck * 624*c2c66affSColin Finck * NOTES 625*c2c66affSColin Finck * if ulPropTag has a property type of PT_UNSPECIFIED, then only the property 626*c2c66affSColin Finck * Ids need to match for a successful match to occur. 627*c2c66affSColin Finck */ 628*c2c66affSColin Finck LPSPropValue WINAPI PpropFindProp(LPSPropValue lpProps, ULONG cValues, ULONG ulPropTag) 629*c2c66affSColin Finck { 630*c2c66affSColin Finck TRACE("(%p,%d,%d)\n", lpProps, cValues, ulPropTag); 631*c2c66affSColin Finck 632*c2c66affSColin Finck if (lpProps && cValues) 633*c2c66affSColin Finck { 634*c2c66affSColin Finck ULONG i; 635*c2c66affSColin Finck for (i = 0; i < cValues; i++) 636*c2c66affSColin Finck { 637*c2c66affSColin Finck if (!FBadPropTag(lpProps[i].ulPropTag) && 638*c2c66affSColin Finck (lpProps[i].ulPropTag == ulPropTag || 639*c2c66affSColin Finck (PROP_TYPE(ulPropTag) == PT_UNSPECIFIED && 640*c2c66affSColin Finck PROP_ID(lpProps[i].ulPropTag) == PROP_ID(ulPropTag)))) 641*c2c66affSColin Finck return &lpProps[i]; 642*c2c66affSColin Finck } 643*c2c66affSColin Finck } 644*c2c66affSColin Finck return NULL; 645*c2c66affSColin Finck } 646*c2c66affSColin Finck 647*c2c66affSColin Finck /************************************************************************* 648*c2c66affSColin Finck * FreePadrlist@4 (MAPI32.139) 649*c2c66affSColin Finck * 650*c2c66affSColin Finck * Free the memory used by an address book list. 651*c2c66affSColin Finck * 652*c2c66affSColin Finck * PARAMS 653*c2c66affSColin Finck * lpAddrs [I] Address book list to free 654*c2c66affSColin Finck * 655*c2c66affSColin Finck * RETURNS 656*c2c66affSColin Finck * Nothing. 657*c2c66affSColin Finck */ 658*c2c66affSColin Finck VOID WINAPI FreePadrlist(LPADRLIST lpAddrs) 659*c2c66affSColin Finck { 660*c2c66affSColin Finck TRACE("(%p)\n", lpAddrs); 661*c2c66affSColin Finck 662*c2c66affSColin Finck /* Structures are binary compatible; use the same implementation */ 663*c2c66affSColin Finck FreeProws((LPSRowSet)lpAddrs); 664*c2c66affSColin Finck } 665*c2c66affSColin Finck 666*c2c66affSColin Finck /************************************************************************* 667*c2c66affSColin Finck * FreeProws@4 (MAPI32.140) 668*c2c66affSColin Finck * 669*c2c66affSColin Finck * Free the memory used by a row set. 670*c2c66affSColin Finck * 671*c2c66affSColin Finck * PARAMS 672*c2c66affSColin Finck * lpRowSet [I] Row set to free 673*c2c66affSColin Finck * 674*c2c66affSColin Finck * RETURNS 675*c2c66affSColin Finck * Nothing. 676*c2c66affSColin Finck */ 677*c2c66affSColin Finck VOID WINAPI FreeProws(LPSRowSet lpRowSet) 678*c2c66affSColin Finck { 679*c2c66affSColin Finck TRACE("(%p)\n", lpRowSet); 680*c2c66affSColin Finck 681*c2c66affSColin Finck if (lpRowSet) 682*c2c66affSColin Finck { 683*c2c66affSColin Finck ULONG i; 684*c2c66affSColin Finck 685*c2c66affSColin Finck for (i = 0; i < lpRowSet->cRows; i++) 686*c2c66affSColin Finck MAPIFreeBuffer(lpRowSet->aRow[i].lpProps); 687*c2c66affSColin Finck 688*c2c66affSColin Finck MAPIFreeBuffer(lpRowSet); 689*c2c66affSColin Finck } 690*c2c66affSColin Finck } 691*c2c66affSColin Finck 692*c2c66affSColin Finck /************************************************************************* 693*c2c66affSColin Finck * ScCountProps@12 (MAPI32.170) 694*c2c66affSColin Finck * 695*c2c66affSColin Finck * Validate and determine the length of an array of properties. 696*c2c66affSColin Finck * 697*c2c66affSColin Finck * PARAMS 698*c2c66affSColin Finck * iCount [I] Length of the lpProps array 699*c2c66affSColin Finck * lpProps [I] Array of properties to validate/size 700*c2c66affSColin Finck * pcBytes [O] If non-NULL, destination for the size of the property array 701*c2c66affSColin Finck * 702*c2c66affSColin Finck * RETURNS 703*c2c66affSColin Finck * Success: S_OK. If pcBytes is non-NULL, it contains the size of the 704*c2c66affSColin Finck * properties array. 705*c2c66affSColin Finck * Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid or validation 706*c2c66affSColin Finck * of the property array fails. 707*c2c66affSColin Finck */ 708*c2c66affSColin Finck SCODE WINAPI ScCountProps(INT iCount, LPSPropValue lpProps, ULONG *pcBytes) 709*c2c66affSColin Finck { 710*c2c66affSColin Finck ULONG i, ulCount = iCount, ulBytes = 0; 711*c2c66affSColin Finck 712*c2c66affSColin Finck TRACE("(%d,%p,%p)\n", iCount, lpProps, pcBytes); 713*c2c66affSColin Finck 714*c2c66affSColin Finck if (iCount <= 0 || !lpProps || 715*c2c66affSColin Finck IsBadReadPtr(lpProps, iCount * sizeof(SPropValue))) 716*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 717*c2c66affSColin Finck 718*c2c66affSColin Finck for (i = 0; i < ulCount; i++) 719*c2c66affSColin Finck { 720*c2c66affSColin Finck ULONG ulPropSize = 0; 721*c2c66affSColin Finck 722*c2c66affSColin Finck if (FBadProp(&lpProps[i]) || lpProps[i].ulPropTag == PROP_ID_NULL || 723*c2c66affSColin Finck lpProps[i].ulPropTag == PROP_ID_INVALID) 724*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 725*c2c66affSColin Finck 726*c2c66affSColin Finck if (PROP_TYPE(lpProps[i].ulPropTag) != PT_OBJECT) 727*c2c66affSColin Finck { 728*c2c66affSColin Finck ulPropSize = UlPropSize(&lpProps[i]); 729*c2c66affSColin Finck if (!ulPropSize) 730*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 731*c2c66affSColin Finck } 732*c2c66affSColin Finck 733*c2c66affSColin Finck switch (PROP_TYPE(lpProps[i].ulPropTag)) 734*c2c66affSColin Finck { 735*c2c66affSColin Finck case PT_STRING8: 736*c2c66affSColin Finck case PT_UNICODE: 737*c2c66affSColin Finck case PT_CLSID: 738*c2c66affSColin Finck case PT_BINARY: 739*c2c66affSColin Finck case PT_MV_I2: 740*c2c66affSColin Finck case PT_MV_I4: 741*c2c66affSColin Finck case PT_MV_I8: 742*c2c66affSColin Finck case PT_MV_R4: 743*c2c66affSColin Finck case PT_MV_R8: 744*c2c66affSColin Finck case PT_MV_CURRENCY: 745*c2c66affSColin Finck case PT_MV_SYSTIME: 746*c2c66affSColin Finck case PT_MV_APPTIME: 747*c2c66affSColin Finck ulPropSize += sizeof(SPropValue); 748*c2c66affSColin Finck break; 749*c2c66affSColin Finck case PT_MV_CLSID: 750*c2c66affSColin Finck ulPropSize += lpProps[i].Value.MVszA.cValues * sizeof(char*) + sizeof(SPropValue); 751*c2c66affSColin Finck break; 752*c2c66affSColin Finck case PT_MV_STRING8: 753*c2c66affSColin Finck case PT_MV_UNICODE: 754*c2c66affSColin Finck ulPropSize += lpProps[i].Value.MVszA.cValues * sizeof(char*) + sizeof(SPropValue); 755*c2c66affSColin Finck break; 756*c2c66affSColin Finck case PT_MV_BINARY: 757*c2c66affSColin Finck ulPropSize += lpProps[i].Value.MVbin.cValues * sizeof(SBinary) + sizeof(SPropValue); 758*c2c66affSColin Finck break; 759*c2c66affSColin Finck default: 760*c2c66affSColin Finck ulPropSize = sizeof(SPropValue); 761*c2c66affSColin Finck break; 762*c2c66affSColin Finck } 763*c2c66affSColin Finck ulBytes += ulPropSize; 764*c2c66affSColin Finck } 765*c2c66affSColin Finck if (pcBytes) 766*c2c66affSColin Finck *pcBytes = ulBytes; 767*c2c66affSColin Finck 768*c2c66affSColin Finck return S_OK; 769*c2c66affSColin Finck } 770*c2c66affSColin Finck 771*c2c66affSColin Finck /************************************************************************* 772*c2c66affSColin Finck * ScCopyProps@16 (MAPI32.171) 773*c2c66affSColin Finck * 774*c2c66affSColin Finck * Copy an array of property values into a buffer suited for serialisation. 775*c2c66affSColin Finck * 776*c2c66affSColin Finck * PARAMS 777*c2c66affSColin Finck * cValues [I] Number of properties in lpProps 778*c2c66affSColin Finck * lpProps [I] Property array to copy 779*c2c66affSColin Finck * lpDst [O] Destination for the serialised data 780*c2c66affSColin Finck * lpCount [O] If non-NULL, destination for the number of bytes of data written to lpDst 781*c2c66affSColin Finck * 782*c2c66affSColin Finck * RETURNS 783*c2c66affSColin Finck * Success: S_OK. lpDst contains the serialised data from lpProps. 784*c2c66affSColin Finck * Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid. 785*c2c66affSColin Finck * 786*c2c66affSColin Finck * NOTES 787*c2c66affSColin Finck * The resulting property value array is stored in a contiguous block starting at lpDst. 788*c2c66affSColin Finck */ 789*c2c66affSColin Finck SCODE WINAPI ScCopyProps(int cValues, LPSPropValue lpProps, LPVOID lpDst, ULONG *lpCount) 790*c2c66affSColin Finck { 791*c2c66affSColin Finck LPSPropValue lpDest = (LPSPropValue)lpDst; 792*c2c66affSColin Finck char *lpDataDest = (char *)(lpDest + cValues); 793*c2c66affSColin Finck ULONG ulLen, i; 794*c2c66affSColin Finck int iter; 795*c2c66affSColin Finck 796*c2c66affSColin Finck TRACE("(%d,%p,%p,%p)\n", cValues, lpProps, lpDst, lpCount); 797*c2c66affSColin Finck 798*c2c66affSColin Finck if (!lpProps || cValues < 0 || !lpDest) 799*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 800*c2c66affSColin Finck 801*c2c66affSColin Finck memcpy(lpDst, lpProps, cValues * sizeof(SPropValue)); 802*c2c66affSColin Finck 803*c2c66affSColin Finck for (iter = 0; iter < cValues; iter++) 804*c2c66affSColin Finck { 805*c2c66affSColin Finck switch (PROP_TYPE(lpProps->ulPropTag)) 806*c2c66affSColin Finck { 807*c2c66affSColin Finck case PT_CLSID: 808*c2c66affSColin Finck lpDest->Value.lpguid = (LPGUID)lpDataDest; 809*c2c66affSColin Finck *lpDest->Value.lpguid = *lpProps->Value.lpguid; 810*c2c66affSColin Finck lpDataDest += sizeof(GUID); 811*c2c66affSColin Finck break; 812*c2c66affSColin Finck case PT_STRING8: 813*c2c66affSColin Finck ulLen = lstrlenA(lpProps->Value.lpszA) + 1u; 814*c2c66affSColin Finck lpDest->Value.lpszA = lpDataDest; 815*c2c66affSColin Finck memcpy(lpDest->Value.lpszA, lpProps->Value.lpszA, ulLen); 816*c2c66affSColin Finck lpDataDest += ulLen; 817*c2c66affSColin Finck break; 818*c2c66affSColin Finck case PT_UNICODE: 819*c2c66affSColin Finck ulLen = (strlenW(lpProps->Value.lpszW) + 1u) * sizeof(WCHAR); 820*c2c66affSColin Finck lpDest->Value.lpszW = (LPWSTR)lpDataDest; 821*c2c66affSColin Finck memcpy(lpDest->Value.lpszW, lpProps->Value.lpszW, ulLen); 822*c2c66affSColin Finck lpDataDest += ulLen; 823*c2c66affSColin Finck break; 824*c2c66affSColin Finck case PT_BINARY: 825*c2c66affSColin Finck lpDest->Value.bin.lpb = (LPBYTE)lpDataDest; 826*c2c66affSColin Finck memcpy(lpDest->Value.bin.lpb, lpProps->Value.bin.lpb, lpProps->Value.bin.cb); 827*c2c66affSColin Finck lpDataDest += lpProps->Value.bin.cb; 828*c2c66affSColin Finck break; 829*c2c66affSColin Finck default: 830*c2c66affSColin Finck if (lpProps->ulPropTag & MV_FLAG) 831*c2c66affSColin Finck { 832*c2c66affSColin Finck lpDest->Value.MVi.cValues = lpProps->Value.MVi.cValues; 833*c2c66affSColin Finck /* Note: Assignment uses lppszA but covers all cases by union aliasing */ 834*c2c66affSColin Finck lpDest->Value.MVszA.lppszA = (char**)lpDataDest; 835*c2c66affSColin Finck 836*c2c66affSColin Finck switch (PROP_TYPE(lpProps->ulPropTag)) 837*c2c66affSColin Finck { 838*c2c66affSColin Finck case PT_MV_STRING8: 839*c2c66affSColin Finck { 840*c2c66affSColin Finck lpDataDest += lpProps->Value.MVszA.cValues * sizeof(char *); 841*c2c66affSColin Finck 842*c2c66affSColin Finck for (i = 0; i < lpProps->Value.MVszA.cValues; i++) 843*c2c66affSColin Finck { 844*c2c66affSColin Finck ULONG ulStrLen = lstrlenA(lpProps->Value.MVszA.lppszA[i]) + 1u; 845*c2c66affSColin Finck 846*c2c66affSColin Finck lpDest->Value.MVszA.lppszA[i] = lpDataDest; 847*c2c66affSColin Finck memcpy(lpDataDest, lpProps->Value.MVszA.lppszA[i], ulStrLen); 848*c2c66affSColin Finck lpDataDest += ulStrLen; 849*c2c66affSColin Finck } 850*c2c66affSColin Finck break; 851*c2c66affSColin Finck } 852*c2c66affSColin Finck case PT_MV_UNICODE: 853*c2c66affSColin Finck { 854*c2c66affSColin Finck lpDataDest += lpProps->Value.MVszW.cValues * sizeof(WCHAR *); 855*c2c66affSColin Finck 856*c2c66affSColin Finck for (i = 0; i < lpProps->Value.MVszW.cValues; i++) 857*c2c66affSColin Finck { 858*c2c66affSColin Finck ULONG ulStrLen = (strlenW(lpProps->Value.MVszW.lppszW[i]) + 1u) * sizeof(WCHAR); 859*c2c66affSColin Finck 860*c2c66affSColin Finck lpDest->Value.MVszW.lppszW[i] = (LPWSTR)lpDataDest; 861*c2c66affSColin Finck memcpy(lpDataDest, lpProps->Value.MVszW.lppszW[i], ulStrLen); 862*c2c66affSColin Finck lpDataDest += ulStrLen; 863*c2c66affSColin Finck } 864*c2c66affSColin Finck break; 865*c2c66affSColin Finck } 866*c2c66affSColin Finck case PT_MV_BINARY: 867*c2c66affSColin Finck { 868*c2c66affSColin Finck lpDataDest += lpProps->Value.MVszW.cValues * sizeof(SBinary); 869*c2c66affSColin Finck 870*c2c66affSColin Finck for (i = 0; i < lpProps->Value.MVszW.cValues; i++) 871*c2c66affSColin Finck { 872*c2c66affSColin Finck lpDest->Value.MVbin.lpbin[i].cb = lpProps->Value.MVbin.lpbin[i].cb; 873*c2c66affSColin Finck lpDest->Value.MVbin.lpbin[i].lpb = (LPBYTE)lpDataDest; 874*c2c66affSColin Finck memcpy(lpDataDest, lpProps->Value.MVbin.lpbin[i].lpb, lpDest->Value.MVbin.lpbin[i].cb); 875*c2c66affSColin Finck lpDataDest += lpDest->Value.MVbin.lpbin[i].cb; 876*c2c66affSColin Finck } 877*c2c66affSColin Finck break; 878*c2c66affSColin Finck } 879*c2c66affSColin Finck default: 880*c2c66affSColin Finck /* No embedded pointers, just copy the data over */ 881*c2c66affSColin Finck ulLen = UlPropSize(lpProps); 882*c2c66affSColin Finck memcpy(lpDest->Value.MVi.lpi, lpProps->Value.MVi.lpi, ulLen); 883*c2c66affSColin Finck lpDataDest += ulLen; 884*c2c66affSColin Finck break; 885*c2c66affSColin Finck } 886*c2c66affSColin Finck break; 887*c2c66affSColin Finck } 888*c2c66affSColin Finck } 889*c2c66affSColin Finck lpDest++; 890*c2c66affSColin Finck lpProps++; 891*c2c66affSColin Finck } 892*c2c66affSColin Finck if (lpCount) 893*c2c66affSColin Finck *lpCount = lpDataDest - (char *)lpDst; 894*c2c66affSColin Finck 895*c2c66affSColin Finck return S_OK; 896*c2c66affSColin Finck } 897*c2c66affSColin Finck 898*c2c66affSColin Finck /************************************************************************* 899*c2c66affSColin Finck * ScRelocProps@20 (MAPI32.172) 900*c2c66affSColin Finck * 901*c2c66affSColin Finck * Relocate the pointers in an array of property values after it has been copied. 902*c2c66affSColin Finck * 903*c2c66affSColin Finck * PARAMS 904*c2c66affSColin Finck * cValues [I] Number of properties in lpProps 905*c2c66affSColin Finck * lpProps [O] Property array to relocate the pointers in. 906*c2c66affSColin Finck * lpOld [I] Position where the data was copied from 907*c2c66affSColin Finck * lpNew [I] Position where the data was copied to 908*c2c66affSColin Finck * lpCount [O] If non-NULL, destination for the number of bytes of data at lpDst 909*c2c66affSColin Finck * 910*c2c66affSColin Finck * RETURNS 911*c2c66affSColin Finck * Success: S_OK. Any pointers in lpProps are relocated. 912*c2c66affSColin Finck * Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid. 913*c2c66affSColin Finck * 914*c2c66affSColin Finck * NOTES 915*c2c66affSColin Finck * MSDN states that this function can be used for serialisation by passing 916*c2c66affSColin Finck * NULL as either lpOld or lpNew, thus converting any pointers in lpProps 917*c2c66affSColin Finck * between offsets and pointers. This does not work in native (it crashes), 918*c2c66affSColin Finck * and cannot be made to work in Wine because the original interface design 919*c2c66affSColin Finck * is deficient. The only use left for this function is to remap pointers 920*c2c66affSColin Finck * in a contiguous property array that has been copied with memcpy() to 921*c2c66affSColin Finck * another memory location. 922*c2c66affSColin Finck */ 923*c2c66affSColin Finck SCODE WINAPI ScRelocProps(int cValues, LPSPropValue lpProps, LPVOID lpOld, 924*c2c66affSColin Finck LPVOID lpNew, ULONG *lpCount) 925*c2c66affSColin Finck { 926*c2c66affSColin Finck static const BOOL bBadPtr = TRUE; /* Windows bug - Assumes source is bad */ 927*c2c66affSColin Finck LPSPropValue lpDest = lpProps; 928*c2c66affSColin Finck ULONG ulCount = cValues * sizeof(SPropValue); 929*c2c66affSColin Finck ULONG ulLen, i; 930*c2c66affSColin Finck int iter; 931*c2c66affSColin Finck 932*c2c66affSColin Finck TRACE("(%d,%p,%p,%p,%p)\n", cValues, lpProps, lpOld, lpNew, lpCount); 933*c2c66affSColin Finck 934*c2c66affSColin Finck if (!lpProps || cValues < 0 || !lpOld || !lpNew) 935*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 936*c2c66affSColin Finck 937*c2c66affSColin Finck /* The reason native doesn't work as MSDN states is that it assumes that 938*c2c66affSColin Finck * the lpProps pointer contains valid pointers. This is obviously not 939*c2c66affSColin Finck * true if the array is being read back from serialisation (the pointers 940*c2c66affSColin Finck * are just offsets). Native can't actually work converting the pointers to 941*c2c66affSColin Finck * offsets either, because it converts any array pointers to offsets then 942*c2c66affSColin Finck * _dereferences the offset_ in order to convert the array elements! 943*c2c66affSColin Finck * 944*c2c66affSColin Finck * The code below would handle both cases except that the design of this 945*c2c66affSColin Finck * function makes it impossible to know when the pointers in lpProps are 946*c2c66affSColin Finck * valid. If both lpOld and lpNew are non-NULL, native reads the pointers 947*c2c66affSColin Finck * after converting them, so we must do the same. It seems this 948*c2c66affSColin Finck * functionality was never tested by MS. 949*c2c66affSColin Finck */ 950*c2c66affSColin Finck 951*c2c66affSColin Finck #define RELOC_PTR(p) (((char*)(p)) - (char*)lpOld + (char*)lpNew) 952*c2c66affSColin Finck 953*c2c66affSColin Finck for (iter = 0; iter < cValues; iter++) 954*c2c66affSColin Finck { 955*c2c66affSColin Finck switch (PROP_TYPE(lpDest->ulPropTag)) 956*c2c66affSColin Finck { 957*c2c66affSColin Finck case PT_CLSID: 958*c2c66affSColin Finck lpDest->Value.lpguid = (LPGUID)RELOC_PTR(lpDest->Value.lpguid); 959*c2c66affSColin Finck ulCount += sizeof(GUID); 960*c2c66affSColin Finck break; 961*c2c66affSColin Finck case PT_STRING8: 962*c2c66affSColin Finck ulLen = bBadPtr ? 0 : lstrlenA(lpDest->Value.lpszA) + 1u; 963*c2c66affSColin Finck lpDest->Value.lpszA = RELOC_PTR(lpDest->Value.lpszA); 964*c2c66affSColin Finck if (bBadPtr) 965*c2c66affSColin Finck ulLen = lstrlenA(lpDest->Value.lpszA) + 1u; 966*c2c66affSColin Finck ulCount += ulLen; 967*c2c66affSColin Finck break; 968*c2c66affSColin Finck case PT_UNICODE: 969*c2c66affSColin Finck ulLen = bBadPtr ? 0 : (lstrlenW(lpDest->Value.lpszW) + 1u) * sizeof(WCHAR); 970*c2c66affSColin Finck lpDest->Value.lpszW = (LPWSTR)RELOC_PTR(lpDest->Value.lpszW); 971*c2c66affSColin Finck if (bBadPtr) 972*c2c66affSColin Finck ulLen = (strlenW(lpDest->Value.lpszW) + 1u) * sizeof(WCHAR); 973*c2c66affSColin Finck ulCount += ulLen; 974*c2c66affSColin Finck break; 975*c2c66affSColin Finck case PT_BINARY: 976*c2c66affSColin Finck lpDest->Value.bin.lpb = (LPBYTE)RELOC_PTR(lpDest->Value.bin.lpb); 977*c2c66affSColin Finck ulCount += lpDest->Value.bin.cb; 978*c2c66affSColin Finck break; 979*c2c66affSColin Finck default: 980*c2c66affSColin Finck if (lpDest->ulPropTag & MV_FLAG) 981*c2c66affSColin Finck { 982*c2c66affSColin Finck /* Since we have to access the array elements, don't map the 983*c2c66affSColin Finck * array unless it is invalid (otherwise, map it at the end) 984*c2c66affSColin Finck */ 985*c2c66affSColin Finck if (bBadPtr) 986*c2c66affSColin Finck lpDest->Value.MVszA.lppszA = (LPSTR*)RELOC_PTR(lpDest->Value.MVszA.lppszA); 987*c2c66affSColin Finck 988*c2c66affSColin Finck switch (PROP_TYPE(lpProps->ulPropTag)) 989*c2c66affSColin Finck { 990*c2c66affSColin Finck case PT_MV_STRING8: 991*c2c66affSColin Finck { 992*c2c66affSColin Finck ulCount += lpDest->Value.MVszA.cValues * sizeof(char *); 993*c2c66affSColin Finck 994*c2c66affSColin Finck for (i = 0; i < lpDest->Value.MVszA.cValues; i++) 995*c2c66affSColin Finck { 996*c2c66affSColin Finck ULONG ulStrLen = bBadPtr ? 0 : lstrlenA(lpDest->Value.MVszA.lppszA[i]) + 1u; 997*c2c66affSColin Finck 998*c2c66affSColin Finck lpDest->Value.MVszA.lppszA[i] = RELOC_PTR(lpDest->Value.MVszA.lppszA[i]); 999*c2c66affSColin Finck if (bBadPtr) 1000*c2c66affSColin Finck ulStrLen = lstrlenA(lpDest->Value.MVszA.lppszA[i]) + 1u; 1001*c2c66affSColin Finck ulCount += ulStrLen; 1002*c2c66affSColin Finck } 1003*c2c66affSColin Finck break; 1004*c2c66affSColin Finck } 1005*c2c66affSColin Finck case PT_MV_UNICODE: 1006*c2c66affSColin Finck { 1007*c2c66affSColin Finck ulCount += lpDest->Value.MVszW.cValues * sizeof(WCHAR *); 1008*c2c66affSColin Finck 1009*c2c66affSColin Finck for (i = 0; i < lpDest->Value.MVszW.cValues; i++) 1010*c2c66affSColin Finck { 1011*c2c66affSColin Finck ULONG ulStrLen = bBadPtr ? 0 : (strlenW(lpDest->Value.MVszW.lppszW[i]) + 1u) * sizeof(WCHAR); 1012*c2c66affSColin Finck 1013*c2c66affSColin Finck lpDest->Value.MVszW.lppszW[i] = (LPWSTR)RELOC_PTR(lpDest->Value.MVszW.lppszW[i]); 1014*c2c66affSColin Finck if (bBadPtr) 1015*c2c66affSColin Finck ulStrLen = (strlenW(lpDest->Value.MVszW.lppszW[i]) + 1u) * sizeof(WCHAR); 1016*c2c66affSColin Finck ulCount += ulStrLen; 1017*c2c66affSColin Finck } 1018*c2c66affSColin Finck break; 1019*c2c66affSColin Finck } 1020*c2c66affSColin Finck case PT_MV_BINARY: 1021*c2c66affSColin Finck { 1022*c2c66affSColin Finck ulCount += lpDest->Value.MVszW.cValues * sizeof(SBinary); 1023*c2c66affSColin Finck 1024*c2c66affSColin Finck for (i = 0; i < lpDest->Value.MVszW.cValues; i++) 1025*c2c66affSColin Finck { 1026*c2c66affSColin Finck lpDest->Value.MVbin.lpbin[i].lpb = (LPBYTE)RELOC_PTR(lpDest->Value.MVbin.lpbin[i].lpb); 1027*c2c66affSColin Finck ulCount += lpDest->Value.MVbin.lpbin[i].cb; 1028*c2c66affSColin Finck } 1029*c2c66affSColin Finck break; 1030*c2c66affSColin Finck } 1031*c2c66affSColin Finck default: 1032*c2c66affSColin Finck ulCount += UlPropSize(lpDest); 1033*c2c66affSColin Finck break; 1034*c2c66affSColin Finck } 1035*c2c66affSColin Finck if (!bBadPtr) 1036*c2c66affSColin Finck lpDest->Value.MVszA.lppszA = (LPSTR*)RELOC_PTR(lpDest->Value.MVszA.lppszA); 1037*c2c66affSColin Finck break; 1038*c2c66affSColin Finck } 1039*c2c66affSColin Finck } 1040*c2c66affSColin Finck lpDest++; 1041*c2c66affSColin Finck } 1042*c2c66affSColin Finck if (lpCount) 1043*c2c66affSColin Finck *lpCount = ulCount; 1044*c2c66affSColin Finck 1045*c2c66affSColin Finck return S_OK; 1046*c2c66affSColin Finck } 1047*c2c66affSColin Finck 1048*c2c66affSColin Finck /************************************************************************* 1049*c2c66affSColin Finck * LpValFindProp@12 (MAPI32.173) 1050*c2c66affSColin Finck * 1051*c2c66affSColin Finck * Find a property with a given property id in a property array. 1052*c2c66affSColin Finck * 1053*c2c66affSColin Finck * PARAMS 1054*c2c66affSColin Finck * ulPropTag [I] Property tag containing property id to find 1055*c2c66affSColin Finck * cValues [I] Number of properties in lpProps 1056*c2c66affSColin Finck * lpProps [I] Property array to search 1057*c2c66affSColin Finck * 1058*c2c66affSColin Finck * RETURNS 1059*c2c66affSColin Finck * A pointer to the matching property, or NULL if none was found. 1060*c2c66affSColin Finck * 1061*c2c66affSColin Finck * NOTES 1062*c2c66affSColin Finck * This function matches only on the property id and does not care if the 1063*c2c66affSColin Finck * property types differ. 1064*c2c66affSColin Finck */ 1065*c2c66affSColin Finck LPSPropValue WINAPI LpValFindProp(ULONG ulPropTag, ULONG cValues, LPSPropValue lpProps) 1066*c2c66affSColin Finck { 1067*c2c66affSColin Finck TRACE("(%d,%d,%p)\n", ulPropTag, cValues, lpProps); 1068*c2c66affSColin Finck 1069*c2c66affSColin Finck if (lpProps && cValues) 1070*c2c66affSColin Finck { 1071*c2c66affSColin Finck ULONG i; 1072*c2c66affSColin Finck for (i = 0; i < cValues; i++) 1073*c2c66affSColin Finck { 1074*c2c66affSColin Finck if (PROP_ID(ulPropTag) == PROP_ID(lpProps[i].ulPropTag)) 1075*c2c66affSColin Finck return &lpProps[i]; 1076*c2c66affSColin Finck } 1077*c2c66affSColin Finck } 1078*c2c66affSColin Finck return NULL; 1079*c2c66affSColin Finck } 1080*c2c66affSColin Finck 1081*c2c66affSColin Finck /************************************************************************* 1082*c2c66affSColin Finck * ScDupPropset@16 (MAPI32.174) 1083*c2c66affSColin Finck * 1084*c2c66affSColin Finck * Duplicate a property value array into a contiguous block of memory. 1085*c2c66affSColin Finck * 1086*c2c66affSColin Finck * PARAMS 1087*c2c66affSColin Finck * cValues [I] Number of properties in lpProps 1088*c2c66affSColin Finck * lpProps [I] Property array to duplicate 1089*c2c66affSColin Finck * lpAlloc [I] Memory allocation function, use MAPIAllocateBuffer() 1090*c2c66affSColin Finck * lpNewProp [O] Destination for the newly duplicated property value array 1091*c2c66affSColin Finck * 1092*c2c66affSColin Finck * RETURNS 1093*c2c66affSColin Finck * Success: S_OK. *lpNewProp contains the duplicated array. 1094*c2c66affSColin Finck * Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid, 1095*c2c66affSColin Finck * MAPI_E_NOT_ENOUGH_MEMORY, if memory allocation fails. 1096*c2c66affSColin Finck */ 1097*c2c66affSColin Finck SCODE WINAPI ScDupPropset(int cValues, LPSPropValue lpProps, 1098*c2c66affSColin Finck LPALLOCATEBUFFER lpAlloc, LPSPropValue *lpNewProp) 1099*c2c66affSColin Finck { 1100*c2c66affSColin Finck ULONG ulCount; 1101*c2c66affSColin Finck SCODE sc; 1102*c2c66affSColin Finck 1103*c2c66affSColin Finck TRACE("(%d,%p,%p,%p)\n", cValues, lpProps, lpAlloc, lpNewProp); 1104*c2c66affSColin Finck 1105*c2c66affSColin Finck sc = ScCountProps(cValues, lpProps, &ulCount); 1106*c2c66affSColin Finck if (SUCCEEDED(sc)) 1107*c2c66affSColin Finck { 1108*c2c66affSColin Finck sc = lpAlloc(ulCount, (LPVOID*)lpNewProp); 1109*c2c66affSColin Finck if (SUCCEEDED(sc)) 1110*c2c66affSColin Finck sc = ScCopyProps(cValues, lpProps, *lpNewProp, &ulCount); 1111*c2c66affSColin Finck } 1112*c2c66affSColin Finck return sc; 1113*c2c66affSColin Finck } 1114*c2c66affSColin Finck 1115*c2c66affSColin Finck /************************************************************************* 1116*c2c66affSColin Finck * FBadRglpszA@8 (MAPI32.175) 1117*c2c66affSColin Finck * 1118*c2c66affSColin Finck * Determine if an array of strings is invalid 1119*c2c66affSColin Finck * 1120*c2c66affSColin Finck * PARAMS 1121*c2c66affSColin Finck * lppszStrs [I] Array of strings to check 1122*c2c66affSColin Finck * ulCount [I] Number of strings in lppszStrs 1123*c2c66affSColin Finck * 1124*c2c66affSColin Finck * RETURNS 1125*c2c66affSColin Finck * TRUE, if lppszStrs is invalid, FALSE otherwise. 1126*c2c66affSColin Finck */ 1127*c2c66affSColin Finck BOOL WINAPI FBadRglpszA(LPSTR *lppszStrs, ULONG ulCount) 1128*c2c66affSColin Finck { 1129*c2c66affSColin Finck ULONG i; 1130*c2c66affSColin Finck 1131*c2c66affSColin Finck TRACE("(%p,%d)\n", lppszStrs, ulCount); 1132*c2c66affSColin Finck 1133*c2c66affSColin Finck if (!ulCount) 1134*c2c66affSColin Finck return FALSE; 1135*c2c66affSColin Finck 1136*c2c66affSColin Finck if (!lppszStrs || IsBadReadPtr(lppszStrs, ulCount * sizeof(LPWSTR))) 1137*c2c66affSColin Finck return TRUE; 1138*c2c66affSColin Finck 1139*c2c66affSColin Finck for (i = 0; i < ulCount; i++) 1140*c2c66affSColin Finck { 1141*c2c66affSColin Finck if (!lppszStrs[i] || IsBadStringPtrA(lppszStrs[i], -1)) 1142*c2c66affSColin Finck return TRUE; 1143*c2c66affSColin Finck } 1144*c2c66affSColin Finck return FALSE; 1145*c2c66affSColin Finck } 1146*c2c66affSColin Finck 1147*c2c66affSColin Finck /************************************************************************* 1148*c2c66affSColin Finck * FBadRglpszW@8 (MAPI32.176) 1149*c2c66affSColin Finck * 1150*c2c66affSColin Finck * See FBadRglpszA. 1151*c2c66affSColin Finck */ 1152*c2c66affSColin Finck BOOL WINAPI FBadRglpszW(LPWSTR *lppszStrs, ULONG ulCount) 1153*c2c66affSColin Finck { 1154*c2c66affSColin Finck ULONG i; 1155*c2c66affSColin Finck 1156*c2c66affSColin Finck TRACE("(%p,%d)\n", lppszStrs, ulCount); 1157*c2c66affSColin Finck 1158*c2c66affSColin Finck if (!ulCount) 1159*c2c66affSColin Finck return FALSE; 1160*c2c66affSColin Finck 1161*c2c66affSColin Finck if (!lppszStrs || IsBadReadPtr(lppszStrs, ulCount * sizeof(LPWSTR))) 1162*c2c66affSColin Finck return TRUE; 1163*c2c66affSColin Finck 1164*c2c66affSColin Finck for (i = 0; i < ulCount; i++) 1165*c2c66affSColin Finck { 1166*c2c66affSColin Finck if (!lppszStrs[i] || IsBadStringPtrW(lppszStrs[i], -1)) 1167*c2c66affSColin Finck return TRUE; 1168*c2c66affSColin Finck } 1169*c2c66affSColin Finck return FALSE; 1170*c2c66affSColin Finck } 1171*c2c66affSColin Finck 1172*c2c66affSColin Finck /************************************************************************* 1173*c2c66affSColin Finck * FBadRowSet@4 (MAPI32.177) 1174*c2c66affSColin Finck * 1175*c2c66affSColin Finck * Determine if a row is invalid 1176*c2c66affSColin Finck * 1177*c2c66affSColin Finck * PARAMS 1178*c2c66affSColin Finck * lpRow [I] Row to check 1179*c2c66affSColin Finck * 1180*c2c66affSColin Finck * RETURNS 1181*c2c66affSColin Finck * TRUE, if lpRow is invalid, FALSE otherwise. 1182*c2c66affSColin Finck */ 1183*c2c66affSColin Finck BOOL WINAPI FBadRowSet(LPSRowSet lpRowSet) 1184*c2c66affSColin Finck { 1185*c2c66affSColin Finck ULONG i; 1186*c2c66affSColin Finck TRACE("(%p)\n", lpRowSet); 1187*c2c66affSColin Finck 1188*c2c66affSColin Finck if (!lpRowSet || IsBadReadPtr(lpRowSet, CbSRowSet(lpRowSet))) 1189*c2c66affSColin Finck return TRUE; 1190*c2c66affSColin Finck 1191*c2c66affSColin Finck for (i = 0; i < lpRowSet->cRows; i++) 1192*c2c66affSColin Finck { 1193*c2c66affSColin Finck if (FBadRow(&lpRowSet->aRow[i])) 1194*c2c66affSColin Finck return TRUE; 1195*c2c66affSColin Finck } 1196*c2c66affSColin Finck return FALSE; 1197*c2c66affSColin Finck } 1198*c2c66affSColin Finck 1199*c2c66affSColin Finck /************************************************************************* 1200*c2c66affSColin Finck * FBadPropTag@4 (MAPI32.179) 1201*c2c66affSColin Finck * 1202*c2c66affSColin Finck * Determine if a property tag is invalid 1203*c2c66affSColin Finck * 1204*c2c66affSColin Finck * PARAMS 1205*c2c66affSColin Finck * ulPropTag [I] Property tag to check 1206*c2c66affSColin Finck * 1207*c2c66affSColin Finck * RETURNS 1208*c2c66affSColin Finck * TRUE, if ulPropTag is invalid, FALSE otherwise. 1209*c2c66affSColin Finck */ 1210*c2c66affSColin Finck ULONG WINAPI FBadPropTag(ULONG ulPropTag) 1211*c2c66affSColin Finck { 1212*c2c66affSColin Finck TRACE("(0x%08x)\n", ulPropTag); 1213*c2c66affSColin Finck 1214*c2c66affSColin Finck switch (ulPropTag & (~MV_FLAG & PROP_TYPE_MASK)) 1215*c2c66affSColin Finck { 1216*c2c66affSColin Finck case PT_UNSPECIFIED: 1217*c2c66affSColin Finck case PT_NULL: 1218*c2c66affSColin Finck case PT_I2: 1219*c2c66affSColin Finck case PT_LONG: 1220*c2c66affSColin Finck case PT_R4: 1221*c2c66affSColin Finck case PT_DOUBLE: 1222*c2c66affSColin Finck case PT_CURRENCY: 1223*c2c66affSColin Finck case PT_APPTIME: 1224*c2c66affSColin Finck case PT_ERROR: 1225*c2c66affSColin Finck case PT_BOOLEAN: 1226*c2c66affSColin Finck case PT_OBJECT: 1227*c2c66affSColin Finck case PT_I8: 1228*c2c66affSColin Finck case PT_STRING8: 1229*c2c66affSColin Finck case PT_UNICODE: 1230*c2c66affSColin Finck case PT_SYSTIME: 1231*c2c66affSColin Finck case PT_CLSID: 1232*c2c66affSColin Finck case PT_BINARY: 1233*c2c66affSColin Finck return FALSE; 1234*c2c66affSColin Finck } 1235*c2c66affSColin Finck return TRUE; 1236*c2c66affSColin Finck } 1237*c2c66affSColin Finck 1238*c2c66affSColin Finck /************************************************************************* 1239*c2c66affSColin Finck * FBadRow@4 (MAPI32.180) 1240*c2c66affSColin Finck * 1241*c2c66affSColin Finck * Determine if a row is invalid 1242*c2c66affSColin Finck * 1243*c2c66affSColin Finck * PARAMS 1244*c2c66affSColin Finck * lpRow [I] Row to check 1245*c2c66affSColin Finck * 1246*c2c66affSColin Finck * RETURNS 1247*c2c66affSColin Finck * TRUE, if lpRow is invalid, FALSE otherwise. 1248*c2c66affSColin Finck */ 1249*c2c66affSColin Finck ULONG WINAPI FBadRow(LPSRow lpRow) 1250*c2c66affSColin Finck { 1251*c2c66affSColin Finck ULONG i; 1252*c2c66affSColin Finck TRACE("(%p)\n", lpRow); 1253*c2c66affSColin Finck 1254*c2c66affSColin Finck if (!lpRow || IsBadReadPtr(lpRow, sizeof(SRow)) || !lpRow->lpProps || 1255*c2c66affSColin Finck IsBadReadPtr(lpRow->lpProps, lpRow->cValues * sizeof(SPropValue))) 1256*c2c66affSColin Finck return TRUE; 1257*c2c66affSColin Finck 1258*c2c66affSColin Finck for (i = 0; i < lpRow->cValues; i++) 1259*c2c66affSColin Finck { 1260*c2c66affSColin Finck if (FBadProp(&lpRow->lpProps[i])) 1261*c2c66affSColin Finck return TRUE; 1262*c2c66affSColin Finck } 1263*c2c66affSColin Finck return FALSE; 1264*c2c66affSColin Finck } 1265*c2c66affSColin Finck 1266*c2c66affSColin Finck /************************************************************************* 1267*c2c66affSColin Finck * FBadProp@4 (MAPI32.181) 1268*c2c66affSColin Finck * 1269*c2c66affSColin Finck * Determine if a property is invalid 1270*c2c66affSColin Finck * 1271*c2c66affSColin Finck * PARAMS 1272*c2c66affSColin Finck * lpProp [I] Property to check 1273*c2c66affSColin Finck * 1274*c2c66affSColin Finck * RETURNS 1275*c2c66affSColin Finck * TRUE, if lpProp is invalid, FALSE otherwise. 1276*c2c66affSColin Finck */ 1277*c2c66affSColin Finck ULONG WINAPI FBadProp(LPSPropValue lpProp) 1278*c2c66affSColin Finck { 1279*c2c66affSColin Finck if (!lpProp || IsBadReadPtr(lpProp, sizeof(SPropValue)) || 1280*c2c66affSColin Finck FBadPropTag(lpProp->ulPropTag)) 1281*c2c66affSColin Finck return TRUE; 1282*c2c66affSColin Finck 1283*c2c66affSColin Finck switch (PROP_TYPE(lpProp->ulPropTag)) 1284*c2c66affSColin Finck { 1285*c2c66affSColin Finck /* Single value properties containing pointers */ 1286*c2c66affSColin Finck case PT_STRING8: 1287*c2c66affSColin Finck if (!lpProp->Value.lpszA || IsBadStringPtrA(lpProp->Value.lpszA, -1)) 1288*c2c66affSColin Finck return TRUE; 1289*c2c66affSColin Finck break; 1290*c2c66affSColin Finck case PT_UNICODE: 1291*c2c66affSColin Finck if (!lpProp->Value.lpszW || IsBadStringPtrW(lpProp->Value.lpszW, -1)) 1292*c2c66affSColin Finck return TRUE; 1293*c2c66affSColin Finck break; 1294*c2c66affSColin Finck case PT_BINARY: 1295*c2c66affSColin Finck if (IsBadReadPtr(lpProp->Value.bin.lpb, lpProp->Value.bin.cb)) 1296*c2c66affSColin Finck return TRUE; 1297*c2c66affSColin Finck break; 1298*c2c66affSColin Finck case PT_CLSID: 1299*c2c66affSColin Finck if (IsBadReadPtr(lpProp->Value.lpguid, sizeof(GUID))) 1300*c2c66affSColin Finck return TRUE; 1301*c2c66affSColin Finck break; 1302*c2c66affSColin Finck 1303*c2c66affSColin Finck /* Multiple value properties (arrays) containing no pointers */ 1304*c2c66affSColin Finck case PT_MV_I2: 1305*c2c66affSColin Finck return PROP_BadArray(lpProp, sizeof(SHORT)); 1306*c2c66affSColin Finck case PT_MV_LONG: 1307*c2c66affSColin Finck return PROP_BadArray(lpProp, sizeof(LONG)); 1308*c2c66affSColin Finck case PT_MV_LONGLONG: 1309*c2c66affSColin Finck return PROP_BadArray(lpProp, sizeof(LONG64)); 1310*c2c66affSColin Finck case PT_MV_FLOAT: 1311*c2c66affSColin Finck return PROP_BadArray(lpProp, sizeof(float)); 1312*c2c66affSColin Finck case PT_MV_SYSTIME: 1313*c2c66affSColin Finck return PROP_BadArray(lpProp, sizeof(FILETIME)); 1314*c2c66affSColin Finck case PT_MV_APPTIME: 1315*c2c66affSColin Finck case PT_MV_DOUBLE: 1316*c2c66affSColin Finck return PROP_BadArray(lpProp, sizeof(double)); 1317*c2c66affSColin Finck case PT_MV_CURRENCY: 1318*c2c66affSColin Finck return PROP_BadArray(lpProp, sizeof(CY)); 1319*c2c66affSColin Finck case PT_MV_CLSID: 1320*c2c66affSColin Finck return PROP_BadArray(lpProp, sizeof(GUID)); 1321*c2c66affSColin Finck 1322*c2c66affSColin Finck /* Multiple value properties containing pointers */ 1323*c2c66affSColin Finck case PT_MV_STRING8: 1324*c2c66affSColin Finck return FBadRglpszA(lpProp->Value.MVszA.lppszA, 1325*c2c66affSColin Finck lpProp->Value.MVszA.cValues); 1326*c2c66affSColin Finck case PT_MV_UNICODE: 1327*c2c66affSColin Finck return FBadRglpszW(lpProp->Value.MVszW.lppszW, 1328*c2c66affSColin Finck lpProp->Value.MVszW.cValues); 1329*c2c66affSColin Finck case PT_MV_BINARY: 1330*c2c66affSColin Finck return FBadEntryList(&lpProp->Value.MVbin); 1331*c2c66affSColin Finck } 1332*c2c66affSColin Finck return FALSE; 1333*c2c66affSColin Finck } 1334*c2c66affSColin Finck 1335*c2c66affSColin Finck /************************************************************************* 1336*c2c66affSColin Finck * FBadColumnSet@4 (MAPI32.182) 1337*c2c66affSColin Finck * 1338*c2c66affSColin Finck * Determine if an array of property tags is invalid 1339*c2c66affSColin Finck * 1340*c2c66affSColin Finck * PARAMS 1341*c2c66affSColin Finck * lpCols [I] Property tag array to check 1342*c2c66affSColin Finck * 1343*c2c66affSColin Finck * RETURNS 1344*c2c66affSColin Finck * TRUE, if lpCols is invalid, FALSE otherwise. 1345*c2c66affSColin Finck */ 1346*c2c66affSColin Finck ULONG WINAPI FBadColumnSet(LPSPropTagArray lpCols) 1347*c2c66affSColin Finck { 1348*c2c66affSColin Finck ULONG ulRet = FALSE, i; 1349*c2c66affSColin Finck 1350*c2c66affSColin Finck TRACE("(%p)\n", lpCols); 1351*c2c66affSColin Finck 1352*c2c66affSColin Finck if (!lpCols || IsBadReadPtr(lpCols, CbSPropTagArray(lpCols))) 1353*c2c66affSColin Finck ulRet = TRUE; 1354*c2c66affSColin Finck else 1355*c2c66affSColin Finck { 1356*c2c66affSColin Finck for (i = 0; i < lpCols->cValues; i++) 1357*c2c66affSColin Finck { 1358*c2c66affSColin Finck if ((lpCols->aulPropTag[i] & PROP_TYPE_MASK) == PT_ERROR || 1359*c2c66affSColin Finck FBadPropTag(lpCols->aulPropTag[i])) 1360*c2c66affSColin Finck { 1361*c2c66affSColin Finck ulRet = TRUE; 1362*c2c66affSColin Finck break; 1363*c2c66affSColin Finck } 1364*c2c66affSColin Finck } 1365*c2c66affSColin Finck } 1366*c2c66affSColin Finck TRACE("Returning %s\n", ulRet ? "TRUE" : "FALSE"); 1367*c2c66affSColin Finck return ulRet; 1368*c2c66affSColin Finck } 1369*c2c66affSColin Finck 1370*c2c66affSColin Finck 1371*c2c66affSColin Finck /************************************************************************** 1372*c2c66affSColin Finck * IPropData {MAPI32} 1373*c2c66affSColin Finck * 1374*c2c66affSColin Finck * A default Mapi interface to provide manipulation of object properties. 1375*c2c66affSColin Finck * 1376*c2c66affSColin Finck * DESCRIPTION 1377*c2c66affSColin Finck * This object provides a default interface suitable in some cases as an 1378*c2c66affSColin Finck * implementation of the IMAPIProp interface (which has no default 1379*c2c66affSColin Finck * implementation). In addition to the IMAPIProp() methods inherited, this 1380*c2c66affSColin Finck * interface allows read/write control over access to the object and its 1381*c2c66affSColin Finck * individual properties. 1382*c2c66affSColin Finck * 1383*c2c66affSColin Finck * To obtain the default implementation of this interface from Mapi, call 1384*c2c66affSColin Finck * CreateIProp(). 1385*c2c66affSColin Finck * 1386*c2c66affSColin Finck * METHODS 1387*c2c66affSColin Finck */ 1388*c2c66affSColin Finck 1389*c2c66affSColin Finck /* A single property in a property data collection */ 1390*c2c66affSColin Finck typedef struct 1391*c2c66affSColin Finck { 1392*c2c66affSColin Finck struct list entry; 1393*c2c66affSColin Finck ULONG ulAccess; /* The property value access level */ 1394*c2c66affSColin Finck LPSPropValue value; /* The property value */ 1395*c2c66affSColin Finck } IPropDataItem, *LPIPropDataItem; 1396*c2c66affSColin Finck 1397*c2c66affSColin Finck /* The main property data collection structure */ 1398*c2c66affSColin Finck typedef struct 1399*c2c66affSColin Finck { 1400*c2c66affSColin Finck IPropData IPropData_iface; 1401*c2c66affSColin Finck LONG lRef; /* Reference count */ 1402*c2c66affSColin Finck ALLOCATEBUFFER *lpAlloc; /* Memory allocation routine */ 1403*c2c66affSColin Finck ALLOCATEMORE *lpMore; /* Linked memory allocation routine */ 1404*c2c66affSColin Finck FREEBUFFER *lpFree; /* Memory free routine */ 1405*c2c66affSColin Finck ULONG ulObjAccess; /* Object access level */ 1406*c2c66affSColin Finck ULONG ulNumValues; /* Number of items in values list */ 1407*c2c66affSColin Finck struct list values; /* List of property values */ 1408*c2c66affSColin Finck CRITICAL_SECTION cs; /* Lock for thread safety */ 1409*c2c66affSColin Finck } IPropDataImpl; 1410*c2c66affSColin Finck 1411*c2c66affSColin Finck static inline IPropDataImpl *impl_from_IPropData(IPropData *iface) 1412*c2c66affSColin Finck { 1413*c2c66affSColin Finck return CONTAINING_RECORD(iface, IPropDataImpl, IPropData_iface); 1414*c2c66affSColin Finck } 1415*c2c66affSColin Finck 1416*c2c66affSColin Finck /* Internal - Get a property value, assumes lock is held */ 1417*c2c66affSColin Finck static IPropDataItem *IMAPIPROP_GetValue(IPropDataImpl *This, ULONG ulPropTag) 1418*c2c66affSColin Finck { 1419*c2c66affSColin Finck struct list *cursor; 1420*c2c66affSColin Finck 1421*c2c66affSColin Finck LIST_FOR_EACH(cursor, &This->values) 1422*c2c66affSColin Finck { 1423*c2c66affSColin Finck LPIPropDataItem current = LIST_ENTRY(cursor, IPropDataItem, entry); 1424*c2c66affSColin Finck /* Note that property types don't have to match, just Id's */ 1425*c2c66affSColin Finck if (PROP_ID(current->value->ulPropTag) == PROP_ID(ulPropTag)) 1426*c2c66affSColin Finck return current; 1427*c2c66affSColin Finck } 1428*c2c66affSColin Finck return NULL; 1429*c2c66affSColin Finck } 1430*c2c66affSColin Finck 1431*c2c66affSColin Finck /* Internal - Add a new property value, assumes lock is held */ 1432*c2c66affSColin Finck static IPropDataItem *IMAPIPROP_AddValue(IPropDataImpl *This, 1433*c2c66affSColin Finck LPSPropValue lpProp) 1434*c2c66affSColin Finck { 1435*c2c66affSColin Finck LPVOID lpMem; 1436*c2c66affSColin Finck LPIPropDataItem lpNew; 1437*c2c66affSColin Finck HRESULT hRet; 1438*c2c66affSColin Finck 1439*c2c66affSColin Finck hRet = This->lpAlloc(sizeof(IPropDataItem), &lpMem); 1440*c2c66affSColin Finck 1441*c2c66affSColin Finck if (SUCCEEDED(hRet)) 1442*c2c66affSColin Finck { 1443*c2c66affSColin Finck lpNew = lpMem; 1444*c2c66affSColin Finck lpNew->ulAccess = IPROP_READWRITE; 1445*c2c66affSColin Finck 1446*c2c66affSColin Finck /* Allocate the value separately so we can update it easily */ 1447*c2c66affSColin Finck lpMem = NULL; 1448*c2c66affSColin Finck hRet = This->lpAlloc(sizeof(SPropValue), &lpMem); 1449*c2c66affSColin Finck if (SUCCEEDED(hRet)) 1450*c2c66affSColin Finck { 1451*c2c66affSColin Finck lpNew->value = lpMem; 1452*c2c66affSColin Finck 1453*c2c66affSColin Finck hRet = PropCopyMore(lpNew->value, lpProp, This->lpMore, lpMem); 1454*c2c66affSColin Finck if (SUCCEEDED(hRet)) 1455*c2c66affSColin Finck { 1456*c2c66affSColin Finck list_add_tail(&This->values, &lpNew->entry); 1457*c2c66affSColin Finck This->ulNumValues++; 1458*c2c66affSColin Finck return lpNew; 1459*c2c66affSColin Finck } 1460*c2c66affSColin Finck This->lpFree(lpNew->value); 1461*c2c66affSColin Finck } 1462*c2c66affSColin Finck This->lpFree(lpNew); 1463*c2c66affSColin Finck } 1464*c2c66affSColin Finck return NULL; 1465*c2c66affSColin Finck } 1466*c2c66affSColin Finck 1467*c2c66affSColin Finck /* Internal - Lock an IPropData object */ 1468*c2c66affSColin Finck static inline void IMAPIPROP_Lock(IPropDataImpl *This) 1469*c2c66affSColin Finck { 1470*c2c66affSColin Finck EnterCriticalSection(&This->cs); 1471*c2c66affSColin Finck } 1472*c2c66affSColin Finck 1473*c2c66affSColin Finck /* Internal - Unlock an IPropData object */ 1474*c2c66affSColin Finck static inline void IMAPIPROP_Unlock(IPropDataImpl *This) 1475*c2c66affSColin Finck { 1476*c2c66affSColin Finck LeaveCriticalSection(&This->cs); 1477*c2c66affSColin Finck } 1478*c2c66affSColin Finck 1479*c2c66affSColin Finck /* This one seems to be missing from mapidefs.h */ 1480*c2c66affSColin Finck #define CbNewSPropProblemArray(c) \ 1481*c2c66affSColin Finck (offsetof(SPropProblemArray,aProblem)+(c)*sizeof(SPropProblem)) 1482*c2c66affSColin Finck 1483*c2c66affSColin Finck /************************************************************************** 1484*c2c66affSColin Finck * IPropData_QueryInterface {MAPI32} 1485*c2c66affSColin Finck * 1486*c2c66affSColin Finck * Inherited method from the IUnknown Interface. 1487*c2c66affSColin Finck * See IUnknown_QueryInterface. 1488*c2c66affSColin Finck */ 1489*c2c66affSColin Finck static HRESULT WINAPI IPropData_fnQueryInterface(LPPROPDATA iface, REFIID riid, LPVOID *ppvObj) 1490*c2c66affSColin Finck { 1491*c2c66affSColin Finck IPropDataImpl *This = impl_from_IPropData(iface); 1492*c2c66affSColin Finck 1493*c2c66affSColin Finck TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppvObj); 1494*c2c66affSColin Finck 1495*c2c66affSColin Finck if (!ppvObj || !riid) 1496*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 1497*c2c66affSColin Finck 1498*c2c66affSColin Finck *ppvObj = NULL; 1499*c2c66affSColin Finck 1500*c2c66affSColin Finck if(IsEqualIID(riid, &IID_IUnknown) || 1501*c2c66affSColin Finck IsEqualIID(riid, &IID_IMAPIProp) || 1502*c2c66affSColin Finck IsEqualIID(riid, &IID_IMAPIPropData)) 1503*c2c66affSColin Finck { 1504*c2c66affSColin Finck *ppvObj = &This->IPropData_iface; 1505*c2c66affSColin Finck IPropData_AddRef(iface); 1506*c2c66affSColin Finck TRACE("returning %p\n", *ppvObj); 1507*c2c66affSColin Finck return S_OK; 1508*c2c66affSColin Finck } 1509*c2c66affSColin Finck 1510*c2c66affSColin Finck TRACE("returning E_NOINTERFACE\n"); 1511*c2c66affSColin Finck return MAPI_E_INTERFACE_NOT_SUPPORTED; 1512*c2c66affSColin Finck } 1513*c2c66affSColin Finck 1514*c2c66affSColin Finck /************************************************************************** 1515*c2c66affSColin Finck * IPropData_AddRef {MAPI32} 1516*c2c66affSColin Finck * 1517*c2c66affSColin Finck * Inherited method from the IUnknown Interface. 1518*c2c66affSColin Finck * See IUnknown_AddRef. 1519*c2c66affSColin Finck */ 1520*c2c66affSColin Finck static ULONG WINAPI IPropData_fnAddRef(LPPROPDATA iface) 1521*c2c66affSColin Finck { 1522*c2c66affSColin Finck IPropDataImpl *This = impl_from_IPropData(iface); 1523*c2c66affSColin Finck 1524*c2c66affSColin Finck TRACE("(%p)->(count before=%u)\n", This, This->lRef); 1525*c2c66affSColin Finck 1526*c2c66affSColin Finck return InterlockedIncrement(&This->lRef); 1527*c2c66affSColin Finck } 1528*c2c66affSColin Finck 1529*c2c66affSColin Finck /************************************************************************** 1530*c2c66affSColin Finck * IPropData_Release {MAPI32} 1531*c2c66affSColin Finck * 1532*c2c66affSColin Finck * Inherited method from the IUnknown Interface. 1533*c2c66affSColin Finck * See IUnknown_Release. 1534*c2c66affSColin Finck */ 1535*c2c66affSColin Finck static ULONG WINAPI IPropData_fnRelease(LPPROPDATA iface) 1536*c2c66affSColin Finck { 1537*c2c66affSColin Finck IPropDataImpl *This = impl_from_IPropData(iface); 1538*c2c66affSColin Finck LONG lRef; 1539*c2c66affSColin Finck 1540*c2c66affSColin Finck TRACE("(%p)->(count before=%u)\n", This, This->lRef); 1541*c2c66affSColin Finck 1542*c2c66affSColin Finck lRef = InterlockedDecrement(&This->lRef); 1543*c2c66affSColin Finck if (!lRef) 1544*c2c66affSColin Finck { 1545*c2c66affSColin Finck TRACE("Destroying IPropData (%p)\n",This); 1546*c2c66affSColin Finck 1547*c2c66affSColin Finck /* Note: No need to lock, since no other thread is referencing iface */ 1548*c2c66affSColin Finck while (!list_empty(&This->values)) 1549*c2c66affSColin Finck { 1550*c2c66affSColin Finck struct list *head = list_head(&This->values); 1551*c2c66affSColin Finck LPIPropDataItem current = LIST_ENTRY(head, IPropDataItem, entry); 1552*c2c66affSColin Finck list_remove(head); 1553*c2c66affSColin Finck This->lpFree(current->value); 1554*c2c66affSColin Finck This->lpFree(current); 1555*c2c66affSColin Finck } 1556*c2c66affSColin Finck This->cs.DebugInfo->Spare[0] = 0; 1557*c2c66affSColin Finck DeleteCriticalSection(&This->cs); 1558*c2c66affSColin Finck This->lpFree(This); 1559*c2c66affSColin Finck } 1560*c2c66affSColin Finck return (ULONG)lRef; 1561*c2c66affSColin Finck } 1562*c2c66affSColin Finck 1563*c2c66affSColin Finck /************************************************************************** 1564*c2c66affSColin Finck * IPropData_GetLastError {MAPI32} 1565*c2c66affSColin Finck * 1566*c2c66affSColin Finck * Get information about the last error that occurred in an IMAPIProp object. 1567*c2c66affSColin Finck * 1568*c2c66affSColin Finck * PARAMS 1569*c2c66affSColin Finck * iface [I] IMAPIProp object that experienced the error 1570*c2c66affSColin Finck * hRes [I] Result of the call that returned an error 1571*c2c66affSColin Finck * ulFlags [I] 0=return Ascii strings, MAPI_UNICODE=return Unicode strings 1572*c2c66affSColin Finck * lppError [O] Destination for detailed error information 1573*c2c66affSColin Finck * 1574*c2c66affSColin Finck * RETURNS 1575*c2c66affSColin Finck * Success: S_OK. *lppError contains details about the last error. 1576*c2c66affSColin Finck * Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid, 1577*c2c66affSColin Finck * MAPI_E_NOT_ENOUGH_MEMORY, if memory allocation fails. 1578*c2c66affSColin Finck * 1579*c2c66affSColin Finck * NOTES 1580*c2c66affSColin Finck * - If this function succeeds, the returned information in *lppError must be 1581*c2c66affSColin Finck * freed using MAPIFreeBuffer() once the caller is finished with it. 1582*c2c66affSColin Finck * - It is possible for this function to succeed and set *lppError to NULL, 1583*c2c66affSColin Finck * if there is no further information to report about hRes. 1584*c2c66affSColin Finck */ 1585*c2c66affSColin Finck static HRESULT WINAPI IPropData_fnGetLastError(LPPROPDATA iface, HRESULT hRes, ULONG ulFlags, 1586*c2c66affSColin Finck LPMAPIERROR *lppError) 1587*c2c66affSColin Finck { 1588*c2c66affSColin Finck TRACE("(%p,0x%08X,0x%08X,%p)\n", iface, hRes, ulFlags, lppError); 1589*c2c66affSColin Finck 1590*c2c66affSColin Finck if (!lppError || SUCCEEDED(hRes) || (ulFlags & ~MAPI_UNICODE)) 1591*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 1592*c2c66affSColin Finck 1593*c2c66affSColin Finck *lppError = NULL; 1594*c2c66affSColin Finck return S_OK; 1595*c2c66affSColin Finck } 1596*c2c66affSColin Finck 1597*c2c66affSColin Finck /************************************************************************** 1598*c2c66affSColin Finck * IPropData_SaveChanges {MAPI32} 1599*c2c66affSColin Finck * 1600*c2c66affSColin Finck * Update any changes made to a transactional IMAPIProp object. 1601*c2c66affSColin Finck * 1602*c2c66affSColin Finck * PARAMS 1603*c2c66affSColin Finck * iface [I] IMAPIProp object to update 1604*c2c66affSColin Finck * ulFlags [I] Flags controlling the update. 1605*c2c66affSColin Finck * 1606*c2c66affSColin Finck * RETURNS 1607*c2c66affSColin Finck * Success: S_OK. Any outstanding changes are committed to the object. 1608*c2c66affSColin Finck * Failure: An HRESULT error code describing the error. 1609*c2c66affSColin Finck */ 1610*c2c66affSColin Finck static HRESULT WINAPI IPropData_fnSaveChanges(LPPROPDATA iface, ULONG ulFlags) 1611*c2c66affSColin Finck { 1612*c2c66affSColin Finck TRACE("(%p,0x%08X)\n", iface, ulFlags); 1613*c2c66affSColin Finck 1614*c2c66affSColin Finck /* Since this object is not transacted we do not need to implement this */ 1615*c2c66affSColin Finck /* FIXME: Should we set the access levels to clean? */ 1616*c2c66affSColin Finck return S_OK; 1617*c2c66affSColin Finck } 1618*c2c66affSColin Finck 1619*c2c66affSColin Finck /************************************************************************** 1620*c2c66affSColin Finck * IPropData_GetProps {MAPI32} 1621*c2c66affSColin Finck * 1622*c2c66affSColin Finck * Get property values from an IMAPIProp object. 1623*c2c66affSColin Finck * 1624*c2c66affSColin Finck * PARAMS 1625*c2c66affSColin Finck * iface [I] IMAPIProp object to get the property values from 1626*c2c66affSColin Finck * lpTags [I] Property tags of property values to be retrieved 1627*c2c66affSColin Finck * ulFlags [I] Return 0=Ascii MAPI_UNICODE=Unicode strings for 1628*c2c66affSColin Finck * unspecified types 1629*c2c66affSColin Finck * lpCount [O] Destination for number of properties returned 1630*c2c66affSColin Finck * lppProps [O] Destination for returned property values 1631*c2c66affSColin Finck * 1632*c2c66affSColin Finck * RETURNS 1633*c2c66affSColin Finck * Success: S_OK. *lppProps and *lpCount are updated. 1634*c2c66affSColin Finck * Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid. 1635*c2c66affSColin Finck * MAPI_E_NOT_ENOUGH_MEMORY, if memory allocation fails, or 1636*c2c66affSColin Finck * MAPI_W_ERRORS_RETURNED if not all properties were retrieved 1637*c2c66affSColin Finck * successfully. 1638*c2c66affSColin Finck * NOTES 1639*c2c66affSColin Finck * - If MAPI_W_ERRORS_RETURNED is returned, any properties that could not be 1640*c2c66affSColin Finck * retrieved from iface are present in lppProps with their type 1641*c2c66affSColin Finck * changed to PT_ERROR and Id unchanged. 1642*c2c66affSColin Finck */ 1643*c2c66affSColin Finck static HRESULT WINAPI IPropData_fnGetProps(LPPROPDATA iface, LPSPropTagArray lpTags, ULONG ulFlags, 1644*c2c66affSColin Finck ULONG *lpCount, LPSPropValue *lppProps) 1645*c2c66affSColin Finck { 1646*c2c66affSColin Finck IPropDataImpl *This = impl_from_IPropData(iface); 1647*c2c66affSColin Finck ULONG i; 1648*c2c66affSColin Finck HRESULT hRet = S_OK; 1649*c2c66affSColin Finck 1650*c2c66affSColin Finck TRACE("(%p,%p,0x%08x,%p,%p) stub\n", iface, lpTags, ulFlags, 1651*c2c66affSColin Finck lpCount, lppProps); 1652*c2c66affSColin Finck 1653*c2c66affSColin Finck if (!iface || ulFlags & ~MAPI_UNICODE || !lpTags || *lpCount || !lppProps) 1654*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 1655*c2c66affSColin Finck 1656*c2c66affSColin Finck FIXME("semi-stub, flags not supported\n"); 1657*c2c66affSColin Finck 1658*c2c66affSColin Finck *lpCount = lpTags->cValues; 1659*c2c66affSColin Finck *lppProps = NULL; 1660*c2c66affSColin Finck 1661*c2c66affSColin Finck if (*lpCount) 1662*c2c66affSColin Finck { 1663*c2c66affSColin Finck hRet = MAPIAllocateBuffer(*lpCount * sizeof(SPropValue), (LPVOID*)lppProps); 1664*c2c66affSColin Finck if (FAILED(hRet)) 1665*c2c66affSColin Finck return hRet; 1666*c2c66affSColin Finck 1667*c2c66affSColin Finck IMAPIPROP_Lock(This); 1668*c2c66affSColin Finck 1669*c2c66affSColin Finck for (i = 0; i < lpTags->cValues; i++) 1670*c2c66affSColin Finck { 1671*c2c66affSColin Finck HRESULT hRetTmp = E_INVALIDARG; 1672*c2c66affSColin Finck LPIPropDataItem item; 1673*c2c66affSColin Finck 1674*c2c66affSColin Finck item = IMAPIPROP_GetValue(This, lpTags->aulPropTag[i]); 1675*c2c66affSColin Finck 1676*c2c66affSColin Finck if (item) 1677*c2c66affSColin Finck hRetTmp = PropCopyMore(&(*lppProps)[i], item->value, 1678*c2c66affSColin Finck This->lpMore, *lppProps); 1679*c2c66affSColin Finck if (FAILED(hRetTmp)) 1680*c2c66affSColin Finck { 1681*c2c66affSColin Finck hRet = MAPI_W_ERRORS_RETURNED; 1682*c2c66affSColin Finck (*lppProps)[i].ulPropTag = 1683*c2c66affSColin Finck CHANGE_PROP_TYPE(lpTags->aulPropTag[i], PT_ERROR); 1684*c2c66affSColin Finck } 1685*c2c66affSColin Finck } 1686*c2c66affSColin Finck 1687*c2c66affSColin Finck IMAPIPROP_Unlock(This); 1688*c2c66affSColin Finck } 1689*c2c66affSColin Finck return hRet; 1690*c2c66affSColin Finck } 1691*c2c66affSColin Finck 1692*c2c66affSColin Finck /************************************************************************** 1693*c2c66affSColin Finck * MAPIProp_GetPropList {MAPI32} 1694*c2c66affSColin Finck * 1695*c2c66affSColin Finck * Get the list of property tags for all values in an IMAPIProp object. 1696*c2c66affSColin Finck * 1697*c2c66affSColin Finck * PARAMS 1698*c2c66affSColin Finck * iface [I] IMAPIProp object to get the property tag list from 1699*c2c66affSColin Finck * ulFlags [I] Return 0=Ascii MAPI_UNICODE=Unicode strings for 1700*c2c66affSColin Finck * unspecified types 1701*c2c66affSColin Finck * lppTags [O] Destination for the retrieved property tag list 1702*c2c66affSColin Finck * 1703*c2c66affSColin Finck * RETURNS 1704*c2c66affSColin Finck * Success: S_OK. *lppTags contains the tags for all available properties. 1705*c2c66affSColin Finck * Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid. 1706*c2c66affSColin Finck * MAPI_E_BAD_CHARWIDTH, if Ascii or Unicode strings are requested 1707*c2c66affSColin Finck * and that type of string is not supported. 1708*c2c66affSColin Finck */ 1709*c2c66affSColin Finck static HRESULT WINAPI IPropData_fnGetPropList(LPPROPDATA iface, ULONG ulFlags, 1710*c2c66affSColin Finck LPSPropTagArray *lppTags) 1711*c2c66affSColin Finck { 1712*c2c66affSColin Finck IPropDataImpl *This = impl_from_IPropData(iface); 1713*c2c66affSColin Finck ULONG i; 1714*c2c66affSColin Finck HRESULT hRet; 1715*c2c66affSColin Finck 1716*c2c66affSColin Finck TRACE("(%p,0x%08x,%p) stub\n", iface, ulFlags, lppTags); 1717*c2c66affSColin Finck 1718*c2c66affSColin Finck if (!iface || ulFlags & ~MAPI_UNICODE || !lppTags) 1719*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 1720*c2c66affSColin Finck 1721*c2c66affSColin Finck FIXME("semi-stub, flags not supported\n"); 1722*c2c66affSColin Finck 1723*c2c66affSColin Finck *lppTags = NULL; 1724*c2c66affSColin Finck 1725*c2c66affSColin Finck IMAPIPROP_Lock(This); 1726*c2c66affSColin Finck 1727*c2c66affSColin Finck hRet = MAPIAllocateBuffer(CbNewSPropTagArray(This->ulNumValues), 1728*c2c66affSColin Finck (LPVOID*)lppTags); 1729*c2c66affSColin Finck if (SUCCEEDED(hRet)) 1730*c2c66affSColin Finck { 1731*c2c66affSColin Finck struct list *cursor; 1732*c2c66affSColin Finck 1733*c2c66affSColin Finck i = 0; 1734*c2c66affSColin Finck LIST_FOR_EACH(cursor, &This->values) 1735*c2c66affSColin Finck { 1736*c2c66affSColin Finck LPIPropDataItem current = LIST_ENTRY(cursor, IPropDataItem, entry); 1737*c2c66affSColin Finck (*lppTags)->aulPropTag[i] = current->value->ulPropTag; 1738*c2c66affSColin Finck i++; 1739*c2c66affSColin Finck } 1740*c2c66affSColin Finck (*lppTags)->cValues = This->ulNumValues; 1741*c2c66affSColin Finck } 1742*c2c66affSColin Finck 1743*c2c66affSColin Finck IMAPIPROP_Unlock(This); 1744*c2c66affSColin Finck return hRet; 1745*c2c66affSColin Finck } 1746*c2c66affSColin Finck 1747*c2c66affSColin Finck /************************************************************************** 1748*c2c66affSColin Finck * IPropData_OpenProperty {MAPI32} 1749*c2c66affSColin Finck * 1750*c2c66affSColin Finck * Not documented at this time. 1751*c2c66affSColin Finck * 1752*c2c66affSColin Finck * RETURNS 1753*c2c66affSColin Finck * An HRESULT success/failure code. 1754*c2c66affSColin Finck */ 1755*c2c66affSColin Finck static HRESULT WINAPI IPropData_fnOpenProperty(LPPROPDATA iface, ULONG ulPropTag, LPCIID iid, 1756*c2c66affSColin Finck ULONG ulOpts, ULONG ulFlags, LPUNKNOWN *lpUnk) 1757*c2c66affSColin Finck { 1758*c2c66affSColin Finck FIXME("(%p,%u,%s,%u,0x%08x,%p) stub\n", iface, ulPropTag, 1759*c2c66affSColin Finck debugstr_guid(iid), ulOpts, ulFlags, lpUnk); 1760*c2c66affSColin Finck return MAPI_E_NO_SUPPORT; 1761*c2c66affSColin Finck } 1762*c2c66affSColin Finck 1763*c2c66affSColin Finck 1764*c2c66affSColin Finck /************************************************************************** 1765*c2c66affSColin Finck * IPropData_SetProps {MAPI32} 1766*c2c66affSColin Finck * 1767*c2c66affSColin Finck * Add or edit the property values in an IMAPIProp object. 1768*c2c66affSColin Finck * 1769*c2c66affSColin Finck * PARAMS 1770*c2c66affSColin Finck * iface [I] IMAPIProp object to get the property tag list from 1771*c2c66affSColin Finck * ulValues [I] Number of properties in lpProps 1772*c2c66affSColin Finck * lpProps [I] Property values to set 1773*c2c66affSColin Finck * lppProbs [O] Optional destination for any problems that occurred 1774*c2c66affSColin Finck * 1775*c2c66affSColin Finck * RETURNS 1776*c2c66affSColin Finck * Success: S_OK. The properties in lpProps are added to iface if they don't 1777*c2c66affSColin Finck * exist, or changed to the values in lpProps if they do 1778*c2c66affSColin Finck * Failure: An HRESULT error code describing the error 1779*c2c66affSColin Finck */ 1780*c2c66affSColin Finck static HRESULT WINAPI IPropData_fnSetProps(LPPROPDATA iface, ULONG ulValues, LPSPropValue lpProps, 1781*c2c66affSColin Finck LPSPropProblemArray *lppProbs) 1782*c2c66affSColin Finck { 1783*c2c66affSColin Finck IPropDataImpl *This = impl_from_IPropData(iface); 1784*c2c66affSColin Finck HRESULT hRet = S_OK; 1785*c2c66affSColin Finck ULONG i; 1786*c2c66affSColin Finck 1787*c2c66affSColin Finck TRACE("(%p,%u,%p,%p)\n", iface, ulValues, lpProps, lppProbs); 1788*c2c66affSColin Finck 1789*c2c66affSColin Finck if (!iface || !lpProps) 1790*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 1791*c2c66affSColin Finck 1792*c2c66affSColin Finck for (i = 0; i < ulValues; i++) 1793*c2c66affSColin Finck { 1794*c2c66affSColin Finck if (FBadProp(&lpProps[i]) || 1795*c2c66affSColin Finck PROP_TYPE(lpProps[i].ulPropTag) == PT_OBJECT || 1796*c2c66affSColin Finck PROP_TYPE(lpProps[i].ulPropTag) == PT_NULL) 1797*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 1798*c2c66affSColin Finck } 1799*c2c66affSColin Finck 1800*c2c66affSColin Finck IMAPIPROP_Lock(This); 1801*c2c66affSColin Finck 1802*c2c66affSColin Finck /* FIXME: Under what circumstances is lpProbs created? */ 1803*c2c66affSColin Finck for (i = 0; i < ulValues; i++) 1804*c2c66affSColin Finck { 1805*c2c66affSColin Finck LPIPropDataItem item = IMAPIPROP_GetValue(This, lpProps[i].ulPropTag); 1806*c2c66affSColin Finck 1807*c2c66affSColin Finck if (item) 1808*c2c66affSColin Finck { 1809*c2c66affSColin Finck HRESULT hRetTmp; 1810*c2c66affSColin Finck LPVOID lpMem = NULL; 1811*c2c66affSColin Finck 1812*c2c66affSColin Finck /* Found, so update the existing value */ 1813*c2c66affSColin Finck if (item->value->ulPropTag != lpProps[i].ulPropTag) 1814*c2c66affSColin Finck FIXME("semi-stub, overwriting type (not coercing)\n"); 1815*c2c66affSColin Finck 1816*c2c66affSColin Finck hRetTmp = This->lpAlloc(sizeof(SPropValue), &lpMem); 1817*c2c66affSColin Finck if (SUCCEEDED(hRetTmp)) 1818*c2c66affSColin Finck { 1819*c2c66affSColin Finck hRetTmp = PropCopyMore(lpMem, &lpProps[i], This->lpMore, lpMem); 1820*c2c66affSColin Finck if (SUCCEEDED(hRetTmp)) 1821*c2c66affSColin Finck { 1822*c2c66affSColin Finck This->lpFree(item->value); 1823*c2c66affSColin Finck item->value = lpMem; 1824*c2c66affSColin Finck continue; 1825*c2c66affSColin Finck } 1826*c2c66affSColin Finck This->lpFree(lpMem); 1827*c2c66affSColin Finck } 1828*c2c66affSColin Finck hRet = hRetTmp; 1829*c2c66affSColin Finck } 1830*c2c66affSColin Finck else 1831*c2c66affSColin Finck { 1832*c2c66affSColin Finck /* Add new value */ 1833*c2c66affSColin Finck if (!IMAPIPROP_AddValue(This, &lpProps[i])) 1834*c2c66affSColin Finck hRet = MAPI_E_NOT_ENOUGH_MEMORY; 1835*c2c66affSColin Finck } 1836*c2c66affSColin Finck } 1837*c2c66affSColin Finck 1838*c2c66affSColin Finck IMAPIPROP_Unlock(This); 1839*c2c66affSColin Finck return hRet; 1840*c2c66affSColin Finck } 1841*c2c66affSColin Finck 1842*c2c66affSColin Finck /************************************************************************** 1843*c2c66affSColin Finck * IPropData_DeleteProps {MAPI32} 1844*c2c66affSColin Finck * 1845*c2c66affSColin Finck * Delete one or more property values from an IMAPIProp object. 1846*c2c66affSColin Finck * 1847*c2c66affSColin Finck * PARAMS 1848*c2c66affSColin Finck * iface [I] IMAPIProp object to remove property values from. 1849*c2c66affSColin Finck * lpTags [I] Collection of property Id's to remove from iface. 1850*c2c66affSColin Finck * lppProbs [O] Destination for problems encountered, if any. 1851*c2c66affSColin Finck * 1852*c2c66affSColin Finck * RETURNS 1853*c2c66affSColin Finck * Success: S_OK. Any properties in iface matching property Id's in lpTags have 1854*c2c66affSColin Finck * been deleted. If lppProbs is non-NULL it contains details of any 1855*c2c66affSColin Finck * errors that occurred. 1856*c2c66affSColin Finck * Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid. 1857*c2c66affSColin Finck * E_ACCESSDENIED, if this object was created using CreateIProp() and 1858*c2c66affSColin Finck * a subsequent call to IPropData_SetObjAccess() was made specifying 1859*c2c66affSColin Finck * IPROP_READONLY as the access type. 1860*c2c66affSColin Finck * 1861*c2c66affSColin Finck * NOTES 1862*c2c66affSColin Finck * - lppProbs will not be populated for cases where a property Id is present 1863*c2c66affSColin Finck * in lpTags but not in iface. 1864*c2c66affSColin Finck * - lppProbs should be deleted with MAPIFreeBuffer() if returned. 1865*c2c66affSColin Finck */ 1866*c2c66affSColin Finck static HRESULT WINAPI IPropData_fnDeleteProps(LPPROPDATA iface, LPSPropTagArray lpTags, 1867*c2c66affSColin Finck LPSPropProblemArray *lppProbs) 1868*c2c66affSColin Finck { 1869*c2c66affSColin Finck IPropDataImpl *This = impl_from_IPropData(iface); 1870*c2c66affSColin Finck ULONG i, numProbs = 0; 1871*c2c66affSColin Finck HRESULT hRet = S_OK; 1872*c2c66affSColin Finck 1873*c2c66affSColin Finck TRACE("(%p,%p,%p)\n", iface, lpTags, lppProbs); 1874*c2c66affSColin Finck 1875*c2c66affSColin Finck if (!iface || !lpTags) 1876*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 1877*c2c66affSColin Finck 1878*c2c66affSColin Finck if (lppProbs) 1879*c2c66affSColin Finck *lppProbs = NULL; 1880*c2c66affSColin Finck 1881*c2c66affSColin Finck for (i = 0; i < lpTags->cValues; i++) 1882*c2c66affSColin Finck { 1883*c2c66affSColin Finck if (FBadPropTag(lpTags->aulPropTag[i]) || 1884*c2c66affSColin Finck PROP_TYPE(lpTags->aulPropTag[i]) == PT_OBJECT || 1885*c2c66affSColin Finck PROP_TYPE(lpTags->aulPropTag[i]) == PT_NULL) 1886*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 1887*c2c66affSColin Finck } 1888*c2c66affSColin Finck 1889*c2c66affSColin Finck IMAPIPROP_Lock(This); 1890*c2c66affSColin Finck 1891*c2c66affSColin Finck if (This->ulObjAccess != IPROP_READWRITE) 1892*c2c66affSColin Finck { 1893*c2c66affSColin Finck IMAPIPROP_Unlock(This); 1894*c2c66affSColin Finck return E_ACCESSDENIED; 1895*c2c66affSColin Finck } 1896*c2c66affSColin Finck 1897*c2c66affSColin Finck for (i = 0; i < lpTags->cValues; i++) 1898*c2c66affSColin Finck { 1899*c2c66affSColin Finck LPIPropDataItem item = IMAPIPROP_GetValue(This, lpTags->aulPropTag[i]); 1900*c2c66affSColin Finck 1901*c2c66affSColin Finck if (item) 1902*c2c66affSColin Finck { 1903*c2c66affSColin Finck if (item->ulAccess & IPROP_READWRITE) 1904*c2c66affSColin Finck { 1905*c2c66affSColin Finck /* Everything hunky-dory, remove the item */ 1906*c2c66affSColin Finck list_remove(&item->entry); 1907*c2c66affSColin Finck This->lpFree(item->value); /* Also frees value pointers */ 1908*c2c66affSColin Finck This->lpFree(item); 1909*c2c66affSColin Finck This->ulNumValues--; 1910*c2c66affSColin Finck } 1911*c2c66affSColin Finck else if (lppProbs) 1912*c2c66affSColin Finck { 1913*c2c66affSColin Finck /* Can't write the value. Create/populate problems array */ 1914*c2c66affSColin Finck if (!*lppProbs) 1915*c2c66affSColin Finck { 1916*c2c66affSColin Finck /* Create problems array */ 1917*c2c66affSColin Finck ULONG ulSize = CbNewSPropProblemArray(lpTags->cValues - i); 1918*c2c66affSColin Finck HRESULT hRetTmp = MAPIAllocateBuffer(ulSize, (LPVOID*)lppProbs); 1919*c2c66affSColin Finck if (FAILED(hRetTmp)) 1920*c2c66affSColin Finck hRet = hRetTmp; 1921*c2c66affSColin Finck } 1922*c2c66affSColin Finck if (*lppProbs) 1923*c2c66affSColin Finck { 1924*c2c66affSColin Finck LPSPropProblem lpProb = &(*lppProbs)->aProblem[numProbs]; 1925*c2c66affSColin Finck lpProb->ulIndex = i; 1926*c2c66affSColin Finck lpProb->ulPropTag = lpTags->aulPropTag[i]; 1927*c2c66affSColin Finck lpProb->scode = E_ACCESSDENIED; 1928*c2c66affSColin Finck numProbs++; 1929*c2c66affSColin Finck } 1930*c2c66affSColin Finck } 1931*c2c66affSColin Finck } 1932*c2c66affSColin Finck } 1933*c2c66affSColin Finck if (lppProbs && *lppProbs) 1934*c2c66affSColin Finck (*lppProbs)->cProblem = numProbs; 1935*c2c66affSColin Finck 1936*c2c66affSColin Finck IMAPIPROP_Unlock(This); 1937*c2c66affSColin Finck return hRet; 1938*c2c66affSColin Finck } 1939*c2c66affSColin Finck 1940*c2c66affSColin Finck 1941*c2c66affSColin Finck /************************************************************************** 1942*c2c66affSColin Finck * IPropData_CopyTo {MAPI32} 1943*c2c66affSColin Finck * 1944*c2c66affSColin Finck * Not documented at this time. 1945*c2c66affSColin Finck * 1946*c2c66affSColin Finck * RETURNS 1947*c2c66affSColin Finck * An HRESULT success/failure code. 1948*c2c66affSColin Finck */ 1949*c2c66affSColin Finck static HRESULT WINAPI IPropData_fnCopyTo(LPPROPDATA iface, ULONG niids, LPCIID lpiidExcl, 1950*c2c66affSColin Finck LPSPropTagArray lpPropsExcl, ULONG ulParam, 1951*c2c66affSColin Finck LPMAPIPROGRESS lpIProgress, LPCIID lpIfaceIid, 1952*c2c66affSColin Finck LPVOID lpDstObj, ULONG ulFlags, 1953*c2c66affSColin Finck LPSPropProblemArray *lppProbs) 1954*c2c66affSColin Finck { 1955*c2c66affSColin Finck FIXME("(%p,%u,%p,%p,%x,%p,%s,%p,0x%08X,%p) stub\n", iface, niids, 1956*c2c66affSColin Finck lpiidExcl, lpPropsExcl, ulParam, lpIProgress, 1957*c2c66affSColin Finck debugstr_guid(lpIfaceIid), lpDstObj, ulFlags, lppProbs); 1958*c2c66affSColin Finck return MAPI_E_NO_SUPPORT; 1959*c2c66affSColin Finck } 1960*c2c66affSColin Finck 1961*c2c66affSColin Finck /************************************************************************** 1962*c2c66affSColin Finck * IPropData_CopyProps {MAPI32} 1963*c2c66affSColin Finck * 1964*c2c66affSColin Finck * Not documented at this time. 1965*c2c66affSColin Finck * 1966*c2c66affSColin Finck * RETURNS 1967*c2c66affSColin Finck * An HRESULT success/failure code. 1968*c2c66affSColin Finck */ 1969*c2c66affSColin Finck static HRESULT WINAPI IPropData_fnCopyProps(LPPROPDATA iface, LPSPropTagArray lpInclProps, 1970*c2c66affSColin Finck ULONG ulParam, LPMAPIPROGRESS lpIProgress, 1971*c2c66affSColin Finck LPCIID lpIface, LPVOID lpDstObj, ULONG ulFlags, 1972*c2c66affSColin Finck LPSPropProblemArray *lppProbs) 1973*c2c66affSColin Finck { 1974*c2c66affSColin Finck FIXME("(%p,%p,%x,%p,%s,%p,0x%08X,%p) stub\n", iface, lpInclProps, 1975*c2c66affSColin Finck ulParam, lpIProgress, debugstr_guid(lpIface), lpDstObj, ulFlags, 1976*c2c66affSColin Finck lppProbs); 1977*c2c66affSColin Finck return MAPI_E_NO_SUPPORT; 1978*c2c66affSColin Finck } 1979*c2c66affSColin Finck 1980*c2c66affSColin Finck /************************************************************************** 1981*c2c66affSColin Finck * IPropData_GetNamesFromIDs {MAPI32} 1982*c2c66affSColin Finck * 1983*c2c66affSColin Finck * Get the names of properties from their identifiers. 1984*c2c66affSColin Finck * 1985*c2c66affSColin Finck * PARAMS 1986*c2c66affSColin Finck * iface [I] IMAPIProp object to operate on 1987*c2c66affSColin Finck * lppPropTags [I/O] Property identifiers to get the names for, or NULL to 1988*c2c66affSColin Finck * get all names 1989*c2c66affSColin Finck * iid [I] Property set identifier, or NULL 1990*c2c66affSColin Finck * ulFlags [I] MAPI_NO_IDS=Don't return numeric named properties, 1991*c2c66affSColin Finck * or MAPI_NO_STRINGS=Don't return strings 1992*c2c66affSColin Finck * lpCount [O] Destination for number of properties returned 1993*c2c66affSColin Finck * lpppNames [O] Destination for returned names 1994*c2c66affSColin Finck * 1995*c2c66affSColin Finck * RETURNS 1996*c2c66affSColin Finck * Success: S_OK. *lppPropTags and lpppNames contain the returned 1997*c2c66affSColin Finck * name/identifiers. 1998*c2c66affSColin Finck * Failure: MAPI_E_NO_SUPPORT, if the object does not support named properties, 1999*c2c66affSColin Finck * MAPI_E_NOT_ENOUGH_MEMORY, if memory allocation fails, or 2000*c2c66affSColin Finck * MAPI_W_ERRORS_RETURNED if not all properties were retrieved 2001*c2c66affSColin Finck * successfully. 2002*c2c66affSColin Finck */ 2003*c2c66affSColin Finck static HRESULT WINAPI IPropData_fnGetNamesFromIDs(LPPROPDATA iface, LPSPropTagArray *lppPropTags, 2004*c2c66affSColin Finck LPGUID iid, ULONG ulFlags, ULONG *lpCount, 2005*c2c66affSColin Finck LPMAPINAMEID **lpppNames) 2006*c2c66affSColin Finck { 2007*c2c66affSColin Finck FIXME("(%p,%p,%s,0x%08X,%p,%p) stub\n", iface, lppPropTags, 2008*c2c66affSColin Finck debugstr_guid(iid), ulFlags, lpCount, lpppNames); 2009*c2c66affSColin Finck return MAPI_E_NO_SUPPORT; 2010*c2c66affSColin Finck } 2011*c2c66affSColin Finck 2012*c2c66affSColin Finck /************************************************************************** 2013*c2c66affSColin Finck * IPropData_GetIDsFromNames {MAPI32} 2014*c2c66affSColin Finck * 2015*c2c66affSColin Finck * Get property identifiers associated with one or more named properties. 2016*c2c66affSColin Finck * 2017*c2c66affSColin Finck * PARAMS 2018*c2c66affSColin Finck * iface [I] IMAPIProp object to operate on 2019*c2c66affSColin Finck * ulNames [I] Number of names in lppNames 2020*c2c66affSColin Finck * lppNames [I] Names to query or create, or NULL to query all names 2021*c2c66affSColin Finck * ulFlags [I] Pass MAPI_CREATE to create new named properties 2022*c2c66affSColin Finck * lppPropTags [O] Destination for queried or created property identifiers 2023*c2c66affSColin Finck * 2024*c2c66affSColin Finck * RETURNS 2025*c2c66affSColin Finck * Success: S_OK. *lppPropTags contains the property tags created or requested. 2026*c2c66affSColin Finck * Failure: MAPI_E_NO_SUPPORT, if the object does not support named properties, 2027*c2c66affSColin Finck * MAPI_E_TOO_BIG, if the object cannot process the number of 2028*c2c66affSColin Finck * properties involved. 2029*c2c66affSColin Finck * MAPI_E_NOT_ENOUGH_MEMORY, if memory allocation fails, or 2030*c2c66affSColin Finck * MAPI_W_ERRORS_RETURNED if not all properties were retrieved 2031*c2c66affSColin Finck * successfully. 2032*c2c66affSColin Finck */ 2033*c2c66affSColin Finck static HRESULT WINAPI IPropData_fnGetIDsFromNames(LPPROPDATA iface, ULONG ulNames, 2034*c2c66affSColin Finck LPMAPINAMEID *lppNames, ULONG ulFlags, 2035*c2c66affSColin Finck LPSPropTagArray *lppPropTags) 2036*c2c66affSColin Finck { 2037*c2c66affSColin Finck FIXME("(%p,%d,%p,0x%08X,%p) stub\n", 2038*c2c66affSColin Finck iface, ulNames, lppNames, ulFlags, lppPropTags); 2039*c2c66affSColin Finck return MAPI_E_NO_SUPPORT; 2040*c2c66affSColin Finck } 2041*c2c66affSColin Finck 2042*c2c66affSColin Finck /************************************************************************** 2043*c2c66affSColin Finck * IPropData_HrSetObjAccess {MAPI32} 2044*c2c66affSColin Finck * 2045*c2c66affSColin Finck * Set the access level of an IPropData object. 2046*c2c66affSColin Finck * 2047*c2c66affSColin Finck * PARAMS 2048*c2c66affSColin Finck * iface [I] IPropData object to set the access on 2049*c2c66affSColin Finck * ulAccess [I] Either IPROP_READONLY or IPROP_READWRITE for read or 2050*c2c66affSColin Finck * read/write access respectively. 2051*c2c66affSColin Finck * 2052*c2c66affSColin Finck * RETURNS 2053*c2c66affSColin Finck * Success: S_OK. The objects access level is changed. 2054*c2c66affSColin Finck * Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid. 2055*c2c66affSColin Finck */ 2056*c2c66affSColin Finck static HRESULT WINAPI 2057*c2c66affSColin Finck IPropData_fnHrSetObjAccess(LPPROPDATA iface, ULONG ulAccess) 2058*c2c66affSColin Finck { 2059*c2c66affSColin Finck IPropDataImpl *This = impl_from_IPropData(iface); 2060*c2c66affSColin Finck 2061*c2c66affSColin Finck TRACE("(%p,%x)\n", iface, ulAccess); 2062*c2c66affSColin Finck 2063*c2c66affSColin Finck if (!iface || ulAccess < IPROP_READONLY || ulAccess > IPROP_READWRITE) 2064*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 2065*c2c66affSColin Finck 2066*c2c66affSColin Finck IMAPIPROP_Lock(This); 2067*c2c66affSColin Finck 2068*c2c66affSColin Finck This->ulObjAccess = ulAccess; 2069*c2c66affSColin Finck 2070*c2c66affSColin Finck IMAPIPROP_Unlock(This); 2071*c2c66affSColin Finck return S_OK; 2072*c2c66affSColin Finck } 2073*c2c66affSColin Finck 2074*c2c66affSColin Finck /* Internal - determine if an access value is bad */ 2075*c2c66affSColin Finck static inline BOOL PROP_IsBadAccess(ULONG ulAccess) 2076*c2c66affSColin Finck { 2077*c2c66affSColin Finck switch (ulAccess) 2078*c2c66affSColin Finck { 2079*c2c66affSColin Finck case IPROP_READONLY|IPROP_CLEAN: 2080*c2c66affSColin Finck case IPROP_READONLY|IPROP_DIRTY: 2081*c2c66affSColin Finck case IPROP_READWRITE|IPROP_CLEAN: 2082*c2c66affSColin Finck case IPROP_READWRITE|IPROP_DIRTY: 2083*c2c66affSColin Finck return FALSE; 2084*c2c66affSColin Finck } 2085*c2c66affSColin Finck return TRUE; 2086*c2c66affSColin Finck } 2087*c2c66affSColin Finck 2088*c2c66affSColin Finck /************************************************************************** 2089*c2c66affSColin Finck * IPropData_HrSetPropAccess {MAPI32} 2090*c2c66affSColin Finck * 2091*c2c66affSColin Finck * Set the access levels for a group of property values in an IPropData object. 2092*c2c66affSColin Finck * 2093*c2c66affSColin Finck * PARAMS 2094*c2c66affSColin Finck * iface [I] IPropData object to set access levels in. 2095*c2c66affSColin Finck * lpTags [I] List of property Id's to set access for. 2096*c2c66affSColin Finck * lpAccess [O] Access level for each property in lpTags. 2097*c2c66affSColin Finck * 2098*c2c66affSColin Finck * RETURNS 2099*c2c66affSColin Finck * Success: S_OK. The access level of each property value in lpTags that is 2100*c2c66affSColin Finck * present in iface is changed. 2101*c2c66affSColin Finck * Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid. 2102*c2c66affSColin Finck * 2103*c2c66affSColin Finck * NOTES 2104*c2c66affSColin Finck * - Each access level in lpAccess must contain at least one of IPROP_READONLY 2105*c2c66affSColin Finck * or IPROP_READWRITE, but not both, and also IPROP_CLEAN or IPROP_DIRTY, 2106*c2c66affSColin Finck * but not both. No other bits should be set. 2107*c2c66affSColin Finck * - If a property Id in lpTags is not present in iface, it is ignored. 2108*c2c66affSColin Finck */ 2109*c2c66affSColin Finck static HRESULT WINAPI 2110*c2c66affSColin Finck IPropData_fnHrSetPropAccess(LPPROPDATA iface, LPSPropTagArray lpTags, 2111*c2c66affSColin Finck ULONG *lpAccess) 2112*c2c66affSColin Finck { 2113*c2c66affSColin Finck IPropDataImpl *This = impl_from_IPropData(iface); 2114*c2c66affSColin Finck ULONG i; 2115*c2c66affSColin Finck 2116*c2c66affSColin Finck TRACE("(%p,%p,%p)\n", iface, lpTags, lpAccess); 2117*c2c66affSColin Finck 2118*c2c66affSColin Finck if (!iface || !lpTags || !lpAccess) 2119*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 2120*c2c66affSColin Finck 2121*c2c66affSColin Finck for (i = 0; i < lpTags->cValues; i++) 2122*c2c66affSColin Finck { 2123*c2c66affSColin Finck if (FBadPropTag(lpTags->aulPropTag[i]) || PROP_IsBadAccess(lpAccess[i])) 2124*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 2125*c2c66affSColin Finck } 2126*c2c66affSColin Finck 2127*c2c66affSColin Finck IMAPIPROP_Lock(This); 2128*c2c66affSColin Finck 2129*c2c66affSColin Finck for (i = 0; i < lpTags->cValues; i++) 2130*c2c66affSColin Finck { 2131*c2c66affSColin Finck LPIPropDataItem item = IMAPIPROP_GetValue(This, lpTags->aulPropTag[i]); 2132*c2c66affSColin Finck 2133*c2c66affSColin Finck if (item) 2134*c2c66affSColin Finck item->ulAccess = lpAccess[i]; 2135*c2c66affSColin Finck } 2136*c2c66affSColin Finck 2137*c2c66affSColin Finck IMAPIPROP_Unlock(This); 2138*c2c66affSColin Finck return S_OK; 2139*c2c66affSColin Finck } 2140*c2c66affSColin Finck 2141*c2c66affSColin Finck /************************************************************************** 2142*c2c66affSColin Finck * IPropData_HrGetPropAccess {MAPI32} 2143*c2c66affSColin Finck * 2144*c2c66affSColin Finck * Get the access levels for a group of property values in an IPropData object. 2145*c2c66affSColin Finck * 2146*c2c66affSColin Finck * PARAMS 2147*c2c66affSColin Finck * iface [I] IPropData object to get access levels from. 2148*c2c66affSColin Finck * lppTags [O] Destination for the list of property Id's in iface. 2149*c2c66affSColin Finck * lppAccess [O] Destination for access level for each property in lppTags. 2150*c2c66affSColin Finck * 2151*c2c66affSColin Finck * RETURNS 2152*c2c66affSColin Finck * Success: S_OK. lppTags and lppAccess contain the property Id's and the 2153*c2c66affSColin Finck * Access level of each property value in iface. 2154*c2c66affSColin Finck * Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid, or 2155*c2c66affSColin Finck * MAPI_E_NOT_ENOUGH_MEMORY if memory allocation fails. 2156*c2c66affSColin Finck * 2157*c2c66affSColin Finck * NOTES 2158*c2c66affSColin Finck * - *lppTags and *lppAccess should be freed with MAPIFreeBuffer() by the caller. 2159*c2c66affSColin Finck */ 2160*c2c66affSColin Finck static HRESULT WINAPI 2161*c2c66affSColin Finck IPropData_fnHrGetPropAccess(LPPROPDATA iface, LPSPropTagArray *lppTags, 2162*c2c66affSColin Finck ULONG **lppAccess) 2163*c2c66affSColin Finck { 2164*c2c66affSColin Finck IPropDataImpl *This = impl_from_IPropData(iface); 2165*c2c66affSColin Finck LPVOID lpMem; 2166*c2c66affSColin Finck HRESULT hRet; 2167*c2c66affSColin Finck ULONG i; 2168*c2c66affSColin Finck 2169*c2c66affSColin Finck TRACE("(%p,%p,%p) stub\n", iface, lppTags, lppAccess); 2170*c2c66affSColin Finck 2171*c2c66affSColin Finck if (!iface || !lppTags || !lppAccess) 2172*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 2173*c2c66affSColin Finck 2174*c2c66affSColin Finck *lppTags = NULL; 2175*c2c66affSColin Finck *lppAccess = NULL; 2176*c2c66affSColin Finck 2177*c2c66affSColin Finck IMAPIPROP_Lock(This); 2178*c2c66affSColin Finck 2179*c2c66affSColin Finck hRet = This->lpAlloc(CbNewSPropTagArray(This->ulNumValues), &lpMem); 2180*c2c66affSColin Finck if (SUCCEEDED(hRet)) 2181*c2c66affSColin Finck { 2182*c2c66affSColin Finck *lppTags = lpMem; 2183*c2c66affSColin Finck 2184*c2c66affSColin Finck hRet = This->lpAlloc(This->ulNumValues * sizeof(ULONG), &lpMem); 2185*c2c66affSColin Finck if (SUCCEEDED(hRet)) 2186*c2c66affSColin Finck { 2187*c2c66affSColin Finck struct list *cursor; 2188*c2c66affSColin Finck 2189*c2c66affSColin Finck *lppAccess = lpMem; 2190*c2c66affSColin Finck (*lppTags)->cValues = This->ulNumValues; 2191*c2c66affSColin Finck 2192*c2c66affSColin Finck i = 0; 2193*c2c66affSColin Finck LIST_FOR_EACH(cursor, &This->values) 2194*c2c66affSColin Finck { 2195*c2c66affSColin Finck LPIPropDataItem item = LIST_ENTRY(cursor, IPropDataItem, entry); 2196*c2c66affSColin Finck (*lppTags)->aulPropTag[i] = item->value->ulPropTag; 2197*c2c66affSColin Finck (*lppAccess)[i] = item->ulAccess; 2198*c2c66affSColin Finck i++; 2199*c2c66affSColin Finck } 2200*c2c66affSColin Finck IMAPIPROP_Unlock(This); 2201*c2c66affSColin Finck return S_OK; 2202*c2c66affSColin Finck } 2203*c2c66affSColin Finck This->lpFree(*lppTags); 2204*c2c66affSColin Finck *lppTags = 0; 2205*c2c66affSColin Finck } 2206*c2c66affSColin Finck IMAPIPROP_Unlock(This); 2207*c2c66affSColin Finck return MAPI_E_NOT_ENOUGH_MEMORY; 2208*c2c66affSColin Finck } 2209*c2c66affSColin Finck 2210*c2c66affSColin Finck /************************************************************************** 2211*c2c66affSColin Finck * IPropData_HrAddObjProps {MAPI32} 2212*c2c66affSColin Finck * 2213*c2c66affSColin Finck * Not documented at this time. 2214*c2c66affSColin Finck * 2215*c2c66affSColin Finck * RETURNS 2216*c2c66affSColin Finck * An HRESULT success/failure code. 2217*c2c66affSColin Finck */ 2218*c2c66affSColin Finck static HRESULT WINAPI 2219*c2c66affSColin Finck IPropData_fnHrAddObjProps(LPPROPDATA iface, LPSPropTagArray lpTags, 2220*c2c66affSColin Finck LPSPropProblemArray *lppProbs) 2221*c2c66affSColin Finck { 2222*c2c66affSColin Finck #if 0 2223*c2c66affSColin Finck ULONG i; 2224*c2c66affSColin Finck HRESULT hRet; 2225*c2c66affSColin Finck LPSPropValue lpValues; 2226*c2c66affSColin Finck #endif 2227*c2c66affSColin Finck 2228*c2c66affSColin Finck FIXME("(%p,%p,%p) stub\n", iface, lpTags, lppProbs); 2229*c2c66affSColin Finck 2230*c2c66affSColin Finck if (!iface || !lpTags) 2231*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 2232*c2c66affSColin Finck 2233*c2c66affSColin Finck /* FIXME: Below is the obvious implementation, adding all the properties 2234*c2c66affSColin Finck * in lpTags to the object. However, it doesn't appear that this 2235*c2c66affSColin Finck * is what this function does. 2236*c2c66affSColin Finck */ 2237*c2c66affSColin Finck return S_OK; 2238*c2c66affSColin Finck #if 0 2239*c2c66affSColin Finck if (!lpTags->cValues) 2240*c2c66affSColin Finck return S_OK; 2241*c2c66affSColin Finck 2242*c2c66affSColin Finck lpValues = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2243*c2c66affSColin Finck lpTags->cValues * sizeof(SPropValue)); 2244*c2c66affSColin Finck if (!lpValues) 2245*c2c66affSColin Finck return MAPI_E_NOT_ENOUGH_MEMORY; 2246*c2c66affSColin Finck 2247*c2c66affSColin Finck for (i = 0; i < lpTags->cValues; i++) 2248*c2c66affSColin Finck lpValues[i].ulPropTag = lpTags->aulPropTag[i]; 2249*c2c66affSColin Finck 2250*c2c66affSColin Finck hRet = IPropData_SetProps(iface, lpTags->cValues, lpValues, lppProbs); 2251*c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, lpValues); 2252*c2c66affSColin Finck return hRet; 2253*c2c66affSColin Finck #endif 2254*c2c66affSColin Finck } 2255*c2c66affSColin Finck 2256*c2c66affSColin Finck static const IPropDataVtbl IPropDataImpl_vtbl = 2257*c2c66affSColin Finck { 2258*c2c66affSColin Finck IPropData_fnQueryInterface, 2259*c2c66affSColin Finck IPropData_fnAddRef, 2260*c2c66affSColin Finck IPropData_fnRelease, 2261*c2c66affSColin Finck IPropData_fnGetLastError, 2262*c2c66affSColin Finck IPropData_fnSaveChanges, 2263*c2c66affSColin Finck IPropData_fnGetProps, 2264*c2c66affSColin Finck IPropData_fnGetPropList, 2265*c2c66affSColin Finck IPropData_fnOpenProperty, 2266*c2c66affSColin Finck IPropData_fnSetProps, 2267*c2c66affSColin Finck IPropData_fnDeleteProps, 2268*c2c66affSColin Finck IPropData_fnCopyTo, 2269*c2c66affSColin Finck IPropData_fnCopyProps, 2270*c2c66affSColin Finck IPropData_fnGetNamesFromIDs, 2271*c2c66affSColin Finck IPropData_fnGetIDsFromNames, 2272*c2c66affSColin Finck IPropData_fnHrSetObjAccess, 2273*c2c66affSColin Finck IPropData_fnHrSetPropAccess, 2274*c2c66affSColin Finck IPropData_fnHrGetPropAccess, 2275*c2c66affSColin Finck IPropData_fnHrAddObjProps 2276*c2c66affSColin Finck }; 2277*c2c66affSColin Finck 2278*c2c66affSColin Finck /************************************************************************* 2279*c2c66affSColin Finck * CreateIProp@24 (MAPI32.60) 2280*c2c66affSColin Finck * 2281*c2c66affSColin Finck * Create an IPropData object. 2282*c2c66affSColin Finck * 2283*c2c66affSColin Finck * PARAMS 2284*c2c66affSColin Finck * iid [I] GUID of the object to create. Use &IID_IMAPIPropData or NULL 2285*c2c66affSColin Finck * lpAlloc [I] Memory allocation function. Use MAPIAllocateBuffer() 2286*c2c66affSColin Finck * lpMore [I] Linked memory allocation function. Use MAPIAllocateMore() 2287*c2c66affSColin Finck * lpFree [I] Memory free function. Use MAPIFreeBuffer() 2288*c2c66affSColin Finck * lpReserved [I] Reserved, set to NULL 2289*c2c66affSColin Finck * lppPropData [O] Destination for created IPropData object 2290*c2c66affSColin Finck * 2291*c2c66affSColin Finck * RETURNS 2292*c2c66affSColin Finck * Success: S_OK. *lppPropData contains the newly created object. 2293*c2c66affSColin Finck * Failure: MAPI_E_INTERFACE_NOT_SUPPORTED, if iid is non-NULL and not supported, 2294*c2c66affSColin Finck * MAPI_E_INVALID_PARAMETER, if any parameter is invalid 2295*c2c66affSColin Finck */ 2296*c2c66affSColin Finck SCODE WINAPI CreateIProp(LPCIID iid, ALLOCATEBUFFER *lpAlloc, 2297*c2c66affSColin Finck ALLOCATEMORE *lpMore, FREEBUFFER *lpFree, 2298*c2c66affSColin Finck LPVOID lpReserved, LPPROPDATA *lppPropData) 2299*c2c66affSColin Finck { 2300*c2c66affSColin Finck IPropDataImpl *lpPropData; 2301*c2c66affSColin Finck SCODE scode; 2302*c2c66affSColin Finck 2303*c2c66affSColin Finck TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_guid(iid), lpAlloc, lpMore, lpFree, 2304*c2c66affSColin Finck lpReserved, lppPropData); 2305*c2c66affSColin Finck 2306*c2c66affSColin Finck if (lppPropData) 2307*c2c66affSColin Finck *lppPropData = NULL; 2308*c2c66affSColin Finck 2309*c2c66affSColin Finck if (iid && !IsEqualGUID(iid, &IID_IMAPIPropData)) 2310*c2c66affSColin Finck return MAPI_E_INTERFACE_NOT_SUPPORTED; 2311*c2c66affSColin Finck 2312*c2c66affSColin Finck if (!lpAlloc || !lpMore || !lpFree || lpReserved || !lppPropData) 2313*c2c66affSColin Finck return MAPI_E_INVALID_PARAMETER; 2314*c2c66affSColin Finck 2315*c2c66affSColin Finck scode = lpAlloc(sizeof(IPropDataImpl), (LPVOID*)&lpPropData); 2316*c2c66affSColin Finck 2317*c2c66affSColin Finck if (SUCCEEDED(scode)) 2318*c2c66affSColin Finck { 2319*c2c66affSColin Finck lpPropData->IPropData_iface.lpVtbl = &IPropDataImpl_vtbl; 2320*c2c66affSColin Finck lpPropData->lRef = 1; 2321*c2c66affSColin Finck lpPropData->lpAlloc = lpAlloc; 2322*c2c66affSColin Finck lpPropData->lpMore = lpMore; 2323*c2c66affSColin Finck lpPropData->lpFree = lpFree; 2324*c2c66affSColin Finck lpPropData->ulObjAccess = IPROP_READWRITE; 2325*c2c66affSColin Finck lpPropData->ulNumValues = 0; 2326*c2c66affSColin Finck list_init(&lpPropData->values); 2327*c2c66affSColin Finck InitializeCriticalSection(&lpPropData->cs); 2328*c2c66affSColin Finck lpPropData->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IPropDataImpl.cs"); 2329*c2c66affSColin Finck *lppPropData = &lpPropData->IPropData_iface; 2330*c2c66affSColin Finck } 2331*c2c66affSColin Finck return scode; 2332*c2c66affSColin Finck } 2333