mfreadwrite/reader: Add missing allocation check (Coverity).
[wine/zf.git] / dlls / mapi32 / tests / prop.c
blob61ec5f16a9fc7d9cb00b74c2154af0ae0881c1ac
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"
30 #include "mapi32_test.h"
32 static HMODULE hMapi32 = 0;
34 static SCODE (WINAPI *pScInitMapiUtil)(ULONG);
35 static void (WINAPI *pDeinitMapiUtil)(void);
36 static SCODE (WINAPI *pPropCopyMore)(LPSPropValue,LPSPropValue,ALLOCATEMORE*,LPVOID);
37 static ULONG (WINAPI *pUlPropSize)(LPSPropValue);
38 static BOOL (WINAPI *pFPropContainsProp)(LPSPropValue,LPSPropValue,ULONG);
39 static BOOL (WINAPI *pFPropCompareProp)(LPSPropValue,ULONG,LPSPropValue);
40 static LONG (WINAPI *pLPropCompareProp)(LPSPropValue,LPSPropValue);
41 static LPSPropValue (WINAPI *pPpropFindProp)(LPSPropValue,ULONG,ULONG);
42 static SCODE (WINAPI *pScCountProps)(INT,LPSPropValue,ULONG*);
43 static SCODE (WINAPI *pScCopyProps)(int,LPSPropValue,LPVOID,ULONG*);
44 static SCODE (WINAPI *pScRelocProps)(int,LPSPropValue,LPVOID,LPVOID,ULONG*);
45 static LPSPropValue (WINAPI *pLpValFindProp)(ULONG,ULONG,LPSPropValue);
46 static BOOL (WINAPI *pFBadRglpszA)(LPSTR*,ULONG);
47 static BOOL (WINAPI *pFBadRglpszW)(LPWSTR*,ULONG);
48 static BOOL (WINAPI *pFBadRowSet)(LPSRowSet);
49 static ULONG (WINAPI *pFBadPropTag)(ULONG);
50 static ULONG (WINAPI *pFBadRow)(LPSRow);
51 static ULONG (WINAPI *pFBadProp)(LPSPropValue);
52 static ULONG (WINAPI *pFBadColumnSet)(LPSPropTagArray);
53 static SCODE (WINAPI *pCreateIProp)(LPCIID,ALLOCATEBUFFER*,ALLOCATEMORE*,
54 FREEBUFFER*,LPVOID,LPPROPDATA*);
55 static SCODE (WINAPI *pMAPIAllocateBuffer)(ULONG, LPVOID);
56 static SCODE (WINAPI *pMAPIAllocateMore)(ULONG, LPVOID, LPVOID);
57 static SCODE (WINAPI *pMAPIInitialize)(LPVOID);
58 static SCODE (WINAPI *pMAPIFreeBuffer)(LPVOID);
59 static void (WINAPI *pMAPIUninitialize)(void);
61 static BOOL InitFuncPtrs(void)
63 hMapi32 = LoadLibraryA("mapi32.dll");
65 pPropCopyMore = (void*)GetProcAddress(hMapi32, "PropCopyMore@16");
66 pUlPropSize = (void*)GetProcAddress(hMapi32, "UlPropSize@4");
67 pFPropContainsProp = (void*)GetProcAddress(hMapi32, "FPropContainsProp@12");
68 pFPropCompareProp = (void*)GetProcAddress(hMapi32, "FPropCompareProp@12");
69 pLPropCompareProp = (void*)GetProcAddress(hMapi32, "LPropCompareProp@8");
70 pPpropFindProp = (void*)GetProcAddress(hMapi32, "PpropFindProp@12");
71 pScCountProps = (void*)GetProcAddress(hMapi32, "ScCountProps@12");
72 pScCopyProps = (void*)GetProcAddress(hMapi32, "ScCopyProps@16");
73 pScRelocProps = (void*)GetProcAddress(hMapi32, "ScRelocProps@20");
74 pLpValFindProp = (void*)GetProcAddress(hMapi32, "LpValFindProp@12");
75 pFBadRglpszA = (void*)GetProcAddress(hMapi32, "FBadRglpszA@8");
76 pFBadRglpszW = (void*)GetProcAddress(hMapi32, "FBadRglpszW@8");
77 pFBadRowSet = (void*)GetProcAddress(hMapi32, "FBadRowSet@4");
78 pFBadPropTag = (void*)GetProcAddress(hMapi32, "FBadPropTag@4");
79 pFBadRow = (void*)GetProcAddress(hMapi32, "FBadRow@4");
80 pFBadProp = (void*)GetProcAddress(hMapi32, "FBadProp@4");
81 pFBadColumnSet = (void*)GetProcAddress(hMapi32, "FBadColumnSet@4");
82 pCreateIProp = (void*)GetProcAddress(hMapi32, "CreateIProp@24");
84 pScInitMapiUtil = (void*)GetProcAddress(hMapi32, "ScInitMapiUtil@4");
85 pDeinitMapiUtil = (void*)GetProcAddress(hMapi32, "DeinitMapiUtil@0");
86 pMAPIAllocateBuffer = (void*)GetProcAddress(hMapi32, "MAPIAllocateBuffer");
87 pMAPIAllocateMore = (void*)GetProcAddress(hMapi32, "MAPIAllocateMore");
88 pMAPIFreeBuffer = (void*)GetProcAddress(hMapi32, "MAPIFreeBuffer");
89 pMAPIInitialize = (void*)GetProcAddress(hMapi32, "MAPIInitialize");
90 pMAPIUninitialize = (void*)GetProcAddress(hMapi32, "MAPIUninitialize");
92 return pMAPIAllocateBuffer && pMAPIAllocateMore && pMAPIFreeBuffer &&
93 pScInitMapiUtil && pDeinitMapiUtil;
96 /* FIXME: Test PT_I2, PT_I4, PT_R4, PT_R8, PT_CURRENCY, PT_APPTIME, PT_SYSTIME,
97 * PT_ERROR, PT_BOOLEAN, PT_I8, and PT_CLSID. */
98 static ULONG ptTypes[] = {
99 PT_STRING8, PT_BINARY, PT_UNICODE
102 static void test_PropCopyMore(void)
104 static char szHiA[] = "Hi!";
105 static WCHAR szHiW[] = L"Hi!";
106 SPropValue *lpDest = NULL, *lpSrc = NULL;
107 ULONG i;
108 SCODE scode;
110 if (!pPropCopyMore)
112 win_skip("PropCopyMore is not available\n");
113 return;
116 scode = pMAPIAllocateBuffer(sizeof(SPropValue), &lpDest);
117 ok(scode == S_OK, "Expected MAPIAllocateBuffer to return S_OK, got 0x%x\n", scode);
118 if (FAILED(scode))
120 skip("MAPIAllocateBuffer failed\n");
121 return;
124 scode = pMAPIAllocateMore(sizeof(SPropValue), lpDest, &lpSrc);
125 ok(scode == S_OK, "Expected MAPIAllocateMore to return S_OK, got 0x%x\n", scode);
126 if (FAILED(scode))
128 skip("MAPIAllocateMore failed\n");
129 return;
132 for (i = 0; i < ARRAY_SIZE(ptTypes); i++)
134 lpSrc->ulPropTag = ptTypes[i];
136 switch (ptTypes[i])
138 case PT_STRING8:
139 lpSrc->Value.lpszA = szHiA;
140 break;
141 case PT_UNICODE:
142 lpSrc->Value.lpszW = szHiW;
143 break;
144 case PT_BINARY:
145 lpSrc->Value.bin.cb = 4;
146 lpSrc->Value.bin.lpb = (LPBYTE)szHiA;
147 break;
150 memset(lpDest, 0xff, sizeof(SPropValue));
152 scode = pPropCopyMore(lpDest, lpSrc, (ALLOCATEMORE*)pMAPIAllocateMore, lpDest);
153 ok(!scode && lpDest->ulPropTag == lpSrc->ulPropTag,
154 "PropCopyMore: Expected 0x0,%d, got 0x%08x,%d\n",
155 lpSrc->ulPropTag, scode, lpDest->ulPropTag);
156 if (SUCCEEDED(scode))
158 switch (ptTypes[i])
160 case PT_STRING8:
161 ok(lstrcmpA(lpDest->Value.lpszA, lpSrc->Value.lpszA) == 0,
162 "PropCopyMore: Ascii string differs\n");
163 break;
164 case PT_UNICODE:
165 ok(wcscmp(lpDest->Value.lpszW, lpSrc->Value.lpszW) == 0,
166 "PropCopyMore: Unicode string differs\n");
167 break;
168 case PT_BINARY:
169 ok(lpDest->Value.bin.cb == 4 &&
170 !memcmp(lpSrc->Value.bin.lpb, lpDest->Value.bin.lpb, 4),
171 "PropCopyMore: Binary array differs\n");
172 break;
177 /* Since all allocations are linked, freeing lpDest frees everything */
178 scode = pMAPIFreeBuffer(lpDest);
179 ok(scode == S_OK, "Expected MAPIFreeBuffer to return S_OK, got 0x%x\n", scode);
182 static void test_UlPropSize(void)
184 static char szHiA[] = "Hi!";
185 static WCHAR szHiW[] = L"Hi!";
186 LPSTR buffa[2];
187 LPWSTR buffw[2];
188 SBinary buffbin[2];
189 ULONG pt, exp, res;
191 if (!pUlPropSize)
193 win_skip("UlPropSize is not available\n");
194 return;
197 for (pt = 0; pt < PROP_ID_INVALID; pt++)
199 SPropValue pv;
201 memset(&pv, 0 ,sizeof(pv));
202 pv.ulPropTag = pt;
204 exp = 1u; /* Default to one item for non-MV properties */
206 switch (PROP_TYPE(pt))
208 case PT_MV_I2: pv.Value.MVi.cValues = exp = 2;
209 case PT_I2: exp *= sizeof(USHORT); break;
210 case PT_MV_I4: pv.Value.MVl.cValues = exp = 2;
211 case PT_I4: exp *= sizeof(LONG); break;
212 case PT_MV_R4: pv.Value.MVflt.cValues = exp = 2;
213 case PT_R4: exp *= sizeof(float); break;
214 case PT_MV_DOUBLE: pv.Value.MVdbl.cValues = exp = 2;
215 case PT_R8: exp *= sizeof(double); break;
216 case PT_MV_CURRENCY: pv.Value.MVcur.cValues = exp = 2;
217 case PT_CURRENCY: exp *= sizeof(CY); break;
218 case PT_MV_APPTIME: pv.Value.MVat.cValues = exp = 2;
219 case PT_APPTIME: exp *= sizeof(double); break;
220 case PT_MV_SYSTIME: pv.Value.MVft.cValues = exp = 2;
221 case PT_SYSTIME: exp *= sizeof(FILETIME); break;
222 case PT_ERROR: exp = sizeof(SCODE); break;
223 case PT_BOOLEAN: exp = sizeof(USHORT); break;
224 case PT_OBJECT: exp = 0; break;
225 case PT_MV_I8: pv.Value.MVli.cValues = exp = 2;
226 case PT_I8: exp *= sizeof(LONG64); break;
227 #if 0
228 /* My version of native mapi returns 0 for PT_MV_CLSID even if a valid
229 * array is given. This _has_ to be a bug, so Wine does
230 * the right thing(tm) and we don't test it here.
232 case PT_MV_CLSID: pv.Value.MVguid.cValues = exp = 2;
233 #endif
234 case PT_CLSID: exp *= sizeof(GUID); break;
235 case PT_STRING8:
236 pv.Value.lpszA = szHiA;
237 exp = 4;
238 break;
239 case PT_UNICODE:
240 pv.Value.lpszW = szHiW;
241 exp = 4 * sizeof(WCHAR);
242 break;
243 case PT_BINARY:
244 pv.Value.bin.cb = exp = 19;
245 break;
246 case PT_MV_STRING8:
247 pv.Value.MVszA.cValues = 2;
248 pv.Value.MVszA.lppszA = buffa;
249 buffa[0] = szHiA;
250 buffa[1] = szHiA;
251 exp = 8;
252 break;
253 case PT_MV_UNICODE:
254 pv.Value.MVszW.cValues = 2;
255 pv.Value.MVszW.lppszW = buffw;
256 buffw[0] = szHiW;
257 buffw[1] = szHiW;
258 exp = 8 * sizeof(WCHAR);
259 break;
260 case PT_MV_BINARY:
261 pv.Value.MVbin.cValues = 2;
262 pv.Value.MVbin.lpbin = buffbin;
263 buffbin[0].cb = 19;
264 buffbin[1].cb = 1;
265 exp = 20;
266 break;
267 default:
268 exp = 0;
271 res = pUlPropSize(&pv);
272 ok(res == exp,
273 "pt= %d: Expected %d, got %d\n", pt, exp, res);
277 static void test_FPropContainsProp(void)
279 static char szFull[] = "Full String";
280 static char szFullLower[] = "full string";
281 static char szPrefix[] = "Full";
282 static char szPrefixLower[] = "full";
283 static char szSubstring[] = "ll St";
284 static char szSubstringLower[] = "ll st";
285 SPropValue pvLeft, pvRight;
286 ULONG pt;
287 BOOL bRet;
289 if (!pFPropContainsProp)
291 win_skip("FPropContainsProp is not available\n");
292 return;
295 /* Ensure that only PT_STRING8 and PT_BINARY are handled */
296 for (pt = 0; pt < PROP_ID_INVALID; pt++)
298 if (pt == PT_STRING8 || pt == PT_BINARY)
299 continue; /* test these later */
301 memset(&pvLeft, 0 ,sizeof(pvLeft));
302 memset(&pvRight, 0 ,sizeof(pvRight));
303 pvLeft.ulPropTag = pvRight.ulPropTag = pt;
305 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
306 ok(bRet == FALSE, "pt= %d: Expected FALSE, got %d\n", pt, bRet);
309 /* test the various flag combinations */
310 pvLeft.ulPropTag = pvRight.ulPropTag = PT_STRING8;
311 pvLeft.Value.lpszA = szFull;
312 pvRight.Value.lpszA = szFull;
314 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
315 ok(bRet == TRUE, "(full,full)[] match failed\n");
316 pvRight.Value.lpszA = szPrefix;
317 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
318 ok(bRet == FALSE, "(full,prefix)[] match failed\n");
319 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
320 ok(bRet == TRUE, "(full,prefix)[PREFIX] match failed\n");
321 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
322 ok(bRet == TRUE, "(full,prefix)[SUBSTRING] match failed\n");
323 pvRight.Value.lpszA = szPrefixLower;
324 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
325 ok(bRet == FALSE, "(full,prefixlow)[PREFIX] match failed\n");
326 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
327 ok(bRet == FALSE, "(full,prefixlow)[SUBSTRING] match failed\n");
328 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE);
329 ok(bRet == TRUE, "(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
330 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
331 ok(bRet == TRUE, "(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
332 pvRight.Value.lpszA = szSubstring;
333 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
334 ok(bRet == FALSE, "(full,substr)[] match failed\n");
335 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
336 ok(bRet == FALSE, "(full,substr)[PREFIX] match failed\n");
337 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
338 ok(bRet == TRUE, "(full,substr)[SUBSTRING] match failed\n");
339 pvRight.Value.lpszA = szSubstringLower;
340 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
341 ok(bRet == FALSE, "(full,substrlow)[PREFIX] match failed\n");
342 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
343 ok(bRet == FALSE, "(full,substrlow)[SUBSTRING] match failed\n");
344 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE);
345 ok(bRet == FALSE, "(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
346 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
347 ok(bRet == TRUE, "(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
348 pvRight.Value.lpszA = szFullLower;
349 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING|FL_IGNORECASE);
350 ok(bRet == TRUE, "(full,fulllow)[IGNORECASE] match failed\n");
352 pvLeft.ulPropTag = pvRight.ulPropTag = PT_BINARY;
353 pvLeft.Value.bin.lpb = (LPBYTE)szFull;
354 pvRight.Value.bin.lpb = (LPBYTE)szFull;
355 pvLeft.Value.bin.cb = pvRight.Value.bin.cb = strlen(szFull);
357 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
358 ok(bRet == TRUE, "bin(full,full)[] match failed\n");
359 pvRight.Value.bin.lpb = (LPBYTE)szPrefix;
360 pvRight.Value.bin.cb = strlen(szPrefix);
361 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
362 ok(bRet == FALSE, "bin(full,prefix)[] match failed\n");
363 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
364 ok(bRet == TRUE, "bin(full,prefix)[PREFIX] match failed\n");
365 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
366 ok(bRet == TRUE, "bin(full,prefix)[SUBSTRING] match failed\n");
367 pvRight.Value.bin.lpb = (LPBYTE)szPrefixLower;
368 pvRight.Value.bin.cb = strlen(szPrefixLower);
369 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
370 ok(bRet == FALSE, "bin(full,prefixlow)[PREFIX] match failed\n");
371 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
372 ok(bRet == FALSE, "bin(full,prefixlow)[SUBSTRING] match failed\n");
373 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE);
374 ok(bRet == FALSE, "bin(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
375 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
376 ok(bRet == FALSE, "bin(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
377 pvRight.Value.bin.lpb = (LPBYTE)szSubstring;
378 pvRight.Value.bin.cb = strlen(szSubstring);
379 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
380 ok(bRet == FALSE, "bin(full,substr)[] match failed\n");
381 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
382 ok(bRet == FALSE, "bin(full,substr)[PREFIX] match failed\n");
383 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
384 ok(bRet == TRUE, "bin(full,substr)[SUBSTRING] match failed\n");
385 pvRight.Value.bin.lpb = (LPBYTE)szSubstringLower;
386 pvRight.Value.bin.cb = strlen(szSubstringLower);
387 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX);
388 ok(bRet == FALSE, "bin(full,substrlow)[PREFIX] match failed\n");
389 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
390 ok(bRet == FALSE, "bin(full,substrlow)[SUBSTRING] match failed\n");
391 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE);
392 ok(bRet == FALSE, "bin(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
393 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
394 ok(bRet == FALSE, "bin(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
395 pvRight.Value.bin.lpb = (LPBYTE)szFullLower;
396 pvRight.Value.bin.cb = strlen(szFullLower);
397 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING|FL_IGNORECASE);
398 ok(bRet == FALSE, "bin(full,fulllow)[IGNORECASE] match failed\n");
401 typedef struct tagFPropCompareProp_Result
403 SHORT lVal;
404 SHORT rVal;
405 ULONG relOp;
406 BOOL bRet;
407 } FPropCompareProp_Result;
409 static const FPropCompareProp_Result FPCProp_Results[] =
411 { 1, 2, RELOP_LT, TRUE },
412 { 1, 1, RELOP_LT, FALSE },
413 { 2, 1, RELOP_LT, FALSE },
414 { 1, 2, RELOP_LE, TRUE },
415 { 1, 1, RELOP_LE, TRUE },
416 { 2, 1, RELOP_LE, FALSE },
417 { 1, 2, RELOP_GT, FALSE },
418 { 1, 1, RELOP_GT, FALSE },
419 { 2, 1, RELOP_GT, TRUE },
420 { 1, 2, RELOP_GE, FALSE },
421 { 1, 1, RELOP_GE, TRUE },
422 { 2, 1, RELOP_GE, TRUE },
423 { 1, 2, RELOP_EQ, FALSE },
424 { 1, 1, RELOP_EQ, TRUE },
425 { 2, 1, RELOP_EQ, FALSE }
428 static const char *relops[] = { "RELOP_LT", "RELOP_LE", "RELOP_GT", "RELOP_GE", "RELOP_EQ" };
430 static void test_FPropCompareProp(void)
432 SPropValue pvLeft, pvRight;
433 GUID lguid, rguid;
434 char lbuffa[2], rbuffa[2];
435 WCHAR lbuffw[2], rbuffw[2];
436 ULONG i, j;
437 BOOL bRet, bExp;
439 if (!pFPropCompareProp)
441 win_skip("FPropCompareProp is not available\n");
442 return;
445 lbuffa[1] = '\0';
446 rbuffa[1] = '\0';
447 lbuffw[1] = '\0';
448 rbuffw[1] = '\0';
450 for (i = 0; i < ARRAY_SIZE(ptTypes); i++)
452 pvLeft.ulPropTag = pvRight.ulPropTag = ptTypes[i];
454 for (j = 0; j < ARRAY_SIZE(FPCProp_Results); j++)
456 SHORT lVal = FPCProp_Results[j].lVal;
457 SHORT rVal = FPCProp_Results[j].rVal;
459 bExp = FPCProp_Results[j].bRet;
461 switch (ptTypes[i])
463 case PT_BOOLEAN:
464 /* Boolean values have no concept of less or greater than, only equality */
465 if ((lVal == 1 && rVal == 2 && FPCProp_Results[j].relOp == RELOP_LT) ||
466 (lVal == 2 && rVal == 1 && FPCProp_Results[j].relOp == RELOP_LE)||
467 (lVal == 2 && rVal == 1 && FPCProp_Results[j].relOp == RELOP_GT)||
468 (lVal == 1 && rVal == 2 && FPCProp_Results[j].relOp == RELOP_GE)||
469 (lVal == 1 && rVal == 2 && FPCProp_Results[j].relOp == RELOP_EQ)||
470 (lVal == 2 && rVal == 1 && FPCProp_Results[j].relOp == RELOP_EQ))
471 bExp = !bExp;
472 /* Fall through ... */
473 case PT_I2:
474 pvLeft.Value.i = lVal;
475 pvRight.Value.i = rVal;
476 break;
477 case PT_ERROR:
478 case PT_I4:
479 pvLeft.Value.l = lVal;
480 pvRight.Value.l = rVal;
481 break;
482 case PT_R4:
483 pvLeft.Value.flt = lVal;
484 pvRight.Value.flt = rVal;
485 break;
486 case PT_APPTIME:
487 case PT_R8:
488 pvLeft.Value.dbl = lVal;
489 pvRight.Value.dbl = rVal;
490 break;
491 case PT_CURRENCY:
492 pvLeft.Value.cur.int64 = lVal;
493 pvRight.Value.cur.int64 = rVal;
494 break;
495 case PT_SYSTIME:
496 pvLeft.Value.ft.dwLowDateTime = lVal;
497 pvLeft.Value.ft.dwHighDateTime = 0;
498 pvRight.Value.ft.dwLowDateTime = rVal;
499 pvRight.Value.ft.dwHighDateTime = 0;
500 break;
501 case PT_I8:
502 pvLeft.Value.li.u.LowPart = lVal;
503 pvLeft.Value.li.u.HighPart = 0;
504 pvRight.Value.li.u.LowPart = rVal;
505 pvRight.Value.li.u.HighPart = 0;
506 break;
507 case PT_CLSID:
508 memset(&lguid, 0, sizeof(GUID));
509 memset(&rguid, 0, sizeof(GUID));
510 lguid.Data4[7] = lVal;
511 rguid.Data4[7] = rVal;
512 pvLeft.Value.lpguid = &lguid;
513 pvRight.Value.lpguid = &rguid;
514 break;
515 case PT_STRING8:
516 pvLeft.Value.lpszA = lbuffa;
517 pvRight.Value.lpszA = rbuffa;
518 lbuffa[0] = '0' + lVal;
519 rbuffa[0] = '0' + rVal;
520 break;
521 case PT_UNICODE:
522 pvLeft.Value.lpszW = lbuffw;
523 pvRight.Value.lpszW = rbuffw;
524 lbuffw[0] = '0' + lVal;
525 rbuffw[0] = '0' + rVal;
526 break;
527 case PT_BINARY:
528 pvLeft.Value.bin.cb = 1;
529 pvRight.Value.bin.cb = 1;
530 pvLeft.Value.bin.lpb = (LPBYTE)lbuffa;
531 pvRight.Value.bin.lpb = (LPBYTE)rbuffa;
532 lbuffa[0] = lVal;
533 rbuffa[0] = rVal;
534 break;
537 bRet = pFPropCompareProp(&pvLeft, FPCProp_Results[j].relOp, &pvRight);
538 ok(bRet == bExp,
539 "pt %d (%d,%d,%s): expected %d, got %d\n", ptTypes[i],
540 FPCProp_Results[j].lVal, FPCProp_Results[j].rVal,
541 relops[FPCProp_Results[j].relOp], bExp, bRet);
546 typedef struct tagLPropCompareProp_Result
548 SHORT lVal;
549 SHORT rVal;
550 INT iRet;
551 } LPropCompareProp_Result;
553 static const LPropCompareProp_Result LPCProp_Results[] =
555 { 1, 2, -1 },
556 { 1, 1, 0 },
557 { 2, 1, 1 },
560 static void test_LPropCompareProp(void)
562 SPropValue pvLeft, pvRight;
563 GUID lguid, rguid;
564 char lbuffa[2], rbuffa[2];
565 WCHAR lbuffw[2], rbuffw[2];
566 ULONG i, j;
567 INT iRet, iExp;
569 if (!pLPropCompareProp)
571 win_skip("LPropCompareProp is not available\n");
572 return;
575 lbuffa[1] = '\0';
576 rbuffa[1] = '\0';
577 lbuffw[1] = '\0';
578 rbuffw[1] = '\0';
580 for (i = 0; i < ARRAY_SIZE(ptTypes); i++)
582 pvLeft.ulPropTag = pvRight.ulPropTag = ptTypes[i];
584 for (j = 0; j < ARRAY_SIZE(LPCProp_Results); j++)
586 SHORT lVal = LPCProp_Results[j].lVal;
587 SHORT rVal = LPCProp_Results[j].rVal;
589 iExp = LPCProp_Results[j].iRet;
591 switch (ptTypes[i])
593 case PT_BOOLEAN:
594 /* Boolean values have no concept of less or greater than, only equality */
595 if (lVal && rVal)
596 iExp = 0;
597 /* Fall through ... */
598 case PT_I2:
599 pvLeft.Value.i = lVal;
600 pvRight.Value.i = rVal;
601 break;
602 case PT_ERROR:
603 case PT_I4:
604 pvLeft.Value.l = lVal;
605 pvRight.Value.l = rVal;
606 break;
607 case PT_R4:
608 pvLeft.Value.flt = lVal;
609 pvRight.Value.flt = rVal;
610 break;
611 case PT_APPTIME:
612 case PT_R8:
613 pvLeft.Value.dbl = lVal;
614 pvRight.Value.dbl = rVal;
615 break;
616 case PT_CURRENCY:
617 pvLeft.Value.cur.int64 = lVal;
618 pvRight.Value.cur.int64 = rVal;
619 break;
620 case PT_SYSTIME:
621 pvLeft.Value.ft.dwLowDateTime = lVal;
622 pvLeft.Value.ft.dwHighDateTime = 0;
623 pvRight.Value.ft.dwLowDateTime = rVal;
624 pvRight.Value.ft.dwHighDateTime = 0;
625 break;
626 case PT_I8:
627 pvLeft.Value.li.u.LowPart = lVal;
628 pvLeft.Value.li.u.HighPart = 0;
629 pvRight.Value.li.u.LowPart = rVal;
630 pvRight.Value.li.u.HighPart = 0;
631 break;
632 case PT_CLSID:
633 memset(&lguid, 0, sizeof(GUID));
634 memset(&rguid, 0, sizeof(GUID));
635 lguid.Data4[7] = lVal;
636 rguid.Data4[7] = rVal;
637 pvLeft.Value.lpguid = &lguid;
638 pvRight.Value.lpguid = &rguid;
639 break;
640 case PT_STRING8:
641 pvLeft.Value.lpszA = lbuffa;
642 pvRight.Value.lpszA = rbuffa;
643 lbuffa[0] = '0' + lVal;
644 rbuffa[0] = '0' + rVal;
645 break;
646 case PT_UNICODE:
647 pvLeft.Value.lpszW = lbuffw;
648 pvRight.Value.lpszW = rbuffw;
649 lbuffw[0] = '0' + lVal;
650 rbuffw[0] = '0' + rVal;
651 break;
652 case PT_BINARY:
653 pvLeft.Value.bin.cb = 1;
654 pvRight.Value.bin.cb = 1;
655 pvLeft.Value.bin.lpb = (LPBYTE)lbuffa;
656 pvRight.Value.bin.lpb = (LPBYTE)rbuffa;
657 lbuffa[0] = lVal;
658 rbuffa[0] = rVal;
659 break;
662 iRet = pLPropCompareProp(&pvLeft, &pvRight);
663 ok(iRet == iExp,
664 "pt %d (%d,%d): expected %d, got %d\n", ptTypes[i],
665 LPCProp_Results[j].lVal, LPCProp_Results[j].rVal, iExp, iRet);
670 static void test_PpropFindProp(void)
672 SPropValue pvProp, *pRet;
673 ULONG i;
675 if (!pPpropFindProp)
677 win_skip("PpropFindProp is not available\n");
678 return;
681 for (i = 0; i < ARRAY_SIZE(ptTypes); i++)
683 pvProp.ulPropTag = ptTypes[i];
685 pRet = pPpropFindProp(&pvProp, 1u, ptTypes[i]);
686 ok(pRet == &pvProp,
687 "PpropFindProp[%d]: Didn't find existing property\n",
688 ptTypes[i]);
690 pRet = pPpropFindProp(&pvProp, 1u, i ? ptTypes[i-1] : ptTypes[i+1]);
691 ok(pRet == NULL, "PpropFindProp[%d]: Found nonexistent property\n",
692 ptTypes[i]);
695 pvProp.ulPropTag = PROP_TAG(PT_I2, 1u);
696 pRet = pPpropFindProp(&pvProp, 1u, PROP_TAG(PT_UNSPECIFIED, 0u));
697 ok(pRet == NULL, "PpropFindProp[UNSPECIFIED]: Matched on different id\n");
698 pRet = pPpropFindProp(&pvProp, 1u, PROP_TAG(PT_UNSPECIFIED, 1u));
699 ok(pRet == &pvProp, "PpropFindProp[UNSPECIFIED]: Didn't match id\n");
702 static void test_ScCountProps(void)
704 static char szHiA[] = "Hi!";
705 static WCHAR szHiW[] = L"Hi!";
706 static const ULONG ULHILEN = 4; /* chars in szHiA/W incl. NUL */
707 LPSTR buffa[3];
708 LPWSTR buffw[3];
709 SBinary buffbin[3];
710 GUID iids[4], *iid = iids;
711 SCODE res;
712 ULONG pt, exp, ulRet;
713 BOOL success = TRUE;
715 if (!pScCountProps)
717 win_skip("ScCountProps is not available\n");
718 return;
721 for (pt = 0; pt < PROP_ID_INVALID && success; pt++)
723 SPropValue pv;
725 memset(&pv, 0 ,sizeof(pv));
726 pv.ulPropTag = PROP_TAG(pt, 1u);
728 switch (PROP_TYPE(pt))
730 case PT_I2:
731 case PT_I4:
732 case PT_R4:
733 case PT_R8:
734 case PT_CURRENCY:
735 case PT_APPTIME:
736 case PT_SYSTIME:
737 case PT_ERROR:
738 case PT_BOOLEAN:
739 case PT_OBJECT:
740 case PT_I8:
741 exp = sizeof(pv);
742 break;
743 case PT_CLSID:
744 pv.Value.lpguid = iid;
745 exp = sizeof(GUID) + sizeof(pv);
746 break;
747 case PT_STRING8:
748 pv.Value.lpszA = szHiA;
749 exp = 4 + sizeof(pv);
750 break;
751 case PT_UNICODE:
752 pv.Value.lpszW = szHiW;
753 exp = 4 * sizeof(WCHAR) + sizeof(pv);
754 break;
755 case PT_BINARY:
756 pv.Value.bin.cb = 2;
757 pv.Value.bin.lpb = (LPBYTE)iid;
758 exp = 2 + sizeof(pv);
759 break;
760 case PT_MV_I2:
761 pv.Value.MVi.cValues = 3;
762 pv.Value.MVi.lpi = (SHORT*)iid;
763 exp = 3 * sizeof(SHORT) + sizeof(pv);
764 break;
765 case PT_MV_I4:
766 pv.Value.MVl.cValues = 3;
767 pv.Value.MVl.lpl = (LONG*)iid;
768 exp = 3 * sizeof(LONG) + sizeof(pv);
769 break;
770 case PT_MV_I8:
771 pv.Value.MVli.cValues = 3;
772 pv.Value.MVli.lpli = (LARGE_INTEGER*)iid;
773 exp = 3 * sizeof(LARGE_INTEGER) + sizeof(pv);
774 break;
775 case PT_MV_R4:
776 pv.Value.MVflt.cValues = 3;
777 pv.Value.MVflt.lpflt = (float*)iid;
778 exp = 3 * sizeof(float) + sizeof(pv);
779 break;
780 case PT_MV_APPTIME:
781 case PT_MV_R8:
782 pv.Value.MVdbl.cValues = 3;
783 pv.Value.MVdbl.lpdbl = (double*)iid;
784 exp = 3 * sizeof(double) + sizeof(pv);
785 break;
786 case PT_MV_CURRENCY:
787 pv.Value.MVcur.cValues = 3;
788 pv.Value.MVcur.lpcur = (CY*)iid;
789 exp = 3 * sizeof(CY) + sizeof(pv);
790 break;
791 case PT_MV_SYSTIME:
792 pv.Value.MVft.cValues = 3;
793 pv.Value.MVft.lpft = (FILETIME*)iid;
794 exp = 3 * sizeof(CY) + sizeof(pv);
795 break;
796 case PT_MV_STRING8:
797 pv.Value.MVszA.cValues = 3;
798 pv.Value.MVszA.lppszA = buffa;
799 buffa[0] = szHiA;
800 buffa[1] = szHiA;
801 buffa[2] = szHiA;
802 exp = ULHILEN * 3 + 3 * sizeof(char*) + sizeof(pv);
803 break;
804 case PT_MV_UNICODE:
805 pv.Value.MVszW.cValues = 3;
806 pv.Value.MVszW.lppszW = buffw;
807 buffw[0] = szHiW;
808 buffw[1] = szHiW;
809 buffw[2] = szHiW;
810 exp = ULHILEN * 3 * sizeof(WCHAR) + 3 * sizeof(WCHAR*) + sizeof(pv);
811 break;
812 case PT_MV_BINARY:
813 pv.Value.MVbin.cValues = 3;
814 pv.Value.MVbin.lpbin = buffbin;
815 buffbin[0].cb = 17;
816 buffbin[0].lpb = (LPBYTE)&iid;
817 buffbin[1].cb = 2;
818 buffbin[1].lpb = (LPBYTE)&iid;
819 buffbin[2].cb = 1;
820 buffbin[2].lpb = (LPBYTE)&iid;
821 exp = 20 + sizeof(pv) + sizeof(SBinary) * 3;
822 break;
823 default:
824 exp = 0;
827 ulRet = 0xffffffff;
828 res = pScCountProps(1, &pv, &ulRet);
829 if (!exp) {
830 success = res == MAPI_E_INVALID_PARAMETER && ulRet == 0xffffffff;
831 ok(success, "pt= %d: Expected failure, got %d, ret=0x%08X\n",
832 pt, ulRet, res);
834 else {
835 success = res == S_OK && ulRet == exp;
836 ok(success, "pt= %d: Expected %d, got %d, ret=0x%08X\n",
837 pt, exp, ulRet, res);
843 static void test_ScCopyRelocProps(void)
845 static char szTestA[] = "Test";
846 char buffer[512], buffer2[512], *lppszA[1];
847 SPropValue pvProp, *lpResProp = (LPSPropValue)buffer;
848 ULONG ulCount;
849 SCODE sc;
851 if (!pScCopyProps || !pScRelocProps)
853 win_skip("SPropValue copy functions are not available\n");
854 return;
857 pvProp.ulPropTag = PROP_TAG(PT_MV_STRING8, 1u);
859 lppszA[0] = szTestA;
860 pvProp.Value.MVszA.cValues = 1;
861 pvProp.Value.MVszA.lppszA = lppszA;
862 ulCount = 0;
864 sc = pScCopyProps(1, &pvProp, buffer, &ulCount);
865 ok(sc == S_OK, "wrong ret %d\n", sc);
866 if(sc == S_OK)
868 ok(lpResProp->ulPropTag == pvProp.ulPropTag, "wrong tag %x\n",lpResProp->ulPropTag);
869 ok(lpResProp->Value.MVszA.cValues == 1, "wrong cValues %d\n", lpResProp->Value.MVszA.cValues);
870 ok(lpResProp->Value.MVszA.lppszA[0] == buffer + sizeof(SPropValue) + sizeof(char*),
871 "wrong lppszA[0] %p\n",lpResProp->Value.MVszA.lppszA[0]);
872 ok(ulCount == sizeof(SPropValue) + sizeof(char*) + 5, "wrong count %d\n", ulCount);
873 ok(!strcmp(lpResProp->Value.MVszA.lppszA[0], szTestA),
874 "wrong string '%s'\n", lpResProp->Value.MVszA.lppszA[0]);
877 memcpy(buffer2, buffer, sizeof(buffer));
879 /* Clear the data in the source buffer. Since pointers in the copied buffer
880 * refer to the source buffer, this proves that native always assumes that
881 * the copied buffers pointers are bad (needing to be relocated first).
883 memset(buffer, 0, sizeof(buffer));
884 ulCount = 0;
886 sc = pScRelocProps(1, (LPSPropValue)buffer2, buffer, buffer2, &ulCount);
887 lpResProp = (LPSPropValue)buffer2;
889 ok(sc == S_OK, "wrong ret %d\n", sc);
890 if(sc == S_OK)
892 ok(lpResProp->ulPropTag == pvProp.ulPropTag, "wrong tag %x\n",lpResProp->ulPropTag);
893 ok(lpResProp->Value.MVszA.cValues == 1, "wrong cValues %d\n", lpResProp->Value.MVszA.cValues);
894 ok(lpResProp->Value.MVszA.lppszA[0] == buffer2 + sizeof(SPropValue) + sizeof(char*),
895 "wrong lppszA[0] %p\n",lpResProp->Value.MVszA.lppszA[0]);
896 /* Native has a bug whereby it calculates the size correctly when copying
897 * but when relocating does not (presumably it uses UlPropSize() which
898 * ignores multivalue pointers). Wine returns the correct value.
900 ok(ulCount == sizeof(SPropValue) + sizeof(char*) + 5 || ulCount == sizeof(SPropValue) + 5,
901 "wrong count %d\n", ulCount);
902 ok(!strcmp(lpResProp->Value.MVszA.lppszA[0], szTestA),
903 "wrong string '%s'\n", lpResProp->Value.MVszA.lppszA[0]);
906 /* Native crashes with lpNew or lpOld set to NULL so skip testing this */
909 static void test_LpValFindProp(void)
911 SPropValue pvProp, *pRet;
912 ULONG i;
914 if (!pLpValFindProp)
916 win_skip("LpValFindProp is not available\n");
917 return;
920 for (i = 0; i < ARRAY_SIZE(ptTypes); i++)
922 pvProp.ulPropTag = PROP_TAG(ptTypes[i], 1u);
924 pRet = pLpValFindProp(PROP_TAG(ptTypes[i], 1u), 1u, &pvProp);
925 ok(pRet == &pvProp,
926 "LpValFindProp[%d]: Didn't find existing property id/type\n",
927 ptTypes[i]);
929 pRet = pLpValFindProp(PROP_TAG(ptTypes[i], 0u), 1u, &pvProp);
930 ok(pRet == NULL, "LpValFindProp[%d]: Found nonexistent property id\n",
931 ptTypes[i]);
933 pRet = pLpValFindProp(PROP_TAG(PT_NULL, 0u), 1u, &pvProp);
934 ok(pRet == NULL, "LpValFindProp[%d]: Found nonexistent property id/type\n",
935 ptTypes[i]);
937 pRet = pLpValFindProp(PROP_TAG(PT_NULL, 1u), 1u, &pvProp);
938 ok(pRet == &pvProp,
939 "LpValFindProp[%d]: Didn't find existing property id\n",
940 ptTypes[i]);
944 static void test_FBadRglpszA(void)
946 LPSTR lpStrs[4];
947 static CHAR szString[] = "A String";
948 BOOL bRet;
950 if (!pFBadRglpszA)
952 win_skip("FBadRglpszA is not available\n");
953 return;
956 bRet = pFBadRglpszA(NULL, 10);
957 ok(bRet == TRUE, "FBadRglpszA(Null): expected TRUE, got FALSE\n");
959 lpStrs[0] = lpStrs[1] = lpStrs[2] = lpStrs[3] = NULL;
960 bRet = pFBadRglpszA(lpStrs, 4);
961 ok(bRet == TRUE, "FBadRglpszA(Nulls): expected TRUE, got FALSE\n");
963 lpStrs[0] = lpStrs[1] = lpStrs[2] = szString;
964 bRet = pFBadRglpszA(lpStrs, 3);
965 ok(bRet == FALSE, "FBadRglpszA(valid): expected FALSE, got TRUE\n");
967 bRet = pFBadRglpszA(lpStrs, 4);
968 ok(bRet == TRUE, "FBadRglpszA(1 invalid): expected TRUE, got FALSE\n");
971 static void test_FBadRglpszW(void)
973 LPWSTR lpStrs[4];
974 static WCHAR szString[] = L"A String";
975 BOOL bRet;
977 if (!pFBadRglpszW)
979 win_skip("FBadRglpszW is not available\n");
980 return;
983 bRet = pFBadRglpszW(NULL, 10);
984 ok(bRet == TRUE, "FBadRglpszW(Null): expected TRUE, got FALSE\n");
986 lpStrs[0] = lpStrs[1] = lpStrs[2] = lpStrs[3] = NULL;
987 bRet = pFBadRglpszW(lpStrs, 4);
988 ok(bRet == TRUE, "FBadRglpszW(Nulls): expected TRUE, got FALSE\n");
990 lpStrs[0] = lpStrs[1] = lpStrs[2] = szString;
991 bRet = pFBadRglpszW(lpStrs, 3);
992 ok(bRet == FALSE, "FBadRglpszW(valid): expected FALSE, got TRUE\n");
994 bRet = pFBadRglpszW(lpStrs, 4);
995 ok(bRet == TRUE, "FBadRglpszW(1 invalid): expected TRUE, got FALSE\n");
998 static void test_FBadRowSet(void)
1000 ULONG ulRet;
1002 if (!pFBadRowSet)
1004 win_skip("FBadRowSet is not available\n");
1005 return;
1008 ulRet = pFBadRowSet(NULL);
1009 ok(ulRet != 0, "FBadRow(null): Expected non-zero, got 0\n");
1011 /* FIXME */
1014 static void test_FBadPropTag(void)
1016 ULONG pt, res;
1018 if (!pFBadPropTag)
1020 win_skip("FBadPropTag is not available\n");
1021 return;
1024 for (pt = 0; pt < PROP_ID_INVALID; pt++)
1026 BOOL bBad = TRUE;
1028 switch (pt & (~MV_FLAG & PROP_TYPE_MASK))
1030 case PT_UNSPECIFIED:
1031 case PT_NULL: case PT_I2: case PT_I4: case PT_R4:
1032 case PT_R8: case PT_CURRENCY: case PT_APPTIME:
1033 case PT_ERROR: case PT_BOOLEAN: case PT_OBJECT:
1034 case PT_I8: case PT_STRING8: case PT_UNICODE:
1035 case PT_SYSTIME: case PT_CLSID: case PT_BINARY:
1036 bBad = FALSE;
1039 res = pFBadPropTag(pt);
1040 if (bBad)
1041 ok(res != 0, "pt= %d: Expected non-zero, got 0\n", pt);
1042 else
1043 ok(res == 0,
1044 "pt= %d: Expected zero, got %d\n", pt, res);
1048 static void test_FBadRow(void)
1050 ULONG ulRet;
1052 if (!pFBadRow)
1054 win_skip("FBadRow is not available\n");
1055 return;
1058 ulRet = pFBadRow(NULL);
1059 ok(ulRet != 0, "FBadRow(null): Expected non-zero, got 0\n");
1061 /* FIXME */
1064 static void test_FBadProp(void)
1066 static WCHAR szEmpty[] = L"";
1067 GUID iid;
1068 ULONG pt, res;
1069 SPropValue pv;
1071 if (!pFBadProp)
1073 win_skip("FBadProp is not available\n");
1074 return;
1077 for (pt = 0; pt < PROP_ID_INVALID; pt++)
1079 BOOL bBad = TRUE;
1081 memset(&pv, 0, sizeof(pv));
1082 pv.ulPropTag = pt;
1084 /* Note that MV values are valid below because their array count is 0,
1085 * so no pointers are validated.
1087 switch (PROP_TYPE(pt))
1089 case (MV_FLAG|PT_UNSPECIFIED):
1090 case PT_UNSPECIFIED:
1091 case (MV_FLAG|PT_NULL):
1092 case PT_NULL:
1093 case PT_MV_I2:
1094 case PT_I2:
1095 case PT_MV_I4:
1096 case PT_I4:
1097 case PT_MV_I8:
1098 case PT_I8:
1099 case PT_MV_R4:
1100 case PT_R4:
1101 case PT_MV_R8:
1102 case PT_R8:
1103 case PT_MV_CURRENCY:
1104 case PT_CURRENCY:
1105 case PT_MV_APPTIME:
1106 case PT_APPTIME:
1107 case (MV_FLAG|PT_ERROR):
1108 case PT_ERROR:
1109 case (MV_FLAG|PT_BOOLEAN):
1110 case PT_BOOLEAN:
1111 case (MV_FLAG|PT_OBJECT):
1112 case PT_OBJECT:
1113 case PT_MV_STRING8:
1114 case PT_MV_UNICODE:
1115 case PT_MV_SYSTIME:
1116 case PT_SYSTIME:
1117 case PT_MV_BINARY:
1118 case PT_BINARY:
1119 case PT_MV_CLSID:
1120 bBad = FALSE;
1121 break;
1122 case PT_STRING8:
1123 case PT_UNICODE:
1124 pv.Value.lpszW = szEmpty;
1125 bBad = FALSE;
1126 break;
1127 case PT_CLSID:
1128 pv.Value.lpguid = &iid;
1129 bBad = FALSE;
1130 break;
1133 res = pFBadProp(&pv);
1134 if (bBad)
1135 ok(res != 0, "pt= %d: Expected non-zero, got 0\n", pt);
1136 else
1137 ok(res == 0,
1138 "pt= %d: Expected zero, got %d\n", pt, res);
1142 static void test_FBadColumnSet(void)
1144 SPropTagArray pta;
1145 ULONG pt, res;
1147 if (!pFBadColumnSet)
1149 win_skip("FBadColumnSet is not available\n");
1150 return;
1153 res = pFBadColumnSet(NULL);
1154 ok(res != 0, "(null): Expected non-zero, got 0\n");
1156 pta.cValues = 1;
1158 for (pt = 0; pt < PROP_ID_INVALID; pt++)
1160 BOOL bBad = TRUE;
1162 pta.aulPropTag[0] = pt;
1164 switch (pt & (~MV_FLAG & PROP_TYPE_MASK))
1166 case PT_UNSPECIFIED:
1167 case PT_NULL:
1168 case PT_I2:
1169 case PT_I4:
1170 case PT_R4:
1171 case PT_R8:
1172 case PT_CURRENCY:
1173 case PT_APPTIME:
1174 case PT_BOOLEAN:
1175 case PT_OBJECT:
1176 case PT_I8:
1177 case PT_STRING8:
1178 case PT_UNICODE:
1179 case PT_SYSTIME:
1180 case PT_CLSID:
1181 case PT_BINARY:
1182 bBad = FALSE;
1184 if (pt == (MV_FLAG|PT_ERROR))
1185 bBad = FALSE;
1187 res = pFBadColumnSet(&pta);
1188 if (bBad)
1189 ok(res != 0, "pt= %d: Expected non-zero, got 0\n", pt);
1190 else
1191 ok(res == 0,
1192 "pt= %d: Expected zero, got %d\n", pt, res);
1197 static void test_IProp(void)
1199 IPropData *lpIProp;
1200 LPMAPIERROR lpError;
1201 LPSPropProblemArray lpProbs;
1202 LPSPropValue lpProps;
1203 LPSPropTagArray lpTags;
1204 SPropValue pvs[2];
1205 SizedSPropTagArray(2,tags);
1206 ULONG access[2], count;
1207 SCODE sc;
1209 if (!pCreateIProp)
1211 win_skip("CreateIProp is not available\n");
1212 return;
1215 memset(&tags, 0 , sizeof(tags));
1217 /* Create the object */
1218 lpIProp = NULL;
1219 sc = pCreateIProp(&IID_IMAPIPropData, (ALLOCATEBUFFER *)pMAPIAllocateBuffer, (ALLOCATEMORE*)pMAPIAllocateMore,
1220 (FREEBUFFER *)pMAPIFreeBuffer, NULL, &lpIProp);
1221 ok(sc == S_OK && lpIProp,
1222 "CreateIProp: expected S_OK, non-null, got 0x%08X,%p\n", sc, lpIProp);
1224 if (sc != S_OK || !lpIProp)
1225 return;
1227 /* GetLastError - No errors set */
1228 lpError = NULL;
1229 sc = IPropData_GetLastError(lpIProp, E_INVALIDARG, 0, &lpError);
1230 ok(sc == S_OK && !lpError,
1231 "GetLastError: Expected S_OK, null, got 0x%08X,%p\n", sc, lpError);
1233 /* Get prop tags - succeeds returning 0 items */
1234 lpTags = NULL;
1235 sc = IPropData_GetPropList(lpIProp, 0, &lpTags);
1236 ok(sc == S_OK && lpTags && lpTags->cValues == 0,
1237 "GetPropList(empty): Expected S_OK, non-null, 0, got 0x%08X,%p,%d\n",
1238 sc, lpTags, lpTags ? lpTags->cValues : 0);
1239 if (lpTags)
1240 pMAPIFreeBuffer(lpTags);
1242 /* Get props - succeeds returning 0 items */
1243 lpProps = NULL;
1244 count = 0;
1245 tags.cValues = 1;
1246 tags.aulPropTag[0] = PR_IMPORTANCE;
1247 sc = IPropData_GetProps(lpIProp, (LPSPropTagArray)&tags, 0, &count, &lpProps);
1248 ok(sc == MAPI_W_ERRORS_RETURNED && lpProps && count == 1,
1249 "GetProps(empty): Expected ERRORS_RETURNED, non-null, 1, got 0x%08X,%p,%d\n",
1250 sc, lpProps, count);
1251 if (lpProps && count > 0)
1253 ok(lpProps[0].ulPropTag == CHANGE_PROP_TYPE(PR_IMPORTANCE,PT_ERROR),
1254 "GetProps(empty): Expected %x, got %x\n",
1255 CHANGE_PROP_TYPE(PR_IMPORTANCE,PT_ERROR), lpProps[0].ulPropTag);
1257 pMAPIFreeBuffer(lpProps);
1260 /* Add (NULL) - Can't add NULLs */
1261 lpProbs = NULL;
1262 pvs[0].ulPropTag = PROP_TAG(PT_NULL,0x01);
1263 sc = IPropData_SetProps(lpIProp, 1, pvs, &lpProbs);
1264 ok(sc == MAPI_E_INVALID_PARAMETER && !lpProbs,
1265 "SetProps(): Expected INVALID_PARAMETER, null, got 0x%08X,%p\n",
1266 sc, lpProbs);
1268 /* Add (OBJECT) - Can't add OBJECTs */
1269 lpProbs = NULL;
1270 pvs[0].ulPropTag = PROP_TAG(PT_OBJECT,0x01);
1271 sc = IPropData_SetProps(lpIProp, 1, pvs, &lpProbs);
1272 ok(sc == MAPI_E_INVALID_PARAMETER && !lpProbs,
1273 "SetProps(OBJECT): Expected INVALID_PARAMETER, null, got 0x%08X,%p\n",
1274 sc, lpProbs);
1276 /* Add - Adds value */
1277 lpProbs = NULL;
1278 pvs[0].ulPropTag = PR_IMPORTANCE;
1279 sc = IPropData_SetProps(lpIProp, 1, pvs, &lpProbs);
1280 ok(sc == S_OK && !lpProbs,
1281 "SetProps(ERROR): Expected S_OK, null, got 0x%08X,%p\n", sc, lpProbs);
1283 /* Get prop list - returns 1 item */
1284 lpTags = NULL;
1285 IPropData_GetPropList(lpIProp, 0, &lpTags);
1286 ok(sc == S_OK && lpTags && lpTags->cValues == 1,
1287 "GetPropList: Expected S_OK, non-null, 1, got 0x%08X,%p,%d\n",
1288 sc, lpTags, lpTags ? lpTags->cValues : 0);
1289 if (lpTags && lpTags->cValues > 0)
1291 ok(lpTags->aulPropTag[0] == PR_IMPORTANCE,
1292 "GetPropList: Expected %x, got %x\n",
1293 PR_IMPORTANCE, lpTags->aulPropTag[0]);
1294 pMAPIFreeBuffer(lpTags);
1297 /* Set access to read and write */
1298 sc = IPropData_HrSetObjAccess(lpIProp, IPROP_READWRITE);
1299 ok(sc == S_OK, "SetObjAccess(WRITE): Expected S_OK got 0x%08X\n", sc);
1301 tags.cValues = 1;
1302 tags.aulPropTag[0] = PR_IMPORTANCE;
1304 /* Set item access (bad access) - Fails */
1305 access[0] = 0;
1306 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1307 ok(sc == MAPI_E_INVALID_PARAMETER,
1308 "SetPropAccess(0): Expected INVALID_PARAMETER got 0x%08X\n",sc);
1309 access[0] = IPROP_READWRITE;
1310 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1311 ok(sc == MAPI_E_INVALID_PARAMETER,
1312 "SetPropAccess(RW): Expected INVALID_PARAMETER got 0x%08X\n",sc);
1313 access[0] = IPROP_CLEAN;
1314 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1315 ok(sc == MAPI_E_INVALID_PARAMETER,
1316 "SetPropAccess(C): Expected INVALID_PARAMETER got 0x%08X\n",sc);
1318 /* Set item access to read/write/clean */
1319 tags.cValues = 1;
1320 tags.aulPropTag[0] = PR_IMPORTANCE;
1321 access[0] = IPROP_READWRITE|IPROP_CLEAN;
1322 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1323 ok(sc == S_OK, "SetPropAccess(RW/C): Expected S_OK got 0x%08X\n",sc);
1325 /* Set object access to read only */
1326 sc = IPropData_HrSetObjAccess(lpIProp, IPROP_READONLY);
1327 ok(sc == S_OK, "SetObjAccess(READ): Expected S_OK got 0x%08X\n", sc);
1329 /* Set item access to read/write/dirty - doesn't care about RO object */
1330 access[0] = IPROP_READONLY|IPROP_DIRTY;
1331 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1332 ok(sc == S_OK, "SetPropAccess(WRITE): Expected S_OK got 0x%08X\n", sc);
1334 /* Delete any item when set to read only - Error */
1335 lpProbs = NULL;
1336 tags.aulPropTag[0] = PR_RESPONSE_REQUESTED;
1337 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1338 ok(sc == E_ACCESSDENIED && !lpProbs,
1339 "DeleteProps(nonexistent): Expected E_ACCESSDENIED null got 0x%08X %p\n",
1340 sc, lpProbs);
1342 /* Set access to read and write */
1343 sc = IPropData_HrSetObjAccess(lpIProp, IPROP_READWRITE);
1344 ok(sc == S_OK, "SetObjAccess(WRITE): Expected S_OK got 0x%08X\n", sc);
1346 /* Delete nonexistent item - No error */
1347 lpProbs = NULL;
1348 tags.aulPropTag[0] = PR_RESPONSE_REQUESTED;
1349 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1350 ok(sc == S_OK && !lpProbs,
1351 "DeleteProps(nonexistent): Expected S_OK null got 0x%08X %p\n",
1352 sc, lpProbs);
1354 /* Delete existing item (r/o) - No error, but lpProbs populated */
1355 lpProbs = NULL;
1356 tags.aulPropTag[0] = PR_IMPORTANCE;
1357 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1358 ok(sc == S_OK && lpProbs,
1359 "DeleteProps(RO): Expected S_OK non-null got 0x%08X %p\n", sc, lpProbs);
1361 if (lpProbs && lpProbs->cProblem > 0)
1363 ok(lpProbs->cProblem == 1 &&
1364 lpProbs->aProblem[0].ulIndex == 0 &&
1365 lpProbs->aProblem[0].ulPropTag == PR_IMPORTANCE &&
1366 lpProbs->aProblem[0].scode == E_ACCESSDENIED,
1367 "DeleteProps(RO): Expected (1,0,%x,%x) got (%d,%x,%x)\n",
1368 PR_IMPORTANCE, E_ACCESSDENIED,
1369 lpProbs->aProblem[0].ulIndex, lpProbs->aProblem[0].ulPropTag,
1370 lpProbs->aProblem[0].scode);
1371 pMAPIFreeBuffer(lpProbs);
1374 lpProbs = NULL;
1375 tags.cValues = 1;
1376 tags.aulPropTag[0] = PR_RESPONSE_REQUESTED;
1377 IPropData_HrAddObjProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1378 ok(sc == S_OK && !lpProbs,
1379 "AddObjProps(RO): Expected S_OK null got 0x%08X %p\n", sc, lpProbs);
1381 /* Get prop list - returns 1 item */
1382 lpTags = NULL;
1383 IPropData_GetPropList(lpIProp, 0, &lpTags);
1384 ok(sc == S_OK && lpTags && lpTags->cValues == 1,
1385 "GetPropList: Expected S_OK, non-null, 1, got 0x%08X,%p,%d\n",
1386 sc, lpTags, lpTags ? lpTags->cValues : 0);
1387 if (lpTags && lpTags->cValues > 0)
1389 ok(lpTags->aulPropTag[0] == PR_IMPORTANCE,
1390 "GetPropList: Expected %x, got %x\n",
1391 PR_IMPORTANCE, lpTags->aulPropTag[0]);
1392 pMAPIFreeBuffer(lpTags);
1395 /* Set item to r/w again */
1396 access[0] = IPROP_READWRITE|IPROP_DIRTY;
1397 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1398 ok(sc == S_OK, "SetPropAccess(WRITE): Expected S_OK got 0x%08X\n", sc);
1400 /* Delete existing item (r/w) - No error, no problems */
1401 lpProbs = NULL;
1402 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1403 ok(sc == S_OK && !lpProbs,
1404 "DeleteProps(RO): Expected S_OK null got 0x%08X %p\n", sc, lpProbs);
1406 /* Free the list */
1407 IPropData_Release(lpIProp);
1410 START_TEST(prop)
1412 SCODE ret;
1414 if (!HaveDefaultMailClient())
1416 win_skip("No default mail client installed\n");
1417 return;
1420 if(!InitFuncPtrs())
1422 win_skip("Needed functions are not available\n");
1423 return;
1426 SetLastError(0xdeadbeef);
1427 ret = pScInitMapiUtil(0);
1428 if ((ret != S_OK) && (GetLastError() == ERROR_PROC_NOT_FOUND))
1430 win_skip("ScInitMapiUtil is not implemented\n");
1431 FreeLibrary(hMapi32);
1432 return;
1434 else if ((ret == E_FAIL) && (GetLastError() == ERROR_INVALID_HANDLE))
1436 win_skip("ScInitMapiUtil doesn't work on some Win98 and WinME systems\n");
1437 FreeLibrary(hMapi32);
1438 return;
1441 test_PropCopyMore();
1442 test_UlPropSize();
1444 /* We call MAPIInitialize here for the benefit of native extended MAPI
1445 * providers which crash in the FPropContainsProp tests when MAPIInitialize
1446 * has not been called. Since MAPIInitialize is irrelevant for FPropContainsProp
1447 * on Wine, we do not care whether MAPIInitialize succeeds. */
1448 if (pMAPIInitialize)
1449 ret = pMAPIInitialize(NULL);
1450 test_FPropContainsProp();
1451 if (pMAPIUninitialize && ret == S_OK)
1452 pMAPIUninitialize();
1454 test_FPropCompareProp();
1455 test_LPropCompareProp();
1456 test_PpropFindProp();
1457 test_ScCountProps();
1458 test_ScCopyRelocProps();
1459 test_LpValFindProp();
1460 test_FBadRglpszA();
1461 test_FBadRglpszW();
1462 test_FBadRowSet();
1463 test_FBadPropTag();
1464 test_FBadRow();
1465 test_FBadProp();
1466 test_FBadColumnSet();
1468 test_IProp();
1470 pDeinitMapiUtil();
1471 FreeLibrary(hMapi32);