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