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"
31 static HMODULE hMapi32
= 0;
33 static SCODE (WINAPI
*pScInitMapiUtil
)(ULONG
);
34 static SCODE (WINAPI
*pPropCopyMore
)(LPSPropValue
,LPSPropValue
,ALLOCATEMORE
*,LPVOID
);
35 static ULONG (WINAPI
*pUlPropSize
)(LPSPropValue
);
36 static BOOL (WINAPI
*pFPropContainsProp
)(LPSPropValue
,LPSPropValue
,ULONG
);
37 static BOOL (WINAPI
*pFPropCompareProp
)(LPSPropValue
,ULONG
,LPSPropValue
);
38 static LONG (WINAPI
*pLPropCompareProp
)(LPSPropValue
,LPSPropValue
);
39 static LPSPropValue (WINAPI
*pPpropFindProp
)(LPSPropValue
,ULONG
,ULONG
);
40 static SCODE (WINAPI
*pScCountProps
)(INT
,LPSPropValue
,ULONG
*);
41 static SCODE (WINAPI
*pScCopyProps
)(int,LPSPropValue
,LPVOID
,ULONG
*);
42 static SCODE (WINAPI
*pScRelocProps
)(int,LPSPropValue
,LPVOID
,LPVOID
,ULONG
*);
43 static LPSPropValue (WINAPI
*pLpValFindProp
)(ULONG
,ULONG
,LPSPropValue
);
44 static BOOL (WINAPI
*pFBadRglpszA
)(LPSTR
*,ULONG
);
45 static BOOL (WINAPI
*pFBadRglpszW
)(LPWSTR
*,ULONG
);
46 static BOOL (WINAPI
*pFBadRowSet
)(LPSRowSet
);
47 static ULONG (WINAPI
*pFBadPropTag
)(ULONG
);
48 static ULONG (WINAPI
*pFBadRow
)(LPSRow
);
49 static ULONG (WINAPI
*pFBadProp
)(LPSPropValue
);
50 static ULONG (WINAPI
*pFBadColumnSet
)(LPSPropTagArray
);
51 static SCODE (WINAPI
*pCreateIProp
)(LPCIID
,ALLOCATEBUFFER
*,ALLOCATEMORE
*,
52 FREEBUFFER
*,LPVOID
,LPPROPDATA
*);
53 static SCODE (WINAPI
*pMAPIAllocateBuffer
)(ULONG
, LPVOID
);
54 static SCODE (WINAPI
*pMAPIAllocateMore
)(ULONG
, LPVOID
, LPVOID
);
55 static SCODE (WINAPI
*pMAPIFreeBuffer
)(LPVOID
);
57 static BOOL
InitFuncPtrs(void)
59 hMapi32
= LoadLibraryA("mapi32.dll");
61 pScInitMapiUtil
= (void*)GetProcAddress(hMapi32
, "ScInitMapiUtil@4");
62 pMAPIAllocateBuffer
= (void*)GetProcAddress(hMapi32
, "MAPIAllocateBuffer");
63 pMAPIAllocateMore
= (void*)GetProcAddress(hMapi32
, "MAPIAllocateMore");
64 pMAPIFreeBuffer
= (void*)GetProcAddress(hMapi32
, "MAPIFreeBuffer");
65 if(pScInitMapiUtil
&& pMAPIAllocateBuffer
&& pMAPIAllocateMore
&& pMAPIFreeBuffer
)
71 static ULONG ptTypes
[] = {
72 PT_I2
, PT_I4
, PT_R4
, PT_R8
, PT_CURRENCY
, PT_APPTIME
, PT_SYSTIME
,
73 PT_ERROR
, PT_BOOLEAN
, PT_I8
, PT_CLSID
, PT_STRING8
, PT_BINARY
,
77 static inline int strcmpW(const WCHAR
*str1
, const WCHAR
*str2
)
79 while (*str1
&& (*str1
== *str2
)) { str1
++; str2
++; }
83 static void test_PropCopyMore(void)
85 static char szHiA
[] = "Hi!";
86 static WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
87 SPropValue
*lpDest
= NULL
, *lpSrc
= NULL
;
91 pPropCopyMore
= (void*)GetProcAddress(hMapi32
, "PropCopyMore@16");
96 scode
= pMAPIAllocateBuffer(sizeof(LPSPropValue
), lpDest
);
100 scode
= pMAPIAllocateMore(sizeof(LPSPropValue
), lpDest
, lpSrc
);
104 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
106 lpSrc
->ulPropTag
= ptTypes
[i
];
111 lpSrc
->Value
.lpszA
= szHiA
;
114 lpSrc
->Value
.lpszW
= szHiW
;
117 lpSrc
->Value
.bin
.cb
= 4;
118 lpSrc
->Value
.bin
.lpb
= (LPBYTE
)szHiA
;
122 memset(lpDest
, 0xff, sizeof(SPropValue
));
124 scode
= pPropCopyMore(lpDest
, lpSrc
, (ALLOCATEMORE
*)pMAPIAllocateMore
, lpDest
);
125 ok(!scode
&& lpDest
->ulPropTag
== lpSrc
->ulPropTag
,
126 "PropCopyMore: Expected 0x0,%d, got 0x%08x,%d\n",
127 lpSrc
->ulPropTag
, scode
, lpDest
->ulPropTag
);
128 if (SUCCEEDED(scode
))
133 ok(lstrcmpA(lpDest
->Value
.lpszA
, lpSrc
->Value
.lpszA
) == 0,
134 "PropCopyMore: Ascii string differs\n");
137 ok(strcmpW(lpDest
->Value
.lpszW
, lpSrc
->Value
.lpszW
) == 0,
138 "PropCopyMore: Unicode string differs\n");
141 ok(lpDest
->Value
.bin
.cb
== 4 &&
142 !memcmp(lpSrc
->Value
.bin
.lpb
, lpDest
->Value
.bin
.lpb
, 4),
143 "PropCopyMore: Binary array differs\n");
149 /* Since all allocations are linked, freeing lpDest frees everything */
150 pMAPIFreeBuffer(lpDest
);
153 static void test_UlPropSize(void)
155 static char szHiA
[] = "Hi!";
156 static WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
162 pUlPropSize
= (void*)GetProcAddress(hMapi32
, "UlPropSize@4");
167 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
171 memset(&pv
, 0 ,sizeof(pv
));
174 exp
= 1u; /* Default to one item for non-MV properties */
176 switch (PROP_TYPE(pt
))
178 case PT_MV_I2
: pv
.Value
.MVi
.cValues
= exp
= 2;
179 case PT_I2
: exp
*= sizeof(USHORT
); break;
180 case PT_MV_I4
: pv
.Value
.MVl
.cValues
= exp
= 2;
181 case PT_I4
: exp
*= sizeof(LONG
); break;
182 case PT_MV_R4
: pv
.Value
.MVflt
.cValues
= exp
= 2;
183 case PT_R4
: exp
*= sizeof(float); break;
184 case PT_MV_DOUBLE
: pv
.Value
.MVdbl
.cValues
= exp
= 2;
185 case PT_R8
: exp
*= sizeof(double); break;
186 case PT_MV_CURRENCY
: pv
.Value
.MVcur
.cValues
= exp
= 2;
187 case PT_CURRENCY
: exp
*= sizeof(CY
); break;
188 case PT_MV_APPTIME
: pv
.Value
.MVat
.cValues
= exp
= 2;
189 case PT_APPTIME
: exp
*= sizeof(double); break;
190 case PT_MV_SYSTIME
: pv
.Value
.MVft
.cValues
= exp
= 2;
191 case PT_SYSTIME
: exp
*= sizeof(FILETIME
); break;
192 case PT_ERROR
: exp
= sizeof(SCODE
); break;
193 case PT_BOOLEAN
: exp
= sizeof(USHORT
); break;
194 case PT_OBJECT
: exp
= 0; break;
195 case PT_MV_I8
: pv
.Value
.MVli
.cValues
= exp
= 2;
196 case PT_I8
: exp
*= sizeof(LONG64
); break;
198 /* My version of native mapi returns 0 for PT_MV_CLSID even if a valid
199 * array is given. This _has_ to be a bug, so Wine does
200 * the right thing(tm) and we don't test it here.
202 case PT_MV_CLSID
: pv
.Value
.MVguid
.cValues
= exp
= 2;
204 case PT_CLSID
: exp
*= sizeof(GUID
); break;
206 pv
.Value
.lpszA
= szHiA
;
210 pv
.Value
.lpszW
= szHiW
;
211 exp
= 4 * sizeof(WCHAR
);
214 pv
.Value
.bin
.cb
= exp
= 19;
217 pv
.Value
.MVszA
.cValues
= 2;
218 pv
.Value
.MVszA
.lppszA
= buffa
;
224 pv
.Value
.MVszW
.cValues
= 2;
225 pv
.Value
.MVszW
.lppszW
= buffw
;
228 exp
= 8 * sizeof(WCHAR
);
231 pv
.Value
.MVbin
.cValues
= 2;
232 pv
.Value
.MVbin
.lpbin
= buffbin
;
241 res
= pUlPropSize(&pv
);
242 ok(res
== exp
, "pt= %d: Expected %d, got %d\n", pt
, exp
, res
);
246 static void test_FPropContainsProp(void)
248 static char szFull
[] = "Full String";
249 static char szFullLower
[] = "full string";
250 static char szPrefix
[] = "Full";
251 static char szPrefixLower
[] = "full";
252 static char szSubstring
[] = "ll St";
253 static char szSubstringLower
[] = "ll st";
254 SPropValue pvLeft
, pvRight
;
258 pFPropContainsProp
= (void*)GetProcAddress(hMapi32
, "FPropContainsProp@12");
260 if (!pFPropContainsProp
)
263 /* Ensure that only PT_STRING8 and PT_BINARY are handled */
264 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
266 if (pt
== PT_STRING8
|| pt
== PT_BINARY
)
267 continue; /* test these later */
269 memset(&pvLeft
, 0 ,sizeof(pvLeft
));
270 memset(&pvRight
, 0 ,sizeof(pvRight
));
271 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= pt
;
273 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
274 ok(bRet
== FALSE
, "pt= %d: Expected FALSE, got %d\n", pt
, bRet
);
277 /* test the various flag combinations */
278 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= PT_STRING8
;
279 pvLeft
.Value
.lpszA
= szFull
;
280 pvRight
.Value
.lpszA
= szFull
;
282 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
283 ok(bRet
== TRUE
, "(full,full)[] match failed\n");
284 pvRight
.Value
.lpszA
= szPrefix
;
285 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
286 ok(bRet
== FALSE
, "(full,prefix)[] match failed\n");
287 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
288 ok(bRet
== TRUE
, "(full,prefix)[PREFIX] match failed\n");
289 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
290 ok(bRet
== TRUE
, "(full,prefix)[SUBSTRING] match failed\n");
291 pvRight
.Value
.lpszA
= szPrefixLower
;
292 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
293 ok(bRet
== FALSE
, "(full,prefixlow)[PREFIX] match failed\n");
294 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
295 ok(bRet
== FALSE
, "(full,prefixlow)[SUBSTRING] match failed\n");
296 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
297 ok(bRet
== TRUE
, "(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
298 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
299 ok(bRet
== TRUE
, "(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
300 pvRight
.Value
.lpszA
= szSubstring
;
301 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
302 ok(bRet
== FALSE
, "(full,substr)[] match failed\n");
303 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
304 ok(bRet
== FALSE
, "(full,substr)[PREFIX] match failed\n");
305 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
306 ok(bRet
== TRUE
, "(full,substr)[SUBSTRING] match failed\n");
307 pvRight
.Value
.lpszA
= szSubstringLower
;
308 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
309 ok(bRet
== FALSE
, "(full,substrlow)[PREFIX] match failed\n");
310 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
311 ok(bRet
== FALSE
, "(full,substrlow)[SUBSTRING] match failed\n");
312 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
313 ok(bRet
== FALSE
, "(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
314 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
315 ok(bRet
== TRUE
, "(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
316 pvRight
.Value
.lpszA
= szFullLower
;
317 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
|FL_IGNORECASE
);
318 ok(bRet
== TRUE
, "(full,fulllow)[IGNORECASE] match failed\n");
320 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= PT_BINARY
;
321 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)szFull
;
322 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szFull
;
323 pvLeft
.Value
.bin
.cb
= pvRight
.Value
.bin
.cb
= strlen(szFull
);
325 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
326 ok(bRet
== TRUE
, "bin(full,full)[] match failed\n");
327 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szPrefix
;
328 pvRight
.Value
.bin
.cb
= strlen(szPrefix
);
329 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
330 ok(bRet
== FALSE
, "bin(full,prefix)[] match failed\n");
331 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
332 ok(bRet
== TRUE
, "bin(full,prefix)[PREFIX] match failed\n");
333 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
334 ok(bRet
== TRUE
, "bin(full,prefix)[SUBSTRING] match failed\n");
335 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szPrefixLower
;
336 pvRight
.Value
.bin
.cb
= strlen(szPrefixLower
);
337 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
338 ok(bRet
== FALSE
, "bin(full,prefixlow)[PREFIX] match failed\n");
339 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
340 ok(bRet
== FALSE
, "bin(full,prefixlow)[SUBSTRING] match failed\n");
341 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
342 ok(bRet
== FALSE
, "bin(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
343 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
344 ok(bRet
== FALSE
, "bin(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
345 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szSubstring
;
346 pvRight
.Value
.bin
.cb
= strlen(szSubstring
);
347 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
348 ok(bRet
== FALSE
, "bin(full,substr)[] match failed\n");
349 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
350 ok(bRet
== FALSE
, "bin(full,substr)[PREFIX] match failed\n");
351 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
352 ok(bRet
== TRUE
, "bin(full,substr)[SUBSTRING] match failed\n");
353 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szSubstringLower
;
354 pvRight
.Value
.bin
.cb
= strlen(szSubstringLower
);
355 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
356 ok(bRet
== FALSE
, "bin(full,substrlow)[PREFIX] match failed\n");
357 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
358 ok(bRet
== FALSE
, "bin(full,substrlow)[SUBSTRING] match failed\n");
359 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
360 ok(bRet
== FALSE
, "bin(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
361 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
362 ok(bRet
== FALSE
, "bin(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
363 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szFullLower
;
364 pvRight
.Value
.bin
.cb
= strlen(szFullLower
);
365 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
|FL_IGNORECASE
);
366 ok(bRet
== FALSE
, "bin(full,fulllow)[IGNORECASE] match failed\n");
369 typedef struct tagFPropCompareProp_Result
375 } FPropCompareProp_Result
;
377 static const FPropCompareProp_Result FPCProp_Results
[] =
379 { 1, 2, RELOP_LT
, TRUE
},
380 { 1, 1, RELOP_LT
, FALSE
},
381 { 2, 1, RELOP_LT
, FALSE
},
382 { 1, 2, RELOP_LE
, TRUE
},
383 { 1, 1, RELOP_LE
, TRUE
},
384 { 2, 1, RELOP_LE
, FALSE
},
385 { 1, 2, RELOP_GT
, FALSE
},
386 { 1, 1, RELOP_GT
, FALSE
},
387 { 2, 1, RELOP_GT
, TRUE
},
388 { 1, 2, RELOP_GE
, FALSE
},
389 { 1, 1, RELOP_GE
, TRUE
},
390 { 2, 1, RELOP_GE
, TRUE
},
391 { 1, 2, RELOP_EQ
, FALSE
},
392 { 1, 1, RELOP_EQ
, TRUE
},
393 { 2, 1, RELOP_EQ
, FALSE
}
396 static const char *relops
[] = { "RELOP_LT", "RELOP_LE", "RELOP_GT", "RELOP_GE", "RELOP_EQ" };
398 static void test_FPropCompareProp(void)
400 SPropValue pvLeft
, pvRight
;
402 char lbuffa
[2], rbuffa
[2];
403 WCHAR lbuffw
[2], rbuffw
[2];
407 pFPropCompareProp
= (void*)GetProcAddress(hMapi32
, "FPropCompareProp@12");
409 if (!pFPropCompareProp
)
417 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
419 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= ptTypes
[i
];
421 for (j
= 0; j
< sizeof(FPCProp_Results
)/sizeof(FPCProp_Results
[0]); j
++)
423 SHORT lVal
= FPCProp_Results
[j
].lVal
;
424 SHORT rVal
= FPCProp_Results
[j
].rVal
;
426 bExp
= FPCProp_Results
[j
].bRet
;
431 /* Boolean values have no concept of less or greater than, only equality */
432 if ((lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_LT
) ||
433 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_LE
)||
434 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_GT
)||
435 (lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_GE
)||
436 (lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_EQ
)||
437 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_EQ
))
439 /* Fall through ... */
441 pvLeft
.Value
.i
= lVal
;
442 pvRight
.Value
.i
= rVal
;
446 pvLeft
.Value
.l
= lVal
;
447 pvRight
.Value
.l
= rVal
;
450 pvLeft
.Value
.flt
= lVal
;
451 pvRight
.Value
.flt
= rVal
;
455 pvLeft
.Value
.dbl
= lVal
;
456 pvRight
.Value
.dbl
= rVal
;
459 pvLeft
.Value
.cur
.int64
= lVal
;
460 pvRight
.Value
.cur
.int64
= rVal
;
463 pvLeft
.Value
.ft
.dwLowDateTime
= lVal
;
464 pvLeft
.Value
.ft
.dwHighDateTime
= 0;
465 pvRight
.Value
.ft
.dwLowDateTime
= rVal
;
466 pvRight
.Value
.ft
.dwHighDateTime
= 0;
469 pvLeft
.Value
.li
.u
.LowPart
= lVal
;
470 pvLeft
.Value
.li
.u
.HighPart
= 0;
471 pvRight
.Value
.li
.u
.LowPart
= rVal
;
472 pvRight
.Value
.li
.u
.HighPart
= 0;
475 memset(&lguid
, 0, sizeof(GUID
));
476 memset(&rguid
, 0, sizeof(GUID
));
477 lguid
.Data4
[7] = lVal
;
478 rguid
.Data4
[7] = rVal
;
479 pvLeft
.Value
.lpguid
= &lguid
;
480 pvRight
.Value
.lpguid
= &rguid
;
483 pvLeft
.Value
.lpszA
= lbuffa
;
484 pvRight
.Value
.lpszA
= rbuffa
;
485 lbuffa
[0] = '0' + lVal
;
486 rbuffa
[0] = '0' + rVal
;
489 pvLeft
.Value
.lpszW
= lbuffw
;
490 pvRight
.Value
.lpszW
= rbuffw
;
491 lbuffw
[0] = '0' + lVal
;
492 rbuffw
[0] = '0' + rVal
;
495 pvLeft
.Value
.bin
.cb
= 1;
496 pvRight
.Value
.bin
.cb
= 1;
497 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)lbuffa
;
498 pvRight
.Value
.bin
.lpb
= (LPBYTE
)rbuffa
;
504 bRet
= pFPropCompareProp(&pvLeft
, FPCProp_Results
[j
].relOp
, &pvRight
);
505 ok(bRet
== bExp
, "pt %d (%d,%d,%s): expected %d, got %d\n", ptTypes
[i
],
506 FPCProp_Results
[j
].lVal
, FPCProp_Results
[j
].rVal
,
507 relops
[FPCProp_Results
[j
].relOp
], bExp
, bRet
);
512 typedef struct tagLPropCompareProp_Result
517 } LPropCompareProp_Result
;
519 static const LPropCompareProp_Result LPCProp_Results
[] =
526 static void test_LPropCompareProp(void)
528 SPropValue pvLeft
, pvRight
;
530 char lbuffa
[2], rbuffa
[2];
531 WCHAR lbuffw
[2], rbuffw
[2];
535 pLPropCompareProp
= (void*)GetProcAddress(hMapi32
, "LPropCompareProp@8");
537 if (!pLPropCompareProp
)
545 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
547 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= ptTypes
[i
];
549 for (j
= 0; j
< sizeof(LPCProp_Results
)/sizeof(LPCProp_Results
[0]); j
++)
551 SHORT lVal
= LPCProp_Results
[j
].lVal
;
552 SHORT rVal
= LPCProp_Results
[j
].rVal
;
554 iExp
= LPCProp_Results
[j
].iRet
;
559 /* Boolean values have no concept of less or greater than, only equality */
562 /* Fall through ... */
564 pvLeft
.Value
.i
= lVal
;
565 pvRight
.Value
.i
= rVal
;
569 pvLeft
.Value
.l
= lVal
;
570 pvRight
.Value
.l
= rVal
;
573 pvLeft
.Value
.flt
= lVal
;
574 pvRight
.Value
.flt
= rVal
;
578 pvLeft
.Value
.dbl
= lVal
;
579 pvRight
.Value
.dbl
= rVal
;
582 pvLeft
.Value
.cur
.int64
= lVal
;
583 pvRight
.Value
.cur
.int64
= rVal
;
586 pvLeft
.Value
.ft
.dwLowDateTime
= lVal
;
587 pvLeft
.Value
.ft
.dwHighDateTime
= 0;
588 pvRight
.Value
.ft
.dwLowDateTime
= rVal
;
589 pvRight
.Value
.ft
.dwHighDateTime
= 0;
592 pvLeft
.Value
.li
.u
.LowPart
= lVal
;
593 pvLeft
.Value
.li
.u
.HighPart
= 0;
594 pvRight
.Value
.li
.u
.LowPart
= rVal
;
595 pvRight
.Value
.li
.u
.HighPart
= 0;
598 memset(&lguid
, 0, sizeof(GUID
));
599 memset(&rguid
, 0, sizeof(GUID
));
600 lguid
.Data4
[7] = lVal
;
601 rguid
.Data4
[7] = rVal
;
602 pvLeft
.Value
.lpguid
= &lguid
;
603 pvRight
.Value
.lpguid
= &rguid
;
606 pvLeft
.Value
.lpszA
= lbuffa
;
607 pvRight
.Value
.lpszA
= rbuffa
;
608 lbuffa
[0] = '0' + lVal
;
609 rbuffa
[0] = '0' + rVal
;
612 pvLeft
.Value
.lpszW
= lbuffw
;
613 pvRight
.Value
.lpszW
= rbuffw
;
614 lbuffw
[0] = '0' + lVal
;
615 rbuffw
[0] = '0' + rVal
;
618 pvLeft
.Value
.bin
.cb
= 1;
619 pvRight
.Value
.bin
.cb
= 1;
620 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)lbuffa
;
621 pvRight
.Value
.bin
.lpb
= (LPBYTE
)rbuffa
;
627 iRet
= pLPropCompareProp(&pvLeft
, &pvRight
);
628 ok(iRet
== iExp
, "pt %d (%d,%d): expected %d, got %d\n", ptTypes
[i
],
629 LPCProp_Results
[j
].lVal
, LPCProp_Results
[j
].rVal
, iExp
, iRet
);
634 static void test_PpropFindProp(void)
636 SPropValue pvProp
, *pRet
;
639 pPpropFindProp
= (void*)GetProcAddress(hMapi32
, "PpropFindProp@12");
644 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
646 pvProp
.ulPropTag
= ptTypes
[i
];
648 pRet
= pPpropFindProp(&pvProp
, 1u, ptTypes
[i
]);
649 ok(pRet
== &pvProp
, "PpropFindProp[%d]: Didn't find existing propery\n",
652 pRet
= pPpropFindProp(&pvProp
, 1u, i
? ptTypes
[i
-1] : ptTypes
[i
+1]);
653 ok(pRet
== NULL
, "PpropFindProp[%d]: Found nonexistent propery\n",
657 pvProp
.ulPropTag
= PROP_TAG(PT_I2
, 1u);
658 pRet
= pPpropFindProp(&pvProp
, 1u, PROP_TAG(PT_UNSPECIFIED
, 0u));
659 ok(pRet
== NULL
, "PpropFindProp[UNSPECIFIED]: Matched on different id\n");
660 pRet
= pPpropFindProp(&pvProp
, 1u, PROP_TAG(PT_UNSPECIFIED
, 1u));
661 ok(pRet
== &pvProp
, "PpropFindProp[UNSPECIFIED]: Didn't match id\n");
664 static void test_ScCountProps(void)
666 static char szHiA
[] = "Hi!";
667 static WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
668 static const ULONG ULHILEN
= 4; /* chars in szHiA/W incl. NUL */
672 GUID iids
[4], *iid
= iids
;
674 ULONG pt
, exp
, ulRet
;
677 pScCountProps
= (void*)GetProcAddress(hMapi32
, "ScCountProps@12");
682 for (pt
= 0; pt
< PROP_ID_INVALID
&& success
; pt
++)
686 memset(&pv
, 0 ,sizeof(pv
));
687 pv
.ulPropTag
= PROP_TAG(pt
, 1u);
689 switch (PROP_TYPE(pt
))
705 pv
.Value
.lpguid
= iid
;
706 exp
= sizeof(GUID
) + sizeof(pv
);
709 pv
.Value
.lpszA
= szHiA
;
710 exp
= 4 + sizeof(pv
);
713 pv
.Value
.lpszW
= szHiW
;
714 exp
= 4 * sizeof(WCHAR
) + sizeof(pv
);
718 pv
.Value
.bin
.lpb
= (LPBYTE
)iid
;
719 exp
= 2 + sizeof(pv
);
722 pv
.Value
.MVi
.cValues
= 3;
723 pv
.Value
.MVi
.lpi
= (SHORT
*)iid
;
724 exp
= 3 * sizeof(SHORT
) + sizeof(pv
);
727 pv
.Value
.MVl
.cValues
= 3;
728 pv
.Value
.MVl
.lpl
= (LONG
*)iid
;
729 exp
= 3 * sizeof(LONG
) + sizeof(pv
);
732 pv
.Value
.MVli
.cValues
= 3;
733 pv
.Value
.MVli
.lpli
= (LARGE_INTEGER
*)iid
;
734 exp
= 3 * sizeof(LARGE_INTEGER
) + sizeof(pv
);
737 pv
.Value
.MVflt
.cValues
= 3;
738 pv
.Value
.MVflt
.lpflt
= (float*)iid
;
739 exp
= 3 * sizeof(float) + sizeof(pv
);
743 pv
.Value
.MVdbl
.cValues
= 3;
744 pv
.Value
.MVdbl
.lpdbl
= (double*)iid
;
745 exp
= 3 * sizeof(double) + sizeof(pv
);
748 pv
.Value
.MVcur
.cValues
= 3;
749 pv
.Value
.MVcur
.lpcur
= (CY
*)iid
;
750 exp
= 3 * sizeof(CY
) + sizeof(pv
);
753 pv
.Value
.MVft
.cValues
= 3;
754 pv
.Value
.MVft
.lpft
= (FILETIME
*)iid
;
755 exp
= 3 * sizeof(CY
) + sizeof(pv
);
758 pv
.Value
.MVszA
.cValues
= 3;
759 pv
.Value
.MVszA
.lppszA
= buffa
;
763 exp
= ULHILEN
* 3 + 3 * sizeof(char*) + sizeof(pv
);
766 pv
.Value
.MVszW
.cValues
= 3;
767 pv
.Value
.MVszW
.lppszW
= buffw
;
771 exp
= ULHILEN
* 3 * sizeof(WCHAR
) + 3 * sizeof(WCHAR
*) + sizeof(pv
);
774 pv
.Value
.MVbin
.cValues
= 3;
775 pv
.Value
.MVbin
.lpbin
= buffbin
;
777 buffbin
[0].lpb
= (LPBYTE
)&iid
;
779 buffbin
[1].lpb
= (LPBYTE
)&iid
;
781 buffbin
[2].lpb
= (LPBYTE
)&iid
;
782 exp
= 20 + sizeof(pv
) + sizeof(SBinary
) * 3;
789 res
= pScCountProps(1, &pv
, &ulRet
);
791 success
= res
== MAPI_E_INVALID_PARAMETER
&& ulRet
== 0xffffffff;
792 ok(success
, "pt= %d: Expected failure, got %d, ret=0x%08X\n",
796 success
= res
== S_OK
&& ulRet
== exp
;
797 ok(success
, "pt= %d: Expected %d, got %d, ret=0x%08X\n",
798 pt
, exp
, ulRet
, res
);
804 static void test_ScCopyRelocProps(void)
806 static char szTestA
[] = "Test";
807 char buffer
[512], buffer2
[512], *lppszA
[1];
808 SPropValue pvProp
, *lpResProp
= (LPSPropValue
)buffer
;
812 pScCopyProps
= (void*)GetProcAddress(hMapi32
, "ScCopyProps@16");
813 pScRelocProps
= (void*)GetProcAddress(hMapi32
, "ScRelocProps@20");
815 if (!pScCopyProps
|| !pScRelocProps
)
818 pvProp
.ulPropTag
= PROP_TAG(PT_MV_STRING8
, 1u);
821 pvProp
.Value
.MVszA
.cValues
= 1;
822 pvProp
.Value
.MVszA
.lppszA
= lppszA
;
825 sc
= pScCopyProps(1, &pvProp
, buffer
, &ulCount
);
826 ok(sc
== S_OK
, "wrong ret %d\n", sc
);
829 ok(lpResProp
->ulPropTag
== pvProp
.ulPropTag
, "wrong tag %x\n",lpResProp
->ulPropTag
);
830 ok(lpResProp
->Value
.MVszA
.cValues
== 1, "wrong cValues %d\n", lpResProp
->Value
.MVszA
.cValues
);
831 ok(lpResProp
->Value
.MVszA
.lppszA
[0] == buffer
+ sizeof(SPropValue
) + sizeof(char*),
832 "wrong lppszA[0] %p\n",lpResProp
->Value
.MVszA
.lppszA
[0]);
833 ok(ulCount
== sizeof(SPropValue
) + sizeof(char*) + 5, "wrong count %d\n", ulCount
);
834 ok(!strcmp(lpResProp
->Value
.MVszA
.lppszA
[0], szTestA
),
835 "wrong string '%s'\n", lpResProp
->Value
.MVszA
.lppszA
[0]);
838 memcpy(buffer2
, buffer
, sizeof(buffer
));
840 /* Clear the data in the source buffer. Since pointers in the copied buffer
841 * refer to the source buffer, this proves that native always assumes that
842 * the copied buffers pointers are bad (needing to be relocated first).
844 memset(buffer
, 0, sizeof(buffer
));
847 sc
= pScRelocProps(1, (LPSPropValue
)buffer2
, buffer
, buffer2
, &ulCount
);
848 lpResProp
= (LPSPropValue
)buffer2
;
850 ok(sc
== S_OK
, "wrong ret %d\n", sc
);
853 ok(lpResProp
->ulPropTag
== pvProp
.ulPropTag
, "wrong tag %x\n",lpResProp
->ulPropTag
);
854 ok(lpResProp
->Value
.MVszA
.cValues
== 1, "wrong cValues %d\n", lpResProp
->Value
.MVszA
.cValues
);
855 ok(lpResProp
->Value
.MVszA
.lppszA
[0] == buffer2
+ sizeof(SPropValue
) + sizeof(char*),
856 "wrong lppszA[0] %p\n",lpResProp
->Value
.MVszA
.lppszA
[0]);
857 /* Native has a bug whereby it calculates the size correctly when copying
858 * but when relocating does not (presumably it uses UlPropSize() which
859 * ignores multivalue pointers). Wine returns the correct value.
861 ok(ulCount
== sizeof(SPropValue
) + sizeof(char*) + 5 || ulCount
== sizeof(SPropValue
) + 5,
862 "wrong count %d\n", ulCount
);
863 ok(!strcmp(lpResProp
->Value
.MVszA
.lppszA
[0], szTestA
),
864 "wrong string '%s'\n", lpResProp
->Value
.MVszA
.lppszA
[0]);
867 /* Native crashes with lpNew or lpOld set to NULL so skip testing this */
870 static void test_LpValFindProp(void)
872 SPropValue pvProp
, *pRet
;
875 pLpValFindProp
= (void*)GetProcAddress(hMapi32
, "LpValFindProp@12");
880 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
882 pvProp
.ulPropTag
= PROP_TAG(ptTypes
[i
], 1u);
884 pRet
= pLpValFindProp(PROP_TAG(ptTypes
[i
], 1u), 1u, &pvProp
);
885 ok(pRet
== &pvProp
, "LpValFindProp[%d]: Didn't find existing propery id/type\n",
888 pRet
= pLpValFindProp(PROP_TAG(ptTypes
[i
], 0u), 1u, &pvProp
);
889 ok(pRet
== NULL
, "LpValFindProp[%d]: Found nonexistent propery id\n",
892 pRet
= pLpValFindProp(PROP_TAG(PT_NULL
, 0u), 1u, &pvProp
);
893 ok(pRet
== NULL
, "LpValFindProp[%d]: Found nonexistent propery id/type\n",
896 pRet
= pLpValFindProp(PROP_TAG(PT_NULL
, 1u), 1u, &pvProp
);
897 ok(pRet
== &pvProp
, "LpValFindProp[%d]: Didn't find existing propery id\n",
902 static void test_FBadRglpszA(void)
905 static CHAR szString
[] = "A String";
908 pFBadRglpszA
= (void*)GetProcAddress(hMapi32
, "FBadRglpszA@8");
912 bRet
= pFBadRglpszA(NULL
, 10);
913 ok(bRet
== TRUE
, "FBadRglpszA(Null): expected TRUE, got FALSE\n");
915 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = lpStrs
[3] = NULL
;
916 bRet
= pFBadRglpszA(lpStrs
, 4);
917 ok(bRet
== TRUE
, "FBadRglpszA(Nulls): expected TRUE, got FALSE\n");
919 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = szString
;
920 bRet
= pFBadRglpszA(lpStrs
, 3);
921 ok(bRet
== FALSE
, "FBadRglpszA(valid): expected FALSE, got TRUE\n");
923 bRet
= pFBadRglpszA(lpStrs
, 4);
924 ok(bRet
== TRUE
, "FBadRglpszA(1 invalid): expected TRUE, got FALSE\n");
927 static void test_FBadRglpszW(void)
930 static WCHAR szString
[] = { 'A',' ','S','t','r','i','n','g','\0' };
933 pFBadRglpszW
= (void*)GetProcAddress(hMapi32
, "FBadRglpszW@8");
937 bRet
= pFBadRglpszW(NULL
, 10);
938 ok(bRet
== TRUE
, "FBadRglpszW(Null): expected TRUE, got FALSE\n");
940 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = lpStrs
[3] = NULL
;
941 bRet
= pFBadRglpszW(lpStrs
, 4);
942 ok(bRet
== TRUE
, "FBadRglpszW(Nulls): expected TRUE, got FALSE\n");
944 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = szString
;
945 bRet
= pFBadRglpszW(lpStrs
, 3);
946 ok(bRet
== FALSE
, "FBadRglpszW(valid): expected FALSE, got TRUE\n");
948 bRet
= pFBadRglpszW(lpStrs
, 4);
949 ok(bRet
== TRUE
, "FBadRglpszW(1 invalid): expected TRUE, got FALSE\n");
952 static void test_FBadRowSet(void)
956 pFBadRowSet
= (void*)GetProcAddress(hMapi32
, "FBadRowSet@4");
960 ulRet
= pFBadRowSet(NULL
);
961 ok(ulRet
!= 0, "FBadRow(null): Expected non-zero, got 0\n");
966 static void test_FBadPropTag(void)
970 pFBadPropTag
= (void*)GetProcAddress(hMapi32
, "FBadPropTag@4");
974 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
978 switch (pt
& (~MV_FLAG
& PROP_TYPE_MASK
))
981 case PT_NULL
: case PT_I2
: case PT_I4
: case PT_R4
:
982 case PT_R8
: case PT_CURRENCY
: case PT_APPTIME
:
983 case PT_ERROR
: case PT_BOOLEAN
: case PT_OBJECT
:
984 case PT_I8
: case PT_STRING8
: case PT_UNICODE
:
985 case PT_SYSTIME
: case PT_CLSID
: case PT_BINARY
:
989 res
= pFBadPropTag(pt
);
991 ok(res
!= 0, "pt= %d: Expected non-zero, got 0\n", pt
);
993 ok(res
== 0, "pt= %d: Expected zero, got %d\n", pt
, res
);
997 static void test_FBadRow(void)
1001 pFBadRow
= (void*)GetProcAddress(hMapi32
, "FBadRow@4");
1005 ulRet
= pFBadRow(NULL
);
1006 ok(ulRet
!= 0, "FBadRow(null): Expected non-zero, got 0\n");
1011 static void test_FBadProp(void)
1013 static WCHAR szEmpty
[] = { '\0' };
1018 pFBadProp
= (void*)GetProcAddress(hMapi32
, "FBadProp@4");
1022 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1026 memset(&pv
, 0, sizeof(pv
));
1029 /* Note that MV values are valid below because their array count is 0,
1030 * so no pointers are validated.
1032 switch (PROP_TYPE(pt
))
1034 case (MV_FLAG
|PT_UNSPECIFIED
):
1035 case PT_UNSPECIFIED
:
1036 case (MV_FLAG
|PT_NULL
):
1048 case PT_MV_CURRENCY
:
1052 case (MV_FLAG
|PT_ERROR
):
1054 case (MV_FLAG
|PT_BOOLEAN
):
1056 case (MV_FLAG
|PT_OBJECT
):
1069 pv
.Value
.lpszW
= szEmpty
;
1073 pv
.Value
.lpguid
= &iid
;
1078 res
= pFBadProp(&pv
);
1080 ok(res
!= 0, "pt= %d: Expected non-zero, got 0\n", pt
);
1082 ok(res
== 0, "pt= %d: Expected zero, got %d\n", pt
, res
);
1086 static void test_FBadColumnSet(void)
1091 pFBadColumnSet
= (void*)GetProcAddress(hMapi32
, "FBadColumnSet@4");
1092 if (!pFBadColumnSet
)
1095 res
= pFBadColumnSet(NULL
);
1096 ok(res
!= 0, "(null): Expected non-zero, got 0\n");
1100 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1104 pta
.aulPropTag
[0] = pt
;
1106 switch (pt
& (~MV_FLAG
& PROP_TYPE_MASK
))
1108 case PT_UNSPECIFIED
:
1126 if (pt
== (MV_FLAG
|PT_ERROR
))
1129 res
= pFBadColumnSet(&pta
);
1131 ok(res
!= 0, "pt= %d: Expected non-zero, got 0\n", pt
);
1133 ok(res
== 0, "pt= %d: Expected zero, got %d\n", pt
, res
);
1138 static void test_IProp(void)
1141 LPMAPIERROR lpError
;
1142 LPSPropProblemArray lpProbs
;
1143 LPSPropValue lpProps
;
1144 LPSPropTagArray lpTags
;
1146 SizedSPropTagArray(2,tags
);
1147 ULONG access
[2], count
;
1150 pCreateIProp
= (void*)GetProcAddress(hMapi32
, "CreateIProp@24");
1155 memset(&tags
, 0 , sizeof(tags
));
1157 /* Create the object */
1159 sc
= pCreateIProp(&IID_IMAPIPropData
, (ALLOCATEBUFFER
*)pMAPIAllocateBuffer
, (ALLOCATEMORE
*)pMAPIAllocateMore
,
1160 (FREEBUFFER
*)pMAPIFreeBuffer
, NULL
, &lpIProp
);
1161 ok(sc
== S_OK
&& lpIProp
,
1162 "CreateIProp: expected S_OK, non-null, got 0x%08X,%p\n", sc
, lpIProp
);
1164 if (sc
!= S_OK
|| !lpIProp
)
1167 /* GetLastError - No errors set */
1169 IPropData_GetLastError(lpIProp
, E_INVALIDARG
, 0, &lpError
);
1170 ok(sc
== S_OK
&& !lpError
,
1171 "GetLastError: Expected S_OK, null, got 0x%08X,%p\n", sc
, lpError
);
1173 /* Get prop tags - succeeds returning 0 items */
1175 sc
= IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1176 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 0,
1177 "GetPropList(empty): Expected S_OK, non-null, 0, got 0x%08X,%p,%d\n",
1178 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1180 pMAPIFreeBuffer(lpTags
);
1182 /* Get props - succeeds returning 0 items */
1186 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1187 sc
= IPropData_GetProps(lpIProp
, (LPSPropTagArray
)&tags
, 0, &count
, &lpProps
);
1188 ok(sc
== MAPI_W_ERRORS_RETURNED
&& lpProps
&& count
== 1,
1189 "GetProps(empty): Expected ERRORS_RETURNED, non-null, 1, got 0x%08X,%p,%d\n",
1190 sc
, lpProps
, count
);
1191 if (lpProps
&& count
> 0)
1193 ok(lpProps
[0].ulPropTag
== CHANGE_PROP_TYPE(PR_IMPORTANCE
,PT_ERROR
),
1194 "GetProps(empty): Expected %x, got %x\n",
1195 CHANGE_PROP_TYPE(PR_IMPORTANCE
,PT_ERROR
), lpProps
[0].ulPropTag
);
1197 pMAPIFreeBuffer(lpProps
);
1200 /* Add (NULL) - Can't add NULLs */
1202 pvs
[0].ulPropTag
= PROP_TAG(PT_NULL
,0x01);
1203 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1204 ok(sc
== MAPI_E_INVALID_PARAMETER
&& !lpProbs
,
1205 "SetProps(): Expected INVALID_PARAMETER, null, got 0x%08X,%p\n",
1208 /* Add (OBJECT) - Can't add OBJECTs */
1210 pvs
[0].ulPropTag
= PROP_TAG(PT_OBJECT
,0x01);
1211 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1212 ok(sc
== MAPI_E_INVALID_PARAMETER
&& !lpProbs
,
1213 "SetProps(OBJECT): Expected INVALID_PARAMETER, null, got 0x%08X,%p\n",
1216 /* Add - Adds value */
1218 pvs
[0].ulPropTag
= PR_IMPORTANCE
;
1219 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1220 ok(sc
== S_OK
&& !lpProbs
,
1221 "SetProps(ERROR): Expected S_OK, null, got 0x%08X,%p\n", sc
, lpProbs
);
1223 /* Get prop list - returns 1 item */
1225 IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1226 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 1,
1227 "GetPropList: Expected S_OK, non-null, 1, got 0x%08X,%p,%d\n",
1228 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1229 if (lpTags
&& lpTags
->cValues
> 0)
1231 ok(lpTags
->aulPropTag
[0] == PR_IMPORTANCE
,
1232 "GetPropList: Expected %x, got %x\n",
1233 PR_IMPORTANCE
, lpTags
->aulPropTag
[0]);
1234 pMAPIFreeBuffer(lpTags
);
1237 /* Set access to read and write */
1238 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READWRITE
);
1239 ok(sc
== S_OK
, "SetObjAcess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1242 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1244 /* Set item access (bad access) - Fails */
1246 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1247 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1248 "SetPropAcess(0): Expected INVALID_PARAMETER got 0x%08X\n",sc
);
1249 access
[0] = IPROP_READWRITE
;
1250 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1251 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1252 "SetPropAcess(RW): Expected INVALID_PARAMETER got 0x%08X\n",sc
);
1253 access
[0] = IPROP_CLEAN
;
1254 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1255 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1256 "SetPropAcess(C): Expected INVALID_PARAMETER got 0x%08X\n",sc
);
1258 /* Set item access to read/write/clean */
1260 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1261 access
[0] = IPROP_READWRITE
|IPROP_CLEAN
;
1262 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1263 ok(sc
== S_OK
, "SetPropAcess(RW/C): Expected S_OK got 0x%08X\n",sc
);
1265 /* Set object access to read only */
1266 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READONLY
);
1267 ok(sc
== S_OK
, "SetObjAcess(READ): Expected S_OK got 0x%08X\n", sc
);
1269 /* Set item access to read/write/dirty - doesn't care about RO object */
1270 access
[0] = IPROP_READONLY
|IPROP_DIRTY
;
1271 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1272 ok(sc
== S_OK
, "SetPropAcess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1274 /* Delete any item when set to read only - Error */
1276 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1277 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1278 ok(sc
== E_ACCESSDENIED
&& !lpProbs
,
1279 "DeleteProps(nonexistent): Expected E_ACCESSDENIED null got 0x%08X %p\n",
1282 /* Set access to read and write */
1283 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READWRITE
);
1284 ok(sc
== S_OK
, "SetObjAcess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1286 /* Delete nonexistent item - No error */
1288 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1289 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1290 ok(sc
== S_OK
&& !lpProbs
,
1291 "DeleteProps(nonexistent): Expected S_OK null got 0x%08X %p\n",
1294 /* Delete existing item (r/o) - No error, but lpProbs populated */
1296 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1297 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1298 ok(sc
== S_OK
&& lpProbs
,
1299 "DeleteProps(RO): Expected S_OK non-null got 0x%08X %p\n", sc
, lpProbs
);
1301 if (lpProbs
&& lpProbs
->cProblem
> 0)
1303 ok(lpProbs
->cProblem
== 1 &&
1304 lpProbs
->aProblem
[0].ulIndex
== 0 &&
1305 lpProbs
->aProblem
[0].ulPropTag
== PR_IMPORTANCE
&&
1306 lpProbs
->aProblem
[0].scode
== E_ACCESSDENIED
,
1307 "DeleteProps(RO): Expected (1,0,%x,%x) got (%d,%x,%x)\n",
1308 PR_IMPORTANCE
, E_ACCESSDENIED
,
1309 lpProbs
->aProblem
[0].ulIndex
, lpProbs
->aProblem
[0].ulPropTag
,
1310 lpProbs
->aProblem
[0].scode
);
1311 pMAPIFreeBuffer(lpProbs
);
1316 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1317 IPropData_HrAddObjProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1318 ok(sc
== S_OK
&& !lpProbs
,
1319 "AddObjProps(RO): Expected S_OK null got 0x%08X %p\n", sc
, lpProbs
);
1321 /* Get prop list - returns 1 item */
1323 IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1324 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 1,
1325 "GetPropList: Expected S_OK, non-null, 1, got 0x%08X,%p,%d\n",
1326 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1327 if (lpTags
&& lpTags
->cValues
> 0)
1329 ok(lpTags
->aulPropTag
[0] == PR_IMPORTANCE
,
1330 "GetPropList: Expected %x, got %x\n",
1331 PR_IMPORTANCE
, lpTags
->aulPropTag
[0]);
1332 pMAPIFreeBuffer(lpTags
);
1335 /* Set item to r/w again */
1336 access
[0] = IPROP_READWRITE
|IPROP_DIRTY
;
1337 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1338 ok(sc
== S_OK
, "SetPropAcess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1340 /* Delete existing item (r/w) - No error, no problems */
1342 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1343 ok(sc
== S_OK
&& !lpProbs
,
1344 "DeleteProps(RO): Expected S_OK null got 0x%08X %p\n", sc
, lpProbs
);
1347 IPropData_Release(lpIProp
);
1356 skip("Needed functions are not available\n");
1360 SetLastError(0xdeadbeef);
1361 ret
= pScInitMapiUtil(0);
1362 if ((ret
!= S_OK
) && (GetLastError() == ERROR_PROC_NOT_FOUND
))
1364 skip("ScInitMapiUtil is not implemented\n");
1365 FreeLibrary(hMapi32
);
1369 test_PropCopyMore();
1371 test_FPropContainsProp();
1372 test_FPropCompareProp();
1373 test_LPropCompareProp();
1374 test_PpropFindProp();
1375 test_ScCountProps();
1376 test_ScCopyRelocProps();
1377 test_LpValFindProp();
1384 test_FBadColumnSet();
1387 FreeLibrary(hMapi32
);