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