mapi32: Skip tests on error.
[wine/wine64.git] / dlls / mapi32 / tests / prop.c
bloba2b92891934d09917511bac0fdf8c573f743a824
1 /*
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"
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winuser.h"
25 #include "winerror.h"
26 #include "winnt.h"
27 #include "initguid.h"
28 #include "mapiutil.h"
29 #include "mapitags.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)
66 return TRUE;
67 else
68 return FALSE;
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,
74 PT_UNICODE
77 static inline int strcmpW(const WCHAR *str1, const WCHAR *str2)
79 while (*str1 && (*str1 == *str2)) { str1++; str2++; }
80 return *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;
88 ULONG i;
89 SCODE scode;
91 pPropCopyMore = (void*)GetProcAddress(hMapi32, "PropCopyMore@16");
93 if (!pPropCopyMore)
94 return;
96 scode = pMAPIAllocateBuffer(sizeof(LPSPropValue), (LPVOID *)lpDest);
97 if (FAILED(scode))
98 return;
100 scode = pMAPIAllocateMore(sizeof(LPSPropValue), lpDest, (LPVOID *)lpSrc);
101 if (FAILED(scode))
102 return;
104 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
106 lpSrc->ulPropTag = ptTypes[i];
108 switch (ptTypes[i])
110 case PT_STRING8:
111 lpSrc->Value.lpszA = szHiA;
112 break;
113 case PT_UNICODE:
114 lpSrc->Value.lpszW = szHiW;
115 break;
116 case PT_BINARY:
117 lpSrc->Value.bin.cb = 4;
118 lpSrc->Value.bin.lpb = (LPBYTE)szHiA;
119 break;
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))
130 switch (ptTypes[i])
132 case PT_STRING8:
133 ok(lstrcmpA(lpDest->Value.lpszA, lpSrc->Value.lpszA) == 0,
134 "PropCopyMore: Ascii string differs\n");
135 break;
136 case PT_UNICODE:
137 ok(strcmpW(lpDest->Value.lpszW, lpSrc->Value.lpszW) == 0,
138 "PropCopyMore: Unicode string differs\n");
139 break;
140 case PT_BINARY:
141 ok(lpDest->Value.bin.cb == 4 &&
142 !memcmp(lpSrc->Value.bin.lpb, lpDest->Value.bin.lpb, 4),
143 "PropCopyMore: Binary array differs\n");
144 break;
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' };
157 LPSTR buffa[2];
158 LPWSTR buffw[2];
159 SBinary buffbin[2];
160 ULONG pt, exp, res;
162 pUlPropSize = (void*)GetProcAddress(hMapi32, "UlPropSize@4");
164 if (!pUlPropSize)
165 return;
167 for (pt = 0; pt < PROP_ID_INVALID; pt++)
169 SPropValue pv;
171 memset(&pv, 0 ,sizeof(pv));
172 pv.ulPropTag = pt;
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;
197 #if 0
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;
203 #endif
204 case PT_CLSID: exp *= sizeof(GUID); break;
205 case PT_STRING8:
206 pv.Value.lpszA = szHiA;
207 exp = 4;
208 break;
209 case PT_UNICODE:
210 pv.Value.lpszW = szHiW;
211 exp = 4 * sizeof(WCHAR);
212 break;
213 case PT_BINARY:
214 pv.Value.bin.cb = exp = 19;
215 break;
216 case PT_MV_STRING8:
217 pv.Value.MVszA.cValues = 2;
218 pv.Value.MVszA.lppszA = buffa;
219 buffa[0] = szHiA;
220 buffa[1] = szHiA;
221 exp = 8;
222 break;
223 case PT_MV_UNICODE:
224 pv.Value.MVszW.cValues = 2;
225 pv.Value.MVszW.lppszW = buffw;
226 buffw[0] = szHiW;
227 buffw[1] = szHiW;
228 exp = 8 * sizeof(WCHAR);
229 break;
230 case PT_MV_BINARY:
231 pv.Value.MVbin.cValues = 2;
232 pv.Value.MVbin.lpbin = buffbin;
233 buffbin[0].cb = 19;
234 buffbin[1].cb = 1;
235 exp = 20;
236 break;
237 default:
238 exp = 0;
241 res = pUlPropSize(&pv);
242 ok(res == exp, "pt= %d: Expected %d, got %d\n", pt, exp, res);
246 static void test_FPropContainsProp(void)
248 static char szFull[] = "Full String";
249 static char szFullLower[] = "full string";
250 static char szPrefix[] = "Full";
251 static char szPrefixLower[] = "full";
252 static char szSubstring[] = "ll St";
253 static char szSubstringLower[] = "ll st";
254 SPropValue pvLeft, pvRight;
255 ULONG pt;
256 BOOL bRet;
258 pFPropContainsProp = (void*)GetProcAddress(hMapi32, "FPropContainsProp@12");
260 if (!pFPropContainsProp)
261 return;
263 /* Ensure that only PT_STRING8 and PT_BINARY are handled */
264 for (pt = 0; pt < PROP_ID_INVALID; pt++)
266 if (pt == PT_STRING8 || pt == PT_BINARY)
267 continue; /* test these later */
269 memset(&pvLeft, 0 ,sizeof(pvLeft));
270 memset(&pvRight, 0 ,sizeof(pvRight));
271 pvLeft.ulPropTag = pvRight.ulPropTag = pt;
273 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
274 ok(bRet == FALSE, "pt= %d: Expected FALSE, got %d\n", pt, bRet);
277 /* test the various flag combinations */
278 pvLeft.ulPropTag = pvRight.ulPropTag = PT_STRING8;
279 pvLeft.Value.lpszA = szFull;
280 pvRight.Value.lpszA = szFull;
282 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
283 ok(bRet == TRUE, "(full,full)[] match failed\n");
284 pvRight.Value.lpszA = szPrefix;
285 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
286 ok(bRet == FALSE, "(full,prefix)[] match failed\n");
287 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
288 ok(bRet == TRUE, "(full,prefix)[PREFIX] match failed\n");
289 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
290 ok(bRet == TRUE, "(full,prefix)[SUBSTRING] match failed\n");
291 pvRight.Value.lpszA = szPrefixLower;
292 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
293 ok(bRet == FALSE, "(full,prefixlow)[PREFIX] match failed\n");
294 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
295 ok(bRet == FALSE, "(full,prefixlow)[SUBSTRING] match failed\n");
296 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE);
297 ok(bRet == TRUE, "(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
298 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
299 ok(bRet == TRUE, "(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
300 pvRight.Value.lpszA = szSubstring;
301 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
302 ok(bRet == FALSE, "(full,substr)[] match failed\n");
303 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
304 ok(bRet == FALSE, "(full,substr)[PREFIX] match failed\n");
305 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
306 ok(bRet == TRUE, "(full,substr)[SUBSTRING] match failed\n");
307 pvRight.Value.lpszA = szSubstringLower;
308 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
309 ok(bRet == FALSE, "(full,substrlow)[PREFIX] match failed\n");
310 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
311 ok(bRet == FALSE, "(full,substrlow)[SUBSTRING] match failed\n");
312 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE);
313 ok(bRet == FALSE, "(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
314 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
315 ok(bRet == TRUE, "(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
316 pvRight.Value.lpszA = szFullLower;
317 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING|FL_IGNORECASE);
318 ok(bRet == TRUE, "(full,fulllow)[IGNORECASE] match failed\n");
320 pvLeft.ulPropTag = pvRight.ulPropTag = PT_BINARY;
321 pvLeft.Value.bin.lpb = (LPBYTE)szFull;
322 pvRight.Value.bin.lpb = (LPBYTE)szFull;
323 pvLeft.Value.bin.cb = pvRight.Value.bin.cb = strlen(szFull);
325 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
326 ok(bRet == TRUE, "bin(full,full)[] match failed\n");
327 pvRight.Value.bin.lpb = (LPBYTE)szPrefix;
328 pvRight.Value.bin.cb = strlen(szPrefix);
329 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
330 ok(bRet == FALSE, "bin(full,prefix)[] match failed\n");
331 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
332 ok(bRet == TRUE, "bin(full,prefix)[PREFIX] match failed\n");
333 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
334 ok(bRet == TRUE, "bin(full,prefix)[SUBSTRING] match failed\n");
335 pvRight.Value.bin.lpb = (LPBYTE)szPrefixLower;
336 pvRight.Value.bin.cb = strlen(szPrefixLower);
337 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
338 ok(bRet == FALSE, "bin(full,prefixlow)[PREFIX] match failed\n");
339 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
340 ok(bRet == FALSE, "bin(full,prefixlow)[SUBSTRING] match failed\n");
341 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE);
342 ok(bRet == FALSE, "bin(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
343 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
344 ok(bRet == FALSE, "bin(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
345 pvRight.Value.bin.lpb = (LPBYTE)szSubstring;
346 pvRight.Value.bin.cb = strlen(szSubstring);
347 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
348 ok(bRet == FALSE, "bin(full,substr)[] match failed\n");
349 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
350 ok(bRet == FALSE, "bin(full,substr)[PREFIX] match failed\n");
351 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
352 ok(bRet == TRUE, "bin(full,substr)[SUBSTRING] match failed\n");
353 pvRight.Value.bin.lpb = (LPBYTE)szSubstringLower;
354 pvRight.Value.bin.cb = strlen(szSubstringLower);
355 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
356 ok(bRet == FALSE, "bin(full,substrlow)[PREFIX] match failed\n");
357 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
358 ok(bRet == FALSE, "bin(full,substrlow)[SUBSTRING] match failed\n");
359 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE);
360 ok(bRet == FALSE, "bin(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
361 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
362 ok(bRet == FALSE, "bin(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
363 pvRight.Value.bin.lpb = (LPBYTE)szFullLower;
364 pvRight.Value.bin.cb = strlen(szFullLower);
365 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING|FL_IGNORECASE);
366 ok(bRet == FALSE, "bin(full,fulllow)[IGNORECASE] match failed\n");
369 typedef struct tagFPropCompareProp_Result
371 SHORT lVal;
372 SHORT rVal;
373 ULONG relOp;
374 BOOL bRet;
375 } FPropCompareProp_Result;
377 static const FPropCompareProp_Result FPCProp_Results[] =
379 { 1, 2, RELOP_LT, TRUE },
380 { 1, 1, RELOP_LT, FALSE },
381 { 2, 1, RELOP_LT, FALSE },
382 { 1, 2, RELOP_LE, TRUE },
383 { 1, 1, RELOP_LE, TRUE },
384 { 2, 1, RELOP_LE, FALSE },
385 { 1, 2, RELOP_GT, FALSE },
386 { 1, 1, RELOP_GT, FALSE },
387 { 2, 1, RELOP_GT, TRUE },
388 { 1, 2, RELOP_GE, FALSE },
389 { 1, 1, RELOP_GE, TRUE },
390 { 2, 1, RELOP_GE, TRUE },
391 { 1, 2, RELOP_EQ, FALSE },
392 { 1, 1, RELOP_EQ, TRUE },
393 { 2, 1, RELOP_EQ, FALSE }
396 static const char *relops[] = { "RELOP_LT", "RELOP_LE", "RELOP_GT", "RELOP_GE", "RELOP_EQ" };
398 static void test_FPropCompareProp(void)
400 SPropValue pvLeft, pvRight;
401 GUID lguid, rguid;
402 char lbuffa[2], rbuffa[2];
403 WCHAR lbuffw[2], rbuffw[2];
404 ULONG i, j;
405 BOOL bRet, bExp;
407 pFPropCompareProp = (void*)GetProcAddress(hMapi32, "FPropCompareProp@12");
409 if (!pFPropCompareProp)
410 return;
412 lbuffa[1] = '\0';
413 rbuffa[1] = '\0';
414 lbuffw[1] = '\0';
415 rbuffw[1] = '\0';
417 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
419 pvLeft.ulPropTag = pvRight.ulPropTag = ptTypes[i];
421 for (j = 0; j < sizeof(FPCProp_Results)/sizeof(FPCProp_Results[0]); j++)
423 SHORT lVal = FPCProp_Results[j].lVal;
424 SHORT rVal = FPCProp_Results[j].rVal;
426 bExp = FPCProp_Results[j].bRet;
428 switch (ptTypes[i])
430 case PT_BOOLEAN:
431 /* Boolean values have no concept of less or greater than, only equality */
432 if ((lVal == 1 && rVal == 2 && FPCProp_Results[j].relOp == RELOP_LT) ||
433 (lVal == 2 && rVal == 1 && FPCProp_Results[j].relOp == RELOP_LE)||
434 (lVal == 2 && rVal == 1 && FPCProp_Results[j].relOp == RELOP_GT)||
435 (lVal == 1 && rVal == 2 && FPCProp_Results[j].relOp == RELOP_GE)||
436 (lVal == 1 && rVal == 2 && FPCProp_Results[j].relOp == RELOP_EQ)||
437 (lVal == 2 && rVal == 1 && FPCProp_Results[j].relOp == RELOP_EQ))
438 bExp = !bExp;
439 /* Fall through ... */
440 case PT_I2:
441 pvLeft.Value.i = lVal;
442 pvRight.Value.i = rVal;
443 break;
444 case PT_ERROR:
445 case PT_I4:
446 pvLeft.Value.l = lVal;
447 pvRight.Value.l = rVal;
448 break;
449 case PT_R4:
450 pvLeft.Value.flt = lVal;
451 pvRight.Value.flt = rVal;
452 break;
453 case PT_APPTIME:
454 case PT_R8:
455 pvLeft.Value.dbl = lVal;
456 pvRight.Value.dbl = rVal;
457 break;
458 case PT_CURRENCY:
459 pvLeft.Value.cur.int64 = lVal;
460 pvRight.Value.cur.int64 = rVal;
461 break;
462 case PT_SYSTIME:
463 pvLeft.Value.ft.dwLowDateTime = lVal;
464 pvLeft.Value.ft.dwHighDateTime = 0;
465 pvRight.Value.ft.dwLowDateTime = rVal;
466 pvRight.Value.ft.dwHighDateTime = 0;
467 break;
468 case PT_I8:
469 pvLeft.Value.li.u.LowPart = lVal;
470 pvLeft.Value.li.u.HighPart = 0;
471 pvRight.Value.li.u.LowPart = rVal;
472 pvRight.Value.li.u.HighPart = 0;
473 break;
474 case PT_CLSID:
475 memset(&lguid, 0, sizeof(GUID));
476 memset(&rguid, 0, sizeof(GUID));
477 lguid.Data4[7] = lVal;
478 rguid.Data4[7] = rVal;
479 pvLeft.Value.lpguid = &lguid;
480 pvRight.Value.lpguid = &rguid;
481 break;
482 case PT_STRING8:
483 pvLeft.Value.lpszA = lbuffa;
484 pvRight.Value.lpszA = rbuffa;
485 lbuffa[0] = '0' + lVal;
486 rbuffa[0] = '0' + rVal;
487 break;
488 case PT_UNICODE:
489 pvLeft.Value.lpszW = lbuffw;
490 pvRight.Value.lpszW = rbuffw;
491 lbuffw[0] = '0' + lVal;
492 rbuffw[0] = '0' + rVal;
493 break;
494 case PT_BINARY:
495 pvLeft.Value.bin.cb = 1;
496 pvRight.Value.bin.cb = 1;
497 pvLeft.Value.bin.lpb = (LPBYTE)lbuffa;
498 pvRight.Value.bin.lpb = (LPBYTE)rbuffa;
499 lbuffa[0] = lVal;
500 rbuffa[0] = rVal;
501 break;
504 bRet = pFPropCompareProp(&pvLeft, FPCProp_Results[j].relOp, &pvRight);
505 ok(bRet == bExp, "pt %d (%d,%d,%s): expected %d, got %d\n", ptTypes[i],
506 FPCProp_Results[j].lVal, FPCProp_Results[j].rVal,
507 relops[FPCProp_Results[j].relOp], bExp, bRet);
512 typedef struct tagLPropCompareProp_Result
514 SHORT lVal;
515 SHORT rVal;
516 INT iRet;
517 } LPropCompareProp_Result;
519 static const LPropCompareProp_Result LPCProp_Results[] =
521 { 1, 2, -1 },
522 { 1, 1, 0 },
523 { 2, 1, 1 },
526 static void test_LPropCompareProp(void)
528 SPropValue pvLeft, pvRight;
529 GUID lguid, rguid;
530 char lbuffa[2], rbuffa[2];
531 WCHAR lbuffw[2], rbuffw[2];
532 ULONG i, j;
533 INT iRet, iExp;
535 pLPropCompareProp = (void*)GetProcAddress(hMapi32, "LPropCompareProp@8");
537 if (!pLPropCompareProp)
538 return;
540 lbuffa[1] = '\0';
541 rbuffa[1] = '\0';
542 lbuffw[1] = '\0';
543 rbuffw[1] = '\0';
545 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
547 pvLeft.ulPropTag = pvRight.ulPropTag = ptTypes[i];
549 for (j = 0; j < sizeof(LPCProp_Results)/sizeof(LPCProp_Results[0]); j++)
551 SHORT lVal = LPCProp_Results[j].lVal;
552 SHORT rVal = LPCProp_Results[j].rVal;
554 iExp = LPCProp_Results[j].iRet;
556 switch (ptTypes[i])
558 case PT_BOOLEAN:
559 /* Boolean values have no concept of less or greater than, only equality */
560 if (lVal && rVal)
561 iExp = 0;
562 /* Fall through ... */
563 case PT_I2:
564 pvLeft.Value.i = lVal;
565 pvRight.Value.i = rVal;
566 break;
567 case PT_ERROR:
568 case PT_I4:
569 pvLeft.Value.l = lVal;
570 pvRight.Value.l = rVal;
571 break;
572 case PT_R4:
573 pvLeft.Value.flt = lVal;
574 pvRight.Value.flt = rVal;
575 break;
576 case PT_APPTIME:
577 case PT_R8:
578 pvLeft.Value.dbl = lVal;
579 pvRight.Value.dbl = rVal;
580 break;
581 case PT_CURRENCY:
582 pvLeft.Value.cur.int64 = lVal;
583 pvRight.Value.cur.int64 = rVal;
584 break;
585 case PT_SYSTIME:
586 pvLeft.Value.ft.dwLowDateTime = lVal;
587 pvLeft.Value.ft.dwHighDateTime = 0;
588 pvRight.Value.ft.dwLowDateTime = rVal;
589 pvRight.Value.ft.dwHighDateTime = 0;
590 break;
591 case PT_I8:
592 pvLeft.Value.li.u.LowPart = lVal;
593 pvLeft.Value.li.u.HighPart = 0;
594 pvRight.Value.li.u.LowPart = rVal;
595 pvRight.Value.li.u.HighPart = 0;
596 break;
597 case PT_CLSID:
598 memset(&lguid, 0, sizeof(GUID));
599 memset(&rguid, 0, sizeof(GUID));
600 lguid.Data4[7] = lVal;
601 rguid.Data4[7] = rVal;
602 pvLeft.Value.lpguid = &lguid;
603 pvRight.Value.lpguid = &rguid;
604 break;
605 case PT_STRING8:
606 pvLeft.Value.lpszA = lbuffa;
607 pvRight.Value.lpszA = rbuffa;
608 lbuffa[0] = '0' + lVal;
609 rbuffa[0] = '0' + rVal;
610 break;
611 case PT_UNICODE:
612 pvLeft.Value.lpszW = lbuffw;
613 pvRight.Value.lpszW = rbuffw;
614 lbuffw[0] = '0' + lVal;
615 rbuffw[0] = '0' + rVal;
616 break;
617 case PT_BINARY:
618 pvLeft.Value.bin.cb = 1;
619 pvRight.Value.bin.cb = 1;
620 pvLeft.Value.bin.lpb = (LPBYTE)lbuffa;
621 pvRight.Value.bin.lpb = (LPBYTE)rbuffa;
622 lbuffa[0] = lVal;
623 rbuffa[0] = rVal;
624 break;
627 iRet = pLPropCompareProp(&pvLeft, &pvRight);
628 ok(iRet == iExp, "pt %d (%d,%d): expected %d, got %d\n", ptTypes[i],
629 LPCProp_Results[j].lVal, LPCProp_Results[j].rVal, iExp, iRet);
634 static void test_PpropFindProp(void)
636 SPropValue pvProp, *pRet;
637 ULONG i;
639 pPpropFindProp = (void*)GetProcAddress(hMapi32, "PpropFindProp@12");
641 if (!pPpropFindProp)
642 return;
644 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
646 pvProp.ulPropTag = ptTypes[i];
648 pRet = pPpropFindProp(&pvProp, 1u, ptTypes[i]);
649 ok(pRet == &pvProp, "PpropFindProp[%d]: Didn't find existing propery\n",
650 ptTypes[i]);
652 pRet = pPpropFindProp(&pvProp, 1u, i ? ptTypes[i-1] : ptTypes[i+1]);
653 ok(pRet == NULL, "PpropFindProp[%d]: Found nonexistent propery\n",
654 ptTypes[i]);
657 pvProp.ulPropTag = PROP_TAG(PT_I2, 1u);
658 pRet = pPpropFindProp(&pvProp, 1u, PROP_TAG(PT_UNSPECIFIED, 0u));
659 ok(pRet == NULL, "PpropFindProp[UNSPECIFIED]: Matched on different id\n");
660 pRet = pPpropFindProp(&pvProp, 1u, PROP_TAG(PT_UNSPECIFIED, 1u));
661 ok(pRet == &pvProp, "PpropFindProp[UNSPECIFIED]: Didn't match id\n");
664 static void test_ScCountProps(void)
666 static char szHiA[] = "Hi!";
667 static WCHAR szHiW[] = { 'H', 'i', '!', '\0' };
668 static const ULONG ULHILEN = 4; /* chars in szHiA/W incl. NUL */
669 LPSTR buffa[3];
670 LPWSTR buffw[3];
671 SBinary buffbin[3];
672 GUID iids[4], *iid = iids;
673 SCODE res;
674 ULONG pt, exp, ulRet;
675 int success = 1;
677 pScCountProps = (void*)GetProcAddress(hMapi32, "ScCountProps@12");
679 if (!pScCountProps)
680 return;
682 for (pt = 0; pt < PROP_ID_INVALID && success; pt++)
684 SPropValue pv;
686 memset(&pv, 0 ,sizeof(pv));
687 pv.ulPropTag = PROP_TAG(pt, 1u);
689 switch (PROP_TYPE(pt))
691 case PT_I2:
692 case PT_I4:
693 case PT_R4:
694 case PT_R8:
695 case PT_CURRENCY:
696 case PT_APPTIME:
697 case PT_SYSTIME:
698 case PT_ERROR:
699 case PT_BOOLEAN:
700 case PT_OBJECT:
701 case PT_I8:
702 exp = sizeof(pv);
703 break;
704 case PT_CLSID:
705 pv.Value.lpguid = iid;
706 exp = sizeof(GUID) + sizeof(pv);
707 break;
708 case PT_STRING8:
709 pv.Value.lpszA = szHiA;
710 exp = 4 + sizeof(pv);
711 break;
712 case PT_UNICODE:
713 pv.Value.lpszW = szHiW;
714 exp = 4 * sizeof(WCHAR) + sizeof(pv);
715 break;
716 case PT_BINARY:
717 pv.Value.bin.cb = 2;
718 pv.Value.bin.lpb = (LPBYTE)iid;
719 exp = 2 + sizeof(pv);
720 break;
721 case PT_MV_I2:
722 pv.Value.MVi.cValues = 3;
723 pv.Value.MVi.lpi = (SHORT*)iid;
724 exp = 3 * sizeof(SHORT) + sizeof(pv);
725 break;
726 case PT_MV_I4:
727 pv.Value.MVl.cValues = 3;
728 pv.Value.MVl.lpl = (LONG*)iid;
729 exp = 3 * sizeof(LONG) + sizeof(pv);
730 break;
731 case PT_MV_I8:
732 pv.Value.MVli.cValues = 3;
733 pv.Value.MVli.lpli = (LARGE_INTEGER*)iid;
734 exp = 3 * sizeof(LARGE_INTEGER) + sizeof(pv);
735 break;
736 case PT_MV_R4:
737 pv.Value.MVflt.cValues = 3;
738 pv.Value.MVflt.lpflt = (float*)iid;
739 exp = 3 * sizeof(float) + sizeof(pv);
740 break;
741 case PT_MV_APPTIME:
742 case PT_MV_R8:
743 pv.Value.MVdbl.cValues = 3;
744 pv.Value.MVdbl.lpdbl = (double*)iid;
745 exp = 3 * sizeof(double) + sizeof(pv);
746 break;
747 case PT_MV_CURRENCY:
748 pv.Value.MVcur.cValues = 3;
749 pv.Value.MVcur.lpcur = (CY*)iid;
750 exp = 3 * sizeof(CY) + sizeof(pv);
751 break;
752 case PT_MV_SYSTIME:
753 pv.Value.MVft.cValues = 3;
754 pv.Value.MVft.lpft = (FILETIME*)iid;
755 exp = 3 * sizeof(CY) + sizeof(pv);
756 break;
757 case PT_MV_STRING8:
758 pv.Value.MVszA.cValues = 3;
759 pv.Value.MVszA.lppszA = buffa;
760 buffa[0] = szHiA;
761 buffa[1] = szHiA;
762 buffa[2] = szHiA;
763 exp = ULHILEN * 3 + 3 * sizeof(char*) + sizeof(pv);
764 break;
765 case PT_MV_UNICODE:
766 pv.Value.MVszW.cValues = 3;
767 pv.Value.MVszW.lppszW = buffw;
768 buffw[0] = szHiW;
769 buffw[1] = szHiW;
770 buffw[2] = szHiW;
771 exp = ULHILEN * 3 * sizeof(WCHAR) + 3 * sizeof(WCHAR*) + sizeof(pv);
772 break;
773 case PT_MV_BINARY:
774 pv.Value.MVbin.cValues = 3;
775 pv.Value.MVbin.lpbin = buffbin;
776 buffbin[0].cb = 17;
777 buffbin[0].lpb = (LPBYTE)&iid;
778 buffbin[1].cb = 2;
779 buffbin[1].lpb = (LPBYTE)&iid;
780 buffbin[2].cb = 1;
781 buffbin[2].lpb = (LPBYTE)&iid;
782 exp = 20 + sizeof(pv) + sizeof(SBinary) * 3;
783 break;
784 default:
785 exp = 0;
788 ulRet = 0xffffffff;
789 res = pScCountProps(1, &pv, &ulRet);
790 if (!exp) {
791 success = res == MAPI_E_INVALID_PARAMETER && ulRet == 0xffffffff;
792 ok(success, "pt= %d: Expected failure, got %d, ret=0x%08X\n",
793 pt, ulRet, res);
795 else {
796 success = res == S_OK && ulRet == exp;
797 ok(success, "pt= %d: Expected %d, got %d, ret=0x%08X\n",
798 pt, exp, ulRet, res);
804 static void test_ScCopyRelocProps(void)
806 static char szTestA[] = "Test";
807 char buffer[512], buffer2[512], *lppszA[1];
808 SPropValue pvProp, *lpResProp = (LPSPropValue)buffer;
809 ULONG ulCount;
810 SCODE sc;
812 pScCopyProps = (void*)GetProcAddress(hMapi32, "ScCopyProps@16");
813 pScRelocProps = (void*)GetProcAddress(hMapi32, "ScRelocProps@20");
815 if (!pScCopyProps || !pScRelocProps)
816 return;
818 pvProp.ulPropTag = PROP_TAG(PT_MV_STRING8, 1u);
820 lppszA[0] = szTestA;
821 pvProp.Value.MVszA.cValues = 1;
822 pvProp.Value.MVszA.lppszA = lppszA;
823 ulCount = 0;
825 sc = pScCopyProps(1, &pvProp, buffer, &ulCount);
826 ok(sc == S_OK, "wrong ret %d\n", sc);
827 if(sc == S_OK)
829 ok(lpResProp->ulPropTag == pvProp.ulPropTag, "wrong tag %x\n",lpResProp->ulPropTag);
830 ok(lpResProp->Value.MVszA.cValues == 1, "wrong cValues %d\n", lpResProp->Value.MVszA.cValues);
831 ok(lpResProp->Value.MVszA.lppszA[0] == buffer + sizeof(SPropValue) + sizeof(char*),
832 "wrong lppszA[0] %p\n",lpResProp->Value.MVszA.lppszA[0]);
833 ok(ulCount == sizeof(SPropValue) + sizeof(char*) + 5, "wrong count %d\n", ulCount);
834 ok(!strcmp(lpResProp->Value.MVszA.lppszA[0], szTestA),
835 "wrong string '%s'\n", lpResProp->Value.MVszA.lppszA[0]);
838 memcpy(buffer2, buffer, sizeof(buffer));
840 /* Clear the data in the source buffer. Since pointers in the copied buffer
841 * refer to the source buffer, this proves that native always assumes that
842 * the copied buffers pointers are bad (needing to be relocated first).
844 memset(buffer, 0, sizeof(buffer));
845 ulCount = 0;
847 sc = pScRelocProps(1, (LPSPropValue)buffer2, buffer, buffer2, &ulCount);
848 lpResProp = (LPSPropValue)buffer2;
850 ok(sc == S_OK, "wrong ret %d\n", sc);
851 if(sc == S_OK)
853 ok(lpResProp->ulPropTag == pvProp.ulPropTag, "wrong tag %x\n",lpResProp->ulPropTag);
854 ok(lpResProp->Value.MVszA.cValues == 1, "wrong cValues %d\n", lpResProp->Value.MVszA.cValues);
855 ok(lpResProp->Value.MVszA.lppszA[0] == buffer2 + sizeof(SPropValue) + sizeof(char*),
856 "wrong lppszA[0] %p\n",lpResProp->Value.MVszA.lppszA[0]);
857 /* Native has a bug whereby it calculates the size correctly when copying
858 * but when relocating does not (presumably it uses UlPropSize() which
859 * ignores multivalue pointers). Wine returns the correct value.
861 ok(ulCount == sizeof(SPropValue) + sizeof(char*) + 5 || ulCount == sizeof(SPropValue) + 5,
862 "wrong count %d\n", ulCount);
863 ok(!strcmp(lpResProp->Value.MVszA.lppszA[0], szTestA),
864 "wrong string '%s'\n", lpResProp->Value.MVszA.lppszA[0]);
867 /* Native crashes with lpNew or lpOld set to NULL so skip testing this */
870 static void test_LpValFindProp(void)
872 SPropValue pvProp, *pRet;
873 ULONG i;
875 pLpValFindProp = (void*)GetProcAddress(hMapi32, "LpValFindProp@12");
877 if (!pLpValFindProp)
878 return;
880 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
882 pvProp.ulPropTag = PROP_TAG(ptTypes[i], 1u);
884 pRet = pLpValFindProp(PROP_TAG(ptTypes[i], 1u), 1u, &pvProp);
885 ok(pRet == &pvProp, "LpValFindProp[%d]: Didn't find existing propery id/type\n",
886 ptTypes[i]);
888 pRet = pLpValFindProp(PROP_TAG(ptTypes[i], 0u), 1u, &pvProp);
889 ok(pRet == NULL, "LpValFindProp[%d]: Found nonexistent propery id\n",
890 ptTypes[i]);
892 pRet = pLpValFindProp(PROP_TAG(PT_NULL, 0u), 1u, &pvProp);
893 ok(pRet == NULL, "LpValFindProp[%d]: Found nonexistent propery id/type\n",
894 ptTypes[i]);
896 pRet = pLpValFindProp(PROP_TAG(PT_NULL, 1u), 1u, &pvProp);
897 ok(pRet == &pvProp, "LpValFindProp[%d]: Didn't find existing propery id\n",
898 ptTypes[i]);
902 static void test_FBadRglpszA(void)
904 LPSTR lpStrs[4];
905 static CHAR szString[] = "A String";
906 BOOL bRet;
908 pFBadRglpszA = (void*)GetProcAddress(hMapi32, "FBadRglpszA@8");
909 if (!pFBadRglpszA)
910 return;
912 bRet = pFBadRglpszA(NULL, 10);
913 ok(bRet == TRUE, "FBadRglpszA(Null): expected TRUE, got FALSE\n");
915 lpStrs[0] = lpStrs[1] = lpStrs[2] = lpStrs[3] = NULL;
916 bRet = pFBadRglpszA(lpStrs, 4);
917 ok(bRet == TRUE, "FBadRglpszA(Nulls): expected TRUE, got FALSE\n");
919 lpStrs[0] = lpStrs[1] = lpStrs[2] = szString;
920 bRet = pFBadRglpszA(lpStrs, 3);
921 ok(bRet == FALSE, "FBadRglpszA(valid): expected FALSE, got TRUE\n");
923 bRet = pFBadRglpszA(lpStrs, 4);
924 ok(bRet == TRUE, "FBadRglpszA(1 invalid): expected TRUE, got FALSE\n");
927 static void test_FBadRglpszW(void)
929 LPWSTR lpStrs[4];
930 static WCHAR szString[] = { 'A',' ','S','t','r','i','n','g','\0' };
931 BOOL bRet;
933 pFBadRglpszW = (void*)GetProcAddress(hMapi32, "FBadRglpszW@8");
934 if (!pFBadRglpszW)
935 return;
937 bRet = pFBadRglpszW(NULL, 10);
938 ok(bRet == TRUE, "FBadRglpszW(Null): expected TRUE, got FALSE\n");
940 lpStrs[0] = lpStrs[1] = lpStrs[2] = lpStrs[3] = NULL;
941 bRet = pFBadRglpszW(lpStrs, 4);
942 ok(bRet == TRUE, "FBadRglpszW(Nulls): expected TRUE, got FALSE\n");
944 lpStrs[0] = lpStrs[1] = lpStrs[2] = szString;
945 bRet = pFBadRglpszW(lpStrs, 3);
946 ok(bRet == FALSE, "FBadRglpszW(valid): expected FALSE, got TRUE\n");
948 bRet = pFBadRglpszW(lpStrs, 4);
949 ok(bRet == TRUE, "FBadRglpszW(1 invalid): expected TRUE, got FALSE\n");
952 static void test_FBadRowSet(void)
954 ULONG ulRet;
956 pFBadRowSet = (void*)GetProcAddress(hMapi32, "FBadRowSet@4");
957 if (!pFBadRowSet)
958 return;
960 ulRet = pFBadRowSet(NULL);
961 ok(ulRet != 0, "FBadRow(null): Expected non-zero, got 0\n");
963 /* FIXME */
966 static void test_FBadPropTag(void)
968 ULONG pt, res;
970 pFBadPropTag = (void*)GetProcAddress(hMapi32, "FBadPropTag@4");
971 if (!pFBadPropTag)
972 return;
974 for (pt = 0; pt < PROP_ID_INVALID; pt++)
976 BOOL bBad = TRUE;
978 switch (pt & (~MV_FLAG & PROP_TYPE_MASK))
980 case PT_UNSPECIFIED:
981 case PT_NULL: case PT_I2: case PT_I4: case PT_R4:
982 case PT_R8: case PT_CURRENCY: case PT_APPTIME:
983 case PT_ERROR: case PT_BOOLEAN: case PT_OBJECT:
984 case PT_I8: case PT_STRING8: case PT_UNICODE:
985 case PT_SYSTIME: case PT_CLSID: case PT_BINARY:
986 bBad = FALSE;
989 res = pFBadPropTag(pt);
990 if (bBad)
991 ok(res != 0, "pt= %d: Expected non-zero, got 0\n", pt);
992 else
993 ok(res == 0, "pt= %d: Expected zero, got %d\n", pt, res);
997 static void test_FBadRow(void)
999 ULONG ulRet;
1001 pFBadRow = (void*)GetProcAddress(hMapi32, "FBadRow@4");
1002 if (!pFBadRow)
1003 return;
1005 ulRet = pFBadRow(NULL);
1006 ok(ulRet != 0, "FBadRow(null): Expected non-zero, got 0\n");
1008 /* FIXME */
1011 static void test_FBadProp(void)
1013 static WCHAR szEmpty[] = { '\0' };
1014 GUID iid;
1015 ULONG pt, res;
1016 SPropValue pv;
1018 pFBadProp = (void*)GetProcAddress(hMapi32, "FBadProp@4");
1019 if (!pFBadProp)
1020 return;
1022 for (pt = 0; pt < PROP_ID_INVALID; pt++)
1024 BOOL bBad = TRUE;
1026 memset(&pv, 0, sizeof(pv));
1027 pv.ulPropTag = pt;
1029 /* Note that MV values are valid below because their array count is 0,
1030 * so no pointers are validated.
1032 switch (PROP_TYPE(pt))
1034 case (MV_FLAG|PT_UNSPECIFIED):
1035 case PT_UNSPECIFIED:
1036 case (MV_FLAG|PT_NULL):
1037 case PT_NULL:
1038 case PT_MV_I2:
1039 case PT_I2:
1040 case PT_MV_I4:
1041 case PT_I4:
1042 case PT_MV_I8:
1043 case PT_I8:
1044 case PT_MV_R4:
1045 case PT_R4:
1046 case PT_MV_R8:
1047 case PT_R8:
1048 case PT_MV_CURRENCY:
1049 case PT_CURRENCY:
1050 case PT_MV_APPTIME:
1051 case PT_APPTIME:
1052 case (MV_FLAG|PT_ERROR):
1053 case PT_ERROR:
1054 case (MV_FLAG|PT_BOOLEAN):
1055 case PT_BOOLEAN:
1056 case (MV_FLAG|PT_OBJECT):
1057 case PT_OBJECT:
1058 case PT_MV_STRING8:
1059 case PT_MV_UNICODE:
1060 case PT_MV_SYSTIME:
1061 case PT_SYSTIME:
1062 case PT_MV_BINARY:
1063 case PT_BINARY:
1064 case PT_MV_CLSID:
1065 bBad = FALSE;
1066 break;
1067 case PT_STRING8:
1068 case PT_UNICODE:
1069 pv.Value.lpszW = szEmpty;
1070 bBad = FALSE;
1071 break;
1072 case PT_CLSID:
1073 pv.Value.lpguid = &iid;
1074 bBad = FALSE;
1075 break;
1078 res = pFBadProp(&pv);
1079 if (bBad)
1080 ok(res != 0, "pt= %d: Expected non-zero, got 0\n", pt);
1081 else
1082 ok(res == 0, "pt= %d: Expected zero, got %d\n", pt, res);
1086 static void test_FBadColumnSet(void)
1088 SPropTagArray pta;
1089 ULONG pt, res;
1091 pFBadColumnSet = (void*)GetProcAddress(hMapi32, "FBadColumnSet@4");
1092 if (!pFBadColumnSet)
1093 return;
1095 res = pFBadColumnSet(NULL);
1096 ok(res != 0, "(null): Expected non-zero, got 0\n");
1098 pta.cValues = 1;
1100 for (pt = 0; pt < PROP_ID_INVALID; pt++)
1102 BOOL bBad = TRUE;
1104 pta.aulPropTag[0] = pt;
1106 switch (pt & (~MV_FLAG & PROP_TYPE_MASK))
1108 case PT_UNSPECIFIED:
1109 case PT_NULL:
1110 case PT_I2:
1111 case PT_I4:
1112 case PT_R4:
1113 case PT_R8:
1114 case PT_CURRENCY:
1115 case PT_APPTIME:
1116 case PT_BOOLEAN:
1117 case PT_OBJECT:
1118 case PT_I8:
1119 case PT_STRING8:
1120 case PT_UNICODE:
1121 case PT_SYSTIME:
1122 case PT_CLSID:
1123 case PT_BINARY:
1124 bBad = FALSE;
1126 if (pt == (MV_FLAG|PT_ERROR))
1127 bBad = FALSE;
1129 res = pFBadColumnSet(&pta);
1130 if (bBad)
1131 ok(res != 0, "pt= %d: Expected non-zero, got 0\n", pt);
1132 else
1133 ok(res == 0, "pt= %d: Expected zero, got %d\n", pt, res);
1138 static void test_IProp(void)
1140 IPropData *lpIProp;
1141 LPMAPIERROR lpError;
1142 LPSPropProblemArray lpProbs;
1143 LPSPropValue lpProps;
1144 LPSPropTagArray lpTags;
1145 SPropValue pvs[2];
1146 SizedSPropTagArray(2,tags);
1147 ULONG access[2], count;
1148 SCODE sc;
1150 pCreateIProp = (void*)GetProcAddress(hMapi32, "CreateIProp@24");
1152 if (!pCreateIProp)
1153 return;
1155 memset(&tags, 0 , sizeof(tags));
1157 /* Create the object */
1158 lpIProp = NULL;
1159 sc = pCreateIProp(&IID_IMAPIPropData, (ALLOCATEBUFFER *)pMAPIAllocateBuffer, (ALLOCATEMORE*)pMAPIAllocateMore,
1160 (FREEBUFFER *)pMAPIFreeBuffer, NULL, &lpIProp);
1161 ok(sc == S_OK && lpIProp,
1162 "CreateIProp: expected S_OK, non-null, got 0x%08X,%p\n", sc, lpIProp);
1164 if (sc != S_OK || !lpIProp)
1165 return;
1167 /* GetLastError - No errors set */
1168 lpError = NULL;
1169 IPropData_GetLastError(lpIProp, E_INVALIDARG, 0, &lpError);
1170 ok(sc == S_OK && !lpError,
1171 "GetLastError: Expected S_OK, null, got 0x%08X,%p\n", sc, lpError);
1173 /* Get prop tags - succeeds returning 0 items */
1174 lpTags = NULL;
1175 sc = IPropData_GetPropList(lpIProp, 0, &lpTags);
1176 ok(sc == S_OK && lpTags && lpTags->cValues == 0,
1177 "GetPropList(empty): Expected S_OK, non-null, 0, got 0x%08X,%p,%d\n",
1178 sc, lpTags, lpTags ? lpTags->cValues : 0);
1179 if (lpTags)
1180 pMAPIFreeBuffer(lpTags);
1182 /* Get props - succeeds returning 0 items */
1183 lpProps = NULL;
1184 count = 0;
1185 tags.cValues = 1;
1186 tags.aulPropTag[0] = PR_IMPORTANCE;
1187 sc = IPropData_GetProps(lpIProp, (LPSPropTagArray)&tags, 0, &count, &lpProps);
1188 ok(sc == MAPI_W_ERRORS_RETURNED && lpProps && count == 1,
1189 "GetProps(empty): Expected ERRORS_RETURNED, non-null, 1, got 0x%08X,%p,%d\n",
1190 sc, lpProps, count);
1191 if (lpProps && count > 0)
1193 ok(lpProps[0].ulPropTag == CHANGE_PROP_TYPE(PR_IMPORTANCE,PT_ERROR),
1194 "GetProps(empty): Expected %x, got %x\n",
1195 CHANGE_PROP_TYPE(PR_IMPORTANCE,PT_ERROR), lpProps[0].ulPropTag);
1197 pMAPIFreeBuffer(lpProps);
1200 /* Add (NULL) - Can't add NULLs */
1201 lpProbs = NULL;
1202 pvs[0].ulPropTag = PROP_TAG(PT_NULL,0x01);
1203 sc = IPropData_SetProps(lpIProp, 1, pvs, &lpProbs);
1204 ok(sc == MAPI_E_INVALID_PARAMETER && !lpProbs,
1205 "SetProps(): Expected INVALID_PARAMETER, null, got 0x%08X,%p\n",
1206 sc, lpProbs);
1208 /* Add (OBJECT) - Can't add OBJECTs */
1209 lpProbs = NULL;
1210 pvs[0].ulPropTag = PROP_TAG(PT_OBJECT,0x01);
1211 sc = IPropData_SetProps(lpIProp, 1, pvs, &lpProbs);
1212 ok(sc == MAPI_E_INVALID_PARAMETER && !lpProbs,
1213 "SetProps(OBJECT): Expected INVALID_PARAMETER, null, got 0x%08X,%p\n",
1214 sc, lpProbs);
1216 /* Add - Adds value */
1217 lpProbs = NULL;
1218 pvs[0].ulPropTag = PR_IMPORTANCE;
1219 sc = IPropData_SetProps(lpIProp, 1, pvs, &lpProbs);
1220 ok(sc == S_OK && !lpProbs,
1221 "SetProps(ERROR): Expected S_OK, null, got 0x%08X,%p\n", sc, lpProbs);
1223 /* Get prop list - returns 1 item */
1224 lpTags = NULL;
1225 IPropData_GetPropList(lpIProp, 0, &lpTags);
1226 ok(sc == S_OK && lpTags && lpTags->cValues == 1,
1227 "GetPropList: Expected S_OK, non-null, 1, got 0x%08X,%p,%d\n",
1228 sc, lpTags, lpTags ? lpTags->cValues : 0);
1229 if (lpTags && lpTags->cValues > 0)
1231 ok(lpTags->aulPropTag[0] == PR_IMPORTANCE,
1232 "GetPropList: Expected %x, got %x\n",
1233 PR_IMPORTANCE, lpTags->aulPropTag[0]);
1234 pMAPIFreeBuffer(lpTags);
1237 /* Set access to read and write */
1238 sc = IPropData_HrSetObjAccess(lpIProp, IPROP_READWRITE);
1239 ok(sc == S_OK, "SetObjAcess(WRITE): Expected S_OK got 0x%08X\n", sc);
1241 tags.cValues = 1;
1242 tags.aulPropTag[0] = PR_IMPORTANCE;
1244 /* Set item access (bad access) - Fails */
1245 access[0] = 0;
1246 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1247 ok(sc == MAPI_E_INVALID_PARAMETER,
1248 "SetPropAcess(0): Expected INVALID_PARAMETER got 0x%08X\n",sc);
1249 access[0] = IPROP_READWRITE;
1250 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1251 ok(sc == MAPI_E_INVALID_PARAMETER,
1252 "SetPropAcess(RW): Expected INVALID_PARAMETER got 0x%08X\n",sc);
1253 access[0] = IPROP_CLEAN;
1254 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1255 ok(sc == MAPI_E_INVALID_PARAMETER,
1256 "SetPropAcess(C): Expected INVALID_PARAMETER got 0x%08X\n",sc);
1258 /* Set item access to read/write/clean */
1259 tags.cValues = 1;
1260 tags.aulPropTag[0] = PR_IMPORTANCE;
1261 access[0] = IPROP_READWRITE|IPROP_CLEAN;
1262 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1263 ok(sc == S_OK, "SetPropAcess(RW/C): Expected S_OK got 0x%08X\n",sc);
1265 /* Set object access to read only */
1266 sc = IPropData_HrSetObjAccess(lpIProp, IPROP_READONLY);
1267 ok(sc == S_OK, "SetObjAcess(READ): Expected S_OK got 0x%08X\n", sc);
1269 /* Set item access to read/write/dirty - doesn't care about RO object */
1270 access[0] = IPROP_READONLY|IPROP_DIRTY;
1271 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1272 ok(sc == S_OK, "SetPropAcess(WRITE): Expected S_OK got 0x%08X\n", sc);
1274 /* Delete any item when set to read only - Error */
1275 lpProbs = NULL;
1276 tags.aulPropTag[0] = PR_RESPONSE_REQUESTED;
1277 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1278 ok(sc == E_ACCESSDENIED && !lpProbs,
1279 "DeleteProps(nonexistent): Expected E_ACCESSDENIED null got 0x%08X %p\n",
1280 sc, lpProbs);
1282 /* Set access to read and write */
1283 sc = IPropData_HrSetObjAccess(lpIProp, IPROP_READWRITE);
1284 ok(sc == S_OK, "SetObjAcess(WRITE): Expected S_OK got 0x%08X\n", sc);
1286 /* Delete nonexistent item - No error */
1287 lpProbs = NULL;
1288 tags.aulPropTag[0] = PR_RESPONSE_REQUESTED;
1289 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1290 ok(sc == S_OK && !lpProbs,
1291 "DeleteProps(nonexistent): Expected S_OK null got 0x%08X %p\n",
1292 sc, lpProbs);
1294 /* Delete existing item (r/o) - No error, but lpProbs populated */
1295 lpProbs = NULL;
1296 tags.aulPropTag[0] = PR_IMPORTANCE;
1297 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1298 ok(sc == S_OK && lpProbs,
1299 "DeleteProps(RO): Expected S_OK non-null got 0x%08X %p\n", sc, lpProbs);
1301 if (lpProbs && lpProbs->cProblem > 0)
1303 ok(lpProbs->cProblem == 1 &&
1304 lpProbs->aProblem[0].ulIndex == 0 &&
1305 lpProbs->aProblem[0].ulPropTag == PR_IMPORTANCE &&
1306 lpProbs->aProblem[0].scode == E_ACCESSDENIED,
1307 "DeleteProps(RO): Expected (1,0,%x,%x) got (%d,%x,%x)\n",
1308 PR_IMPORTANCE, E_ACCESSDENIED,
1309 lpProbs->aProblem[0].ulIndex, lpProbs->aProblem[0].ulPropTag,
1310 lpProbs->aProblem[0].scode);
1311 pMAPIFreeBuffer(lpProbs);
1314 lpProbs = NULL;
1315 tags.cValues = 1;
1316 tags.aulPropTag[0] = PR_RESPONSE_REQUESTED;
1317 IPropData_HrAddObjProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1318 ok(sc == S_OK && !lpProbs,
1319 "AddObjProps(RO): Expected S_OK null got 0x%08X %p\n", sc, lpProbs);
1321 /* Get prop list - returns 1 item */
1322 lpTags = NULL;
1323 IPropData_GetPropList(lpIProp, 0, &lpTags);
1324 ok(sc == S_OK && lpTags && lpTags->cValues == 1,
1325 "GetPropList: Expected S_OK, non-null, 1, got 0x%08X,%p,%d\n",
1326 sc, lpTags, lpTags ? lpTags->cValues : 0);
1327 if (lpTags && lpTags->cValues > 0)
1329 ok(lpTags->aulPropTag[0] == PR_IMPORTANCE,
1330 "GetPropList: Expected %x, got %x\n",
1331 PR_IMPORTANCE, lpTags->aulPropTag[0]);
1332 pMAPIFreeBuffer(lpTags);
1335 /* Set item to r/w again */
1336 access[0] = IPROP_READWRITE|IPROP_DIRTY;
1337 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1338 ok(sc == S_OK, "SetPropAcess(WRITE): Expected S_OK got 0x%08X\n", sc);
1340 /* Delete existing item (r/w) - No error, no problems */
1341 lpProbs = NULL;
1342 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1343 ok(sc == S_OK && !lpProbs,
1344 "DeleteProps(RO): Expected S_OK null got 0x%08X %p\n", sc, lpProbs);
1346 /* Free the list */
1347 IPropData_Release(lpIProp);
1350 START_TEST(prop)
1352 SCODE ret;
1354 if(!InitFuncPtrs())
1356 skip("Needed functions are not available\n");
1357 return;
1360 SetLastError(0xdeadbeef);
1361 ret = pScInitMapiUtil(0);
1362 if ((ret != S_OK) && (GetLastError() == ERROR_PROC_NOT_FOUND))
1364 skip("ScInitMapiUtil is not implemented\n");
1365 FreeLibrary(hMapi32);
1366 return;
1369 test_PropCopyMore();
1370 test_UlPropSize();
1371 test_FPropContainsProp();
1372 test_FPropCompareProp();
1373 test_LPropCompareProp();
1374 test_PpropFindProp();
1375 test_ScCountProps();
1376 test_ScCopyRelocProps();
1377 test_LpValFindProp();
1378 test_FBadRglpszA();
1379 test_FBadRglpszW();
1380 test_FBadRowSet();
1381 test_FBadPropTag();
1382 test_FBadRow();
1383 test_FBadProp();
1384 test_FBadColumnSet();
1386 test_IProp();
1387 FreeLibrary(hMapi32);