xref: /reactos/dll/win32/mapi32/prop.c (revision 9d3a9694)
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