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