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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "wine/test.h"
31 static HMODULE hMapi32 = 0;
33 static SCODE (WINAPI *pScInitMapiUtil)(ULONG);
34 static SCODE (WINAPI *pPropCopyMore)(LPSPropValue,LPSPropValue,ALLOCATEMORE*,LPVOID);
35 static ULONG (WINAPI *pUlPropSize)(LPSPropValue);
36 static BOOL (WINAPI *pFPropContainsProp)(LPSPropValue,LPSPropValue,ULONG);
37 static BOOL (WINAPI *pFPropCompareProp)(LPSPropValue,ULONG,LPSPropValue);
38 static LONG (WINAPI *pLPropCompareProp)(LPSPropValue,LPSPropValue);
39 static LPSPropValue (WINAPI *pPpropFindProp)(LPSPropValue,ULONG,ULONG);
40 static SCODE (WINAPI *pScCountProps)(INT,LPSPropValue,ULONG*);
41 static SCODE (WINAPI *pScCopyProps)(int,LPSPropValue,LPVOID,ULONG*);
42 static SCODE (WINAPI *pScRelocProps)(int,LPSPropValue,LPVOID,LPVOID,ULONG*);
43 static LPSPropValue (WINAPI *pLpValFindProp)(ULONG,ULONG,LPSPropValue);
44 static BOOL (WINAPI *pFBadRglpszA)(LPSTR*,ULONG);
45 static BOOL (WINAPI *pFBadRglpszW)(LPWSTR*,ULONG);
46 static BOOL (WINAPI *pFBadRowSet)(LPSRowSet);
47 static ULONG (WINAPI *pFBadPropTag)(ULONG);
48 static ULONG (WINAPI *pFBadRow)(LPSRow);
49 static ULONG (WINAPI *pFBadProp)(LPSPropValue);
50 static ULONG (WINAPI *pFBadColumnSet)(LPSPropTagArray);
51 static SCODE (WINAPI *pCreateIProp)(LPCIID,ALLOCATEBUFFER*,ALLOCATEMORE*,
52 FREEBUFFER*,LPVOID,LPPROPDATA*);
53 static SCODE (WINAPI *pMAPIAllocateBuffer)(ULONG, LPVOID);
54 static SCODE (WINAPI *pMAPIAllocateMore)(ULONG, LPVOID, LPVOID);
55 static SCODE (WINAPI *pMAPIFreeBuffer)(LPVOID);
57 static BOOL InitFuncPtrs(void)
59 hMapi32 = LoadLibraryA("mapi32.dll");
61 pScInitMapiUtil = (void*)GetProcAddress(hMapi32, "ScInitMapiUtil@4");
62 pMAPIAllocateBuffer = (void*)GetProcAddress(hMapi32, "MAPIAllocateBuffer");
63 pMAPIAllocateMore = (void*)GetProcAddress(hMapi32, "MAPIAllocateMore");
64 pMAPIFreeBuffer = (void*)GetProcAddress(hMapi32, "MAPIFreeBuffer");
65 if(pScInitMapiUtil && pMAPIAllocateBuffer && pMAPIAllocateMore && pMAPIFreeBuffer)
71 static ULONG ptTypes[] = {
72 PT_I2, PT_I4, PT_R4, PT_R8, PT_CURRENCY, PT_APPTIME, PT_SYSTIME,
73 PT_ERROR, PT_BOOLEAN, PT_I8, PT_CLSID, PT_STRING8, PT_BINARY,
77 static inline int strcmpW(const WCHAR *str1, const WCHAR *str2)
79 while (*str1 && (*str1 == *str2)) { str1++; str2++; }
83 static void test_PropCopyMore(void)
85 static char szHiA[] = "Hi!";
86 static WCHAR szHiW[] = { 'H', 'i', '!', '\0' };
87 SPropValue *lpDest = NULL, *lpSrc = NULL;
91 pPropCopyMore = (void*)GetProcAddress(hMapi32, "PropCopyMore@16");
96 scode = pMAPIAllocateBuffer(sizeof(LPSPropValue), lpDest);
100 scode = pMAPIAllocateMore(sizeof(LPSPropValue), lpDest, lpSrc);
104 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
106 lpSrc->ulPropTag = ptTypes[i];
111 lpSrc->Value.lpszA = szHiA;
114 lpSrc->Value.lpszW = szHiW;
117 lpSrc->Value.bin.cb = 4;
118 lpSrc->Value.bin.lpb = (LPBYTE)szHiA;
122 memset(lpDest, 0xff, sizeof(SPropValue));
124 scode = pPropCopyMore(lpDest, lpSrc, (ALLOCATEMORE*)pMAPIAllocateMore, lpDest);
125 ok(!scode && lpDest->ulPropTag == lpSrc->ulPropTag,
126 "PropCopyMore: Expected 0x0,%d, got 0x%08x,%d\n",
127 lpSrc->ulPropTag, scode, lpDest->ulPropTag);
128 if (SUCCEEDED(scode))
133 ok(lstrcmpA(lpDest->Value.lpszA, lpSrc->Value.lpszA) == 0,
134 "PropCopyMore: Ascii string differs\n");
137 ok(strcmpW(lpDest->Value.lpszW, lpSrc->Value.lpszW) == 0,
138 "PropCopyMore: Unicode string differs\n");
141 ok(lpDest->Value.bin.cb == 4 &&
142 !memcmp(lpSrc->Value.bin.lpb, lpDest->Value.bin.lpb, 4),
143 "PropCopyMore: Binary array differs\n");
149 /* Since all allocations are linked, freeing lpDest frees everything */
150 pMAPIFreeBuffer(lpDest);
153 static void test_UlPropSize(void)
155 static char szHiA[] = "Hi!";
156 static WCHAR szHiW[] = { 'H', 'i', '!', '\0' };
162 pUlPropSize = (void*)GetProcAddress(hMapi32, "UlPropSize@4");
167 for (pt = 0; pt < PROP_ID_INVALID; pt++)
171 memset(&pv, 0 ,sizeof(pv));
174 exp = 1u; /* Default to one item for non-MV properties */
176 switch (PROP_TYPE(pt))
178 case PT_MV_I2: pv.Value.MVi.cValues = exp = 2;
179 case PT_I2: exp *= sizeof(USHORT); break;
180 case PT_MV_I4: pv.Value.MVl.cValues = exp = 2;
181 case PT_I4: exp *= sizeof(LONG); break;
182 case PT_MV_R4: pv.Value.MVflt.cValues = exp = 2;
183 case PT_R4: exp *= sizeof(float); break;
184 case PT_MV_DOUBLE: pv.Value.MVdbl.cValues = exp = 2;
185 case PT_R8: exp *= sizeof(double); break;
186 case PT_MV_CURRENCY: pv.Value.MVcur.cValues = exp = 2;
187 case PT_CURRENCY: exp *= sizeof(CY); break;
188 case PT_MV_APPTIME: pv.Value.MVat.cValues = exp = 2;
189 case PT_APPTIME: exp *= sizeof(double); break;
190 case PT_MV_SYSTIME: pv.Value.MVft.cValues = exp = 2;
191 case PT_SYSTIME: exp *= sizeof(FILETIME); break;
192 case PT_ERROR: exp = sizeof(SCODE); break;
193 case PT_BOOLEAN: exp = sizeof(USHORT); break;
194 case PT_OBJECT: exp = 0; break;
195 case PT_MV_I8: pv.Value.MVli.cValues = exp = 2;
196 case PT_I8: exp *= sizeof(LONG64); break;
198 /* My version of native mapi returns 0 for PT_MV_CLSID even if a valid
199 * array is given. This _has_ to be a bug, so Wine does
200 * the right thing(tm) and we don't test it here.
202 case PT_MV_CLSID: pv.Value.MVguid.cValues = exp = 2;
204 case PT_CLSID: exp *= sizeof(GUID); break;
206 pv.Value.lpszA = szHiA;
210 pv.Value.lpszW = szHiW;
211 exp = 4 * sizeof(WCHAR);
214 pv.Value.bin.cb = exp = 19;
217 pv.Value.MVszA.cValues = 2;
218 pv.Value.MVszA.lppszA = buffa;
224 pv.Value.MVszW.cValues = 2;
225 pv.Value.MVszW.lppszW = buffw;
228 exp = 8 * sizeof(WCHAR);
231 pv.Value.MVbin.cValues = 2;
232 pv.Value.MVbin.lpbin = buffbin;
241 res = pUlPropSize(&pv);
242 ok(res == exp || broken(!res) /* Win9x */,
243 "pt= %d: Expected %d, got %d\n", pt, exp, res);
247 static void test_FPropContainsProp(void)
249 static char szFull[] = "Full String";
250 static char szFullLower[] = "full string";
251 static char szPrefix[] = "Full";
252 static char szPrefixLower[] = "full";
253 static char szSubstring[] = "ll St";
254 static char szSubstringLower[] = "ll st";
255 SPropValue pvLeft, pvRight;
259 pFPropContainsProp = (void*)GetProcAddress(hMapi32, "FPropContainsProp@12");
261 if (!pFPropContainsProp)
264 /* Ensure that only PT_STRING8 and PT_BINARY are handled */
265 for (pt = 0; pt < PROP_ID_INVALID; pt++)
267 if (pt == PT_STRING8 || pt == PT_BINARY)
268 continue; /* test these later */
270 memset(&pvLeft, 0 ,sizeof(pvLeft));
271 memset(&pvRight, 0 ,sizeof(pvRight));
272 pvLeft.ulPropTag = pvRight.ulPropTag = pt;
274 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
275 ok(bRet == FALSE, "pt= %d: Expected FALSE, got %d\n", pt, bRet);
278 /* test the various flag combinations */
279 pvLeft.ulPropTag = pvRight.ulPropTag = PT_STRING8;
280 pvLeft.Value.lpszA = szFull;
281 pvRight.Value.lpszA = szFull;
283 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
284 ok(bRet == TRUE || broken(!bRet) /* Win9x */, "(full,full)[] match failed\n");
285 pvRight.Value.lpszA = szPrefix;
286 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
287 ok(bRet == FALSE, "(full,prefix)[] match failed\n");
288 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
289 ok(bRet == TRUE, "(full,prefix)[PREFIX] match failed\n");
290 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
291 ok(bRet == TRUE || broken(!bRet) /* Win9x */, "(full,prefix)[SUBSTRING] match failed\n");
292 pvRight.Value.lpszA = szPrefixLower;
293 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
294 ok(bRet == FALSE, "(full,prefixlow)[PREFIX] match failed\n");
295 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
296 ok(bRet == FALSE, "(full,prefixlow)[SUBSTRING] match failed\n");
297 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE);
298 ok(bRet == TRUE || broken(!bRet) /* Win9x */, "(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
299 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
300 ok(bRet == TRUE || broken(!bRet) /* Win9x */, "(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
301 pvRight.Value.lpszA = szSubstring;
302 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
303 ok(bRet == FALSE, "(full,substr)[] match failed\n");
304 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
305 ok(bRet == FALSE, "(full,substr)[PREFIX] match failed\n");
306 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
307 ok(bRet == TRUE || broken(!bRet) /* Win9x */, "(full,substr)[SUBSTRING] match failed\n");
308 pvRight.Value.lpszA = szSubstringLower;
309 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
310 ok(bRet == FALSE, "(full,substrlow)[PREFIX] match failed\n");
311 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
312 ok(bRet == FALSE, "(full,substrlow)[SUBSTRING] match failed\n");
313 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE);
314 ok(bRet == FALSE, "(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
315 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
316 ok(bRet == TRUE || broken(!bRet) /* Win9x */, "(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
317 pvRight.Value.lpszA = szFullLower;
318 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING|FL_IGNORECASE);
319 ok(bRet == TRUE || broken(!bRet) /* Win9x */, "(full,fulllow)[IGNORECASE] match failed\n");
321 pvLeft.ulPropTag = pvRight.ulPropTag = PT_BINARY;
322 pvLeft.Value.bin.lpb = (LPBYTE)szFull;
323 pvRight.Value.bin.lpb = (LPBYTE)szFull;
324 pvLeft.Value.bin.cb = pvRight.Value.bin.cb = strlen(szFull);
326 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
327 ok(bRet == TRUE || broken(!bRet) /* Win9x */, "bin(full,full)[] match failed\n");
328 pvRight.Value.bin.lpb = (LPBYTE)szPrefix;
329 pvRight.Value.bin.cb = strlen(szPrefix);
330 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
331 ok(bRet == FALSE, "bin(full,prefix)[] match failed\n");
332 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
333 ok(bRet == TRUE || broken(!bRet) /* Win9x */, "bin(full,prefix)[PREFIX] match failed\n");
334 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
335 ok(bRet == TRUE || broken(!bRet) /* Win9x */, "bin(full,prefix)[SUBSTRING] match failed\n");
336 pvRight.Value.bin.lpb = (LPBYTE)szPrefixLower;
337 pvRight.Value.bin.cb = strlen(szPrefixLower);
338 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
339 ok(bRet == FALSE, "bin(full,prefixlow)[PREFIX] match failed\n");
340 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
341 ok(bRet == FALSE, "bin(full,prefixlow)[SUBSTRING] match failed\n");
342 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE);
343 ok(bRet == FALSE, "bin(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
344 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
345 ok(bRet == FALSE, "bin(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
346 pvRight.Value.bin.lpb = (LPBYTE)szSubstring;
347 pvRight.Value.bin.cb = strlen(szSubstring);
348 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
349 ok(bRet == FALSE, "bin(full,substr)[] match failed\n");
350 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
351 ok(bRet == FALSE, "bin(full,substr)[PREFIX] match failed\n");
352 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
353 ok(bRet == TRUE || broken(!bRet) /* Win9x */, "bin(full,substr)[SUBSTRING] match failed\n");
354 pvRight.Value.bin.lpb = (LPBYTE)szSubstringLower;
355 pvRight.Value.bin.cb = strlen(szSubstringLower);
356 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
357 ok(bRet == FALSE, "bin(full,substrlow)[PREFIX] match failed\n");
358 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
359 ok(bRet == FALSE, "bin(full,substrlow)[SUBSTRING] match failed\n");
360 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE);
361 ok(bRet == FALSE, "bin(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
362 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
363 ok(bRet == FALSE, "bin(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
364 pvRight.Value.bin.lpb = (LPBYTE)szFullLower;
365 pvRight.Value.bin.cb = strlen(szFullLower);
366 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING|FL_IGNORECASE);
367 ok(bRet == FALSE, "bin(full,fulllow)[IGNORECASE] match failed\n");
370 typedef struct tagFPropCompareProp_Result
376 } FPropCompareProp_Result;
378 static const FPropCompareProp_Result FPCProp_Results[] =
380 { 1, 2, RELOP_LT, TRUE },
381 { 1, 1, RELOP_LT, FALSE },
382 { 2, 1, RELOP_LT, FALSE },
383 { 1, 2, RELOP_LE, TRUE },
384 { 1, 1, RELOP_LE, TRUE },
385 { 2, 1, RELOP_LE, FALSE },
386 { 1, 2, RELOP_GT, FALSE },
387 { 1, 1, RELOP_GT, FALSE },
388 { 2, 1, RELOP_GT, TRUE },
389 { 1, 2, RELOP_GE, FALSE },
390 { 1, 1, RELOP_GE, TRUE },
391 { 2, 1, RELOP_GE, TRUE },
392 { 1, 2, RELOP_EQ, FALSE },
393 { 1, 1, RELOP_EQ, TRUE },
394 { 2, 1, RELOP_EQ, FALSE }
397 static const char *relops[] = { "RELOP_LT", "RELOP_LE", "RELOP_GT", "RELOP_GE", "RELOP_EQ" };
399 static void test_FPropCompareProp(void)
401 SPropValue pvLeft, pvRight;
403 char lbuffa[2], rbuffa[2];
404 WCHAR lbuffw[2], rbuffw[2];
408 pFPropCompareProp = (void*)GetProcAddress(hMapi32, "FPropCompareProp@12");
410 if (!pFPropCompareProp)
418 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
420 pvLeft.ulPropTag = pvRight.ulPropTag = ptTypes[i];
422 for (j = 0; j < sizeof(FPCProp_Results)/sizeof(FPCProp_Results[0]); j++)
424 SHORT lVal = FPCProp_Results[j].lVal;
425 SHORT rVal = FPCProp_Results[j].rVal;
427 bExp = FPCProp_Results[j].bRet;
432 /* Boolean values have no concept of less or greater than, only equality */
433 if ((lVal == 1 && rVal == 2 && FPCProp_Results[j].relOp == RELOP_LT) ||
434 (lVal == 2 && rVal == 1 && FPCProp_Results[j].relOp == RELOP_LE)||
435 (lVal == 2 && rVal == 1 && FPCProp_Results[j].relOp == RELOP_GT)||
436 (lVal == 1 && rVal == 2 && FPCProp_Results[j].relOp == RELOP_GE)||
437 (lVal == 1 && rVal == 2 && FPCProp_Results[j].relOp == RELOP_EQ)||
438 (lVal == 2 && rVal == 1 && FPCProp_Results[j].relOp == RELOP_EQ))
440 /* Fall through ... */
442 pvLeft.Value.i = lVal;
443 pvRight.Value.i = rVal;
447 pvLeft.Value.l = lVal;
448 pvRight.Value.l = rVal;
451 pvLeft.Value.flt = lVal;
452 pvRight.Value.flt = rVal;
456 pvLeft.Value.dbl = lVal;
457 pvRight.Value.dbl = rVal;
460 pvLeft.Value.cur.int64 = lVal;
461 pvRight.Value.cur.int64 = rVal;
464 pvLeft.Value.ft.dwLowDateTime = lVal;
465 pvLeft.Value.ft.dwHighDateTime = 0;
466 pvRight.Value.ft.dwLowDateTime = rVal;
467 pvRight.Value.ft.dwHighDateTime = 0;
470 pvLeft.Value.li.u.LowPart = lVal;
471 pvLeft.Value.li.u.HighPart = 0;
472 pvRight.Value.li.u.LowPart = rVal;
473 pvRight.Value.li.u.HighPart = 0;
476 memset(&lguid, 0, sizeof(GUID));
477 memset(&rguid, 0, sizeof(GUID));
478 lguid.Data4[7] = lVal;
479 rguid.Data4[7] = rVal;
480 pvLeft.Value.lpguid = &lguid;
481 pvRight.Value.lpguid = &rguid;
484 pvLeft.Value.lpszA = lbuffa;
485 pvRight.Value.lpszA = rbuffa;
486 lbuffa[0] = '0' + lVal;
487 rbuffa[0] = '0' + rVal;
490 pvLeft.Value.lpszW = lbuffw;
491 pvRight.Value.lpszW = rbuffw;
492 lbuffw[0] = '0' + lVal;
493 rbuffw[0] = '0' + rVal;
496 pvLeft.Value.bin.cb = 1;
497 pvRight.Value.bin.cb = 1;
498 pvLeft.Value.bin.lpb = (LPBYTE)lbuffa;
499 pvRight.Value.bin.lpb = (LPBYTE)rbuffa;
505 bRet = pFPropCompareProp(&pvLeft, FPCProp_Results[j].relOp, &pvRight);
506 ok(bRet == bExp || broken(!bRet) /* Win9x */,
507 "pt %d (%d,%d,%s): expected %d, got %d\n", ptTypes[i],
508 FPCProp_Results[j].lVal, FPCProp_Results[j].rVal,
509 relops[FPCProp_Results[j].relOp], bExp, bRet);
514 typedef struct tagLPropCompareProp_Result
519 } LPropCompareProp_Result;
521 static const LPropCompareProp_Result LPCProp_Results[] =
528 static void test_LPropCompareProp(void)
530 SPropValue pvLeft, pvRight;
532 char lbuffa[2], rbuffa[2];
533 WCHAR lbuffw[2], rbuffw[2];
537 pLPropCompareProp = (void*)GetProcAddress(hMapi32, "LPropCompareProp@8");
539 if (!pLPropCompareProp)
547 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
549 pvLeft.ulPropTag = pvRight.ulPropTag = ptTypes[i];
551 for (j = 0; j < sizeof(LPCProp_Results)/sizeof(LPCProp_Results[0]); j++)
553 SHORT lVal = LPCProp_Results[j].lVal;
554 SHORT rVal = LPCProp_Results[j].rVal;
556 iExp = LPCProp_Results[j].iRet;
561 /* Boolean values have no concept of less or greater than, only equality */
564 /* Fall through ... */
566 pvLeft.Value.i = lVal;
567 pvRight.Value.i = rVal;
571 pvLeft.Value.l = lVal;
572 pvRight.Value.l = rVal;
575 pvLeft.Value.flt = lVal;
576 pvRight.Value.flt = rVal;
580 pvLeft.Value.dbl = lVal;
581 pvRight.Value.dbl = rVal;
584 pvLeft.Value.cur.int64 = lVal;
585 pvRight.Value.cur.int64 = rVal;
588 pvLeft.Value.ft.dwLowDateTime = lVal;
589 pvLeft.Value.ft.dwHighDateTime = 0;
590 pvRight.Value.ft.dwLowDateTime = rVal;
591 pvRight.Value.ft.dwHighDateTime = 0;
594 pvLeft.Value.li.u.LowPart = lVal;
595 pvLeft.Value.li.u.HighPart = 0;
596 pvRight.Value.li.u.LowPart = rVal;
597 pvRight.Value.li.u.HighPart = 0;
600 memset(&lguid, 0, sizeof(GUID));
601 memset(&rguid, 0, sizeof(GUID));
602 lguid.Data4[7] = lVal;
603 rguid.Data4[7] = rVal;
604 pvLeft.Value.lpguid = &lguid;
605 pvRight.Value.lpguid = &rguid;
608 pvLeft.Value.lpszA = lbuffa;
609 pvRight.Value.lpszA = rbuffa;
610 lbuffa[0] = '0' + lVal;
611 rbuffa[0] = '0' + rVal;
614 pvLeft.Value.lpszW = lbuffw;
615 pvRight.Value.lpszW = rbuffw;
616 lbuffw[0] = '0' + lVal;
617 rbuffw[0] = '0' + rVal;
620 pvLeft.Value.bin.cb = 1;
621 pvRight.Value.bin.cb = 1;
622 pvLeft.Value.bin.lpb = (LPBYTE)lbuffa;
623 pvRight.Value.bin.lpb = (LPBYTE)rbuffa;
629 iRet = pLPropCompareProp(&pvLeft, &pvRight);
630 ok(iRet == iExp || broken(iRet == 0) /* Win9x */,
631 "pt %d (%d,%d): expected %d, got %d\n", ptTypes[i],
632 LPCProp_Results[j].lVal, LPCProp_Results[j].rVal, iExp, iRet);
637 static void test_PpropFindProp(void)
639 SPropValue pvProp, *pRet;
642 pPpropFindProp = (void*)GetProcAddress(hMapi32, "PpropFindProp@12");
647 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
649 pvProp.ulPropTag = ptTypes[i];
651 pRet = pPpropFindProp(&pvProp, 1u, ptTypes[i]);
652 ok(pRet == &pvProp || broken(pRet != &pvProp) /* Win9x */,
653 "PpropFindProp[%d]: Didn't find existing propery\n",
656 pRet = pPpropFindProp(&pvProp, 1u, i ? ptTypes[i-1] : ptTypes[i+1]);
657 ok(pRet == NULL, "PpropFindProp[%d]: Found nonexistent propery\n",
661 pvProp.ulPropTag = PROP_TAG(PT_I2, 1u);
662 pRet = pPpropFindProp(&pvProp, 1u, PROP_TAG(PT_UNSPECIFIED, 0u));
663 ok(pRet == NULL, "PpropFindProp[UNSPECIFIED]: Matched on different id\n");
664 pRet = pPpropFindProp(&pvProp, 1u, PROP_TAG(PT_UNSPECIFIED, 1u));
665 ok(pRet == &pvProp, "PpropFindProp[UNSPECIFIED]: Didn't match id\n");
668 static void test_ScCountProps(void)
670 static char szHiA[] = "Hi!";
671 static WCHAR szHiW[] = { 'H', 'i', '!', '\0' };
672 static const ULONG ULHILEN = 4; /* chars in szHiA/W incl. NUL */
676 GUID iids[4], *iid = iids;
678 ULONG pt, exp, ulRet;
681 pScCountProps = (void*)GetProcAddress(hMapi32, "ScCountProps@12");
686 for (pt = 0; pt < PROP_ID_INVALID && success; pt++)
690 memset(&pv, 0 ,sizeof(pv));
691 pv.ulPropTag = PROP_TAG(pt, 1u);
693 switch (PROP_TYPE(pt))
709 pv.Value.lpguid = iid;
710 exp = sizeof(GUID) + sizeof(pv);
713 pv.Value.lpszA = szHiA;
714 exp = 4 + sizeof(pv);
717 pv.Value.lpszW = szHiW;
718 exp = 4 * sizeof(WCHAR) + sizeof(pv);
722 pv.Value.bin.lpb = (LPBYTE)iid;
723 exp = 2 + sizeof(pv);
726 pv.Value.MVi.cValues = 3;
727 pv.Value.MVi.lpi = (SHORT*)iid;
728 exp = 3 * sizeof(SHORT) + sizeof(pv);
731 pv.Value.MVl.cValues = 3;
732 pv.Value.MVl.lpl = (LONG*)iid;
733 exp = 3 * sizeof(LONG) + sizeof(pv);
736 pv.Value.MVli.cValues = 3;
737 pv.Value.MVli.lpli = (LARGE_INTEGER*)iid;
738 exp = 3 * sizeof(LARGE_INTEGER) + sizeof(pv);
741 pv.Value.MVflt.cValues = 3;
742 pv.Value.MVflt.lpflt = (float*)iid;
743 exp = 3 * sizeof(float) + sizeof(pv);
747 pv.Value.MVdbl.cValues = 3;
748 pv.Value.MVdbl.lpdbl = (double*)iid;
749 exp = 3 * sizeof(double) + sizeof(pv);
752 pv.Value.MVcur.cValues = 3;
753 pv.Value.MVcur.lpcur = (CY*)iid;
754 exp = 3 * sizeof(CY) + sizeof(pv);
757 pv.Value.MVft.cValues = 3;
758 pv.Value.MVft.lpft = (FILETIME*)iid;
759 exp = 3 * sizeof(CY) + sizeof(pv);
762 pv.Value.MVszA.cValues = 3;
763 pv.Value.MVszA.lppszA = buffa;
767 exp = ULHILEN * 3 + 3 * sizeof(char*) + sizeof(pv);
770 pv.Value.MVszW.cValues = 3;
771 pv.Value.MVszW.lppszW = buffw;
775 exp = ULHILEN * 3 * sizeof(WCHAR) + 3 * sizeof(WCHAR*) + sizeof(pv);
778 pv.Value.MVbin.cValues = 3;
779 pv.Value.MVbin.lpbin = buffbin;
781 buffbin[0].lpb = (LPBYTE)&iid;
783 buffbin[1].lpb = (LPBYTE)&iid;
785 buffbin[2].lpb = (LPBYTE)&iid;
786 exp = 20 + sizeof(pv) + sizeof(SBinary) * 3;
793 res = pScCountProps(1, &pv, &ulRet);
795 success = res == MAPI_E_INVALID_PARAMETER && ulRet == 0xffffffff;
796 ok(success, "pt= %d: Expected failure, got %d, ret=0x%08X\n",
800 success = res == S_OK && ulRet == exp;
801 ok(success, "pt= %d: Expected %d, got %d, ret=0x%08X\n",
802 pt, exp, ulRet, res);
808 static void test_ScCopyRelocProps(void)
810 static char szTestA[] = "Test";
811 char buffer[512], buffer2[512], *lppszA[1];
812 SPropValue pvProp, *lpResProp = (LPSPropValue)buffer;
816 pScCopyProps = (void*)GetProcAddress(hMapi32, "ScCopyProps@16");
817 pScRelocProps = (void*)GetProcAddress(hMapi32, "ScRelocProps@20");
819 if (!pScCopyProps || !pScRelocProps)
822 pvProp.ulPropTag = PROP_TAG(PT_MV_STRING8, 1u);
825 pvProp.Value.MVszA.cValues = 1;
826 pvProp.Value.MVszA.lppszA = lppszA;
829 sc = pScCopyProps(1, &pvProp, buffer, &ulCount);
830 ok(sc == S_OK, "wrong ret %d\n", sc);
833 ok(lpResProp->ulPropTag == pvProp.ulPropTag, "wrong tag %x\n",lpResProp->ulPropTag);
834 ok(lpResProp->Value.MVszA.cValues == 1, "wrong cValues %d\n", lpResProp->Value.MVszA.cValues);
835 ok(lpResProp->Value.MVszA.lppszA[0] == buffer + sizeof(SPropValue) + sizeof(char*),
836 "wrong lppszA[0] %p\n",lpResProp->Value.MVszA.lppszA[0]);
837 ok(ulCount == sizeof(SPropValue) + sizeof(char*) + 5, "wrong count %d\n", ulCount);
838 ok(!strcmp(lpResProp->Value.MVszA.lppszA[0], szTestA),
839 "wrong string '%s'\n", lpResProp->Value.MVszA.lppszA[0]);
842 memcpy(buffer2, buffer, sizeof(buffer));
844 /* Clear the data in the source buffer. Since pointers in the copied buffer
845 * refer to the source buffer, this proves that native always assumes that
846 * the copied buffers pointers are bad (needing to be relocated first).
848 memset(buffer, 0, sizeof(buffer));
851 sc = pScRelocProps(1, (LPSPropValue)buffer2, buffer, buffer2, &ulCount);
852 lpResProp = (LPSPropValue)buffer2;
854 ok(sc == S_OK, "wrong ret %d\n", sc);
857 ok(lpResProp->ulPropTag == pvProp.ulPropTag, "wrong tag %x\n",lpResProp->ulPropTag);
858 ok(lpResProp->Value.MVszA.cValues == 1, "wrong cValues %d\n", lpResProp->Value.MVszA.cValues);
859 ok(lpResProp->Value.MVszA.lppszA[0] == buffer2 + sizeof(SPropValue) + sizeof(char*),
860 "wrong lppszA[0] %p\n",lpResProp->Value.MVszA.lppszA[0]);
861 /* Native has a bug whereby it calculates the size correctly when copying
862 * but when relocating does not (presumably it uses UlPropSize() which
863 * ignores multivalue pointers). Wine returns the correct value.
865 ok(ulCount == sizeof(SPropValue) + sizeof(char*) + 5 || ulCount == sizeof(SPropValue) + 5,
866 "wrong count %d\n", ulCount);
867 ok(!strcmp(lpResProp->Value.MVszA.lppszA[0], szTestA),
868 "wrong string '%s'\n", lpResProp->Value.MVszA.lppszA[0]);
871 /* Native crashes with lpNew or lpOld set to NULL so skip testing this */
874 static void test_LpValFindProp(void)
876 SPropValue pvProp, *pRet;
879 pLpValFindProp = (void*)GetProcAddress(hMapi32, "LpValFindProp@12");
884 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
886 pvProp.ulPropTag = PROP_TAG(ptTypes[i], 1u);
888 pRet = pLpValFindProp(PROP_TAG(ptTypes[i], 1u), 1u, &pvProp);
889 ok(pRet == &pvProp || broken(pRet != &pvProp) /* Win9x */,
890 "LpValFindProp[%d]: Didn't find existing propery id/type\n",
893 pRet = pLpValFindProp(PROP_TAG(ptTypes[i], 0u), 1u, &pvProp);
894 ok(pRet == NULL, "LpValFindProp[%d]: Found nonexistent propery id\n",
897 pRet = pLpValFindProp(PROP_TAG(PT_NULL, 0u), 1u, &pvProp);
898 ok(pRet == NULL, "LpValFindProp[%d]: Found nonexistent propery id/type\n",
901 pRet = pLpValFindProp(PROP_TAG(PT_NULL, 1u), 1u, &pvProp);
902 ok(pRet == &pvProp || broken(pRet != &pvProp) /* Win9x */,
903 "LpValFindProp[%d]: Didn't find existing propery id\n",
908 static void test_FBadRglpszA(void)
911 static CHAR szString[] = "A String";
914 pFBadRglpszA = (void*)GetProcAddress(hMapi32, "FBadRglpszA@8");
918 bRet = pFBadRglpszA(NULL, 10);
919 ok(bRet == TRUE, "FBadRglpszA(Null): expected TRUE, got FALSE\n");
921 lpStrs[0] = lpStrs[1] = lpStrs[2] = lpStrs[3] = NULL;
922 bRet = pFBadRglpszA(lpStrs, 4);
923 ok(bRet == TRUE, "FBadRglpszA(Nulls): expected TRUE, got FALSE\n");
925 lpStrs[0] = lpStrs[1] = lpStrs[2] = szString;
926 bRet = pFBadRglpszA(lpStrs, 3);
927 ok(bRet == FALSE, "FBadRglpszA(valid): expected FALSE, got TRUE\n");
929 bRet = pFBadRglpszA(lpStrs, 4);
930 ok(bRet == TRUE, "FBadRglpszA(1 invalid): expected TRUE, got FALSE\n");
933 static void test_FBadRglpszW(void)
936 static WCHAR szString[] = { 'A',' ','S','t','r','i','n','g','\0' };
939 pFBadRglpszW = (void*)GetProcAddress(hMapi32, "FBadRglpszW@8");
943 bRet = pFBadRglpszW(NULL, 10);
944 ok(bRet == TRUE, "FBadRglpszW(Null): expected TRUE, got FALSE\n");
946 lpStrs[0] = lpStrs[1] = lpStrs[2] = lpStrs[3] = NULL;
947 bRet = pFBadRglpszW(lpStrs, 4);
948 ok(bRet == TRUE, "FBadRglpszW(Nulls): expected TRUE, got FALSE\n");
950 lpStrs[0] = lpStrs[1] = lpStrs[2] = szString;
951 bRet = pFBadRglpszW(lpStrs, 3);
952 ok(bRet == FALSE, "FBadRglpszW(valid): expected FALSE, got TRUE\n");
954 bRet = pFBadRglpszW(lpStrs, 4);
955 ok(bRet == TRUE, "FBadRglpszW(1 invalid): expected TRUE, got FALSE\n");
958 static void test_FBadRowSet(void)
962 pFBadRowSet = (void*)GetProcAddress(hMapi32, "FBadRowSet@4");
966 ulRet = pFBadRowSet(NULL);
967 ok(ulRet != 0, "FBadRow(null): Expected non-zero, got 0\n");
972 static void test_FBadPropTag(void)
976 pFBadPropTag = (void*)GetProcAddress(hMapi32, "FBadPropTag@4");
980 for (pt = 0; pt < PROP_ID_INVALID; pt++)
984 switch (pt & (~MV_FLAG & PROP_TYPE_MASK))
987 case PT_NULL: case PT_I2: case PT_I4: case PT_R4:
988 case PT_R8: case PT_CURRENCY: case PT_APPTIME:
989 case PT_ERROR: case PT_BOOLEAN: case PT_OBJECT:
990 case PT_I8: case PT_STRING8: case PT_UNICODE:
991 case PT_SYSTIME: case PT_CLSID: case PT_BINARY:
995 res = pFBadPropTag(pt);
997 ok(res != 0, "pt= %d: Expected non-zero, got 0\n", pt);
999 ok(res == 0 || broken(res) /* Win9x */,
1000 "pt= %d: Expected zero, got %d\n", pt, res);
1004 static void test_FBadRow(void)
1008 pFBadRow = (void*)GetProcAddress(hMapi32, "FBadRow@4");
1012 ulRet = pFBadRow(NULL);
1013 ok(ulRet != 0, "FBadRow(null): Expected non-zero, got 0\n");
1018 static void test_FBadProp(void)
1020 static WCHAR szEmpty[] = { '\0' };
1025 pFBadProp = (void*)GetProcAddress(hMapi32, "FBadProp@4");
1029 for (pt = 0; pt < PROP_ID_INVALID; pt++)
1033 memset(&pv, 0, sizeof(pv));
1036 /* Note that MV values are valid below because their array count is 0,
1037 * so no pointers are validated.
1039 switch (PROP_TYPE(pt))
1041 case (MV_FLAG|PT_UNSPECIFIED):
1042 case PT_UNSPECIFIED:
1043 case (MV_FLAG|PT_NULL):
1055 case PT_MV_CURRENCY:
1059 case (MV_FLAG|PT_ERROR):
1061 case (MV_FLAG|PT_BOOLEAN):
1063 case (MV_FLAG|PT_OBJECT):
1076 pv.Value.lpszW = szEmpty;
1080 pv.Value.lpguid = &iid;
1085 res = pFBadProp(&pv);
1087 ok(res != 0, "pt= %d: Expected non-zero, got 0\n", pt);
1089 ok(res == 0 || broken(res) /* Win9x */,
1090 "pt= %d: Expected zero, got %d\n", pt, res);
1094 static void test_FBadColumnSet(void)
1099 pFBadColumnSet = (void*)GetProcAddress(hMapi32, "FBadColumnSet@4");
1100 if (!pFBadColumnSet)
1103 res = pFBadColumnSet(NULL);
1104 ok(res != 0, "(null): Expected non-zero, got 0\n");
1108 for (pt = 0; pt < PROP_ID_INVALID; pt++)
1112 pta.aulPropTag[0] = pt;
1114 switch (pt & (~MV_FLAG & PROP_TYPE_MASK))
1116 case PT_UNSPECIFIED:
1134 if (pt == (MV_FLAG|PT_ERROR))
1137 res = pFBadColumnSet(&pta);
1139 ok(res != 0, "pt= %d: Expected non-zero, got 0\n", pt);
1141 ok(res == 0 || broken(res) /* Win9x */,
1142 "pt= %d: Expected zero, got %d\n", pt, res);
1147 static void test_IProp(void)
1150 LPMAPIERROR lpError;
1151 LPSPropProblemArray lpProbs;
1152 LPSPropValue lpProps;
1153 LPSPropTagArray lpTags;
1155 SizedSPropTagArray(2,tags);
1156 ULONG access[2], count;
1159 pCreateIProp = (void*)GetProcAddress(hMapi32, "CreateIProp@24");
1164 memset(&tags, 0 , sizeof(tags));
1166 /* Create the object */
1168 sc = pCreateIProp(&IID_IMAPIPropData, (ALLOCATEBUFFER *)pMAPIAllocateBuffer, (ALLOCATEMORE*)pMAPIAllocateMore,
1169 (FREEBUFFER *)pMAPIFreeBuffer, NULL, &lpIProp);
1170 ok(sc == S_OK && lpIProp,
1171 "CreateIProp: expected S_OK, non-null, got 0x%08X,%p\n", sc, lpIProp);
1173 if (sc != S_OK || !lpIProp)
1176 /* GetLastError - No errors set */
1178 IPropData_GetLastError(lpIProp, E_INVALIDARG, 0, &lpError);
1179 ok(sc == S_OK && !lpError,
1180 "GetLastError: Expected S_OK, null, got 0x%08X,%p\n", sc, lpError);
1182 /* Get prop tags - succeeds returning 0 items */
1184 sc = IPropData_GetPropList(lpIProp, 0, &lpTags);
1185 ok(sc == S_OK && lpTags && lpTags->cValues == 0,
1186 "GetPropList(empty): Expected S_OK, non-null, 0, got 0x%08X,%p,%d\n",
1187 sc, lpTags, lpTags ? lpTags->cValues : 0);
1189 pMAPIFreeBuffer(lpTags);
1191 /* Get props - succeeds returning 0 items */
1195 tags.aulPropTag[0] = PR_IMPORTANCE;
1196 sc = IPropData_GetProps(lpIProp, (LPSPropTagArray)&tags, 0, &count, &lpProps);
1197 ok(sc == MAPI_W_ERRORS_RETURNED && lpProps && count == 1,
1198 "GetProps(empty): Expected ERRORS_RETURNED, non-null, 1, got 0x%08X,%p,%d\n",
1199 sc, lpProps, count);
1200 if (lpProps && count > 0)
1202 ok(lpProps[0].ulPropTag == CHANGE_PROP_TYPE(PR_IMPORTANCE,PT_ERROR),
1203 "GetProps(empty): Expected %x, got %x\n",
1204 CHANGE_PROP_TYPE(PR_IMPORTANCE,PT_ERROR), lpProps[0].ulPropTag);
1206 pMAPIFreeBuffer(lpProps);
1209 /* Add (NULL) - Can't add NULLs */
1211 pvs[0].ulPropTag = PROP_TAG(PT_NULL,0x01);
1212 sc = IPropData_SetProps(lpIProp, 1, pvs, &lpProbs);
1213 ok(sc == MAPI_E_INVALID_PARAMETER && !lpProbs,
1214 "SetProps(): Expected INVALID_PARAMETER, null, got 0x%08X,%p\n",
1217 /* Add (OBJECT) - Can't add OBJECTs */
1219 pvs[0].ulPropTag = PROP_TAG(PT_OBJECT,0x01);
1220 sc = IPropData_SetProps(lpIProp, 1, pvs, &lpProbs);
1221 ok(sc == MAPI_E_INVALID_PARAMETER && !lpProbs,
1222 "SetProps(OBJECT): Expected INVALID_PARAMETER, null, got 0x%08X,%p\n",
1225 /* Add - Adds value */
1227 pvs[0].ulPropTag = PR_IMPORTANCE;
1228 sc = IPropData_SetProps(lpIProp, 1, pvs, &lpProbs);
1229 ok(sc == S_OK && !lpProbs,
1230 "SetProps(ERROR): Expected S_OK, null, got 0x%08X,%p\n", sc, lpProbs);
1232 /* Get prop list - returns 1 item */
1234 IPropData_GetPropList(lpIProp, 0, &lpTags);
1235 ok(sc == S_OK && lpTags && lpTags->cValues == 1,
1236 "GetPropList: Expected S_OK, non-null, 1, got 0x%08X,%p,%d\n",
1237 sc, lpTags, lpTags ? lpTags->cValues : 0);
1238 if (lpTags && lpTags->cValues > 0)
1240 ok(lpTags->aulPropTag[0] == PR_IMPORTANCE,
1241 "GetPropList: Expected %x, got %x\n",
1242 PR_IMPORTANCE, lpTags->aulPropTag[0]);
1243 pMAPIFreeBuffer(lpTags);
1246 /* Set access to read and write */
1247 sc = IPropData_HrSetObjAccess(lpIProp, IPROP_READWRITE);
1248 ok(sc == S_OK, "SetObjAcess(WRITE): Expected S_OK got 0x%08X\n", sc);
1251 tags.aulPropTag[0] = PR_IMPORTANCE;
1253 /* Set item access (bad access) - Fails */
1255 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1256 ok(sc == MAPI_E_INVALID_PARAMETER,
1257 "SetPropAcess(0): Expected INVALID_PARAMETER got 0x%08X\n",sc);
1258 access[0] = IPROP_READWRITE;
1259 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1260 ok(sc == MAPI_E_INVALID_PARAMETER,
1261 "SetPropAcess(RW): Expected INVALID_PARAMETER got 0x%08X\n",sc);
1262 access[0] = IPROP_CLEAN;
1263 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1264 ok(sc == MAPI_E_INVALID_PARAMETER,
1265 "SetPropAcess(C): Expected INVALID_PARAMETER got 0x%08X\n",sc);
1267 /* Set item access to read/write/clean */
1269 tags.aulPropTag[0] = PR_IMPORTANCE;
1270 access[0] = IPROP_READWRITE|IPROP_CLEAN;
1271 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1272 ok(sc == S_OK, "SetPropAcess(RW/C): Expected S_OK got 0x%08X\n",sc);
1274 /* Set object access to read only */
1275 sc = IPropData_HrSetObjAccess(lpIProp, IPROP_READONLY);
1276 ok(sc == S_OK, "SetObjAcess(READ): Expected S_OK got 0x%08X\n", sc);
1278 /* Set item access to read/write/dirty - doesn't care about RO object */
1279 access[0] = IPROP_READONLY|IPROP_DIRTY;
1280 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1281 ok(sc == S_OK, "SetPropAcess(WRITE): Expected S_OK got 0x%08X\n", sc);
1283 /* Delete any item when set to read only - Error */
1285 tags.aulPropTag[0] = PR_RESPONSE_REQUESTED;
1286 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1287 ok(sc == E_ACCESSDENIED && !lpProbs,
1288 "DeleteProps(nonexistent): Expected E_ACCESSDENIED null got 0x%08X %p\n",
1291 /* Set access to read and write */
1292 sc = IPropData_HrSetObjAccess(lpIProp, IPROP_READWRITE);
1293 ok(sc == S_OK, "SetObjAcess(WRITE): Expected S_OK got 0x%08X\n", sc);
1295 /* Delete nonexistent item - No error */
1297 tags.aulPropTag[0] = PR_RESPONSE_REQUESTED;
1298 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1299 ok(sc == S_OK && !lpProbs,
1300 "DeleteProps(nonexistent): Expected S_OK null got 0x%08X %p\n",
1303 /* Delete existing item (r/o) - No error, but lpProbs populated */
1305 tags.aulPropTag[0] = PR_IMPORTANCE;
1306 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1307 ok(sc == S_OK && lpProbs,
1308 "DeleteProps(RO): Expected S_OK non-null got 0x%08X %p\n", sc, lpProbs);
1310 if (lpProbs && lpProbs->cProblem > 0)
1312 ok(lpProbs->cProblem == 1 &&
1313 lpProbs->aProblem[0].ulIndex == 0 &&
1314 lpProbs->aProblem[0].ulPropTag == PR_IMPORTANCE &&
1315 lpProbs->aProblem[0].scode == E_ACCESSDENIED,
1316 "DeleteProps(RO): Expected (1,0,%x,%x) got (%d,%x,%x)\n",
1317 PR_IMPORTANCE, E_ACCESSDENIED,
1318 lpProbs->aProblem[0].ulIndex, lpProbs->aProblem[0].ulPropTag,
1319 lpProbs->aProblem[0].scode);
1320 pMAPIFreeBuffer(lpProbs);
1325 tags.aulPropTag[0] = PR_RESPONSE_REQUESTED;
1326 IPropData_HrAddObjProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1327 ok(sc == S_OK && !lpProbs,
1328 "AddObjProps(RO): Expected S_OK null got 0x%08X %p\n", sc, lpProbs);
1330 /* Get prop list - returns 1 item */
1332 IPropData_GetPropList(lpIProp, 0, &lpTags);
1333 ok(sc == S_OK && lpTags && lpTags->cValues == 1,
1334 "GetPropList: Expected S_OK, non-null, 1, got 0x%08X,%p,%d\n",
1335 sc, lpTags, lpTags ? lpTags->cValues : 0);
1336 if (lpTags && lpTags->cValues > 0)
1338 ok(lpTags->aulPropTag[0] == PR_IMPORTANCE,
1339 "GetPropList: Expected %x, got %x\n",
1340 PR_IMPORTANCE, lpTags->aulPropTag[0]);
1341 pMAPIFreeBuffer(lpTags);
1344 /* Set item to r/w again */
1345 access[0] = IPROP_READWRITE|IPROP_DIRTY;
1346 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1347 ok(sc == S_OK, "SetPropAcess(WRITE): Expected S_OK got 0x%08X\n", sc);
1349 /* Delete existing item (r/w) - No error, no problems */
1351 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1352 ok(sc == S_OK && !lpProbs,
1353 "DeleteProps(RO): Expected S_OK null got 0x%08X %p\n", sc, lpProbs);
1356 IPropData_Release(lpIProp);
1365 win_skip("Needed functions are not available\n");
1369 SetLastError(0xdeadbeef);
1370 ret = pScInitMapiUtil(0);
1371 if ((ret != S_OK) && (GetLastError() == ERROR_PROC_NOT_FOUND))
1373 win_skip("ScInitMapiUtil is not implemented\n");
1374 FreeLibrary(hMapi32);
1378 test_PropCopyMore();
1380 test_FPropContainsProp();
1381 test_FPropCompareProp();
1382 test_LPropCompareProp();
1383 test_PpropFindProp();
1384 test_ScCountProps();
1385 test_ScCopyRelocProps();
1386 test_LpValFindProp();
1393 test_FBadColumnSet();
1396 FreeLibrary(hMapi32);