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"
30 #include "mapi32_test.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
)
72 /* FIXME: Test PT_I2, PT_I4, PT_R4, PT_R8, PT_CURRENCY, PT_APPTIME, PT_SYSTIME,
73 * PT_ERROR, PT_BOOLEAN, PT_I8, and PT_CLSID. */
74 static ULONG ptTypes
[] = {
75 PT_STRING8
, PT_BINARY
, PT_UNICODE
78 static inline int strcmpW(const WCHAR
*str1
, const WCHAR
*str2
)
80 while (*str1
&& (*str1
== *str2
)) { str1
++; str2
++; }
84 static void test_PropCopyMore(void)
86 static char szHiA
[] = "Hi!";
87 static WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
88 SPropValue
*lpDest
= NULL
, *lpSrc
= NULL
;
92 pPropCopyMore
= (void*)GetProcAddress(hMapi32
, "PropCopyMore@16");
96 win_skip("PropCopyMore is not available\n");
100 scode
= pMAPIAllocateBuffer(sizeof(SPropValue
), &lpDest
);
101 ok(scode
== S_OK
, "Expected MAPIAllocateBuffer to return S_OK, got 0x%x\n", scode
);
104 skip("MAPIAllocateBuffer failed\n");
108 scode
= pMAPIAllocateMore(sizeof(SPropValue
), lpDest
, &lpSrc
);
109 ok(scode
== S_OK
, "Expected MAPIAllocateMore to return S_OK, got 0x%x\n", scode
);
112 skip("MAPIAllocateMore failed\n");
116 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
118 lpSrc
->ulPropTag
= ptTypes
[i
];
123 lpSrc
->Value
.lpszA
= szHiA
;
126 lpSrc
->Value
.lpszW
= szHiW
;
129 lpSrc
->Value
.bin
.cb
= 4;
130 lpSrc
->Value
.bin
.lpb
= (LPBYTE
)szHiA
;
134 memset(lpDest
, 0xff, sizeof(SPropValue
));
136 scode
= pPropCopyMore(lpDest
, lpSrc
, (ALLOCATEMORE
*)pMAPIAllocateMore
, lpDest
);
137 ok(!scode
&& lpDest
->ulPropTag
== lpSrc
->ulPropTag
,
138 "PropCopyMore: Expected 0x0,%d, got 0x%08x,%d\n",
139 lpSrc
->ulPropTag
, scode
, lpDest
->ulPropTag
);
140 if (SUCCEEDED(scode
))
145 ok(lstrcmpA(lpDest
->Value
.lpszA
, lpSrc
->Value
.lpszA
) == 0,
146 "PropCopyMore: Ascii string differs\n");
149 ok(strcmpW(lpDest
->Value
.lpszW
, lpSrc
->Value
.lpszW
) == 0,
150 "PropCopyMore: Unicode string differs\n");
153 ok(lpDest
->Value
.bin
.cb
== 4 &&
154 !memcmp(lpSrc
->Value
.bin
.lpb
, lpDest
->Value
.bin
.lpb
, 4),
155 "PropCopyMore: Binary array differs\n");
161 /* Since all allocations are linked, freeing lpDest frees everything */
162 scode
= pMAPIFreeBuffer(lpDest
);
163 ok(scode
== S_OK
, "Expected MAPIFreeBuffer to return S_OK, got 0x%x\n", scode
);
166 static void test_UlPropSize(void)
168 static char szHiA
[] = "Hi!";
169 static WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
175 pUlPropSize
= (void*)GetProcAddress(hMapi32
, "UlPropSize@4");
179 win_skip("UlPropSize is not available\n");
183 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
187 memset(&pv
, 0 ,sizeof(pv
));
190 exp
= 1u; /* Default to one item for non-MV properties */
192 switch (PROP_TYPE(pt
))
194 case PT_MV_I2
: pv
.Value
.MVi
.cValues
= exp
= 2;
195 case PT_I2
: exp
*= sizeof(USHORT
); break;
196 case PT_MV_I4
: pv
.Value
.MVl
.cValues
= exp
= 2;
197 case PT_I4
: exp
*= sizeof(LONG
); break;
198 case PT_MV_R4
: pv
.Value
.MVflt
.cValues
= exp
= 2;
199 case PT_R4
: exp
*= sizeof(float); break;
200 case PT_MV_DOUBLE
: pv
.Value
.MVdbl
.cValues
= exp
= 2;
201 case PT_R8
: exp
*= sizeof(double); break;
202 case PT_MV_CURRENCY
: pv
.Value
.MVcur
.cValues
= exp
= 2;
203 case PT_CURRENCY
: exp
*= sizeof(CY
); break;
204 case PT_MV_APPTIME
: pv
.Value
.MVat
.cValues
= exp
= 2;
205 case PT_APPTIME
: exp
*= sizeof(double); break;
206 case PT_MV_SYSTIME
: pv
.Value
.MVft
.cValues
= exp
= 2;
207 case PT_SYSTIME
: exp
*= sizeof(FILETIME
); break;
208 case PT_ERROR
: exp
= sizeof(SCODE
); break;
209 case PT_BOOLEAN
: exp
= sizeof(USHORT
); break;
210 case PT_OBJECT
: exp
= 0; break;
211 case PT_MV_I8
: pv
.Value
.MVli
.cValues
= exp
= 2;
212 case PT_I8
: exp
*= sizeof(LONG64
); break;
214 /* My version of native mapi returns 0 for PT_MV_CLSID even if a valid
215 * array is given. This _has_ to be a bug, so Wine does
216 * the right thing(tm) and we don't test it here.
218 case PT_MV_CLSID
: pv
.Value
.MVguid
.cValues
= exp
= 2;
220 case PT_CLSID
: exp
*= sizeof(GUID
); break;
222 pv
.Value
.lpszA
= szHiA
;
226 pv
.Value
.lpszW
= szHiW
;
227 exp
= 4 * sizeof(WCHAR
);
230 pv
.Value
.bin
.cb
= exp
= 19;
233 pv
.Value
.MVszA
.cValues
= 2;
234 pv
.Value
.MVszA
.lppszA
= buffa
;
240 pv
.Value
.MVszW
.cValues
= 2;
241 pv
.Value
.MVszW
.lppszW
= buffw
;
244 exp
= 8 * sizeof(WCHAR
);
247 pv
.Value
.MVbin
.cValues
= 2;
248 pv
.Value
.MVbin
.lpbin
= buffbin
;
257 res
= pUlPropSize(&pv
);
259 "pt= %d: Expected %d, got %d\n", pt
, exp
, res
);
263 static void test_FPropContainsProp(void)
265 static char szFull
[] = "Full String";
266 static char szFullLower
[] = "full string";
267 static char szPrefix
[] = "Full";
268 static char szPrefixLower
[] = "full";
269 static char szSubstring
[] = "ll St";
270 static char szSubstringLower
[] = "ll st";
271 SPropValue pvLeft
, pvRight
;
275 pFPropContainsProp
= (void*)GetProcAddress(hMapi32
, "FPropContainsProp@12");
277 if (!pFPropContainsProp
)
279 win_skip("FPropContainsProp is not available\n");
283 /* Ensure that only PT_STRING8 and PT_BINARY are handled */
284 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
286 if (pt
== PT_STRING8
|| pt
== PT_BINARY
)
287 continue; /* test these later */
289 memset(&pvLeft
, 0 ,sizeof(pvLeft
));
290 memset(&pvRight
, 0 ,sizeof(pvRight
));
291 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= pt
;
293 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
294 ok(bRet
== FALSE
, "pt= %d: Expected FALSE, got %d\n", pt
, bRet
);
297 /* test the various flag combinations */
298 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= PT_STRING8
;
299 pvLeft
.Value
.lpszA
= szFull
;
300 pvRight
.Value
.lpszA
= szFull
;
302 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
303 ok(bRet
== TRUE
, "(full,full)[] match failed\n");
304 pvRight
.Value
.lpszA
= szPrefix
;
305 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
306 ok(bRet
== FALSE
, "(full,prefix)[] match failed\n");
307 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
308 ok(bRet
== TRUE
, "(full,prefix)[PREFIX] match failed\n");
309 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
310 ok(bRet
== TRUE
, "(full,prefix)[SUBSTRING] match failed\n");
311 pvRight
.Value
.lpszA
= szPrefixLower
;
312 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
313 ok(bRet
== FALSE
, "(full,prefixlow)[PREFIX] match failed\n");
314 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
315 ok(bRet
== FALSE
, "(full,prefixlow)[SUBSTRING] match failed\n");
316 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
317 ok(bRet
== TRUE
, "(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
318 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
319 ok(bRet
== TRUE
, "(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
320 pvRight
.Value
.lpszA
= szSubstring
;
321 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
322 ok(bRet
== FALSE
, "(full,substr)[] match failed\n");
323 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
324 ok(bRet
== FALSE
, "(full,substr)[PREFIX] match failed\n");
325 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
326 ok(bRet
== TRUE
, "(full,substr)[SUBSTRING] match failed\n");
327 pvRight
.Value
.lpszA
= szSubstringLower
;
328 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
329 ok(bRet
== FALSE
, "(full,substrlow)[PREFIX] match failed\n");
330 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
331 ok(bRet
== FALSE
, "(full,substrlow)[SUBSTRING] match failed\n");
332 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
333 ok(bRet
== FALSE
, "(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
334 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
335 ok(bRet
== TRUE
, "(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
336 pvRight
.Value
.lpszA
= szFullLower
;
337 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
|FL_IGNORECASE
);
338 ok(bRet
== TRUE
, "(full,fulllow)[IGNORECASE] match failed\n");
340 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= PT_BINARY
;
341 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)szFull
;
342 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szFull
;
343 pvLeft
.Value
.bin
.cb
= pvRight
.Value
.bin
.cb
= strlen(szFull
);
345 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
346 ok(bRet
== TRUE
, "bin(full,full)[] match failed\n");
347 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szPrefix
;
348 pvRight
.Value
.bin
.cb
= strlen(szPrefix
);
349 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
350 ok(bRet
== FALSE
, "bin(full,prefix)[] match failed\n");
351 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
352 ok(bRet
== TRUE
, "bin(full,prefix)[PREFIX] match failed\n");
353 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
354 ok(bRet
== TRUE
, "bin(full,prefix)[SUBSTRING] match failed\n");
355 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szPrefixLower
;
356 pvRight
.Value
.bin
.cb
= strlen(szPrefixLower
);
357 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
358 ok(bRet
== FALSE
, "bin(full,prefixlow)[PREFIX] match failed\n");
359 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
360 ok(bRet
== FALSE
, "bin(full,prefixlow)[SUBSTRING] match failed\n");
361 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
362 ok(bRet
== FALSE
, "bin(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
363 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
364 ok(bRet
== FALSE
, "bin(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
365 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szSubstring
;
366 pvRight
.Value
.bin
.cb
= strlen(szSubstring
);
367 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
368 ok(bRet
== FALSE
, "bin(full,substr)[] match failed\n");
369 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
370 ok(bRet
== FALSE
, "bin(full,substr)[PREFIX] match failed\n");
371 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
372 ok(bRet
== TRUE
, "bin(full,substr)[SUBSTRING] match failed\n");
373 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szSubstringLower
;
374 pvRight
.Value
.bin
.cb
= strlen(szSubstringLower
);
375 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
376 ok(bRet
== FALSE
, "bin(full,substrlow)[PREFIX] match failed\n");
377 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
378 ok(bRet
== FALSE
, "bin(full,substrlow)[SUBSTRING] match failed\n");
379 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
380 ok(bRet
== FALSE
, "bin(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
381 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
382 ok(bRet
== FALSE
, "bin(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
383 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szFullLower
;
384 pvRight
.Value
.bin
.cb
= strlen(szFullLower
);
385 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
|FL_IGNORECASE
);
386 ok(bRet
== FALSE
, "bin(full,fulllow)[IGNORECASE] match failed\n");
389 typedef struct tagFPropCompareProp_Result
395 } FPropCompareProp_Result
;
397 static const FPropCompareProp_Result FPCProp_Results
[] =
399 { 1, 2, RELOP_LT
, TRUE
},
400 { 1, 1, RELOP_LT
, FALSE
},
401 { 2, 1, RELOP_LT
, FALSE
},
402 { 1, 2, RELOP_LE
, TRUE
},
403 { 1, 1, RELOP_LE
, TRUE
},
404 { 2, 1, RELOP_LE
, FALSE
},
405 { 1, 2, RELOP_GT
, FALSE
},
406 { 1, 1, RELOP_GT
, FALSE
},
407 { 2, 1, RELOP_GT
, TRUE
},
408 { 1, 2, RELOP_GE
, FALSE
},
409 { 1, 1, RELOP_GE
, TRUE
},
410 { 2, 1, RELOP_GE
, TRUE
},
411 { 1, 2, RELOP_EQ
, FALSE
},
412 { 1, 1, RELOP_EQ
, TRUE
},
413 { 2, 1, RELOP_EQ
, FALSE
}
416 static const char *relops
[] = { "RELOP_LT", "RELOP_LE", "RELOP_GT", "RELOP_GE", "RELOP_EQ" };
418 static void test_FPropCompareProp(void)
420 SPropValue pvLeft
, pvRight
;
422 char lbuffa
[2], rbuffa
[2];
423 WCHAR lbuffw
[2], rbuffw
[2];
427 pFPropCompareProp
= (void*)GetProcAddress(hMapi32
, "FPropCompareProp@12");
429 if (!pFPropCompareProp
)
431 win_skip("FPropCompareProp is not available\n");
440 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
442 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= ptTypes
[i
];
444 for (j
= 0; j
< sizeof(FPCProp_Results
)/sizeof(FPCProp_Results
[0]); j
++)
446 SHORT lVal
= FPCProp_Results
[j
].lVal
;
447 SHORT rVal
= FPCProp_Results
[j
].rVal
;
449 bExp
= FPCProp_Results
[j
].bRet
;
454 /* Boolean values have no concept of less or greater than, only equality */
455 if ((lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_LT
) ||
456 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_LE
)||
457 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_GT
)||
458 (lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_GE
)||
459 (lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_EQ
)||
460 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_EQ
))
462 /* Fall through ... */
464 pvLeft
.Value
.i
= lVal
;
465 pvRight
.Value
.i
= rVal
;
469 pvLeft
.Value
.l
= lVal
;
470 pvRight
.Value
.l
= rVal
;
473 pvLeft
.Value
.flt
= lVal
;
474 pvRight
.Value
.flt
= rVal
;
478 pvLeft
.Value
.dbl
= lVal
;
479 pvRight
.Value
.dbl
= rVal
;
482 pvLeft
.Value
.cur
.int64
= lVal
;
483 pvRight
.Value
.cur
.int64
= rVal
;
486 pvLeft
.Value
.ft
.dwLowDateTime
= lVal
;
487 pvLeft
.Value
.ft
.dwHighDateTime
= 0;
488 pvRight
.Value
.ft
.dwLowDateTime
= rVal
;
489 pvRight
.Value
.ft
.dwHighDateTime
= 0;
492 pvLeft
.Value
.li
.u
.LowPart
= lVal
;
493 pvLeft
.Value
.li
.u
.HighPart
= 0;
494 pvRight
.Value
.li
.u
.LowPart
= rVal
;
495 pvRight
.Value
.li
.u
.HighPart
= 0;
498 memset(&lguid
, 0, sizeof(GUID
));
499 memset(&rguid
, 0, sizeof(GUID
));
500 lguid
.Data4
[7] = lVal
;
501 rguid
.Data4
[7] = rVal
;
502 pvLeft
.Value
.lpguid
= &lguid
;
503 pvRight
.Value
.lpguid
= &rguid
;
506 pvLeft
.Value
.lpszA
= lbuffa
;
507 pvRight
.Value
.lpszA
= rbuffa
;
508 lbuffa
[0] = '0' + lVal
;
509 rbuffa
[0] = '0' + rVal
;
512 pvLeft
.Value
.lpszW
= lbuffw
;
513 pvRight
.Value
.lpszW
= rbuffw
;
514 lbuffw
[0] = '0' + lVal
;
515 rbuffw
[0] = '0' + rVal
;
518 pvLeft
.Value
.bin
.cb
= 1;
519 pvRight
.Value
.bin
.cb
= 1;
520 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)lbuffa
;
521 pvRight
.Value
.bin
.lpb
= (LPBYTE
)rbuffa
;
527 bRet
= pFPropCompareProp(&pvLeft
, FPCProp_Results
[j
].relOp
, &pvRight
);
529 "pt %d (%d,%d,%s): expected %d, got %d\n", ptTypes
[i
],
530 FPCProp_Results
[j
].lVal
, FPCProp_Results
[j
].rVal
,
531 relops
[FPCProp_Results
[j
].relOp
], bExp
, bRet
);
536 typedef struct tagLPropCompareProp_Result
541 } LPropCompareProp_Result
;
543 static const LPropCompareProp_Result LPCProp_Results
[] =
550 static void test_LPropCompareProp(void)
552 SPropValue pvLeft
, pvRight
;
554 char lbuffa
[2], rbuffa
[2];
555 WCHAR lbuffw
[2], rbuffw
[2];
559 pLPropCompareProp
= (void*)GetProcAddress(hMapi32
, "LPropCompareProp@8");
561 if (!pLPropCompareProp
)
563 win_skip("LPropCompareProp is not available\n");
572 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
574 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= ptTypes
[i
];
576 for (j
= 0; j
< sizeof(LPCProp_Results
)/sizeof(LPCProp_Results
[0]); j
++)
578 SHORT lVal
= LPCProp_Results
[j
].lVal
;
579 SHORT rVal
= LPCProp_Results
[j
].rVal
;
581 iExp
= LPCProp_Results
[j
].iRet
;
586 /* Boolean values have no concept of less or greater than, only equality */
589 /* Fall through ... */
591 pvLeft
.Value
.i
= lVal
;
592 pvRight
.Value
.i
= rVal
;
596 pvLeft
.Value
.l
= lVal
;
597 pvRight
.Value
.l
= rVal
;
600 pvLeft
.Value
.flt
= lVal
;
601 pvRight
.Value
.flt
= rVal
;
605 pvLeft
.Value
.dbl
= lVal
;
606 pvRight
.Value
.dbl
= rVal
;
609 pvLeft
.Value
.cur
.int64
= lVal
;
610 pvRight
.Value
.cur
.int64
= rVal
;
613 pvLeft
.Value
.ft
.dwLowDateTime
= lVal
;
614 pvLeft
.Value
.ft
.dwHighDateTime
= 0;
615 pvRight
.Value
.ft
.dwLowDateTime
= rVal
;
616 pvRight
.Value
.ft
.dwHighDateTime
= 0;
619 pvLeft
.Value
.li
.u
.LowPart
= lVal
;
620 pvLeft
.Value
.li
.u
.HighPart
= 0;
621 pvRight
.Value
.li
.u
.LowPart
= rVal
;
622 pvRight
.Value
.li
.u
.HighPart
= 0;
625 memset(&lguid
, 0, sizeof(GUID
));
626 memset(&rguid
, 0, sizeof(GUID
));
627 lguid
.Data4
[7] = lVal
;
628 rguid
.Data4
[7] = rVal
;
629 pvLeft
.Value
.lpguid
= &lguid
;
630 pvRight
.Value
.lpguid
= &rguid
;
633 pvLeft
.Value
.lpszA
= lbuffa
;
634 pvRight
.Value
.lpszA
= rbuffa
;
635 lbuffa
[0] = '0' + lVal
;
636 rbuffa
[0] = '0' + rVal
;
639 pvLeft
.Value
.lpszW
= lbuffw
;
640 pvRight
.Value
.lpszW
= rbuffw
;
641 lbuffw
[0] = '0' + lVal
;
642 rbuffw
[0] = '0' + rVal
;
645 pvLeft
.Value
.bin
.cb
= 1;
646 pvRight
.Value
.bin
.cb
= 1;
647 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)lbuffa
;
648 pvRight
.Value
.bin
.lpb
= (LPBYTE
)rbuffa
;
654 iRet
= pLPropCompareProp(&pvLeft
, &pvRight
);
656 "pt %d (%d,%d): expected %d, got %d\n", ptTypes
[i
],
657 LPCProp_Results
[j
].lVal
, LPCProp_Results
[j
].rVal
, iExp
, iRet
);
662 static void test_PpropFindProp(void)
664 SPropValue pvProp
, *pRet
;
667 pPpropFindProp
= (void*)GetProcAddress(hMapi32
, "PpropFindProp@12");
671 win_skip("PpropFindProp is not available\n");
675 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
677 pvProp
.ulPropTag
= ptTypes
[i
];
679 pRet
= pPpropFindProp(&pvProp
, 1u, ptTypes
[i
]);
681 "PpropFindProp[%d]: Didn't find existing propery\n",
684 pRet
= pPpropFindProp(&pvProp
, 1u, i
? ptTypes
[i
-1] : ptTypes
[i
+1]);
685 ok(pRet
== NULL
, "PpropFindProp[%d]: Found nonexistent propery\n",
689 pvProp
.ulPropTag
= PROP_TAG(PT_I2
, 1u);
690 pRet
= pPpropFindProp(&pvProp
, 1u, PROP_TAG(PT_UNSPECIFIED
, 0u));
691 ok(pRet
== NULL
, "PpropFindProp[UNSPECIFIED]: Matched on different id\n");
692 pRet
= pPpropFindProp(&pvProp
, 1u, PROP_TAG(PT_UNSPECIFIED
, 1u));
693 ok(pRet
== &pvProp
, "PpropFindProp[UNSPECIFIED]: Didn't match id\n");
696 static void test_ScCountProps(void)
698 static char szHiA
[] = "Hi!";
699 static WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
700 static const ULONG ULHILEN
= 4; /* chars in szHiA/W incl. NUL */
704 GUID iids
[4], *iid
= iids
;
706 ULONG pt
, exp
, ulRet
;
709 pScCountProps
= (void*)GetProcAddress(hMapi32
, "ScCountProps@12");
713 win_skip("ScCountProps is not available\n");
717 for (pt
= 0; pt
< PROP_ID_INVALID
&& success
; pt
++)
721 memset(&pv
, 0 ,sizeof(pv
));
722 pv
.ulPropTag
= PROP_TAG(pt
, 1u);
724 switch (PROP_TYPE(pt
))
740 pv
.Value
.lpguid
= iid
;
741 exp
= sizeof(GUID
) + sizeof(pv
);
744 pv
.Value
.lpszA
= szHiA
;
745 exp
= 4 + sizeof(pv
);
748 pv
.Value
.lpszW
= szHiW
;
749 exp
= 4 * sizeof(WCHAR
) + sizeof(pv
);
753 pv
.Value
.bin
.lpb
= (LPBYTE
)iid
;
754 exp
= 2 + sizeof(pv
);
757 pv
.Value
.MVi
.cValues
= 3;
758 pv
.Value
.MVi
.lpi
= (SHORT
*)iid
;
759 exp
= 3 * sizeof(SHORT
) + sizeof(pv
);
762 pv
.Value
.MVl
.cValues
= 3;
763 pv
.Value
.MVl
.lpl
= (LONG
*)iid
;
764 exp
= 3 * sizeof(LONG
) + sizeof(pv
);
767 pv
.Value
.MVli
.cValues
= 3;
768 pv
.Value
.MVli
.lpli
= (LARGE_INTEGER
*)iid
;
769 exp
= 3 * sizeof(LARGE_INTEGER
) + sizeof(pv
);
772 pv
.Value
.MVflt
.cValues
= 3;
773 pv
.Value
.MVflt
.lpflt
= (float*)iid
;
774 exp
= 3 * sizeof(float) + sizeof(pv
);
778 pv
.Value
.MVdbl
.cValues
= 3;
779 pv
.Value
.MVdbl
.lpdbl
= (double*)iid
;
780 exp
= 3 * sizeof(double) + sizeof(pv
);
783 pv
.Value
.MVcur
.cValues
= 3;
784 pv
.Value
.MVcur
.lpcur
= (CY
*)iid
;
785 exp
= 3 * sizeof(CY
) + sizeof(pv
);
788 pv
.Value
.MVft
.cValues
= 3;
789 pv
.Value
.MVft
.lpft
= (FILETIME
*)iid
;
790 exp
= 3 * sizeof(CY
) + sizeof(pv
);
793 pv
.Value
.MVszA
.cValues
= 3;
794 pv
.Value
.MVszA
.lppszA
= buffa
;
798 exp
= ULHILEN
* 3 + 3 * sizeof(char*) + sizeof(pv
);
801 pv
.Value
.MVszW
.cValues
= 3;
802 pv
.Value
.MVszW
.lppszW
= buffw
;
806 exp
= ULHILEN
* 3 * sizeof(WCHAR
) + 3 * sizeof(WCHAR
*) + sizeof(pv
);
809 pv
.Value
.MVbin
.cValues
= 3;
810 pv
.Value
.MVbin
.lpbin
= buffbin
;
812 buffbin
[0].lpb
= (LPBYTE
)&iid
;
814 buffbin
[1].lpb
= (LPBYTE
)&iid
;
816 buffbin
[2].lpb
= (LPBYTE
)&iid
;
817 exp
= 20 + sizeof(pv
) + sizeof(SBinary
) * 3;
824 res
= pScCountProps(1, &pv
, &ulRet
);
826 success
= res
== MAPI_E_INVALID_PARAMETER
&& ulRet
== 0xffffffff;
827 ok(success
, "pt= %d: Expected failure, got %d, ret=0x%08X\n",
831 success
= res
== S_OK
&& ulRet
== exp
;
832 ok(success
, "pt= %d: Expected %d, got %d, ret=0x%08X\n",
833 pt
, exp
, ulRet
, res
);
839 static void test_ScCopyRelocProps(void)
841 static char szTestA
[] = "Test";
842 char buffer
[512], buffer2
[512], *lppszA
[1];
843 SPropValue pvProp
, *lpResProp
= (LPSPropValue
)buffer
;
847 pScCopyProps
= (void*)GetProcAddress(hMapi32
, "ScCopyProps@16");
848 pScRelocProps
= (void*)GetProcAddress(hMapi32
, "ScRelocProps@20");
850 if (!pScCopyProps
|| !pScRelocProps
)
852 win_skip("SPropValue copy functions are not available\n");
856 pvProp
.ulPropTag
= PROP_TAG(PT_MV_STRING8
, 1u);
859 pvProp
.Value
.MVszA
.cValues
= 1;
860 pvProp
.Value
.MVszA
.lppszA
= lppszA
;
863 sc
= pScCopyProps(1, &pvProp
, buffer
, &ulCount
);
864 ok(sc
== S_OK
, "wrong ret %d\n", sc
);
867 ok(lpResProp
->ulPropTag
== pvProp
.ulPropTag
, "wrong tag %x\n",lpResProp
->ulPropTag
);
868 ok(lpResProp
->Value
.MVszA
.cValues
== 1, "wrong cValues %d\n", lpResProp
->Value
.MVszA
.cValues
);
869 ok(lpResProp
->Value
.MVszA
.lppszA
[0] == buffer
+ sizeof(SPropValue
) + sizeof(char*),
870 "wrong lppszA[0] %p\n",lpResProp
->Value
.MVszA
.lppszA
[0]);
871 ok(ulCount
== sizeof(SPropValue
) + sizeof(char*) + 5, "wrong count %d\n", ulCount
);
872 ok(!strcmp(lpResProp
->Value
.MVszA
.lppszA
[0], szTestA
),
873 "wrong string '%s'\n", lpResProp
->Value
.MVszA
.lppszA
[0]);
876 memcpy(buffer2
, buffer
, sizeof(buffer
));
878 /* Clear the data in the source buffer. Since pointers in the copied buffer
879 * refer to the source buffer, this proves that native always assumes that
880 * the copied buffers pointers are bad (needing to be relocated first).
882 memset(buffer
, 0, sizeof(buffer
));
885 sc
= pScRelocProps(1, (LPSPropValue
)buffer2
, buffer
, buffer2
, &ulCount
);
886 lpResProp
= (LPSPropValue
)buffer2
;
888 ok(sc
== S_OK
, "wrong ret %d\n", sc
);
891 ok(lpResProp
->ulPropTag
== pvProp
.ulPropTag
, "wrong tag %x\n",lpResProp
->ulPropTag
);
892 ok(lpResProp
->Value
.MVszA
.cValues
== 1, "wrong cValues %d\n", lpResProp
->Value
.MVszA
.cValues
);
893 ok(lpResProp
->Value
.MVszA
.lppszA
[0] == buffer2
+ sizeof(SPropValue
) + sizeof(char*),
894 "wrong lppszA[0] %p\n",lpResProp
->Value
.MVszA
.lppszA
[0]);
895 /* Native has a bug whereby it calculates the size correctly when copying
896 * but when relocating does not (presumably it uses UlPropSize() which
897 * ignores multivalue pointers). Wine returns the correct value.
899 ok(ulCount
== sizeof(SPropValue
) + sizeof(char*) + 5 || ulCount
== sizeof(SPropValue
) + 5,
900 "wrong count %d\n", ulCount
);
901 ok(!strcmp(lpResProp
->Value
.MVszA
.lppszA
[0], szTestA
),
902 "wrong string '%s'\n", lpResProp
->Value
.MVszA
.lppszA
[0]);
905 /* Native crashes with lpNew or lpOld set to NULL so skip testing this */
908 static void test_LpValFindProp(void)
910 SPropValue pvProp
, *pRet
;
913 pLpValFindProp
= (void*)GetProcAddress(hMapi32
, "LpValFindProp@12");
917 win_skip("LpValFindProp is not available\n");
921 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
923 pvProp
.ulPropTag
= PROP_TAG(ptTypes
[i
], 1u);
925 pRet
= pLpValFindProp(PROP_TAG(ptTypes
[i
], 1u), 1u, &pvProp
);
927 "LpValFindProp[%d]: Didn't find existing propery id/type\n",
930 pRet
= pLpValFindProp(PROP_TAG(ptTypes
[i
], 0u), 1u, &pvProp
);
931 ok(pRet
== NULL
, "LpValFindProp[%d]: Found nonexistent propery id\n",
934 pRet
= pLpValFindProp(PROP_TAG(PT_NULL
, 0u), 1u, &pvProp
);
935 ok(pRet
== NULL
, "LpValFindProp[%d]: Found nonexistent propery id/type\n",
938 pRet
= pLpValFindProp(PROP_TAG(PT_NULL
, 1u), 1u, &pvProp
);
940 "LpValFindProp[%d]: Didn't find existing propery id\n",
945 static void test_FBadRglpszA(void)
948 static CHAR szString
[] = "A String";
951 pFBadRglpszA
= (void*)GetProcAddress(hMapi32
, "FBadRglpszA@8");
954 win_skip("FBadRglpszA is not available\n");
958 bRet
= pFBadRglpszA(NULL
, 10);
959 ok(bRet
== TRUE
, "FBadRglpszA(Null): expected TRUE, got FALSE\n");
961 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = lpStrs
[3] = NULL
;
962 bRet
= pFBadRglpszA(lpStrs
, 4);
963 ok(bRet
== TRUE
, "FBadRglpszA(Nulls): expected TRUE, got FALSE\n");
965 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = szString
;
966 bRet
= pFBadRglpszA(lpStrs
, 3);
967 ok(bRet
== FALSE
, "FBadRglpszA(valid): expected FALSE, got TRUE\n");
969 bRet
= pFBadRglpszA(lpStrs
, 4);
970 ok(bRet
== TRUE
, "FBadRglpszA(1 invalid): expected TRUE, got FALSE\n");
973 static void test_FBadRglpszW(void)
976 static WCHAR szString
[] = { 'A',' ','S','t','r','i','n','g','\0' };
979 pFBadRglpszW
= (void*)GetProcAddress(hMapi32
, "FBadRglpszW@8");
982 win_skip("FBadRglpszW is not available\n");
986 bRet
= pFBadRglpszW(NULL
, 10);
987 ok(bRet
== TRUE
, "FBadRglpszW(Null): expected TRUE, got FALSE\n");
989 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = lpStrs
[3] = NULL
;
990 bRet
= pFBadRglpszW(lpStrs
, 4);
991 ok(bRet
== TRUE
, "FBadRglpszW(Nulls): expected TRUE, got FALSE\n");
993 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = szString
;
994 bRet
= pFBadRglpszW(lpStrs
, 3);
995 ok(bRet
== FALSE
, "FBadRglpszW(valid): expected FALSE, got TRUE\n");
997 bRet
= pFBadRglpszW(lpStrs
, 4);
998 ok(bRet
== TRUE
, "FBadRglpszW(1 invalid): expected TRUE, got FALSE\n");
1001 static void test_FBadRowSet(void)
1005 pFBadRowSet
= (void*)GetProcAddress(hMapi32
, "FBadRowSet@4");
1008 win_skip("FBadRowSet is not available\n");
1012 ulRet
= pFBadRowSet(NULL
);
1013 ok(ulRet
!= 0, "FBadRow(null): Expected non-zero, got 0\n");
1018 static void test_FBadPropTag(void)
1022 pFBadPropTag
= (void*)GetProcAddress(hMapi32
, "FBadPropTag@4");
1025 win_skip("FBadPropTag is not available\n");
1029 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1033 switch (pt
& (~MV_FLAG
& PROP_TYPE_MASK
))
1035 case PT_UNSPECIFIED
:
1036 case PT_NULL
: case PT_I2
: case PT_I4
: case PT_R4
:
1037 case PT_R8
: case PT_CURRENCY
: case PT_APPTIME
:
1038 case PT_ERROR
: case PT_BOOLEAN
: case PT_OBJECT
:
1039 case PT_I8
: case PT_STRING8
: case PT_UNICODE
:
1040 case PT_SYSTIME
: case PT_CLSID
: case PT_BINARY
:
1044 res
= pFBadPropTag(pt
);
1046 ok(res
!= 0, "pt= %d: Expected non-zero, got 0\n", pt
);
1049 "pt= %d: Expected zero, got %d\n", pt
, res
);
1053 static void test_FBadRow(void)
1057 pFBadRow
= (void*)GetProcAddress(hMapi32
, "FBadRow@4");
1060 win_skip("FBadRow is not available\n");
1064 ulRet
= pFBadRow(NULL
);
1065 ok(ulRet
!= 0, "FBadRow(null): Expected non-zero, got 0\n");
1070 static void test_FBadProp(void)
1072 static WCHAR szEmpty
[] = { '\0' };
1077 pFBadProp
= (void*)GetProcAddress(hMapi32
, "FBadProp@4");
1080 win_skip("FBadProp is not available\n");
1084 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1088 memset(&pv
, 0, sizeof(pv
));
1091 /* Note that MV values are valid below because their array count is 0,
1092 * so no pointers are validated.
1094 switch (PROP_TYPE(pt
))
1096 case (MV_FLAG
|PT_UNSPECIFIED
):
1097 case PT_UNSPECIFIED
:
1098 case (MV_FLAG
|PT_NULL
):
1110 case PT_MV_CURRENCY
:
1114 case (MV_FLAG
|PT_ERROR
):
1116 case (MV_FLAG
|PT_BOOLEAN
):
1118 case (MV_FLAG
|PT_OBJECT
):
1131 pv
.Value
.lpszW
= szEmpty
;
1135 pv
.Value
.lpguid
= &iid
;
1140 res
= pFBadProp(&pv
);
1142 ok(res
!= 0, "pt= %d: Expected non-zero, got 0\n", pt
);
1145 "pt= %d: Expected zero, got %d\n", pt
, res
);
1149 static void test_FBadColumnSet(void)
1154 pFBadColumnSet
= (void*)GetProcAddress(hMapi32
, "FBadColumnSet@4");
1155 if (!pFBadColumnSet
)
1157 win_skip("FBadColumnSet is not available\n");
1161 res
= pFBadColumnSet(NULL
);
1162 ok(res
!= 0, "(null): Expected non-zero, got 0\n");
1166 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1170 pta
.aulPropTag
[0] = pt
;
1172 switch (pt
& (~MV_FLAG
& PROP_TYPE_MASK
))
1174 case PT_UNSPECIFIED
:
1192 if (pt
== (MV_FLAG
|PT_ERROR
))
1195 res
= pFBadColumnSet(&pta
);
1197 ok(res
!= 0, "pt= %d: Expected non-zero, got 0\n", pt
);
1200 "pt= %d: Expected zero, got %d\n", pt
, res
);
1205 static void test_IProp(void)
1208 LPMAPIERROR lpError
;
1209 LPSPropProblemArray lpProbs
;
1210 LPSPropValue lpProps
;
1211 LPSPropTagArray lpTags
;
1213 SizedSPropTagArray(2,tags
);
1214 ULONG access
[2], count
;
1217 pCreateIProp
= (void*)GetProcAddress(hMapi32
, "CreateIProp@24");
1221 win_skip("CreateIProp is not available\n");
1225 memset(&tags
, 0 , sizeof(tags
));
1227 /* Create the object */
1229 sc
= pCreateIProp(&IID_IMAPIPropData
, (ALLOCATEBUFFER
*)pMAPIAllocateBuffer
, (ALLOCATEMORE
*)pMAPIAllocateMore
,
1230 (FREEBUFFER
*)pMAPIFreeBuffer
, NULL
, &lpIProp
);
1231 ok(sc
== S_OK
&& lpIProp
,
1232 "CreateIProp: expected S_OK, non-null, got 0x%08X,%p\n", sc
, lpIProp
);
1234 if (sc
!= S_OK
|| !lpIProp
)
1237 /* GetLastError - No errors set */
1239 IPropData_GetLastError(lpIProp
, E_INVALIDARG
, 0, &lpError
);
1240 ok(sc
== S_OK
&& !lpError
,
1241 "GetLastError: Expected S_OK, null, got 0x%08X,%p\n", sc
, lpError
);
1243 /* Get prop tags - succeeds returning 0 items */
1245 sc
= IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1246 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 0,
1247 "GetPropList(empty): Expected S_OK, non-null, 0, got 0x%08X,%p,%d\n",
1248 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1250 pMAPIFreeBuffer(lpTags
);
1252 /* Get props - succeeds returning 0 items */
1256 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1257 sc
= IPropData_GetProps(lpIProp
, (LPSPropTagArray
)&tags
, 0, &count
, &lpProps
);
1258 ok(sc
== MAPI_W_ERRORS_RETURNED
&& lpProps
&& count
== 1,
1259 "GetProps(empty): Expected ERRORS_RETURNED, non-null, 1, got 0x%08X,%p,%d\n",
1260 sc
, lpProps
, count
);
1261 if (lpProps
&& count
> 0)
1263 ok(lpProps
[0].ulPropTag
== CHANGE_PROP_TYPE(PR_IMPORTANCE
,PT_ERROR
),
1264 "GetProps(empty): Expected %x, got %x\n",
1265 CHANGE_PROP_TYPE(PR_IMPORTANCE
,PT_ERROR
), lpProps
[0].ulPropTag
);
1267 pMAPIFreeBuffer(lpProps
);
1270 /* Add (NULL) - Can't add NULLs */
1272 pvs
[0].ulPropTag
= PROP_TAG(PT_NULL
,0x01);
1273 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1274 ok(sc
== MAPI_E_INVALID_PARAMETER
&& !lpProbs
,
1275 "SetProps(): Expected INVALID_PARAMETER, null, got 0x%08X,%p\n",
1278 /* Add (OBJECT) - Can't add OBJECTs */
1280 pvs
[0].ulPropTag
= PROP_TAG(PT_OBJECT
,0x01);
1281 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1282 ok(sc
== MAPI_E_INVALID_PARAMETER
&& !lpProbs
,
1283 "SetProps(OBJECT): Expected INVALID_PARAMETER, null, got 0x%08X,%p\n",
1286 /* Add - Adds value */
1288 pvs
[0].ulPropTag
= PR_IMPORTANCE
;
1289 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1290 ok(sc
== S_OK
&& !lpProbs
,
1291 "SetProps(ERROR): Expected S_OK, null, got 0x%08X,%p\n", sc
, lpProbs
);
1293 /* Get prop list - returns 1 item */
1295 IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1296 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 1,
1297 "GetPropList: Expected S_OK, non-null, 1, got 0x%08X,%p,%d\n",
1298 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1299 if (lpTags
&& lpTags
->cValues
> 0)
1301 ok(lpTags
->aulPropTag
[0] == PR_IMPORTANCE
,
1302 "GetPropList: Expected %x, got %x\n",
1303 PR_IMPORTANCE
, lpTags
->aulPropTag
[0]);
1304 pMAPIFreeBuffer(lpTags
);
1307 /* Set access to read and write */
1308 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READWRITE
);
1309 ok(sc
== S_OK
, "SetObjAcess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1312 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1314 /* Set item access (bad access) - Fails */
1316 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1317 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1318 "SetPropAcess(0): Expected INVALID_PARAMETER got 0x%08X\n",sc
);
1319 access
[0] = IPROP_READWRITE
;
1320 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1321 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1322 "SetPropAcess(RW): Expected INVALID_PARAMETER got 0x%08X\n",sc
);
1323 access
[0] = IPROP_CLEAN
;
1324 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1325 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1326 "SetPropAcess(C): Expected INVALID_PARAMETER got 0x%08X\n",sc
);
1328 /* Set item access to read/write/clean */
1330 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1331 access
[0] = IPROP_READWRITE
|IPROP_CLEAN
;
1332 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1333 ok(sc
== S_OK
, "SetPropAcess(RW/C): Expected S_OK got 0x%08X\n",sc
);
1335 /* Set object access to read only */
1336 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READONLY
);
1337 ok(sc
== S_OK
, "SetObjAcess(READ): Expected S_OK got 0x%08X\n", sc
);
1339 /* Set item access to read/write/dirty - doesn't care about RO object */
1340 access
[0] = IPROP_READONLY
|IPROP_DIRTY
;
1341 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1342 ok(sc
== S_OK
, "SetPropAcess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1344 /* Delete any item when set to read only - Error */
1346 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1347 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1348 ok(sc
== E_ACCESSDENIED
&& !lpProbs
,
1349 "DeleteProps(nonexistent): Expected E_ACCESSDENIED null got 0x%08X %p\n",
1352 /* Set access to read and write */
1353 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READWRITE
);
1354 ok(sc
== S_OK
, "SetObjAcess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1356 /* Delete nonexistent item - No error */
1358 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1359 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1360 ok(sc
== S_OK
&& !lpProbs
,
1361 "DeleteProps(nonexistent): Expected S_OK null got 0x%08X %p\n",
1364 /* Delete existing item (r/o) - No error, but lpProbs populated */
1366 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1367 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1368 ok(sc
== S_OK
&& lpProbs
,
1369 "DeleteProps(RO): Expected S_OK non-null got 0x%08X %p\n", sc
, lpProbs
);
1371 if (lpProbs
&& lpProbs
->cProblem
> 0)
1373 ok(lpProbs
->cProblem
== 1 &&
1374 lpProbs
->aProblem
[0].ulIndex
== 0 &&
1375 lpProbs
->aProblem
[0].ulPropTag
== PR_IMPORTANCE
&&
1376 lpProbs
->aProblem
[0].scode
== E_ACCESSDENIED
,
1377 "DeleteProps(RO): Expected (1,0,%x,%x) got (%d,%x,%x)\n",
1378 PR_IMPORTANCE
, E_ACCESSDENIED
,
1379 lpProbs
->aProblem
[0].ulIndex
, lpProbs
->aProblem
[0].ulPropTag
,
1380 lpProbs
->aProblem
[0].scode
);
1381 pMAPIFreeBuffer(lpProbs
);
1386 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1387 IPropData_HrAddObjProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1388 ok(sc
== S_OK
&& !lpProbs
,
1389 "AddObjProps(RO): Expected S_OK null got 0x%08X %p\n", sc
, lpProbs
);
1391 /* Get prop list - returns 1 item */
1393 IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1394 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 1,
1395 "GetPropList: Expected S_OK, non-null, 1, got 0x%08X,%p,%d\n",
1396 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1397 if (lpTags
&& lpTags
->cValues
> 0)
1399 ok(lpTags
->aulPropTag
[0] == PR_IMPORTANCE
,
1400 "GetPropList: Expected %x, got %x\n",
1401 PR_IMPORTANCE
, lpTags
->aulPropTag
[0]);
1402 pMAPIFreeBuffer(lpTags
);
1405 /* Set item to r/w again */
1406 access
[0] = IPROP_READWRITE
|IPROP_DIRTY
;
1407 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1408 ok(sc
== S_OK
, "SetPropAcess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1410 /* Delete existing item (r/w) - No error, no problems */
1412 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1413 ok(sc
== S_OK
&& !lpProbs
,
1414 "DeleteProps(RO): Expected S_OK null got 0x%08X %p\n", sc
, lpProbs
);
1417 IPropData_Release(lpIProp
);
1424 if (!HaveDefaultMailClient())
1426 win_skip("No default mail client installed\n");
1432 win_skip("Needed functions are not available\n");
1436 SetLastError(0xdeadbeef);
1437 ret
= pScInitMapiUtil(0);
1438 if ((ret
!= S_OK
) && (GetLastError() == ERROR_PROC_NOT_FOUND
))
1440 win_skip("ScInitMapiUtil is not implemented\n");
1441 FreeLibrary(hMapi32
);
1444 else if ((ret
== E_FAIL
) && (GetLastError() == ERROR_INVALID_HANDLE
))
1446 win_skip("ScInitMapiUtil doesn't work on some Win98 and WinME systems\n");
1447 FreeLibrary(hMapi32
);
1451 test_PropCopyMore();
1453 test_FPropContainsProp();
1454 test_FPropCompareProp();
1455 test_LPropCompareProp();
1456 test_PpropFindProp();
1457 test_ScCountProps();
1458 test_ScCopyRelocProps();
1459 test_LpValFindProp();
1466 test_FBadColumnSet();
1469 FreeLibrary(hMapi32
);