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"
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 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
,
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 const char *szHiA
= "Hi!";
87 static const WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
88 SPropValue
*lpDest
= NULL
, *lpSrc
= NULL
;
92 pPropCopyMore
= (void*)GetProcAddress(hMapi32
, "PropCopyMore@16");
97 scode
= pMAPIAllocateBuffer(sizeof(LPSPropValue
), (LPVOID
*)lpDest
);
101 scode
= pMAPIAllocateMore(sizeof(LPSPropValue
), lpDest
, (LPVOID
*)lpSrc
);
105 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
107 lpSrc
->ulPropTag
= ptTypes
[i
];
112 lpSrc
->Value
.lpszA
= (char*)szHiA
;
115 lpSrc
->Value
.lpszW
= (WCHAR
*)szHiW
;
118 lpSrc
->Value
.bin
.cb
= 4;
119 lpSrc
->Value
.bin
.lpb
= (LPBYTE
)szHiA
;
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
))
134 ok(lstrcmpA(lpDest
->Value
.lpszA
, lpSrc
->Value
.lpszA
) == 0,
135 "PropCopyMore: Ascii string differs\n");
138 ok(strcmpW(lpDest
->Value
.lpszW
, lpSrc
->Value
.lpszW
) == 0,
139 "PropCopyMore: Unicode string differs\n");
142 ok(lpDest
->Value
.bin
.cb
== 4 &&
143 !memcmp(lpSrc
->Value
.bin
.lpb
, lpDest
->Value
.bin
.lpb
, 4),
144 "PropCopyMore: Binary array differs\n");
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' };
163 pUlPropSize
= (void*)GetProcAddress(hMapi32
, "UlPropSize@4");
168 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
172 memset(&pv
, 0 ,sizeof(pv
));
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;
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;
205 case PT_CLSID
: exp
*= sizeof(GUID
); break;
207 pv
.Value
.lpszA
= (LPSTR
)szHiA
;
211 pv
.Value
.lpszW
= (LPWSTR
)szHiW
;
212 exp
= 4 * sizeof(WCHAR
);
215 pv
.Value
.bin
.cb
= exp
= 19;
218 pv
.Value
.MVszA
.cValues
= 2;
219 pv
.Value
.MVszA
.lppszA
= buffa
;
220 buffa
[0] = (LPSTR
)szHiA
;
221 buffa
[1] = (LPSTR
)szHiA
;
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
);
232 pv
.Value
.MVbin
.cValues
= 2;
233 pv
.Value
.MVbin
.lpbin
= buffbin
;
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
;
259 pFPropContainsProp
= (void*)GetProcAddress(hMapi32
, "FPropContainsProp@12");
261 if (!pFPropContainsProp
)
264 /* Ensure that only PT_STRING8 and PT_BINARY are handled */
265 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
267 if (pt
== PT_STRING8
|| pt
== PT_BINARY
)
268 continue; /* test these later */
270 memset(&pvLeft
, 0 ,sizeof(pvLeft
));
271 memset(&pvRight
, 0 ,sizeof(pvRight
));
272 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= pt
;
274 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
275 ok(bRet
== FALSE
, "pt= %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
376 } FPropCompareProp_Result
;
378 static const FPropCompareProp_Result FPCProp_Results
[] =
380 { 1, 2, RELOP_LT
, TRUE
},
381 { 1, 1, RELOP_LT
, FALSE
},
382 { 2, 1, RELOP_LT
, FALSE
},
383 { 1, 2, RELOP_LE
, TRUE
},
384 { 1, 1, RELOP_LE
, TRUE
},
385 { 2, 1, RELOP_LE
, FALSE
},
386 { 1, 2, RELOP_GT
, FALSE
},
387 { 1, 1, RELOP_GT
, FALSE
},
388 { 2, 1, RELOP_GT
, TRUE
},
389 { 1, 2, RELOP_GE
, FALSE
},
390 { 1, 1, RELOP_GE
, TRUE
},
391 { 2, 1, RELOP_GE
, TRUE
},
392 { 1, 2, RELOP_EQ
, FALSE
},
393 { 1, 1, RELOP_EQ
, TRUE
},
394 { 2, 1, RELOP_EQ
, FALSE
}
397 static const char *relops
[] = { "RELOP_LT", "RELOP_LE", "RELOP_GT", "RELOP_GE", "RELOP_EQ" };
399 static void test_FPropCompareProp(void)
401 SPropValue pvLeft
, pvRight
;
403 char lbuffa
[2], rbuffa
[2];
404 WCHAR lbuffw
[2], rbuffw
[2];
408 pFPropCompareProp
= (void*)GetProcAddress(hMapi32
, "FPropCompareProp@12");
410 if (!pFPropCompareProp
)
418 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
420 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= ptTypes
[i
];
422 for (j
= 0; j
< sizeof(FPCProp_Results
)/sizeof(FPCProp_Results
[0]); j
++)
424 SHORT lVal
= FPCProp_Results
[j
].lVal
;
425 SHORT rVal
= FPCProp_Results
[j
].rVal
;
427 bExp
= FPCProp_Results
[j
].bRet
;
432 /* Boolean values have no concept of less or greater than, only equality */
433 if ((lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_LT
) ||
434 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_LE
)||
435 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_GT
)||
436 (lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_GE
)||
437 (lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_EQ
)||
438 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_EQ
))
440 /* Fall through ... */
442 pvLeft
.Value
.i
= lVal
;
443 pvRight
.Value
.i
= rVal
;
447 pvLeft
.Value
.l
= lVal
;
448 pvRight
.Value
.l
= rVal
;
451 pvLeft
.Value
.flt
= lVal
;
452 pvRight
.Value
.flt
= rVal
;
456 pvLeft
.Value
.dbl
= lVal
;
457 pvRight
.Value
.dbl
= rVal
;
460 pvLeft
.Value
.cur
.int64
= lVal
;
461 pvRight
.Value
.cur
.int64
= rVal
;
464 pvLeft
.Value
.ft
.dwLowDateTime
= lVal
;
465 pvLeft
.Value
.ft
.dwHighDateTime
= 0;
466 pvRight
.Value
.ft
.dwLowDateTime
= rVal
;
467 pvRight
.Value
.ft
.dwHighDateTime
= 0;
470 pvLeft
.Value
.li
.u
.LowPart
= lVal
;
471 pvLeft
.Value
.li
.u
.HighPart
= 0;
472 pvRight
.Value
.li
.u
.LowPart
= rVal
;
473 pvRight
.Value
.li
.u
.HighPart
= 0;
476 memset(&lguid
, 0, sizeof(GUID
));
477 memset(&rguid
, 0, sizeof(GUID
));
478 lguid
.Data4
[7] = lVal
;
479 rguid
.Data4
[7] = rVal
;
480 pvLeft
.Value
.lpguid
= &lguid
;
481 pvRight
.Value
.lpguid
= &rguid
;
484 pvLeft
.Value
.lpszA
= lbuffa
;
485 pvRight
.Value
.lpszA
= rbuffa
;
486 lbuffa
[0] = '0' + lVal
;
487 rbuffa
[0] = '0' + rVal
;
490 pvLeft
.Value
.lpszW
= lbuffw
;
491 pvRight
.Value
.lpszW
= rbuffw
;
492 lbuffw
[0] = '0' + lVal
;
493 rbuffw
[0] = '0' + rVal
;
496 pvLeft
.Value
.bin
.cb
= 1;
497 pvRight
.Value
.bin
.cb
= 1;
498 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)lbuffa
;
499 pvRight
.Value
.bin
.lpb
= (LPBYTE
)rbuffa
;
505 bRet
= pFPropCompareProp(&pvLeft
, FPCProp_Results
[j
].relOp
, &pvRight
);
506 ok(bRet
== bExp
, "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
518 } LPropCompareProp_Result
;
520 static const LPropCompareProp_Result LPCProp_Results
[] =
527 static void test_LPropCompareProp(void)
529 SPropValue pvLeft
, pvRight
;
531 char lbuffa
[2], rbuffa
[2];
532 WCHAR lbuffw
[2], rbuffw
[2];
536 pLPropCompareProp
= (void*)GetProcAddress(hMapi32
, "LPropCompareProp@8");
538 if (!pLPropCompareProp
)
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
;
560 /* Boolean values have no concept of less or greater than, only equality */
563 /* Fall through ... */
565 pvLeft
.Value
.i
= lVal
;
566 pvRight
.Value
.i
= rVal
;
570 pvLeft
.Value
.l
= lVal
;
571 pvRight
.Value
.l
= rVal
;
574 pvLeft
.Value
.flt
= lVal
;
575 pvRight
.Value
.flt
= rVal
;
579 pvLeft
.Value
.dbl
= lVal
;
580 pvRight
.Value
.dbl
= rVal
;
583 pvLeft
.Value
.cur
.int64
= lVal
;
584 pvRight
.Value
.cur
.int64
= rVal
;
587 pvLeft
.Value
.ft
.dwLowDateTime
= lVal
;
588 pvLeft
.Value
.ft
.dwHighDateTime
= 0;
589 pvRight
.Value
.ft
.dwLowDateTime
= rVal
;
590 pvRight
.Value
.ft
.dwHighDateTime
= 0;
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;
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
;
607 pvLeft
.Value
.lpszA
= lbuffa
;
608 pvRight
.Value
.lpszA
= rbuffa
;
609 lbuffa
[0] = '0' + lVal
;
610 rbuffa
[0] = '0' + rVal
;
613 pvLeft
.Value
.lpszW
= lbuffw
;
614 pvRight
.Value
.lpszW
= rbuffw
;
615 lbuffw
[0] = '0' + lVal
;
616 rbuffw
[0] = '0' + rVal
;
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
;
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
;
640 pPpropFindProp
= (void*)GetProcAddress(hMapi32
, "PpropFindProp@12");
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",
653 pRet
= pPpropFindProp(&pvProp
, 1u, i
? ptTypes
[i
-1] : ptTypes
[i
+1]);
654 ok(pRet
== NULL
, "PpropFindProp[%ld]: Found nonexistent propery\n",
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 */
673 GUID iids
[4], *iid
= iids
;
675 ULONG pt
, exp
, ulRet
;
678 pScCountProps
= (void*)GetProcAddress(hMapi32
, "ScCountProps@12");
683 for (pt
= 0; pt
< PROP_ID_INVALID
&& success
; pt
++)
687 memset(&pv
, 0 ,sizeof(pv
));
688 pv
.ulPropTag
= PROP_TAG(pt
, 1u);
690 switch (PROP_TYPE(pt
))
706 pv
.Value
.lpguid
= iid
;
707 exp
= sizeof(GUID
) + sizeof(pv
);
710 pv
.Value
.lpszA
= (LPSTR
)szHiA
;
711 exp
= 4 + sizeof(pv
);
714 pv
.Value
.lpszW
= (LPWSTR
)szHiW
;
715 exp
= 4 * sizeof(WCHAR
) + sizeof(pv
);
719 pv
.Value
.bin
.lpb
= (LPBYTE
)iid
;
720 exp
= 2 + sizeof(pv
);
723 pv
.Value
.MVi
.cValues
= 3;
724 pv
.Value
.MVi
.lpi
= (SHORT
*)iid
;
725 exp
= 3 * sizeof(SHORT
) + sizeof(pv
);
728 pv
.Value
.MVl
.cValues
= 3;
729 pv
.Value
.MVl
.lpl
= (LONG
*)iid
;
730 exp
= 3 * sizeof(LONG
) + sizeof(pv
);
733 pv
.Value
.MVli
.cValues
= 3;
734 pv
.Value
.MVli
.lpli
= (LARGE_INTEGER
*)iid
;
735 exp
= 3 * sizeof(LARGE_INTEGER
) + sizeof(pv
);
738 pv
.Value
.MVflt
.cValues
= 3;
739 pv
.Value
.MVflt
.lpflt
= (float*)iid
;
740 exp
= 3 * sizeof(float) + sizeof(pv
);
744 pv
.Value
.MVdbl
.cValues
= 3;
745 pv
.Value
.MVdbl
.lpdbl
= (double*)iid
;
746 exp
= 3 * sizeof(double) + sizeof(pv
);
749 pv
.Value
.MVcur
.cValues
= 3;
750 pv
.Value
.MVcur
.lpcur
= (CY
*)iid
;
751 exp
= 3 * sizeof(CY
) + sizeof(pv
);
754 pv
.Value
.MVft
.cValues
= 3;
755 pv
.Value
.MVft
.lpft
= (FILETIME
*)iid
;
756 exp
= 3 * sizeof(CY
) + sizeof(pv
);
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
);
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
);
775 pv
.Value
.MVbin
.cValues
= 3;
776 pv
.Value
.MVbin
.lpbin
= buffbin
;
778 buffbin
[0].lpb
= (LPBYTE
)&iid
;
780 buffbin
[1].lpb
= (LPBYTE
)&iid
;
782 buffbin
[2].lpb
= (LPBYTE
)&iid
;
783 exp
= 20 + sizeof(pv
) + sizeof(SBinary
) * 3;
790 res
= pScCountProps(1, &pv
, &ulRet
);
792 success
= res
== MAPI_E_INVALID_PARAMETER
&& ulRet
== 0xffffffff;
793 ok(success
, "pt= %ld: Expected failure, got %ld, ret=0x%08lX\n",
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
;
813 pScCopyProps
= (void*)GetProcAddress(hMapi32
, "ScCopyProps@16");
814 pScRelocProps
= (void*)GetProcAddress(hMapi32
, "ScRelocProps@20");
816 if (!pScCopyProps
|| !pScRelocProps
)
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
;
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
));
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
;
874 pLpValFindProp
= (void*)GetProcAddress(hMapi32
, "LpValFindProp@12");
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",
887 pRet
= pLpValFindProp(PROP_TAG(ptTypes
[i
], 0u), 1u, &pvProp
);
888 ok(pRet
== NULL
, "LpValFindProp[%ld]: Found nonexistent propery id\n",
891 pRet
= pLpValFindProp(PROP_TAG(PT_NULL
, 0u), 1u, &pvProp
);
892 ok(pRet
== NULL
, "LpValFindProp[%ld]: Found nonexistent propery id/type\n",
895 pRet
= pLpValFindProp(PROP_TAG(PT_NULL
, 1u), 1u, &pvProp
);
896 ok(pRet
== &pvProp
, "LpValFindProp[%ld]: Didn't find existing propery id\n",
901 static void test_FBadRglpszA(void)
904 char *szString
= "A String";
907 pFBadRglpszA
= (void*)GetProcAddress(hMapi32
, "FBadRglpszA@8");
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)
929 WCHAR szString
[] = { 'A',' ','S','t','r','i','n','g','\0' };
932 pFBadRglpszW
= (void*)GetProcAddress(hMapi32
, "FBadRglpszW@8");
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)
955 pFBadRowSet
= (void*)GetProcAddress(hMapi32
, "FBadRowSet@4");
959 ulRet
= pFBadRowSet(NULL
);
960 ok(ulRet
!= 0, "FBadRow(null): Expected non-zero, got 0\n");
965 static void test_FBadPropTag(void)
969 pFBadPropTag
= (void*)GetProcAddress(hMapi32
, "FBadPropTag@4");
973 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
977 switch (pt
& (~MV_FLAG
& PROP_TYPE_MASK
))
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
:
988 res
= pFBadPropTag(pt
);
990 ok(res
!= 0, "pt= %ld: Expected non-zero, got 0\n", pt
);
992 ok(res
== 0, "pt= %ld: Expected zero, got %ld\n", pt
, res
);
996 static void test_FBadRow(void)
1000 pFBadRow
= (void*)GetProcAddress(hMapi32
, "FBadRow@4");
1004 ulRet
= pFBadRow(NULL
);
1005 ok(ulRet
!= 0, "FBadRow(null): Expected non-zero, got 0\n");
1010 static void test_FBadProp(void)
1012 WCHAR szEmpty
[] = { '\0' };
1017 pFBadProp
= (void*)GetProcAddress(hMapi32
, "FBadProp@4");
1021 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1025 memset(&pv
, 0, sizeof(pv
));
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
):
1047 case PT_MV_CURRENCY
:
1051 case (MV_FLAG
|PT_ERROR
):
1053 case (MV_FLAG
|PT_BOOLEAN
):
1055 case (MV_FLAG
|PT_OBJECT
):
1068 pv
.Value
.lpszW
= szEmpty
;
1072 pv
.Value
.lpguid
= &iid
;
1077 res
= pFBadProp(&pv
);
1079 ok(res
!= 0, "pt= %ld: Expected non-zero, got 0\n", pt
);
1081 ok(res
== 0, "pt= %ld: Expected zero, got %ld\n", pt
, res
);
1085 static void test_FBadColumnSet(void)
1090 pFBadColumnSet
= (void*)GetProcAddress(hMapi32
, "FBadColumnSet@4");
1091 if (!pFBadColumnSet
)
1094 res
= pFBadColumnSet(NULL
);
1095 ok(res
!= 0, "(null): Expected non-zero, got 0\n");
1099 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1103 pta
.aulPropTag
[0] = pt
;
1105 switch (pt
& (~MV_FLAG
& PROP_TYPE_MASK
))
1107 case PT_UNSPECIFIED
:
1125 if (pt
== (MV_FLAG
|PT_ERROR
))
1128 res
= pFBadColumnSet(&pta
);
1130 ok(res
!= 0, "pt= %ld: Expected non-zero, got 0\n", pt
);
1132 ok(res
== 0, "pt= %ld: Expected zero, got %ld\n", pt
, res
);
1137 static void test_IProp(void)
1140 LPMAPIERROR lpError
;
1141 LPSPropProblemArray lpProbs
;
1142 LPSPropValue lpProps
;
1143 LPSPropTagArray lpTags
;
1145 SizedSPropTagArray(2,tags
);
1146 ULONG access
[2], count
;
1149 pCreateIProp
= (void*)GetProcAddress(hMapi32
, "CreateIProp@24");
1154 memset(&tags
, 0 , sizeof(tags
));
1156 /* Create the object */
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
)
1166 /* GetLastError - No errors set */
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 */
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);
1179 pMAPIFreeBuffer(lpTags
);
1181 /* Get props - succeeds returning 0 items */
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 */
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",
1207 /* Add (OBJECT) - Can't add OBJECTS's */
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",
1215 /* Add - Adds value */
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 */
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
);
1241 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1243 /* Set item access (bad access) - Fails */
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 */
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 */
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",
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 */
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",
1293 /* Delete existing item (r/o) - No error, but lpProbs populated */
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
);
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 */
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 */
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
);
1346 IPropData_Release(lpIProp
);
1356 test_PropCopyMore();
1358 test_FPropContainsProp();
1359 test_FPropCompareProp();
1360 test_LPropCompareProp();
1361 test_PpropFindProp();
1362 test_ScCountProps();
1363 test_ScCopyRelocProps();
1364 test_LpValFindProp();
1371 test_FBadColumnSet();
1374 FreeLibrary(hMapi32
);