Get rid of FAR keywords.
[wine/multimedia.git] / dlls / mapi32 / tests / prop.c
blob505fc1ad459fca320f7f05bda4137bc6c9ae9865
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define NONAMELESSUNION
22 #define NONAMELESSSTRUCT
23 #include "wine/test.h"
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "winerror.h"
28 #include "winnt.h"
29 #include "mapiutil.h"
30 #include "mapitags.h"
32 static HMODULE hMapi32 = 0;
34 static SCODE (WINAPI *pScInitMapiUtil)(ULONG);
35 static SCODE (WINAPI *pPropCopyMore)(LPSPropValue,LPSPropValue,ALLOCATEMORE*,LPVOID);
36 static ULONG (WINAPI *pUlPropSize)(LPSPropValue);
37 static BOOL (WINAPI *pFPropContainsProp)(LPSPropValue,LPSPropValue,ULONG);
38 static BOOL (WINAPI *pFPropCompareProp)(LPSPropValue,ULONG,LPSPropValue);
39 static LONG (WINAPI *pLPropCompareProp)(LPSPropValue,LPSPropValue);
40 static LPSPropValue (WINAPI *pPpropFindProp)(LPSPropValue,ULONG,ULONG);
41 static SCODE (WINAPI *pScCountProps)(INT,LPSPropValue,ULONG*);
42 static SCODE (WINAPI *pScCopyProps)(int,LPSPropValue,LPVOID,ULONG*);
43 static SCODE (WINAPI *pScRelocProps)(int,LPSPropValue,LPVOID,LPVOID,ULONG*);
44 static LPSPropValue (WINAPI *pLpValFindProp)(ULONG,ULONG,LPSPropValue);
45 static BOOL (WINAPI *pFBadRglpszA)(LPSTR*,ULONG);
46 static BOOL (WINAPI *pFBadRglpszW)(LPWSTR*,ULONG);
47 static BOOL (WINAPI *pFBadRowSet)(LPSRowSet);
48 static ULONG (WINAPI *pFBadPropTag)(ULONG);
49 static ULONG (WINAPI *pFBadRow)(LPSRow);
50 static ULONG (WINAPI *pFBadProp)(LPSPropValue);
51 static ULONG (WINAPI *pFBadColumnSet)(LPSPropTagArray);
52 static SCODE (WINAPI *pCreateIProp)(LPCIID,ALLOCATEBUFFER*,ALLOCATEMORE*,
53 FREEBUFFER*,LPVOID,LPPROPDATA*);
54 static SCODE (WINAPI *pMAPIAllocateBuffer)(ULONG, LPVOID);
55 static SCODE (WINAPI *pMAPIAllocateMore)(ULONG, LPVOID, LPVOID);
56 static SCODE (WINAPI *pMAPIFreeBuffer)(LPVOID);
58 static BOOL InitFuncPtrs(void)
60 hMapi32 = LoadLibraryA("mapi32.dll");
62 pScInitMapiUtil = (void*)GetProcAddress(hMapi32, "ScInitMapiUtil@4");
63 pMAPIAllocateBuffer = (void*)GetProcAddress(hMapi32, "MAPIAllocateBuffer");
64 pMAPIAllocateMore = (void*)GetProcAddress(hMapi32, "MAPIAllocateMore");
65 pMAPIFreeBuffer = (void*)GetProcAddress(hMapi32, "MAPIFreeBuffer");
66 if(pScInitMapiUtil && pMAPIAllocateBuffer && pMAPIAllocateMore && pMAPIFreeBuffer)
67 return TRUE;
68 else
69 return FALSE;
72 static ULONG ptTypes[] = {
73 PT_I2, PT_I4, PT_R4, PT_R8, PT_CURRENCY, PT_APPTIME, PT_SYSTIME,
74 PT_ERROR, PT_BOOLEAN, PT_I8, PT_CLSID, PT_STRING8, PT_BINARY,
75 PT_UNICODE
78 static inline int strcmpW(const WCHAR *str1, const WCHAR *str2)
80 while (*str1 && (*str1 == *str2)) { str1++; str2++; }
81 return *str1 - *str2;
84 static void test_PropCopyMore(void)
86 static const char *szHiA = "Hi!";
87 static const WCHAR szHiW[] = { 'H', 'i', '!', '\0' };
88 SPropValue *lpDest = NULL, *lpSrc = NULL;
89 ULONG i;
90 SCODE scode;
92 pPropCopyMore = (void*)GetProcAddress(hMapi32, "PropCopyMore@16");
94 if (!pPropCopyMore)
95 return;
97 scode = pMAPIAllocateBuffer(sizeof(LPSPropValue), (LPVOID *)lpDest);
98 if (FAILED(scode))
99 return;
101 scode = pMAPIAllocateMore(sizeof(LPSPropValue), lpDest, (LPVOID *)lpSrc);
102 if (FAILED(scode))
103 return;
105 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
107 lpSrc->ulPropTag = ptTypes[i];
109 switch (ptTypes[i])
111 case PT_STRING8:
112 lpSrc->Value.lpszA = (char*)szHiA;
113 break;
114 case PT_UNICODE:
115 lpSrc->Value.lpszW = (WCHAR*)szHiW;
116 break;
117 case PT_BINARY:
118 lpSrc->Value.bin.cb = 4;
119 lpSrc->Value.bin.lpb = (LPBYTE)szHiA;
120 break;
123 memset(lpDest, 0xff, sizeof(SPropValue));
125 scode = pPropCopyMore(lpDest, lpSrc, (ALLOCATEMORE*)pMAPIAllocateMore, lpDest);
126 ok(!scode && lpDest->ulPropTag == lpSrc->ulPropTag,
127 "PropCopyMore: Expected 0x0,%ld, got 0x%08lx,%ld\n",
128 lpSrc->ulPropTag, scode, lpDest->ulPropTag);
129 if (SUCCEEDED(scode))
131 switch (ptTypes[i])
133 case PT_STRING8:
134 ok(lstrcmpA(lpDest->Value.lpszA, lpSrc->Value.lpszA) == 0,
135 "PropCopyMore: Ascii string differs\n");
136 break;
137 case PT_UNICODE:
138 ok(strcmpW(lpDest->Value.lpszW, lpSrc->Value.lpszW) == 0,
139 "PropCopyMore: Unicode string differs\n");
140 break;
141 case PT_BINARY:
142 ok(lpDest->Value.bin.cb == 4 &&
143 !memcmp(lpSrc->Value.bin.lpb, lpDest->Value.bin.lpb, 4),
144 "PropCopyMore: Binary array differs\n");
145 break;
150 /* Since all allocations are linked, freeing lpDest frees everything */
151 pMAPIFreeBuffer(lpDest);
154 static void test_UlPropSize(void)
156 static const char *szHiA = "Hi!";
157 static const WCHAR szHiW[] = { 'H', 'i', '!', '\0' };
158 LPSTR buffa[2];
159 LPWSTR buffw[2];
160 SBinary buffbin[2];
161 ULONG pt, exp, res;
163 pUlPropSize = (void*)GetProcAddress(hMapi32, "UlPropSize@4");
165 if (!pUlPropSize)
166 return;
168 for (pt = 0; pt < PROP_ID_INVALID; pt++)
170 SPropValue pv;
172 memset(&pv, 0 ,sizeof(pv));
173 pv.ulPropTag = pt;
175 exp = 1u; /* Default to one item for non-MV properties */
177 switch (PROP_TYPE(pt))
179 case PT_MV_I2: pv.Value.MVi.cValues = exp = 2;
180 case PT_I2: exp *= sizeof(USHORT); break;
181 case PT_MV_I4: pv.Value.MVl.cValues = exp = 2;
182 case PT_I4: exp *= sizeof(LONG); break;
183 case PT_MV_R4: pv.Value.MVflt.cValues = exp = 2;
184 case PT_R4: exp *= sizeof(float); break;
185 case PT_MV_DOUBLE: pv.Value.MVdbl.cValues = exp = 2;
186 case PT_R8: exp *= sizeof(double); break;
187 case PT_MV_CURRENCY: pv.Value.MVcur.cValues = exp = 2;
188 case PT_CURRENCY: exp *= sizeof(CY); break;
189 case PT_MV_APPTIME: pv.Value.MVat.cValues = exp = 2;
190 case PT_APPTIME: exp *= sizeof(double); break;
191 case PT_MV_SYSTIME: pv.Value.MVft.cValues = exp = 2;
192 case PT_SYSTIME: exp *= sizeof(FILETIME); break;
193 case PT_ERROR: exp = sizeof(SCODE); break;
194 case PT_BOOLEAN: exp = sizeof(USHORT); break;
195 case PT_OBJECT: exp = 0; break;
196 case PT_MV_I8: pv.Value.MVli.cValues = exp = 2;
197 case PT_I8: exp *= sizeof(LONG64); break;
198 #if 0
199 /* My version of native mapi returns 0 for PT_MV_CLSID even if a valid
200 * array is given. This _has_ to be a bug, so Wine does
201 * the right thing(tm) and we don't test it here.
203 case PT_MV_CLSID: pv.Value.MVguid.cValues = exp = 2;
204 #endif
205 case PT_CLSID: exp *= sizeof(GUID); break;
206 case PT_STRING8:
207 pv.Value.lpszA = (LPSTR)szHiA;
208 exp = 4;
209 break;
210 case PT_UNICODE:
211 pv.Value.lpszW = (LPWSTR)szHiW;
212 exp = 4 * sizeof(WCHAR);
213 break;
214 case PT_BINARY:
215 pv.Value.bin.cb = exp = 19;
216 break;
217 case PT_MV_STRING8:
218 pv.Value.MVszA.cValues = 2;
219 pv.Value.MVszA.lppszA = buffa;
220 buffa[0] = (LPSTR)szHiA;
221 buffa[1] = (LPSTR)szHiA;
222 exp = 8;
223 break;
224 case PT_MV_UNICODE:
225 pv.Value.MVszW.cValues = 2;
226 pv.Value.MVszW.lppszW = buffw;
227 buffw[0] = (LPWSTR)szHiW;
228 buffw[1] = (LPWSTR)szHiW;
229 exp = 8 * sizeof(WCHAR);
230 break;
231 case PT_MV_BINARY:
232 pv.Value.MVbin.cValues = 2;
233 pv.Value.MVbin.lpbin = buffbin;
234 buffbin[0].cb = 19;
235 buffbin[1].cb = 1;
236 exp = 20;
237 break;
238 default:
239 exp = 0;
242 res = pUlPropSize(&pv);
243 ok(res == exp, "pt= %ld: Expected %ld, got %ld\n", pt, exp, res);
247 static void test_FPropContainsProp(void)
249 static const char *szFull = "Full String";
250 static const char *szFullLower = "full string";
251 static const char *szPrefix = "Full";
252 static const char *szPrefixLower = "full";
253 static const char *szSubstring = "ll St";
254 static const char *szSubstringLower = "ll st";
255 SPropValue pvLeft, pvRight;
256 ULONG pt;
257 BOOL bRet;
259 pFPropContainsProp = (void*)GetProcAddress(hMapi32, "FPropContainsProp@12");
261 if (!pFPropContainsProp)
262 return;
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= %ld: Expected FALSE, got %d\n", pt, bRet);
278 /* test the various flag combinations */
279 pvLeft.ulPropTag = pvRight.ulPropTag = PT_STRING8;
280 pvLeft.Value.lpszA = (LPSTR)szFull;
281 pvRight.Value.lpszA = (LPSTR)szFull;
283 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING);
284 ok(bRet == TRUE, "(full,full)[] match failed\n");
285 pvRight.Value.lpszA = (LPSTR)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, "(full,prefix)[SUBSTRING] match failed\n");
292 pvRight.Value.lpszA = (LPSTR)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, "(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
299 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE);
300 ok(bRet == TRUE, "(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
301 pvRight.Value.lpszA = (LPSTR)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, "(full,substr)[SUBSTRING] match failed\n");
308 pvRight.Value.lpszA = (LPSTR)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, "(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
317 pvRight.Value.lpszA = (LPSTR)szFullLower;
318 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING|FL_IGNORECASE);
319 ok(bRet == TRUE, "(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, "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, "bin(full,prefix)[PREFIX] match failed\n");
334 bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING);
335 ok(bRet == TRUE, "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, "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
372 SHORT lVal;
373 SHORT rVal;
374 ULONG relOp;
375 BOOL bRet;
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;
402 GUID lguid, rguid;
403 char lbuffa[2], rbuffa[2];
404 WCHAR lbuffw[2], rbuffw[2];
405 ULONG i, j;
406 BOOL bRet, bExp;
408 pFPropCompareProp = (void*)GetProcAddress(hMapi32, "FPropCompareProp@12");
410 if (!pFPropCompareProp)
411 return;
413 lbuffa[1] = '\0';
414 rbuffa[1] = '\0';
415 lbuffw[1] = '\0';
416 rbuffw[1] = '\0';
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;
429 switch (ptTypes[i])
431 case PT_BOOLEAN:
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))
439 bExp = !bExp;
440 /* Fall through ... */
441 case PT_I2:
442 pvLeft.Value.i = lVal;
443 pvRight.Value.i = rVal;
444 break;
445 case PT_ERROR:
446 case PT_I4:
447 pvLeft.Value.l = lVal;
448 pvRight.Value.l = rVal;
449 break;
450 case PT_R4:
451 pvLeft.Value.flt = lVal;
452 pvRight.Value.flt = rVal;
453 break;
454 case PT_APPTIME:
455 case PT_R8:
456 pvLeft.Value.dbl = lVal;
457 pvRight.Value.dbl = rVal;
458 break;
459 case PT_CURRENCY:
460 pvLeft.Value.cur.int64 = lVal;
461 pvRight.Value.cur.int64 = rVal;
462 break;
463 case PT_SYSTIME:
464 pvLeft.Value.ft.dwLowDateTime = lVal;
465 pvLeft.Value.ft.dwHighDateTime = 0;
466 pvRight.Value.ft.dwLowDateTime = rVal;
467 pvRight.Value.ft.dwHighDateTime = 0;
468 break;
469 case PT_I8:
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;
474 break;
475 case PT_CLSID:
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;
482 break;
483 case PT_STRING8:
484 pvLeft.Value.lpszA = lbuffa;
485 pvRight.Value.lpszA = rbuffa;
486 lbuffa[0] = '0' + lVal;
487 rbuffa[0] = '0' + rVal;
488 break;
489 case PT_UNICODE:
490 pvLeft.Value.lpszW = lbuffw;
491 pvRight.Value.lpszW = rbuffw;
492 lbuffw[0] = '0' + lVal;
493 rbuffw[0] = '0' + rVal;
494 break;
495 case PT_BINARY:
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;
500 lbuffa[0] = lVal;
501 rbuffa[0] = rVal;
502 break;
505 bRet = pFPropCompareProp(&pvLeft, FPCProp_Results[j].relOp, &pvRight);
506 ok(bRet == bExp, "pt %ld (%d,%d,%s): expected %d, got %d\n", ptTypes[i],
507 FPCProp_Results[j].lVal, FPCProp_Results[j].rVal,
508 relops[FPCProp_Results[j].relOp], bExp, bRet);
513 typedef struct tagLPropCompareProp_Result
515 SHORT lVal;
516 SHORT rVal;
517 INT iRet;
518 } LPropCompareProp_Result;
520 static const LPropCompareProp_Result LPCProp_Results[] =
522 { 1, 2, -1 },
523 { 1, 1, 0 },
524 { 2, 1, 1 },
527 static void test_LPropCompareProp(void)
529 SPropValue pvLeft, pvRight;
530 GUID lguid, rguid;
531 char lbuffa[2], rbuffa[2];
532 WCHAR lbuffw[2], rbuffw[2];
533 ULONG i, j;
534 INT iRet, iExp;
536 pLPropCompareProp = (void*)GetProcAddress(hMapi32, "LPropCompareProp@8");
538 if (!pLPropCompareProp)
539 return;
541 lbuffa[1] = '\0';
542 rbuffa[1] = '\0';
543 lbuffw[1] = '\0';
544 rbuffw[1] = '\0';
546 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
548 pvLeft.ulPropTag = pvRight.ulPropTag = ptTypes[i];
550 for (j = 0; j < sizeof(LPCProp_Results)/sizeof(LPCProp_Results[0]); j++)
552 SHORT lVal = LPCProp_Results[j].lVal;
553 SHORT rVal = LPCProp_Results[j].rVal;
555 iExp = LPCProp_Results[j].iRet;
557 switch (ptTypes[i])
559 case PT_BOOLEAN:
560 /* Boolean values have no concept of less or greater than, only equality */
561 if (lVal && rVal)
562 iExp = 0;
563 /* Fall through ... */
564 case PT_I2:
565 pvLeft.Value.i = lVal;
566 pvRight.Value.i = rVal;
567 break;
568 case PT_ERROR:
569 case PT_I4:
570 pvLeft.Value.l = lVal;
571 pvRight.Value.l = rVal;
572 break;
573 case PT_R4:
574 pvLeft.Value.flt = lVal;
575 pvRight.Value.flt = rVal;
576 break;
577 case PT_APPTIME:
578 case PT_R8:
579 pvLeft.Value.dbl = lVal;
580 pvRight.Value.dbl = rVal;
581 break;
582 case PT_CURRENCY:
583 pvLeft.Value.cur.int64 = lVal;
584 pvRight.Value.cur.int64 = rVal;
585 break;
586 case PT_SYSTIME:
587 pvLeft.Value.ft.dwLowDateTime = lVal;
588 pvLeft.Value.ft.dwHighDateTime = 0;
589 pvRight.Value.ft.dwLowDateTime = rVal;
590 pvRight.Value.ft.dwHighDateTime = 0;
591 break;
592 case PT_I8:
593 pvLeft.Value.li.u.LowPart = lVal;
594 pvLeft.Value.li.u.HighPart = 0;
595 pvRight.Value.li.u.LowPart = rVal;
596 pvRight.Value.li.u.HighPart = 0;
597 break;
598 case PT_CLSID:
599 memset(&lguid, 0, sizeof(GUID));
600 memset(&rguid, 0, sizeof(GUID));
601 lguid.Data4[7] = lVal;
602 rguid.Data4[7] = rVal;
603 pvLeft.Value.lpguid = &lguid;
604 pvRight.Value.lpguid = &rguid;
605 break;
606 case PT_STRING8:
607 pvLeft.Value.lpszA = lbuffa;
608 pvRight.Value.lpszA = rbuffa;
609 lbuffa[0] = '0' + lVal;
610 rbuffa[0] = '0' + rVal;
611 break;
612 case PT_UNICODE:
613 pvLeft.Value.lpszW = lbuffw;
614 pvRight.Value.lpszW = rbuffw;
615 lbuffw[0] = '0' + lVal;
616 rbuffw[0] = '0' + rVal;
617 break;
618 case PT_BINARY:
619 pvLeft.Value.bin.cb = 1;
620 pvRight.Value.bin.cb = 1;
621 pvLeft.Value.bin.lpb = (LPBYTE)lbuffa;
622 pvRight.Value.bin.lpb = (LPBYTE)rbuffa;
623 lbuffa[0] = lVal;
624 rbuffa[0] = rVal;
625 break;
628 iRet = pLPropCompareProp(&pvLeft, &pvRight);
629 ok(iRet == iExp, "pt %ld (%d,%d): expected %d, got %d\n", ptTypes[i],
630 LPCProp_Results[j].lVal, LPCProp_Results[j].rVal, iExp, iRet);
635 static void test_PpropFindProp(void)
637 SPropValue pvProp, *pRet;
638 ULONG i;
640 pPpropFindProp = (void*)GetProcAddress(hMapi32, "PpropFindProp@12");
642 if (!pPpropFindProp)
643 return;
645 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
647 pvProp.ulPropTag = ptTypes[i];
649 pRet = pPpropFindProp(&pvProp, 1u, ptTypes[i]);
650 ok(pRet == &pvProp, "PpropFindProp[%ld]: Didn't find existing propery\n",
651 ptTypes[i]);
653 pRet = pPpropFindProp(&pvProp, 1u, i ? ptTypes[i-1] : ptTypes[i+1]);
654 ok(pRet == NULL, "PpropFindProp[%ld]: Found nonexistent propery\n",
655 ptTypes[i]);
658 pvProp.ulPropTag = PROP_TAG(PT_I2, 1u);
659 pRet = pPpropFindProp(&pvProp, 1u, PROP_TAG(PT_UNSPECIFIED, 0u));
660 ok(pRet == NULL, "PpropFindProp[UNSPECIFIED]: Matched on different id\n");
661 pRet = pPpropFindProp(&pvProp, 1u, PROP_TAG(PT_UNSPECIFIED, 1u));
662 ok(pRet == &pvProp, "PpropFindProp[UNSPECIFIED]: Didn't match id\n");
665 static void test_ScCountProps(void)
667 static const char *szHiA = "Hi!";
668 static const WCHAR szHiW[] = { 'H', 'i', '!', '\0' };
669 static const ULONG ULHILEN = 4; /* chars in szHiA/W incl. NUL */
670 LPSTR buffa[3];
671 LPWSTR buffw[3];
672 SBinary buffbin[3];
673 GUID iids[4], *iid = iids;
674 SCODE res;
675 ULONG pt, exp, ulRet;
676 int success = 1;
678 pScCountProps = (void*)GetProcAddress(hMapi32, "ScCountProps@12");
680 if (!pScCountProps)
681 return;
683 for (pt = 0; pt < PROP_ID_INVALID && success; pt++)
685 SPropValue pv;
687 memset(&pv, 0 ,sizeof(pv));
688 pv.ulPropTag = PROP_TAG(pt, 1u);
690 switch (PROP_TYPE(pt))
692 case PT_I2:
693 case PT_I4:
694 case PT_R4:
695 case PT_R8:
696 case PT_CURRENCY:
697 case PT_APPTIME:
698 case PT_SYSTIME:
699 case PT_ERROR:
700 case PT_BOOLEAN:
701 case PT_OBJECT:
702 case PT_I8:
703 exp = sizeof(pv);
704 break;
705 case PT_CLSID:
706 pv.Value.lpguid = iid;
707 exp = sizeof(GUID) + sizeof(pv);
708 break;
709 case PT_STRING8:
710 pv.Value.lpszA = (LPSTR)szHiA;
711 exp = 4 + sizeof(pv);
712 break;
713 case PT_UNICODE:
714 pv.Value.lpszW = (LPWSTR)szHiW;
715 exp = 4 * sizeof(WCHAR) + sizeof(pv);
716 break;
717 case PT_BINARY:
718 pv.Value.bin.cb = 2;
719 pv.Value.bin.lpb = (LPBYTE)iid;
720 exp = 2 + sizeof(pv);
721 break;
722 case PT_MV_I2:
723 pv.Value.MVi.cValues = 3;
724 pv.Value.MVi.lpi = (SHORT*)iid;
725 exp = 3 * sizeof(SHORT) + sizeof(pv);
726 break;
727 case PT_MV_I4:
728 pv.Value.MVl.cValues = 3;
729 pv.Value.MVl.lpl = (LONG*)iid;
730 exp = 3 * sizeof(LONG) + sizeof(pv);
731 break;
732 case PT_MV_I8:
733 pv.Value.MVli.cValues = 3;
734 pv.Value.MVli.lpli = (LARGE_INTEGER*)iid;
735 exp = 3 * sizeof(LARGE_INTEGER) + sizeof(pv);
736 break;
737 case PT_MV_R4:
738 pv.Value.MVflt.cValues = 3;
739 pv.Value.MVflt.lpflt = (float*)iid;
740 exp = 3 * sizeof(float) + sizeof(pv);
741 break;
742 case PT_MV_APPTIME:
743 case PT_MV_R8:
744 pv.Value.MVdbl.cValues = 3;
745 pv.Value.MVdbl.lpdbl = (double*)iid;
746 exp = 3 * sizeof(double) + sizeof(pv);
747 break;
748 case PT_MV_CURRENCY:
749 pv.Value.MVcur.cValues = 3;
750 pv.Value.MVcur.lpcur = (CY*)iid;
751 exp = 3 * sizeof(CY) + sizeof(pv);
752 break;
753 case PT_MV_SYSTIME:
754 pv.Value.MVft.cValues = 3;
755 pv.Value.MVft.lpft = (FILETIME*)iid;
756 exp = 3 * sizeof(CY) + sizeof(pv);
757 break;
758 case PT_MV_STRING8:
759 pv.Value.MVszA.cValues = 3;
760 pv.Value.MVszA.lppszA = buffa;
761 buffa[0] = (LPSTR)szHiA;
762 buffa[1] = (LPSTR)szHiA;
763 buffa[2] = (LPSTR)szHiA;
764 exp = ULHILEN * 3 + 3 * sizeof(char*) + sizeof(pv);
765 break;
766 case PT_MV_UNICODE:
767 pv.Value.MVszW.cValues = 3;
768 pv.Value.MVszW.lppszW = buffw;
769 buffw[0] = (LPWSTR)szHiW;
770 buffw[1] = (LPWSTR)szHiW;
771 buffw[2] = (LPWSTR)szHiW;
772 exp = ULHILEN * 3 * sizeof(WCHAR) + 3 * sizeof(WCHAR*) + sizeof(pv);
773 break;
774 case PT_MV_BINARY:
775 pv.Value.MVbin.cValues = 3;
776 pv.Value.MVbin.lpbin = buffbin;
777 buffbin[0].cb = 17;
778 buffbin[0].lpb = (LPBYTE)&iid;
779 buffbin[1].cb = 2;
780 buffbin[1].lpb = (LPBYTE)&iid;
781 buffbin[2].cb = 1;
782 buffbin[2].lpb = (LPBYTE)&iid;
783 exp = 20 + sizeof(pv) + sizeof(SBinary) * 3;
784 break;
785 default:
786 exp = 0;
789 ulRet = 0xffffffff;
790 res = pScCountProps(1, &pv, &ulRet);
791 if (!exp) {
792 success = res == MAPI_E_INVALID_PARAMETER && ulRet == 0xffffffff;
793 ok(success, "pt= %ld: Expected failure, got %ld, ret=0x%08lX\n",
794 pt, ulRet, res);
796 else {
797 success = res == S_OK && ulRet == exp;
798 ok(success, "pt= %ld: Expected %ld, got %ld, ret=0x%08lX\n",
799 pt, exp, ulRet, res);
805 static void test_ScCopyRelocProps(void)
807 static const char* szTestA = "Test";
808 char buffer[512], buffer2[512], *lppszA[1];
809 SPropValue pvProp, *lpResProp = (LPSPropValue)buffer;
810 ULONG ulCount;
811 SCODE sc;
813 pScCopyProps = (void*)GetProcAddress(hMapi32, "ScCopyProps@16");
814 pScRelocProps = (void*)GetProcAddress(hMapi32, "ScRelocProps@20");
816 if (!pScCopyProps || !pScRelocProps)
817 return;
819 pvProp.ulPropTag = PROP_TAG(PT_MV_STRING8, 1u);
821 lppszA[0] = (char *)szTestA;
822 pvProp.Value.MVszA.cValues = 1;
823 pvProp.Value.MVszA.lppszA = lppszA;
824 ulCount = 0;
826 sc = pScCopyProps(1, &pvProp, buffer, &ulCount);
827 ok(sc == S_OK && lpResProp->ulPropTag == pvProp.ulPropTag &&
828 lpResProp->Value.MVszA.cValues == 1 &&
829 lpResProp->Value.MVszA.lppszA[0] == buffer + sizeof(SPropValue) + sizeof(char*) &&
830 ulCount == sizeof(SPropValue) + sizeof(char*) + 5 &&
831 !strcmp(lpResProp->Value.MVszA.lppszA[0], szTestA),
832 "CopyProps(str): Expected 0 {1,%lx,%p,%s} %d got 0x%08lx {%ld,%lx,%p,%s} %ld\n",
833 pvProp.ulPropTag, buffer + sizeof(SPropValue) + sizeof(char*),
834 szTestA, sizeof(SPropValue) + sizeof(char*) + 5, sc,
835 lpResProp->Value.MVszA.cValues, lpResProp->ulPropTag,
836 sc==S_OK?lpResProp->Value.MVszA.lppszA[0]:NULL,
837 sc==S_OK?lpResProp->Value.MVszA.lppszA[0]:NULL, ulCount);
839 memcpy(buffer2, buffer, sizeof(buffer));
841 /* Clear the data in the source buffer. Since pointers in the copied buffer
842 * refer to the source buffer, this proves that native always assumes that
843 * the copied buffers pointers are bad (needing to be relocated first).
845 memset(buffer, 0, sizeof(buffer));
846 ulCount = 0;
848 sc = pScRelocProps(1, (LPSPropValue)buffer2, buffer, buffer2, &ulCount);
849 lpResProp = (LPSPropValue)buffer2;
850 ok(sc == S_OK && lpResProp->ulPropTag == pvProp.ulPropTag &&
851 lpResProp->Value.MVszA.cValues == 1 &&
852 lpResProp->Value.MVszA.lppszA[0] == buffer2 + sizeof(SPropValue) + sizeof(char*) &&
853 /* Native has a bug whereby it calculates the size correctly when copying
854 * but when relocating does not (presumably it uses UlPropSize() which
855 * ignores multivalue pointers). Wine returns the correct value.
857 (ulCount == sizeof(SPropValue) + sizeof(char*) + 5 || ulCount == sizeof(SPropValue) + 5) &&
858 !strcmp(lpResProp->Value.MVszA.lppszA[0], szTestA),
859 "RelocProps(str): Expected 0 {1,%lx,%p,%s} %d got 0x%08lx {%ld,%lx,%p,%s} %ld\n",
860 pvProp.ulPropTag, buffer2 + sizeof(SPropValue) + sizeof(char*),
861 szTestA, sizeof(SPropValue) + sizeof(char*) + 5, sc,
862 lpResProp->Value.MVszA.cValues, lpResProp->ulPropTag,
863 sc==S_OK?lpResProp->Value.MVszA.lppszA[0]:NULL,
864 sc==S_OK?lpResProp->Value.MVszA.lppszA[0]:NULL, ulCount);
866 /* Native crashes with lpNew or lpOld set to NULL so skip testing this */
869 static void test_LpValFindProp(void)
871 SPropValue pvProp, *pRet;
872 ULONG i;
874 pLpValFindProp = (void*)GetProcAddress(hMapi32, "LpValFindProp@12");
876 if (!pLpValFindProp)
877 return;
879 for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
881 pvProp.ulPropTag = PROP_TAG(ptTypes[i], 1u);
883 pRet = pLpValFindProp(PROP_TAG(ptTypes[i], 1u), 1u, &pvProp);
884 ok(pRet == &pvProp, "LpValFindProp[%ld]: Didn't find existing propery id/type\n",
885 ptTypes[i]);
887 pRet = pLpValFindProp(PROP_TAG(ptTypes[i], 0u), 1u, &pvProp);
888 ok(pRet == NULL, "LpValFindProp[%ld]: Found nonexistent propery id\n",
889 ptTypes[i]);
891 pRet = pLpValFindProp(PROP_TAG(PT_NULL, 0u), 1u, &pvProp);
892 ok(pRet == NULL, "LpValFindProp[%ld]: Found nonexistent propery id/type\n",
893 ptTypes[i]);
895 pRet = pLpValFindProp(PROP_TAG(PT_NULL, 1u), 1u, &pvProp);
896 ok(pRet == &pvProp, "LpValFindProp[%ld]: Didn't find existing propery id\n",
897 ptTypes[i]);
901 static void test_FBadRglpszA(void)
903 LPSTR lpStrs[4];
904 char *szString = "A String";
905 BOOL bRet;
907 pFBadRglpszA = (void*)GetProcAddress(hMapi32, "FBadRglpszA@8");
908 if (!pFBadRglpszA)
909 return;
911 bRet = pFBadRglpszA(NULL, 10);
912 ok(bRet == TRUE, "FBadRglpszA(Null): expected TRUE, got FALSE\n");
914 lpStrs[0] = lpStrs[1] = lpStrs[2] = lpStrs[3] = NULL;
915 bRet = pFBadRglpszA(lpStrs, 4);
916 ok(bRet == TRUE, "FBadRglpszA(Nulls): expected TRUE, got FALSE\n");
918 lpStrs[0] = lpStrs[1] = lpStrs[2] = szString;
919 bRet = pFBadRglpszA(lpStrs, 3);
920 ok(bRet == FALSE, "FBadRglpszA(valid): expected FALSE, got TRUE\n");
922 bRet = pFBadRglpszA(lpStrs, 4);
923 ok(bRet == TRUE, "FBadRglpszA(1 invalid): expected TRUE, got FALSE\n");
926 static void test_FBadRglpszW(void)
928 LPWSTR lpStrs[4];
929 WCHAR szString[] = { 'A',' ','S','t','r','i','n','g','\0' };
930 BOOL bRet;
932 pFBadRglpszW = (void*)GetProcAddress(hMapi32, "FBadRglpszW@8");
933 if (!pFBadRglpszW)
934 return;
936 bRet = pFBadRglpszW(NULL, 10);
937 ok(bRet == TRUE, "FBadRglpszW(Null): expected TRUE, got FALSE\n");
939 lpStrs[0] = lpStrs[1] = lpStrs[2] = lpStrs[3] = NULL;
940 bRet = pFBadRglpszW(lpStrs, 4);
941 ok(bRet == TRUE, "FBadRglpszW(Nulls): expected TRUE, got FALSE\n");
943 lpStrs[0] = lpStrs[1] = lpStrs[2] = szString;
944 bRet = pFBadRglpszW(lpStrs, 3);
945 ok(bRet == FALSE, "FBadRglpszW(valid): expected FALSE, got TRUE\n");
947 bRet = pFBadRglpszW(lpStrs, 4);
948 ok(bRet == TRUE, "FBadRglpszW(1 invalid): expected TRUE, got FALSE\n");
951 static void test_FBadRowSet(void)
953 ULONG ulRet;
955 pFBadRowSet = (void*)GetProcAddress(hMapi32, "FBadRowSet@4");
956 if (!pFBadRowSet)
957 return;
959 ulRet = pFBadRowSet(NULL);
960 ok(ulRet != 0, "FBadRow(null): Expected non-zero, got 0\n");
962 /* FIXME */
965 static void test_FBadPropTag(void)
967 ULONG pt, res;
969 pFBadPropTag = (void*)GetProcAddress(hMapi32, "FBadPropTag@4");
970 if (!pFBadPropTag)
971 return;
973 for (pt = 0; pt < PROP_ID_INVALID; pt++)
975 BOOL bBad = TRUE;
977 switch (pt & (~MV_FLAG & PROP_TYPE_MASK))
979 case PT_UNSPECIFIED:
980 case PT_NULL: case PT_I2: case PT_I4: case PT_R4:
981 case PT_R8: case PT_CURRENCY: case PT_APPTIME:
982 case PT_ERROR: case PT_BOOLEAN: case PT_OBJECT:
983 case PT_I8: case PT_STRING8: case PT_UNICODE:
984 case PT_SYSTIME: case PT_CLSID: case PT_BINARY:
985 bBad = FALSE;
988 res = pFBadPropTag(pt);
989 if (bBad)
990 ok(res != 0, "pt= %ld: Expected non-zero, got 0\n", pt);
991 else
992 ok(res == 0, "pt= %ld: Expected zero, got %ld\n", pt, res);
996 static void test_FBadRow(void)
998 ULONG ulRet;
1000 pFBadRow = (void*)GetProcAddress(hMapi32, "FBadRow@4");
1001 if (!pFBadRow)
1002 return;
1004 ulRet = pFBadRow(NULL);
1005 ok(ulRet != 0, "FBadRow(null): Expected non-zero, got 0\n");
1007 /* FIXME */
1010 static void test_FBadProp(void)
1012 WCHAR szEmpty[] = { '\0' };
1013 GUID iid;
1014 ULONG pt, res;
1015 SPropValue pv;
1017 pFBadProp = (void*)GetProcAddress(hMapi32, "FBadProp@4");
1018 if (!pFBadProp)
1019 return;
1021 for (pt = 0; pt < PROP_ID_INVALID; pt++)
1023 BOOL bBad = TRUE;
1025 memset(&pv, 0, sizeof(pv));
1026 pv.ulPropTag = pt;
1028 /* Note that MV values are valid below because their array count is 0,
1029 * so no pointers are validated.
1031 switch (PROP_TYPE(pt))
1033 case (MV_FLAG|PT_UNSPECIFIED):
1034 case PT_UNSPECIFIED:
1035 case (MV_FLAG|PT_NULL):
1036 case PT_NULL:
1037 case PT_MV_I2:
1038 case PT_I2:
1039 case PT_MV_I4:
1040 case PT_I4:
1041 case PT_MV_I8:
1042 case PT_I8:
1043 case PT_MV_R4:
1044 case PT_R4:
1045 case PT_MV_R8:
1046 case PT_R8:
1047 case PT_MV_CURRENCY:
1048 case PT_CURRENCY:
1049 case PT_MV_APPTIME:
1050 case PT_APPTIME:
1051 case (MV_FLAG|PT_ERROR):
1052 case PT_ERROR:
1053 case (MV_FLAG|PT_BOOLEAN):
1054 case PT_BOOLEAN:
1055 case (MV_FLAG|PT_OBJECT):
1056 case PT_OBJECT:
1057 case PT_MV_STRING8:
1058 case PT_MV_UNICODE:
1059 case PT_MV_SYSTIME:
1060 case PT_SYSTIME:
1061 case PT_MV_BINARY:
1062 case PT_BINARY:
1063 case PT_MV_CLSID:
1064 bBad = FALSE;
1065 break;
1066 case PT_STRING8:
1067 case PT_UNICODE:
1068 pv.Value.lpszW = szEmpty;
1069 bBad = FALSE;
1070 break;
1071 case PT_CLSID:
1072 pv.Value.lpguid = &iid;
1073 bBad = FALSE;
1074 break;
1077 res = pFBadProp(&pv);
1078 if (bBad)
1079 ok(res != 0, "pt= %ld: Expected non-zero, got 0\n", pt);
1080 else
1081 ok(res == 0, "pt= %ld: Expected zero, got %ld\n", pt, res);
1085 static void test_FBadColumnSet(void)
1087 SPropTagArray pta;
1088 ULONG pt, res;
1090 pFBadColumnSet = (void*)GetProcAddress(hMapi32, "FBadColumnSet@4");
1091 if (!pFBadColumnSet)
1092 return;
1094 res = pFBadColumnSet(NULL);
1095 ok(res != 0, "(null): Expected non-zero, got 0\n");
1097 pta.cValues = 1;
1099 for (pt = 0; pt < PROP_ID_INVALID; pt++)
1101 BOOL bBad = TRUE;
1103 pta.aulPropTag[0] = pt;
1105 switch (pt & (~MV_FLAG & PROP_TYPE_MASK))
1107 case PT_UNSPECIFIED:
1108 case PT_NULL:
1109 case PT_I2:
1110 case PT_I4:
1111 case PT_R4:
1112 case PT_R8:
1113 case PT_CURRENCY:
1114 case PT_APPTIME:
1115 case PT_BOOLEAN:
1116 case PT_OBJECT:
1117 case PT_I8:
1118 case PT_STRING8:
1119 case PT_UNICODE:
1120 case PT_SYSTIME:
1121 case PT_CLSID:
1122 case PT_BINARY:
1123 bBad = FALSE;
1125 if (pt == (MV_FLAG|PT_ERROR))
1126 bBad = FALSE;
1128 res = pFBadColumnSet(&pta);
1129 if (bBad)
1130 ok(res != 0, "pt= %ld: Expected non-zero, got 0\n", pt);
1131 else
1132 ok(res == 0, "pt= %ld: Expected zero, got %ld\n", pt, res);
1137 static void test_IProp(void)
1139 IPropData *lpIProp;
1140 LPMAPIERROR lpError;
1141 LPSPropProblemArray lpProbs;
1142 LPSPropValue lpProps;
1143 LPSPropTagArray lpTags;
1144 SPropValue pvs[2];
1145 SizedSPropTagArray(2,tags);
1146 ULONG access[2], count;
1147 SCODE sc;
1149 pCreateIProp = (void*)GetProcAddress(hMapi32, "CreateIProp@24");
1151 if (!pCreateIProp)
1152 return;
1154 memset(&tags, 0 , sizeof(tags));
1156 /* Create the object */
1157 lpIProp = NULL;
1158 sc = pCreateIProp(&IID_IMAPIPropData, (ALLOCATEBUFFER *)pMAPIAllocateBuffer, (ALLOCATEMORE*)pMAPIAllocateMore,
1159 (FREEBUFFER *)pMAPIFreeBuffer, NULL, &lpIProp);
1160 ok(sc == S_OK && lpIProp,
1161 "CreateIProp: expected S_OK, non-null, got 0x%08lX,%p\n", sc, lpIProp);
1163 if (sc != S_OK || !lpIProp)
1164 return;
1166 /* GetLastError - No errors set */
1167 lpError = NULL;
1168 IPropData_GetLastError(lpIProp, E_INVALIDARG, 0, &lpError);
1169 ok(sc == S_OK && !lpError,
1170 "GetLastError: Expected S_OK, null, got 0x%08lX,%p\n", sc, lpError);
1172 /* Get prop tags - succeeds returning 0 items */
1173 lpTags = NULL;
1174 sc = IPropData_GetPropList(lpIProp, 0, &lpTags);
1175 ok(sc == S_OK && lpTags && lpTags->cValues == 0,
1176 "GetPropList(empty): Expected S_OK, non-null, 0, got 0x%08lX,%p,%ld\n",
1177 sc, lpTags, lpTags ? lpTags->cValues : 0);
1178 if (lpTags)
1179 pMAPIFreeBuffer(lpTags);
1181 /* Get props - succeeds returning 0 items */
1182 lpProps = NULL;
1183 count = 0;
1184 tags.cValues = 1;
1185 tags.aulPropTag[0] = PR_IMPORTANCE;
1186 sc = IPropData_GetProps(lpIProp, (LPSPropTagArray)&tags, 0, &count, &lpProps);
1187 ok(sc == MAPI_W_ERRORS_RETURNED && lpProps && count == 1,
1188 "GetProps(empty): Expected ERRORS_RETURNED, non-null, 1, got 0x%08lX,%p,%ld\n",
1189 sc, lpProps, count);
1190 if (lpProps && count > 0)
1192 ok(lpProps[0].ulPropTag == CHANGE_PROP_TYPE(PR_IMPORTANCE,PT_ERROR),
1193 "GetProps(empty): Expected %x, got %lx\n",
1194 CHANGE_PROP_TYPE(PR_IMPORTANCE,PT_ERROR), lpProps[0].ulPropTag);
1196 pMAPIFreeBuffer(lpProps);
1199 /* Add (NULL) - Can't add NULL's */
1200 lpProbs = NULL;
1201 pvs[0].ulPropTag = PROP_TAG(PT_NULL,0x01);
1202 sc = IPropData_SetProps(lpIProp, 1, pvs, &lpProbs);
1203 ok(sc == MAPI_E_INVALID_PARAMETER && !lpProbs,
1204 "SetProps(): Expected INVALID_PARAMETER, null, got 0x%08lX,%p\n",
1205 sc, lpProbs);
1207 /* Add (OBJECT) - Can't add OBJECTS's */
1208 lpProbs = NULL;
1209 pvs[0].ulPropTag = PROP_TAG(PT_OBJECT,0x01);
1210 sc = IPropData_SetProps(lpIProp, 1, pvs, &lpProbs);
1211 ok(sc == MAPI_E_INVALID_PARAMETER && !lpProbs,
1212 "SetProps(OBJECT): Expected INVALID_PARAMETER, null, got 0x%08lX,%p\n",
1213 sc, lpProbs);
1215 /* Add - Adds value */
1216 lpProbs = NULL;
1217 pvs[0].ulPropTag = PR_IMPORTANCE;
1218 sc = IPropData_SetProps(lpIProp, 1, pvs, &lpProbs);
1219 ok(sc == S_OK && !lpProbs,
1220 "SetProps(ERROR): Expected S_OK, null, got 0x%08lX,%p\n", sc, lpProbs);
1222 /* Get prop list - returns 1 item */
1223 lpTags = NULL;
1224 IPropData_GetPropList(lpIProp, 0, &lpTags);
1225 ok(sc == S_OK && lpTags && lpTags->cValues == 1,
1226 "GetPropList: Expected S_OK, non-null, 1, got 0x%08lX,%p,%ld\n",
1227 sc, lpTags, lpTags ? lpTags->cValues : 0);
1228 if (lpTags && lpTags->cValues > 0)
1230 ok(lpTags->aulPropTag[0] == PR_IMPORTANCE,
1231 "GetPropList: Expected %x, got %lx\n",
1232 PR_IMPORTANCE, lpTags->aulPropTag[0]);
1233 pMAPIFreeBuffer(lpTags);
1236 /* Set access to read and write */
1237 sc = IPropData_HrSetObjAccess(lpIProp, IPROP_READWRITE);
1238 ok(sc == S_OK, "SetObjAcess(WRITE): Expected S_OK got 0x%08lX\n", sc);
1240 tags.cValues = 1;
1241 tags.aulPropTag[0] = PR_IMPORTANCE;
1243 /* Set item access (bad access) - Fails */
1244 access[0] = 0;
1245 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1246 ok(sc == MAPI_E_INVALID_PARAMETER,
1247 "SetPropAcess(0): Expected INVALID_PARAMETER got 0x%08lX\n",sc);
1248 access[0] = IPROP_READWRITE;
1249 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1250 ok(sc == MAPI_E_INVALID_PARAMETER,
1251 "SetPropAcess(RW): Expected INVALID_PARAMETER got 0x%08lX\n",sc);
1252 access[0] = IPROP_CLEAN;
1253 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1254 ok(sc == MAPI_E_INVALID_PARAMETER,
1255 "SetPropAcess(C): Expected INVALID_PARAMETER got 0x%08lX\n",sc);
1257 /* Set item access to read/write/clean */
1258 tags.cValues = 1;
1259 tags.aulPropTag[0] = PR_IMPORTANCE;
1260 access[0] = IPROP_READWRITE|IPROP_CLEAN;
1261 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1262 ok(sc == S_OK, "SetPropAcess(RW/C): Expected S_OK got 0x%08lX\n",sc);
1264 /* Set object access to read only */
1265 sc = IPropData_HrSetObjAccess(lpIProp, IPROP_READONLY);
1266 ok(sc == S_OK, "SetObjAcess(READ): Expected S_OK got 0x%08lX\n", sc);
1268 /* Set item access to read/write/dirty - doesn't care about RO object */
1269 access[0] = IPROP_READONLY|IPROP_DIRTY;
1270 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1271 ok(sc == S_OK, "SetPropAcess(WRITE): Expected S_OK got 0x%08lX\n", sc);
1273 /* Delete any item when set to read only - Error */
1274 lpProbs = NULL;
1275 tags.aulPropTag[0] = PR_RESPONSE_REQUESTED;
1276 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1277 ok(sc == E_ACCESSDENIED && !lpProbs,
1278 "DeleteProps(nonexistent): Expected E_ACCESSDENIED null got 0x%08lX %p\n",
1279 sc, lpProbs);
1281 /* Set access to read and write */
1282 sc = IPropData_HrSetObjAccess(lpIProp, IPROP_READWRITE);
1283 ok(sc == S_OK, "SetObjAcess(WRITE): Expected S_OK got 0x%08lX\n", sc);
1285 /* Delete nonexistent item - No error */
1286 lpProbs = NULL;
1287 tags.aulPropTag[0] = PR_RESPONSE_REQUESTED;
1288 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1289 ok(sc == S_OK && !lpProbs,
1290 "DeleteProps(nonexistent): Expected S_OK null got 0x%08lX %p\n",
1291 sc, lpProbs);
1293 /* Delete existing item (r/o) - No error, but lpProbs populated */
1294 lpProbs = NULL;
1295 tags.aulPropTag[0] = PR_IMPORTANCE;
1296 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1297 ok(sc == S_OK && lpProbs,
1298 "DeleteProps(RO): Expected S_OK non-null got 0x%08lX %p\n", sc, lpProbs);
1300 if (lpProbs && lpProbs->cProblem > 0)
1302 ok(lpProbs->cProblem == 1 &&
1303 lpProbs->aProblem[0].ulIndex == 0 &&
1304 lpProbs->aProblem[0].ulPropTag == PR_IMPORTANCE &&
1305 lpProbs->aProblem[0].scode == E_ACCESSDENIED,
1306 "DeleteProps(RO): Expected (1,0,%x,%lx) got (%ld,%lx,%lx)\n",
1307 PR_IMPORTANCE, E_ACCESSDENIED,
1308 lpProbs->aProblem[0].ulIndex, lpProbs->aProblem[0].ulPropTag,
1309 lpProbs->aProblem[0].scode);
1310 pMAPIFreeBuffer(lpProbs);
1313 lpProbs = NULL;
1314 tags.cValues = 1;
1315 tags.aulPropTag[0] = PR_RESPONSE_REQUESTED;
1316 IPropData_HrAddObjProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1317 ok(sc == S_OK && !lpProbs,
1318 "AddObjProps(RO): Expected S_OK null got 0x%08lX %p\n", sc, lpProbs);
1320 /* Get prop list - returns 1 item */
1321 lpTags = NULL;
1322 IPropData_GetPropList(lpIProp, 0, &lpTags);
1323 ok(sc == S_OK && lpTags && lpTags->cValues == 1,
1324 "GetPropList: Expected S_OK, non-null, 1, got 0x%08lX,%p,%ld\n",
1325 sc, lpTags, lpTags ? lpTags->cValues : 0);
1326 if (lpTags && lpTags->cValues > 0)
1328 ok(lpTags->aulPropTag[0] == PR_IMPORTANCE,
1329 "GetPropList: Expected %x, got %lx\n",
1330 PR_IMPORTANCE, lpTags->aulPropTag[0]);
1331 pMAPIFreeBuffer(lpTags);
1334 /* Set item to r/w again */
1335 access[0] = IPROP_READWRITE|IPROP_DIRTY;
1336 sc = IPropData_HrSetPropAccess(lpIProp, (LPSPropTagArray)&tags, access);
1337 ok(sc == S_OK, "SetPropAcess(WRITE): Expected S_OK got 0x%08lX\n", sc);
1339 /* Delete existing item (r/w) - No error, no problems */
1340 lpProbs = NULL;
1341 sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs);
1342 ok(sc == S_OK && !lpProbs,
1343 "DeleteProps(RO): Expected S_OK null got 0x%08lX %p\n", sc, lpProbs);
1345 /* Free the list */
1346 IPropData_Release(lpIProp);
1349 START_TEST(prop)
1351 if(!InitFuncPtrs())
1352 return;
1354 pScInitMapiUtil(0);
1356 test_PropCopyMore();
1357 test_UlPropSize();
1358 test_FPropContainsProp();
1359 test_FPropCompareProp();
1360 test_LPropCompareProp();
1361 test_PpropFindProp();
1362 test_ScCountProps();
1363 test_ScCopyRelocProps();
1364 test_LpValFindProp();
1365 test_FBadRglpszA();
1366 test_FBadRglpszW();
1367 test_FBadRowSet();
1368 test_FBadPropTag();
1369 test_FBadRow();
1370 test_FBadProp();
1371 test_FBadColumnSet();
1373 test_IProp();
1374 FreeLibrary(hMapi32);