2 * Unit test suite for MAPI property functions
4 * Copyright 2004 Jon Griffiths
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define NONAMELESSUNION
22 #define NONAMELESSSTRUCT
23 #include "wine/test.h"
32 HRESULT WINAPI MAPIInitialize(LPVOID);
34 static HMODULE hMapi32 = 0;
36 static SCODE (WINAPI *pScInitMapiUtil)(ULONG);
37 static SCODE (WINAPI *pPropCopyMore)(LPSPropValue,LPSPropValue,ALLOCATEMORE*,LPVOID);
38 static ULONG (WINAPI *pUlPropSize)(LPSPropValue);
39 static BOOL (WINAPI *pFPropContainsProp)(LPSPropValue,LPSPropValue,ULONG);
40 static BOOL (WINAPI *pFPropCompareProp)(LPSPropValue,ULONG,LPSPropValue);
41 static LONG (WINAPI *pLPropCompareProp)(LPSPropValue,LPSPropValue);
42 static LPSPropValue (WINAPI *pPpropFindProp)(LPSPropValue,ULONG,ULONG);
43 static SCODE (WINAPI *pScCountProps)(INT,LPSPropValue,ULONG*);
44 static SCODE (WINAPI *pScCopyProps)(int,LPSPropValue,LPVOID,ULONG*);
45 static SCODE (WINAPI *pScRelocProps)(int,LPSPropValue,LPVOID,LPVOID,ULONG*);
46 static LPSPropValue (WINAPI *pLpValFindProp)(ULONG,ULONG,LPSPropValue);
47 static BOOL (WINAPI *pFBadRglpszA)(LPSTR*,ULONG);
48 static BOOL (WINAPI *pFBadRglpszW)(LPWSTR*,ULONG);
49 static BOOL (WINAPI *pFBadRowSet)(LPSRowSet);
50 static ULONG (WINAPI *pFBadPropTag)(ULONG);
51 static ULONG (WINAPI *pFBadRow)(LPSRow);
52 static ULONG (WINAPI *pFBadProp)(LPSPropValue);
53 static ULONG (WINAPI *pFBadColumnSet)(LPSPropTagArray);
54 static SCODE (WINAPI *pCreateIProp)(LPCIID,ALLOCATEBUFFER*,ALLOCATEMORE*,
55 FREEBUFFER*,LPVOID,LPPROPDATA*);
57 static ULONG ptTypes[] = {
58 PT_I2, PT_I4, PT_R4, PT_R8, PT_CURRENCY, PT_APPTIME, PT_SYSTIME,
59 PT_ERROR, PT_BOOLEAN, PT_I8, PT_CLSID, PT_STRING8, PT_BINARY,
63 static inline int strcmpW(const WCHAR *str1, const WCHAR *str2)
65 while (*str1 && (*str1 == *str2)) { str1++; str2++; }
69 static void test_PropCopyMore(void)
71 static const char *szHiA = "Hi!";
72 static const WCHAR szHiW[] = { 'H', 'i', '!', '\0' };
73 SPropValue *lpDest = NULL, *lpSrc = NULL;
77 pPropCopyMore = (void*)GetProcAddress(hMapi32, "PropCopyMore@16");
82 scode = MAPIAllocateBuffer(sizeof(LPSPropValue), (LPVOID *)lpDest);
86 scode = MAPIAllocateMore(sizeof(LPSPropValue), lpDest, (LPVOID *)lpSrc);
90 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
92 lpSrc->ulPropTag = ptTypes[i];
97 lpSrc->Value.lpszA = (char*)szHiA;
100 lpSrc->Value.lpszW = (WCHAR*)szHiW;
103 lpSrc->Value.bin.cb = 4;
104 lpSrc->Value.bin.lpb = (LPBYTE)szHiA;
108 memset(lpDest, 0xff, sizeof(SPropValue));
110 scode = pPropCopyMore(lpDest, lpSrc, MAPIAllocateMore, lpDest);
111 ok(!scode && lpDest->ulPropTag == lpSrc->ulPropTag,
112 "PropCopyMore: Expected 0x0,%ld, got 0x%08lx,%ld\n",
113 lpSrc->ulPropTag, scode, lpDest->ulPropTag);
114 if (SUCCEEDED(scode))
119 ok(lstrcmpA(lpDest->Value.lpszA, lpSrc->Value.lpszA) == 0,
120 "PropCopyMore: Ascii string differs\n");
123 ok(strcmpW(lpDest->Value.lpszW, lpSrc->Value.lpszW) == 0,
124 "PropCopyMore: Unicode string differs\n");
127 ok(lpDest->Value.bin.cb == 4 &&
128 !memcmp(lpSrc->Value.bin.lpb, lpDest->Value.bin.lpb, 4),
129 "PropCopyMore: Binary array differs\n");
135 /* Since all allocations are linked, freeing lpDest frees everything */
136 MAPIFreeBuffer(lpDest);
139 static void test_UlPropSize(void)
141 static const char *szHiA = "Hi!";
142 static const WCHAR szHiW[] = { 'H', 'i', '!', '\0' };
148 pUlPropSize = (void*)GetProcAddress(hMapi32, "UlPropSize@4");
153 for (pt = 0; pt < PROP_ID_INVALID; pt++)
157 memset(&pv, 0 ,sizeof(pv));
160 exp = 1u; /* Default to one item for non-MV properties */
162 switch (PROP_TYPE(pt))
164 case PT_MV_I2: pv.Value.MVi.cValues = exp = 2;
165 case PT_I2: exp *= sizeof(USHORT); break;
166 case PT_MV_I4: pv.Value.MVl.cValues = exp = 2;
167 case PT_I4: exp *= sizeof(LONG); break;
168 case PT_MV_R4: pv.Value.MVflt.cValues = exp = 2;
169 case PT_R4: exp *= sizeof(float); break;
170 case PT_MV_DOUBLE: pv.Value.MVdbl.cValues = exp = 2;
171 case PT_R8: exp *= sizeof(double); break;
172 case PT_MV_CURRENCY: pv.Value.MVcur.cValues = exp = 2;
173 case PT_CURRENCY: exp *= sizeof(CY); break;
174 case PT_MV_APPTIME: pv.Value.MVat.cValues = exp = 2;
175 case PT_APPTIME: exp *= sizeof(double); break;
176 case PT_MV_SYSTIME: pv.Value.MVft.cValues = exp = 2;
177 case PT_SYSTIME: exp *= sizeof(FILETIME); break;
178 case PT_ERROR: exp = sizeof(SCODE); break;
179 case PT_BOOLEAN: exp = sizeof(USHORT); break;
180 case PT_OBJECT: exp = 0; break;
181 case PT_MV_I8: pv.Value.MVli.cValues = exp = 2;
182 case PT_I8: exp *= sizeof(LONG64); break;
184 /* My version of native mapi returns 0 for PT_MV_CLSID even if a valid
185 * array is given. This _has_ to be a bug, so Wine does
186 * the right thing(tm) and we don't test it here.
188 case PT_MV_CLSID: pv.Value.MVguid.cValues = exp = 2;
190 case PT_CLSID: exp *= sizeof(GUID); break;
192 pv.Value.lpszA = (LPSTR)szHiA;
196 pv.Value.lpszW = (LPWSTR)szHiW;
197 exp = 4 * sizeof(WCHAR);
200 pv.Value.bin.cb = exp = 19;
203 pv.Value.MVszA.cValues = 2;
204 pv.Value.MVszA.lppszA = buffa;
205 buffa[0] = (LPSTR)szHiA;
206 buffa[1] = (LPSTR)szHiA;
210 pv.Value.MVszW.cValues = 2;
211 pv.Value.MVszW.lppszW = buffw;
212 buffw[0] = (LPWSTR)szHiW;
213 buffw[1] = (LPWSTR)szHiW;
214 exp = 8 * sizeof(WCHAR);
217 pv.Value.MVbin.cValues = 2;
218 pv.Value.MVbin.lpbin = buffbin;
227 res = pUlPropSize(&pv);
228 ok(res == exp, "pt= %ld: Expected %ld, got %ld\n", pt, exp, res);
232 static void test_FPropContainsProp(void)
234 static const char *szFull = "Full String";
235 static const char *szFullLower = "full string";
236 static const char *szPrefix = "Full";
237 static const char *szPrefixLower = "full";
238 static const char *szSubstring = "ll St";
239 static const char *szSubstringLower = "ll st";
240 SPropValue pvLeft, pvRight;
244 pFPropContainsProp = (void*)GetProcAddress(hMapi32, "FPropContainsProp@12");
246 if (!pFPropContainsProp)
249 /* Ensure that only PT_STRING8 and PT_BINARY are handled */
250 for (pt = 0; pt < PROP_ID_INVALID; pt++)
252 if (pt == PT_STRING8 || pt == PT_BINARY)
253 continue; /* test these later */
255 memset(&pvLeft, 0 ,sizeof(pvLeft));
256 memset(&pvRight, 0 ,sizeof(pvRight));
257 pvLeft.ulPropTag = pvRight.ulPropTag = pt;
259 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
260 ok(bRet == FALSE, "pt= %ld: Expected FALSE, got %d\n", pt, bRet);
263 /* test the various flag combinations */
264 pvLeft.ulPropTag = pvRight.ulPropTag = PT_STRING8;
265 pvLeft.Value.lpszA = (LPSTR)szFull;
266 pvRight.Value.lpszA = (LPSTR)szFull;
268 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
269 ok(bRet == TRUE, "(full,full)[] match failed\n");
270 pvRight.Value.lpszA = (LPSTR)szPrefix;
271 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
272 ok(bRet == FALSE, "(full,prefix)[] match failed\n");
273 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
274 ok(bRet == TRUE, "(full,prefix)[PREFIX] match failed\n");
275 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
276 ok(bRet == TRUE, "(full,prefix)[SUBSTRING] match failed\n");
277 pvRight.Value.lpszA = (LPSTR)szPrefixLower;
278 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
279 ok(bRet == FALSE, "(full,prefixlow)[PREFIX] match failed\n");
280 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
281 ok(bRet == FALSE, "(full,prefixlow)[SUBSTRING] match failed\n");
282 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE);
283 ok(bRet == TRUE, "(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
284 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
285 ok(bRet == TRUE, "(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
286 pvRight.Value.lpszA = (LPSTR)szSubstring;
287 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
288 ok(bRet == FALSE, "(full,substr)[] match failed\n");
289 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
290 ok(bRet == FALSE, "(full,substr)[PREFIX] match failed\n");
291 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
292 ok(bRet == TRUE, "(full,substr)[SUBSTRING] match failed\n");
293 pvRight.Value.lpszA = (LPSTR)szSubstringLower;
294 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
295 ok(bRet == FALSE, "(full,substrlow)[PREFIX] match failed\n");
296 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
297 ok(bRet == FALSE, "(full,substrlow)[SUBSTRING] match failed\n");
298 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE);
299 ok(bRet == FALSE, "(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
300 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
301 ok(bRet == TRUE, "(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
302 pvRight.Value.lpszA = (LPSTR)szFullLower;
303 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING|FL_IGNORECASE);
304 ok(bRet == TRUE, "(full,fulllow)[IGNORECASE] match failed\n");
306 pvLeft.ulPropTag = pvRight.ulPropTag = PT_BINARY;
307 pvLeft.Value.bin.lpb = (LPBYTE)szFull;
308 pvRight.Value.bin.lpb = (LPBYTE)szFull;
309 pvLeft.Value.bin.cb = pvRight.Value.bin.cb = strlen(szFull);
311 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
312 ok(bRet == TRUE, "bin(full,full)[] match failed\n");
313 pvRight.Value.bin.lpb = (LPBYTE)szPrefix;
314 pvRight.Value.bin.cb = strlen(szPrefix);
315 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
316 ok(bRet == FALSE, "bin(full,prefix)[] match failed\n");
317 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
318 ok(bRet == TRUE, "bin(full,prefix)[PREFIX] match failed\n");
319 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
320 ok(bRet == TRUE, "bin(full,prefix)[SUBSTRING] match failed\n");
321 pvRight.Value.bin.lpb = (LPBYTE)szPrefixLower;
322 pvRight.Value.bin.cb = strlen(szPrefixLower);
323 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
324 ok(bRet == FALSE, "bin(full,prefixlow)[PREFIX] match failed\n");
325 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
326 ok(bRet == FALSE, "bin(full,prefixlow)[SUBSTRING] match failed\n");
327 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE);
328 ok(bRet == FALSE, "bin(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
329 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
330 ok(bRet == FALSE, "bin(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
331 pvRight.Value.bin.lpb = (LPBYTE)szSubstring;
332 pvRight.Value.bin.cb = strlen(szSubstring);
333 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
334 ok(bRet == FALSE, "bin(full,substr)[] match failed\n");
335 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
336 ok(bRet == FALSE, "bin(full,substr)[PREFIX] match failed\n");
337 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
338 ok(bRet == TRUE, "bin(full,substr)[SUBSTRING] match failed\n");
339 pvRight.Value.bin.lpb = (LPBYTE)szSubstringLower;
340 pvRight.Value.bin.cb = strlen(szSubstringLower);
341 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
342 ok(bRet == FALSE, "bin(full,substrlow)[PREFIX] match failed\n");
343 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
344 ok(bRet == FALSE, "bin(full,substrlow)[SUBSTRING] match failed\n");
345 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE);
346 ok(bRet == FALSE, "bin(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
347 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
348 ok(bRet == FALSE, "bin(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
349 pvRight.Value.bin.lpb = (LPBYTE)szFullLower;
350 pvRight.Value.bin.cb = strlen(szFullLower);
351 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING|FL_IGNORECASE);
352 ok(bRet == FALSE, "bin(full,fulllow)[IGNORECASE] match failed\n");
355 typedef struct tagFPropCompareProp_Result
361 } FPropCompareProp_Result;
363 static const FPropCompareProp_Result FPCProp_Results[] =
365 { 1, 2, RELOP_LT, TRUE },
366 { 1, 1, RELOP_LT, FALSE },
367 { 2, 1, RELOP_LT, FALSE },
368 { 1, 2, RELOP_LE, TRUE },
369 { 1, 1, RELOP_LE, TRUE },
370 { 2, 1, RELOP_LE, FALSE },
371 { 1, 2, RELOP_GT, FALSE },
372 { 1, 1, RELOP_GT, FALSE },
373 { 2, 1, RELOP_GT, TRUE },
374 { 1, 2, RELOP_GE, FALSE },
375 { 1, 1, RELOP_GE, TRUE },
376 { 2, 1, RELOP_GE, TRUE },
377 { 1, 2, RELOP_EQ, FALSE },
378 { 1, 1, RELOP_EQ, TRUE },
379 { 2, 1, RELOP_EQ, FALSE }
382 static const char *relops[] = { "RELOP_LT", "RELOP_LE", "RELOP_GT", "RELOP_GE", "RELOP_EQ" };
384 static void test_FPropCompareProp(void)
386 SPropValue pvLeft, pvRight;
388 char lbuffa[2], rbuffa[2];
389 WCHAR lbuffw[2], rbuffw[2];
393 pFPropCompareProp = (void*)GetProcAddress(hMapi32, "FPropCompareProp@12");
395 if (!pFPropCompareProp)
403 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
405 pvLeft.ulPropTag = pvRight.ulPropTag = ptTypes[i];
407 for (j = 0; j < sizeof(FPCProp_Results)/sizeof(FPCProp_Results[0]); j++)
409 SHORT lVal = FPCProp_Results[j].lVal;
410 SHORT rVal = FPCProp_Results[j].rVal;
412 bExp = FPCProp_Results[j].bRet;
417 /* Boolean values have no concept of less or greater than, only equality */
418 if ((lVal == 1 && rVal == 2 && FPCProp_Results[j].relOp == RELOP_LT) ||
419 (lVal == 2 && rVal == 1 && FPCProp_Results[j].relOp == RELOP_LE)||
420 (lVal == 2 && rVal == 1 && FPCProp_Results[j].relOp == RELOP_GT)||
421 (lVal == 1 && rVal == 2 && FPCProp_Results[j].relOp == RELOP_GE)||
422 (lVal == 1 && rVal == 2 && FPCProp_Results[j].relOp == RELOP_EQ)||
423 (lVal == 2 && rVal == 1 && FPCProp_Results[j].relOp == RELOP_EQ))
425 /* Fall through ... */
427 pvLeft.Value.i = lVal;
428 pvRight.Value.i = rVal;
432 pvLeft.Value.l = lVal;
433 pvRight.Value.l = rVal;
436 pvLeft.Value.flt = lVal;
437 pvRight.Value.flt = rVal;
441 pvLeft.Value.dbl = lVal;
442 pvRight.Value.dbl = rVal;
445 pvLeft.Value.cur.int64 = lVal;
446 pvRight.Value.cur.int64 = rVal;
449 pvLeft.Value.ft.dwLowDateTime = lVal;
450 pvLeft.Value.ft.dwHighDateTime = 0;
451 pvRight.Value.ft.dwLowDateTime = rVal;
452 pvRight.Value.ft.dwHighDateTime = 0;
455 pvLeft.Value.li.u.LowPart = lVal;
456 pvLeft.Value.li.u.HighPart = 0;
457 pvRight.Value.li.u.LowPart = rVal;
458 pvRight.Value.li.u.HighPart = 0;
461 memset(&lguid, 0, sizeof(GUID));
462 memset(&rguid, 0, sizeof(GUID));
463 lguid.Data4[7] = lVal;
464 rguid.Data4[7] = rVal;
465 pvLeft.Value.lpguid = &lguid;
466 pvRight.Value.lpguid = &rguid;
469 pvLeft.Value.lpszA = lbuffa;
470 pvRight.Value.lpszA = rbuffa;
471 lbuffa[0] = '0' + lVal;
472 rbuffa[0] = '0' + rVal;
475 pvLeft.Value.lpszW = lbuffw;
476 pvRight.Value.lpszW = rbuffw;
477 lbuffw[0] = '0' + lVal;
478 rbuffw[0] = '0' + rVal;
481 pvLeft.Value.bin.cb = 1;
482 pvRight.Value.bin.cb = 1;
483 pvLeft.Value.bin.lpb = lbuffa;
484 pvRight.Value.bin.lpb = rbuffa;
490 bRet = pFPropCompareProp(&pvLeft, FPCProp_Results[j].relOp, &pvRight);
491 ok(bRet == bExp, "pt %ld (%d,%d,%s): expected %d, got %d\n", ptTypes[i],
492 FPCProp_Results[j].lVal, FPCProp_Results[j].rVal,
493 relops[FPCProp_Results[j].relOp], bExp, bRet);
498 typedef struct tagLPropCompareProp_Result
503 } LPropCompareProp_Result;
505 static const LPropCompareProp_Result LPCProp_Results[] =
512 static void test_LPropCompareProp(void)
514 SPropValue pvLeft, pvRight;
516 char lbuffa[2], rbuffa[2];
517 WCHAR lbuffw[2], rbuffw[2];
521 pLPropCompareProp = (void*)GetProcAddress(hMapi32, "LPropCompareProp@8");
523 if (!pLPropCompareProp)
531 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
533 pvLeft.ulPropTag = pvRight.ulPropTag = ptTypes[i];
535 for (j = 0; j < sizeof(LPCProp_Results)/sizeof(LPCProp_Results[0]); j++)
537 SHORT lVal = LPCProp_Results[j].lVal;
538 SHORT rVal = LPCProp_Results[j].rVal;
540 iExp = LPCProp_Results[j].iRet;
545 /* Boolean values have no concept of less or greater than, only equality */
548 /* Fall through ... */
550 pvLeft.Value.i = lVal;
551 pvRight.Value.i = rVal;
555 pvLeft.Value.l = lVal;
556 pvRight.Value.l = rVal;
559 pvLeft.Value.flt = lVal;
560 pvRight.Value.flt = rVal;
564 pvLeft.Value.dbl = lVal;
565 pvRight.Value.dbl = rVal;
568 pvLeft.Value.cur.int64 = lVal;
569 pvRight.Value.cur.int64 = rVal;
572 pvLeft.Value.ft.dwLowDateTime = lVal;
573 pvLeft.Value.ft.dwHighDateTime = 0;
574 pvRight.Value.ft.dwLowDateTime = rVal;
575 pvRight.Value.ft.dwHighDateTime = 0;
578 pvLeft.Value.li.u.LowPart = lVal;
579 pvLeft.Value.li.u.HighPart = 0;
580 pvRight.Value.li.u.LowPart = rVal;
581 pvRight.Value.li.u.HighPart = 0;
584 memset(&lguid, 0, sizeof(GUID));
585 memset(&rguid, 0, sizeof(GUID));
586 lguid.Data4[7] = lVal;
587 rguid.Data4[7] = rVal;
588 pvLeft.Value.lpguid = &lguid;
589 pvRight.Value.lpguid = &rguid;
592 pvLeft.Value.lpszA = lbuffa;
593 pvRight.Value.lpszA = rbuffa;
594 lbuffa[0] = '0' + lVal;
595 rbuffa[0] = '0' + rVal;
598 pvLeft.Value.lpszW = lbuffw;
599 pvRight.Value.lpszW = rbuffw;
600 lbuffw[0] = '0' + lVal;
601 rbuffw[0] = '0' + rVal;
604 pvLeft.Value.bin.cb = 1;
605 pvRight.Value.bin.cb = 1;
606 pvLeft.Value.bin.lpb = lbuffa;
607 pvRight.Value.bin.lpb = rbuffa;
613 iRet = pLPropCompareProp(&pvLeft, &pvRight);
614 ok(iRet == iExp, "pt %ld (%d,%d): expected %d, got %d\n", ptTypes[i],
615 LPCProp_Results[j].lVal, LPCProp_Results[j].rVal, iExp, iRet);
620 static void test_PpropFindProp(void)
622 SPropValue pvProp, *pRet;
625 pPpropFindProp = (void*)GetProcAddress(hMapi32, "PpropFindProp@12");
630 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
632 pvProp.ulPropTag = ptTypes[i];
634 pRet = pPpropFindProp(&pvProp, 1u, ptTypes[i]);
635 ok(pRet == &pvProp, "PpropFindProp[%ld]: Didn't find existing propery\n",
638 pRet = pPpropFindProp(&pvProp, 1u, i ? ptTypes[i-1] : ptTypes[i+1]);
639 ok(pRet == NULL, "PpropFindProp[%ld]: Found nonexistent propery\n",
643 pvProp.ulPropTag = PROP_TAG(PT_I2, 1u);
644 pRet = pPpropFindProp(&pvProp, 1u, PROP_TAG(PT_UNSPECIFIED, 0u));
645 ok(pRet == NULL, "PpropFindProp[UNSPECIFIED]: Matched on different id\n");
646 pRet = pPpropFindProp(&pvProp, 1u, PROP_TAG(PT_UNSPECIFIED, 1u));
647 ok(pRet == &pvProp, "PpropFindProp[UNSPECIFIED]: Didn't match id\n");
650 static void test_ScCountProps(void)
652 static const char *szHiA = "Hi!";
653 static const WCHAR szHiW[] = { 'H', 'i', '!', '\0' };
654 static const ULONG ULHILEN = 4; /* chars in szHiA/W incl. NUL */
658 GUID iids[4], *iid = iids;
660 ULONG pt, exp, ulRet;
663 pScCountProps = (void*)GetProcAddress(hMapi32, "ScCountProps@12");
668 for (pt = 0; pt < PROP_ID_INVALID && success; pt++)
672 memset(&pv, 0 ,sizeof(pv));
673 pv.ulPropTag = PROP_TAG(pt, 1u);
675 switch (PROP_TYPE(pt))
691 pv.Value.lpguid = iid;
692 exp = sizeof(GUID) + sizeof(pv);
695 pv.Value.lpszA = (LPSTR)szHiA;
696 exp = 4 + sizeof(pv);
699 pv.Value.lpszW = (LPWSTR)szHiW;
700 exp = 4 * sizeof(WCHAR) + sizeof(pv);
704 pv.Value.bin.lpb = (LPBYTE)iid;
705 exp = 2 + sizeof(pv);
708 pv.Value.MVi.cValues = 3;
709 pv.Value.MVi.lpi = (SHORT*)iid;
710 exp = 3 * sizeof(SHORT) + sizeof(pv);
713 pv.Value.MVl.cValues = 3;
714 pv.Value.MVl.lpl = (LONG*)iid;
715 exp = 3 * sizeof(LONG) + sizeof(pv);
718 pv.Value.MVli.cValues = 3;
719 pv.Value.MVli.lpli = (LARGE_INTEGER*)iid;
720 exp = 3 * sizeof(LARGE_INTEGER) + sizeof(pv);
723 pv.Value.MVflt.cValues = 3;
724 pv.Value.MVflt.lpflt = (float*)iid;
725 exp = 3 * sizeof(float) + sizeof(pv);
729 pv.Value.MVdbl.cValues = 3;
730 pv.Value.MVdbl.lpdbl = (double*)iid;
731 exp = 3 * sizeof(double) + sizeof(pv);
734 pv.Value.MVcur.cValues = 3;
735 pv.Value.MVcur.lpcur = (CY*)iid;
736 exp = 3 * sizeof(CY) + sizeof(pv);
739 pv.Value.MVft.cValues = 3;
740 pv.Value.MVft.lpft = (FILETIME*)iid;
741 exp = 3 * sizeof(CY) + sizeof(pv);
744 pv.Value.MVszA.cValues = 3;
745 pv.Value.MVszA.lppszA = buffa;
746 buffa[0] = (LPSTR)szHiA;
747 buffa[1] = (LPSTR)szHiA;
748 buffa[2] = (LPSTR)szHiA;
749 exp = ULHILEN * 3 + 3 * sizeof(char*) + sizeof(pv);
752 pv.Value.MVszW.cValues = 3;
753 pv.Value.MVszW.lppszW = buffw;
754 buffw[0] = (LPWSTR)szHiW;
755 buffw[1] = (LPWSTR)szHiW;
756 buffw[2] = (LPWSTR)szHiW;
757 exp = ULHILEN * 3 * sizeof(WCHAR) + 3 * sizeof(WCHAR*) + sizeof(pv);
760 pv.Value.MVbin.cValues = 3;
761 pv.Value.MVbin.lpbin = buffbin;
763 buffbin[0].lpb = (LPBYTE)&iid;
765 buffbin[1].lpb = (LPBYTE)&iid;
767 buffbin[2].lpb = (LPBYTE)&iid;
768 exp = 20 + sizeof(pv) + sizeof(SBinary) * 3;
775 res = pScCountProps(1, &pv, &ulRet);
777 success = res == MAPI_E_INVALID_PARAMETER && ulRet == 0xffffffff;
778 ok(success, "pt= %ld: Expected failure, got %ld, ret=0x%08lX\n",
782 success = res == S_OK && ulRet == exp;
783 ok(success, "pt= %ld: Expected %ld, got %ld, ret=0x%08lX\n",
784 pt, exp, ulRet, res);
790 static void test_ScCopyRelocProps(void)
792 static const char* szTestA = "Test";
793 char buffer[512], buffer2[512], *lppszA[1];
794 SPropValue pvProp, *lpResProp = (LPSPropValue)buffer;
798 pScCopyProps = (void*)GetProcAddress(hMapi32, "ScCopyProps@16");
799 pScRelocProps = (void*)GetProcAddress(hMapi32, "ScRelocProps@20");
801 if (!pScCopyProps || !pScRelocProps)
804 pvProp.ulPropTag = PROP_TAG(PT_MV_STRING8, 1u);
806 lppszA[0] = (char *)szTestA;
807 pvProp.Value.MVszA.cValues = 1;
808 pvProp.Value.MVszA.lppszA = lppszA;
811 sc = pScCopyProps(1, &pvProp, buffer, &ulCount);
812 ok(sc == S_OK && lpResProp->ulPropTag == pvProp.ulPropTag &&
813 lpResProp->Value.MVszA.cValues == 1 &&
814 lpResProp->Value.MVszA.lppszA[0] == buffer + sizeof(SPropValue) + sizeof(char*) &&
815 !strcmp(lpResProp->Value.MVszA.lppszA[0], szTestA) &&
816 ulCount == sizeof(SPropValue) + sizeof(char*) + 5,
817 "CopyProps(str): Expected 0 {1,%lx,%p,%s} %d got 0x%08lx {%ld,%lx,%p,%s} %ld\n",
818 pvProp.ulPropTag, buffer + sizeof(SPropValue) + sizeof(char*),
819 szTestA, sizeof(SPropValue) + sizeof(char*) + 5, sc,
820 lpResProp->Value.MVszA.cValues, lpResProp->ulPropTag,
821 lpResProp->Value.MVszA.lppszA[0], sc==S_OK?lpResProp->Value.MVszA.lppszA[0]:NULL, ulCount);
823 memcpy(buffer2, buffer, sizeof(buffer));
825 /* Clear the data in the source buffer. Since pointers in the copied buffer
826 * refer to the source buffer, this proves that native always assumes that
827 * the copied buffers pointers are bad (needing to be relocated first).
829 memset(buffer, 0, sizeof(buffer));
832 sc = pScRelocProps(1, (LPSPropValue)buffer2, buffer, buffer2, &ulCount);
833 lpResProp = (LPSPropValue)buffer2;
834 ok(sc == S_OK && lpResProp->ulPropTag == pvProp.ulPropTag &&
835 lpResProp->Value.MVszA.cValues == 1 &&
836 lpResProp->Value.MVszA.lppszA[0] == buffer2 + sizeof(SPropValue) + sizeof(char*) &&
837 !strcmp(lpResProp->Value.MVszA.lppszA[0], szTestA) &&
838 /* Native has a bug whereby it calculates the size correctly when copying
839 * but when relocating does not (presumably it uses UlPropSize() which
840 * ignores multivalue pointers). Wine returns the correct value.
842 (ulCount == sizeof(SPropValue) + sizeof(char*) + 5 || ulCount == sizeof(SPropValue) + 5),
843 "RelocProps(str): Expected 0 {1,%lx,%p,%s} %d got 0x%08lx {%ld,%lx,%p,%s} %ld\n",
844 pvProp.ulPropTag, buffer2 + sizeof(SPropValue) + sizeof(char*),
845 szTestA, sizeof(SPropValue) + sizeof(char*) + 5, sc,
846 lpResProp->Value.MVszA.cValues, lpResProp->ulPropTag,
847 lpResProp->Value.MVszA.lppszA[0], sc==S_OK?lpResProp->Value.MVszA.lppszA[0]:NULL, ulCount);
849 /* Native crashes with lpNew or lpOld set to NULL so skip testing this */
852 static void test_LpValFindProp(void)
854 SPropValue pvProp, *pRet;
857 pLpValFindProp = (void*)GetProcAddress(hMapi32, "LpValFindProp@12");
862 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
864 pvProp.ulPropTag = PROP_TAG(ptTypes[i], 1u);
866 pRet = pLpValFindProp(PROP_TAG(ptTypes[i], 1u), 1u, &pvProp);
867 ok(pRet == &pvProp, "LpValFindProp[%ld]: Didn't find existing propery id/type\n",
870 pRet = pLpValFindProp(PROP_TAG(ptTypes[i], 0u), 1u, &pvProp);
871 ok(pRet == NULL, "LpValFindProp[%ld]: Found nonexistent propery id\n",
874 pRet = pLpValFindProp(PROP_TAG(PT_NULL, 0u), 1u, &pvProp);
875 ok(pRet == NULL, "LpValFindProp[%ld]: Found nonexistent propery id/type\n",
878 pRet = pLpValFindProp(PROP_TAG(PT_NULL, 1u), 1u, &pvProp);
879 ok(pRet == &pvProp, "LpValFindProp[%ld]: Didn't find existing propery id\n",
884 static void test_FBadRglpszA(void)
887 char *szString = "A String";
890 pFBadRglpszA = (void*)GetProcAddress(hMapi32, "FBadRglpszA@8");
894 bRet = pFBadRglpszA(NULL, 10);
895 ok(bRet == TRUE, "FBadRglpszA(Null): expected TRUE, got FALSE\n");
897 lpStrs[0] = lpStrs[1] = lpStrs[2] = lpStrs[3] = NULL;
898 bRet = pFBadRglpszA(lpStrs, 4);
899 ok(bRet == TRUE, "FBadRglpszA(Nulls): expected TRUE, got FALSE\n");
901 lpStrs[0] = lpStrs[1] = lpStrs[2] = szString;
902 bRet = pFBadRglpszA(lpStrs, 3);
903 ok(bRet == FALSE, "FBadRglpszA(valid): expected FALSE, got TRUE\n");
905 bRet = pFBadRglpszA(lpStrs, 4);
906 ok(bRet == TRUE, "FBadRglpszA(1 invalid): expected TRUE, got FALSE\n");
909 static void test_FBadRglpszW(void)
912 WCHAR szString[] = { 'A',' ','S','t','r','i','n','g','\0' };
915 pFBadRglpszW = (void*)GetProcAddress(hMapi32, "FBadRglpszW@8");
919 bRet = pFBadRglpszW(NULL, 10);
920 ok(bRet == TRUE, "FBadRglpszW(Null): expected TRUE, got FALSE\n");
922 lpStrs[0] = lpStrs[1] = lpStrs[2] = lpStrs[3] = NULL;
923 bRet = pFBadRglpszW(lpStrs, 4);
924 ok(bRet == TRUE, "FBadRglpszW(Nulls): expected TRUE, got FALSE\n");
926 lpStrs[0] = lpStrs[1] = lpStrs[2] = szString;
927 bRet = pFBadRglpszW(lpStrs, 3);
928 ok(bRet == FALSE, "FBadRglpszW(valid): expected FALSE, got TRUE\n");
930 bRet = pFBadRglpszW(lpStrs, 4);
931 ok(bRet == TRUE, "FBadRglpszW(1 invalid): expected TRUE, got FALSE\n");
934 static void test_FBadRowSet(void)
938 pFBadRowSet = (void*)GetProcAddress(hMapi32, "FBadRowSet@4");
942 ulRet = pFBadRowSet(NULL);
943 ok(ulRet != 0, "FBadRow(null): Expected non-zero, got 0\n");
948 static void test_FBadPropTag(void)
952 pFBadPropTag = (void*)GetProcAddress(hMapi32, "FBadPropTag@4");
956 for (pt = 0; pt < PROP_ID_INVALID; pt++)
960 switch (pt & (~MV_FLAG & PROP_TYPE_MASK))
963 case PT_NULL: case PT_I2: case PT_I4: case PT_R4:
964 case PT_R8: case PT_CURRENCY: case PT_APPTIME:
965 case PT_ERROR: case PT_BOOLEAN: case PT_OBJECT:
966 case PT_I8: case PT_STRING8: case PT_UNICODE:
967 case PT_SYSTIME: case PT_CLSID: case PT_BINARY:
971 res = pFBadPropTag(pt);
973 ok(res != 0, "pt= %ld: Expected non-zero, got 0\n", pt);
975 ok(res == 0, "pt= %ld: Expected zero, got %ld\n", pt, res);
979 static void test_FBadRow(void)
983 pFBadRow = (void*)GetProcAddress(hMapi32, "FBadRow@4");
987 ulRet = pFBadRow(NULL);
988 ok(ulRet != 0, "FBadRow(null): Expected non-zero, got 0\n");
993 static void test_FBadProp(void)
995 WCHAR szEmpty[] = { '\0' };
1000 pFBadProp = (void*)GetProcAddress(hMapi32, "FBadProp@4");
1004 for (pt = 0; pt < PROP_ID_INVALID; pt++)
1008 memset(&pv, 0, sizeof(pv));
1011 /* Note that MV values are valid below because their array count is 0,
1012 * so no pointers are validated.
1014 switch (PROP_TYPE(pt))
1016 case (MV_FLAG|PT_UNSPECIFIED):
1017 case PT_UNSPECIFIED:
1018 case (MV_FLAG|PT_NULL):
1030 case PT_MV_CURRENCY:
1034 case (MV_FLAG|PT_ERROR):
1036 case (MV_FLAG|PT_BOOLEAN):
1038 case (MV_FLAG|PT_OBJECT):
1051 pv.Value.lpszW = szEmpty;
1055 pv.Value.lpguid = &iid;
1060 res = pFBadProp(&pv);
1062 ok(res != 0, "pt= %ld: Expected non-zero, got 0\n", pt);
1064 ok(res == 0, "pt= %ld: Expected zero, got %ld\n", pt, res);
1068 static void test_FBadColumnSet(void)
1073 pFBadColumnSet = (void*)GetProcAddress(hMapi32, "FBadColumnSet@4");
1074 if (!pFBadColumnSet)
1077 res = pFBadColumnSet(NULL);
1078 ok(res != 0, "(null): Expected non-zero, got 0\n");
1082 for (pt = 0; pt < PROP_ID_INVALID; pt++)
1086 pta.aulPropTag[0] = pt;
1088 switch (pt & (~MV_FLAG & PROP_TYPE_MASK))
1090 case PT_UNSPECIFIED:
1108 if (pt == (MV_FLAG|PT_ERROR))
1111 res = pFBadColumnSet(&pta);
1113 ok(res != 0, "pt= %ld: Expected non-zero, got 0\n", pt);
1115 ok(res == 0, "pt= %ld: Expected zero, got %ld\n", pt, res);
1120 static void test_IProp(void)
1123 LPMAPIERROR lpError;
1124 LPSPropProblemArray lpProbs;
1125 LPSPropValue lpProps;
1126 LPSPropTagArray lpTags;
1128 SizedSPropTagArray(2,tags);
1129 ULONG access[2], count;
1132 pCreateIProp = (void*)GetProcAddress(hMapi32, "CreateIProp@24");
1136 memset(&tags, 0 , sizeof(tags));
1138 /* Create the object */
1140 sc = pCreateIProp(&IID_IMAPIPropData, MAPIAllocateBuffer, MAPIAllocateMore,
1141 MAPIFreeBuffer, NULL, &lpIProp);
1142 ok(sc == S_OK && lpIProp,
1143 "CreateIProp: expected S_OK, non-null, got 0x%08lX,%p\n", sc, lpIProp);
1145 if (sc != S_OK || !lpIProp)
1148 /* GetLastError - No errors set */
1150 IPropData_GetLastError(lpIProp, E_INVALIDARG, 0, &lpError);
1151 ok(sc == S_OK && !lpError,
1152 "GetLastError: Expected S_OK, null, got 0x%08lX,%p\n", sc, lpError);
1154 /* Get prop tags - succeeds returning 0 items */
1156 sc = IPropData_GetPropList(lpIProp, 0, &lpTags);
1157 ok(sc == S_OK && lpTags && lpTags->cValues == 0,
1158 "GetPropList(empty): Expected S_OK, non-null, 0, got 0x%08lX,%p,%ld\n",
1159 sc, lpTags, lpTags ? lpTags->cValues : 0);
1161 MAPIFreeBuffer(lpTags);
1163 /* Get props - succeeds returning 0 items */
1167 tags.aulPropTag[0] = PR_IMPORTANCE;
1168 sc = IPropData_GetProps(lpIProp, (LPSPropTagArray)&tags, 0, &count, &lpProps);
1169 ok(sc == MAPI_W_ERRORS_RETURNED && lpProps && count == 1,
1170 "GetProps(empty): Expected ERRORS_RETURNED, non-null, 1, got 0x%08lX,%p,%ld\n",
1171 sc, lpProps, count);
1172 if (lpProps && count > 0)
1174 ok(lpProps[0].ulPropTag == CHANGE_PROP_TYPE(PR_IMPORTANCE,PT_ERROR),
1175 "GetProps(empty): Expected %x, got %lx\n",
1176 CHANGE_PROP_TYPE(PR_IMPORTANCE,PT_ERROR), lpProps[0].ulPropTag);
1178 MAPIFreeBuffer(lpProps);
1181 /* Add (NULL) - Can't add NULL's */
1183 pvs[0].ulPropTag = PROP_TAG(PT_NULL,0x01);
1184 sc = IPropData_SetProps(lpIProp, 1, pvs, &lpProbs);
1185 ok(sc == MAPI_E_INVALID_PARAMETER && !lpProbs,
1186 "SetProps(): Expected INVALID_PARAMETER, null, got 0x%08lX,%p\n",
1189 /* Add (OBJECT) - Can't add OBJECTS's */
1191 pvs[0].ulPropTag = PROP_TAG(PT_OBJECT,0x01);
1192 sc = IPropData_SetProps(lpIProp, 1, pvs, &lpProbs);
1193 ok(sc == MAPI_E_INVALID_PARAMETER && !lpProbs,
1194 "SetProps(OBJECT): Expected INVALID_PARAMETER, null, got 0x%08lX,%p\n",
1197 /* Add - Adds value */
1199 pvs[0].ulPropTag = PR_IMPORTANCE;
1200 sc = IPropData_SetProps(lpIProp, 1, pvs, &lpProbs);
1201 ok(sc == S_OK && !lpProbs,
1202 "SetProps(ERROR): Expected S_OK, null, got 0x%08lX,%p\n", sc, lpProbs);
1204 /* Get prop list - returns 1 item */
1206 IPropData_GetPropList(lpIProp, 0, &lpTags);
1207 ok(sc == S_OK && lpTags && lpTags->cValues == 1,
1208 "GetPropList: Expected S_OK, non-null, 1, got 0x%08lX,%p,%ld\n",
1209 sc, lpTags, lpTags ? lpTags->cValues : 0);
1210 if (lpTags && lpTags->cValues > 0)
1212 ok(lpTags->aulPropTag[0] == PR_IMPORTANCE,
1213 "GetPropList: Expected %x, got %lx\n",
1214 PR_IMPORTANCE, lpTags->aulPropTag[0]);
1215 MAPIFreeBuffer(lpTags);
1218 /* Set access to read and write */
1219 sc = IPropData_HrSetObjAccess(lpIProp, IPROP_READWRITE);
1220 ok(sc == S_OK, "SetObjAcess(WRITE): Expected S_OK got 0x%08lX\n", sc);
1223 tags.aulPropTag[0] = PR_IMPORTANCE;
1225 /* Set item access (bad access) - Fails */
1227 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1228 ok(sc == MAPI_E_INVALID_PARAMETER,
1229 "SetPropAcess(0): Expected INVALID_PARAMETER got 0x%08lX\n",sc);
1230 access[0] = IPROP_READWRITE;
1231 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1232 ok(sc == MAPI_E_INVALID_PARAMETER,
1233 "SetPropAcess(RW): Expected INVALID_PARAMETER got 0x%08lX\n",sc);
1234 access[0] = IPROP_CLEAN;
1235 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1236 ok(sc == MAPI_E_INVALID_PARAMETER,
1237 "SetPropAcess(C): Expected INVALID_PARAMETER got 0x%08lX\n",sc);
1239 /* Set item access to read/write/clean */
1241 tags.aulPropTag[0] = PR_IMPORTANCE;
1242 access[0] = IPROP_READWRITE|IPROP_CLEAN;
1243 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1244 ok(sc == S_OK, "SetPropAcess(RW/C): Expected S_OK got 0x%08lX\n",sc);
1246 /* Set object access to read only */
1247 sc = IPropData_HrSetObjAccess(lpIProp, IPROP_READONLY);
1248 ok(sc == S_OK, "SetObjAcess(READ): Expected S_OK got 0x%08lX\n", sc);
1250 /* Set item access to read/write/dirty - doesn't care about RO object */
1251 access[0] = IPROP_READONLY|IPROP_DIRTY;
1252 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1253 ok(sc == S_OK, "SetPropAcess(WRITE): Expected S_OK got 0x%08lX\n", sc);
1255 /* Delete any item when set to read only - Error */
1257 tags.aulPropTag[0] = PR_RESPONSE_REQUESTED;
1258 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1259 ok(sc == E_ACCESSDENIED && !lpProbs,
1260 "DeleteProps(nonexistent): Expected E_ACCESSDENIED null got 0x%08lX %p\n",
1263 /* Set access to read and write */
1264 sc = IPropData_HrSetObjAccess(lpIProp, IPROP_READWRITE);
1265 ok(sc == S_OK, "SetObjAcess(WRITE): Expected S_OK got 0x%08lX\n", sc);
1267 /* Delete nonexistent item - No error */
1269 tags.aulPropTag[0] = PR_RESPONSE_REQUESTED;
1270 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1271 ok(sc == S_OK && !lpProbs,
1272 "DeleteProps(nonexistent): Expected S_OK null got 0x%08lX %p\n",
1275 /* Delete existing item (r/o) - No error, but lpProbs populated */
1277 tags.aulPropTag[0] = PR_IMPORTANCE;
1278 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1279 ok(sc == S_OK && lpProbs,
1280 "DeleteProps(RO): Expected S_OK non-null got 0x%08lX %p\n", sc, lpProbs);
1282 if (lpProbs && lpProbs->cProblem > 0)
1284 ok(lpProbs->cProblem == 1 &&
1285 lpProbs->aProblem[0].ulIndex == 0 &&
1286 lpProbs->aProblem[0].ulPropTag == PR_IMPORTANCE &&
1287 lpProbs->aProblem[0].scode == E_ACCESSDENIED,
1288 "DeleteProps(RO): Expected (1,0,%x,%lx) got (%ld,%lx,%lx)\n",
1289 PR_IMPORTANCE, E_ACCESSDENIED,
1290 lpProbs->aProblem[0].ulIndex, lpProbs->aProblem[0].ulPropTag,
1291 lpProbs->aProblem[0].scode);
1292 MAPIFreeBuffer(lpProbs);
1297 tags.aulPropTag[0] = PR_RESPONSE_REQUESTED;
1298 IPropData_HrAddObjProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1299 ok(sc == S_OK && !lpProbs,
1300 "AddObjProps(RO): Expected S_OK null got 0x%08lX %p\n", sc, lpProbs);
1302 /* Get prop list - returns 1 item */
1304 IPropData_GetPropList(lpIProp, 0, &lpTags);
1305 ok(sc == S_OK && lpTags && lpTags->cValues == 1,
1306 "GetPropList: Expected S_OK, non-null, 1, got 0x%08lX,%p,%ld\n",
1307 sc, lpTags, lpTags ? lpTags->cValues : 0);
1308 if (lpTags && lpTags->cValues > 0)
1310 ok(lpTags->aulPropTag[0] == PR_IMPORTANCE,
1311 "GetPropList: Expected %x, got %lx\n",
1312 PR_IMPORTANCE, lpTags->aulPropTag[0]);
1313 MAPIFreeBuffer(lpTags);
1316 /* Set item to r/w again */
1317 access[0] = IPROP_READWRITE|IPROP_DIRTY;
1318 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1319 ok(sc == S_OK, "SetPropAcess(WRITE): Expected S_OK got 0x%08lX\n", sc);
1321 /* Delete existing item (r/w) - No error, no problems */
1323 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1324 ok(sc == S_OK && !lpProbs,
1325 "DeleteProps(RO): Expected S_OK null got 0x%08lX %p\n", sc, lpProbs);
1328 IPropData_Release(lpIProp);
1333 hMapi32 = LoadLibraryA("mapi32.dll");
1335 pScInitMapiUtil = (void*)GetProcAddress(hMapi32, "ScInitMapiUtil@4");
1336 if (!pScInitMapiUtil)
1340 test_PropCopyMore();
1342 test_FPropContainsProp();
1343 test_FPropCompareProp();
1344 test_LPropCompareProp();
1345 test_PpropFindProp();
1346 test_ScCountProps();
1347 test_ScCopyRelocProps();
1348 test_LpValFindProp();
1355 test_FBadColumnSet();