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 static HMODULE hMapi32
= 0;
32 static SCODE (WINAPI
*pScInitMapiUtil
)(ULONG
);
33 static SCODE (WINAPI
*pPropCopyMore
)(LPSPropValue
,LPSPropValue
,ALLOCATEMORE
*,LPVOID
);
34 static ULONG (WINAPI
*pUlPropSize
)(LPSPropValue
);
35 static BOOL (WINAPI
*pFPropContainsProp
)(LPSPropValue
,LPSPropValue
,ULONG
);
36 static BOOL (WINAPI
*pFPropCompareProp
)(LPSPropValue
,ULONG
,LPSPropValue
);
37 static LONG (WINAPI
*pLPropCompareProp
)(LPSPropValue
,LPSPropValue
);
38 static LPSPropValue (WINAPI
*pPpropFindProp
)(LPSPropValue
,ULONG
,ULONG
);
39 static SCODE (WINAPI
*pScCountProps
)(INT
,LPSPropValue
,ULONG
*);
40 static SCODE (WINAPI
*pScCopyProps
)(int,LPSPropValue
,LPVOID
,ULONG
*);
41 static SCODE (WINAPI
*pScRelocProps
)(int,LPSPropValue
,LPVOID
,LPVOID
,ULONG
*);
42 static LPSPropValue (WINAPI
*pLpValFindProp
)(ULONG
,ULONG
,LPSPropValue
);
43 static BOOL (WINAPI
*pFBadRglpszA
)(LPSTR
*,ULONG
);
44 static BOOL (WINAPI
*pFBadRglpszW
)(LPWSTR
*,ULONG
);
45 static BOOL (WINAPI
*pFBadRowSet
)(LPSRowSet
);
46 static ULONG (WINAPI
*pFBadPropTag
)(ULONG
);
47 static ULONG (WINAPI
*pFBadRow
)(LPSRow
);
48 static ULONG (WINAPI
*pFBadProp
)(LPSPropValue
);
49 static ULONG (WINAPI
*pFBadColumnSet
)(LPSPropTagArray
);
50 static SCODE (WINAPI
*pCreateIProp
)(LPCIID
,ALLOCATEBUFFER
*,ALLOCATEMORE
*,
51 FREEBUFFER
*,LPVOID
,LPPROPDATA
*);
52 static SCODE (WINAPI
*pMAPIAllocateBuffer
)(ULONG
, LPVOID
);
53 static SCODE (WINAPI
*pMAPIAllocateMore
)(ULONG
, LPVOID
, LPVOID
);
54 static SCODE (WINAPI
*pMAPIFreeBuffer
)(LPVOID
);
56 static BOOL
InitFuncPtrs(void)
58 hMapi32
= LoadLibraryA("mapi32.dll");
60 pScInitMapiUtil
= (void*)GetProcAddress(hMapi32
, "ScInitMapiUtil@4");
61 pMAPIAllocateBuffer
= (void*)GetProcAddress(hMapi32
, "MAPIAllocateBuffer");
62 pMAPIAllocateMore
= (void*)GetProcAddress(hMapi32
, "MAPIAllocateMore");
63 pMAPIFreeBuffer
= (void*)GetProcAddress(hMapi32
, "MAPIFreeBuffer");
64 if(pScInitMapiUtil
&& pMAPIAllocateBuffer
&& pMAPIAllocateMore
&& pMAPIFreeBuffer
)
70 static ULONG ptTypes
[] = {
71 PT_I2
, PT_I4
, PT_R4
, PT_R8
, PT_CURRENCY
, PT_APPTIME
, PT_SYSTIME
,
72 PT_ERROR
, PT_BOOLEAN
, PT_I8
, PT_CLSID
, PT_STRING8
, PT_BINARY
,
76 static inline int strcmpW(const WCHAR
*str1
, const WCHAR
*str2
)
78 while (*str1
&& (*str1
== *str2
)) { str1
++; str2
++; }
82 static void test_PropCopyMore(void)
84 static char szHiA
[] = "Hi!";
85 static WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
86 SPropValue
*lpDest
= NULL
, *lpSrc
= NULL
;
90 pPropCopyMore
= (void*)GetProcAddress(hMapi32
, "PropCopyMore@16");
95 scode
= pMAPIAllocateBuffer(sizeof(LPSPropValue
), (LPVOID
*)lpDest
);
99 scode
= pMAPIAllocateMore(sizeof(LPSPropValue
), lpDest
, (LPVOID
*)lpSrc
);
103 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
105 lpSrc
->ulPropTag
= ptTypes
[i
];
110 lpSrc
->Value
.lpszA
= szHiA
;
113 lpSrc
->Value
.lpszW
= szHiW
;
116 lpSrc
->Value
.bin
.cb
= 4;
117 lpSrc
->Value
.bin
.lpb
= (LPBYTE
)szHiA
;
121 memset(lpDest
, 0xff, sizeof(SPropValue
));
123 scode
= pPropCopyMore(lpDest
, lpSrc
, (ALLOCATEMORE
*)pMAPIAllocateMore
, lpDest
);
124 ok(!scode
&& lpDest
->ulPropTag
== lpSrc
->ulPropTag
,
125 "PropCopyMore: Expected 0x0,%d, got 0x%08x,%d\n",
126 lpSrc
->ulPropTag
, scode
, lpDest
->ulPropTag
);
127 if (SUCCEEDED(scode
))
132 ok(lstrcmpA(lpDest
->Value
.lpszA
, lpSrc
->Value
.lpszA
) == 0,
133 "PropCopyMore: Ascii string differs\n");
136 ok(strcmpW(lpDest
->Value
.lpszW
, lpSrc
->Value
.lpszW
) == 0,
137 "PropCopyMore: Unicode string differs\n");
140 ok(lpDest
->Value
.bin
.cb
== 4 &&
141 !memcmp(lpSrc
->Value
.bin
.lpb
, lpDest
->Value
.bin
.lpb
, 4),
142 "PropCopyMore: Binary array differs\n");
148 /* Since all allocations are linked, freeing lpDest frees everything */
149 pMAPIFreeBuffer(lpDest
);
152 static void test_UlPropSize(void)
154 static char szHiA
[] = "Hi!";
155 static WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
161 pUlPropSize
= (void*)GetProcAddress(hMapi32
, "UlPropSize@4");
166 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
170 memset(&pv
, 0 ,sizeof(pv
));
173 exp
= 1u; /* Default to one item for non-MV properties */
175 switch (PROP_TYPE(pt
))
177 case PT_MV_I2
: pv
.Value
.MVi
.cValues
= exp
= 2;
178 case PT_I2
: exp
*= sizeof(USHORT
); break;
179 case PT_MV_I4
: pv
.Value
.MVl
.cValues
= exp
= 2;
180 case PT_I4
: exp
*= sizeof(LONG
); break;
181 case PT_MV_R4
: pv
.Value
.MVflt
.cValues
= exp
= 2;
182 case PT_R4
: exp
*= sizeof(float); break;
183 case PT_MV_DOUBLE
: pv
.Value
.MVdbl
.cValues
= exp
= 2;
184 case PT_R8
: exp
*= sizeof(double); break;
185 case PT_MV_CURRENCY
: pv
.Value
.MVcur
.cValues
= exp
= 2;
186 case PT_CURRENCY
: exp
*= sizeof(CY
); break;
187 case PT_MV_APPTIME
: pv
.Value
.MVat
.cValues
= exp
= 2;
188 case PT_APPTIME
: exp
*= sizeof(double); break;
189 case PT_MV_SYSTIME
: pv
.Value
.MVft
.cValues
= exp
= 2;
190 case PT_SYSTIME
: exp
*= sizeof(FILETIME
); break;
191 case PT_ERROR
: exp
= sizeof(SCODE
); break;
192 case PT_BOOLEAN
: exp
= sizeof(USHORT
); break;
193 case PT_OBJECT
: exp
= 0; break;
194 case PT_MV_I8
: pv
.Value
.MVli
.cValues
= exp
= 2;
195 case PT_I8
: exp
*= sizeof(LONG64
); break;
197 /* My version of native mapi returns 0 for PT_MV_CLSID even if a valid
198 * array is given. This _has_ to be a bug, so Wine does
199 * the right thing(tm) and we don't test it here.
201 case PT_MV_CLSID
: pv
.Value
.MVguid
.cValues
= exp
= 2;
203 case PT_CLSID
: exp
*= sizeof(GUID
); break;
205 pv
.Value
.lpszA
= szHiA
;
209 pv
.Value
.lpszW
= szHiW
;
210 exp
= 4 * sizeof(WCHAR
);
213 pv
.Value
.bin
.cb
= exp
= 19;
216 pv
.Value
.MVszA
.cValues
= 2;
217 pv
.Value
.MVszA
.lppszA
= buffa
;
223 pv
.Value
.MVszW
.cValues
= 2;
224 pv
.Value
.MVszW
.lppszW
= buffw
;
227 exp
= 8 * sizeof(WCHAR
);
230 pv
.Value
.MVbin
.cValues
= 2;
231 pv
.Value
.MVbin
.lpbin
= buffbin
;
240 res
= pUlPropSize(&pv
);
241 ok(res
== exp
, "pt= %d: Expected %d, got %d\n", pt
, exp
, res
);
245 static void test_FPropContainsProp(void)
247 static char szFull
[] = "Full String";
248 static char szFullLower
[] = "full string";
249 static char szPrefix
[] = "Full";
250 static char szPrefixLower
[] = "full";
251 static char szSubstring
[] = "ll St";
252 static char szSubstringLower
[] = "ll st";
253 SPropValue pvLeft
, pvRight
;
257 pFPropContainsProp
= (void*)GetProcAddress(hMapi32
, "FPropContainsProp@12");
259 if (!pFPropContainsProp
)
262 /* Ensure that only PT_STRING8 and PT_BINARY are handled */
263 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
265 if (pt
== PT_STRING8
|| pt
== PT_BINARY
)
266 continue; /* test these later */
268 memset(&pvLeft
, 0 ,sizeof(pvLeft
));
269 memset(&pvRight
, 0 ,sizeof(pvRight
));
270 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= pt
;
272 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
273 ok(bRet
== FALSE
, "pt= %d: Expected FALSE, got %d\n", pt
, bRet
);
276 /* test the various flag combinations */
277 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= PT_STRING8
;
278 pvLeft
.Value
.lpszA
= szFull
;
279 pvRight
.Value
.lpszA
= szFull
;
281 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
282 ok(bRet
== TRUE
, "(full,full)[] match failed\n");
283 pvRight
.Value
.lpszA
= szPrefix
;
284 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
285 ok(bRet
== FALSE
, "(full,prefix)[] match failed\n");
286 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
287 ok(bRet
== TRUE
, "(full,prefix)[PREFIX] match failed\n");
288 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
289 ok(bRet
== TRUE
, "(full,prefix)[SUBSTRING] match failed\n");
290 pvRight
.Value
.lpszA
= szPrefixLower
;
291 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
292 ok(bRet
== FALSE
, "(full,prefixlow)[PREFIX] match failed\n");
293 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
294 ok(bRet
== FALSE
, "(full,prefixlow)[SUBSTRING] match failed\n");
295 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
296 ok(bRet
== TRUE
, "(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
297 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
298 ok(bRet
== TRUE
, "(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
299 pvRight
.Value
.lpszA
= szSubstring
;
300 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
301 ok(bRet
== FALSE
, "(full,substr)[] match failed\n");
302 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
303 ok(bRet
== FALSE
, "(full,substr)[PREFIX] match failed\n");
304 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
305 ok(bRet
== TRUE
, "(full,substr)[SUBSTRING] match failed\n");
306 pvRight
.Value
.lpszA
= szSubstringLower
;
307 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
308 ok(bRet
== FALSE
, "(full,substrlow)[PREFIX] match failed\n");
309 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
310 ok(bRet
== FALSE
, "(full,substrlow)[SUBSTRING] match failed\n");
311 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
312 ok(bRet
== FALSE
, "(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
313 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
314 ok(bRet
== TRUE
, "(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
315 pvRight
.Value
.lpszA
= szFullLower
;
316 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
|FL_IGNORECASE
);
317 ok(bRet
== TRUE
, "(full,fulllow)[IGNORECASE] match failed\n");
319 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= PT_BINARY
;
320 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)szFull
;
321 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szFull
;
322 pvLeft
.Value
.bin
.cb
= pvRight
.Value
.bin
.cb
= strlen(szFull
);
324 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
325 ok(bRet
== TRUE
, "bin(full,full)[] match failed\n");
326 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szPrefix
;
327 pvRight
.Value
.bin
.cb
= strlen(szPrefix
);
328 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
329 ok(bRet
== FALSE
, "bin(full,prefix)[] match failed\n");
330 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
331 ok(bRet
== TRUE
, "bin(full,prefix)[PREFIX] match failed\n");
332 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
333 ok(bRet
== TRUE
, "bin(full,prefix)[SUBSTRING] match failed\n");
334 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szPrefixLower
;
335 pvRight
.Value
.bin
.cb
= strlen(szPrefixLower
);
336 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
337 ok(bRet
== FALSE
, "bin(full,prefixlow)[PREFIX] match failed\n");
338 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
339 ok(bRet
== FALSE
, "bin(full,prefixlow)[SUBSTRING] match failed\n");
340 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
341 ok(bRet
== FALSE
, "bin(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
342 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
343 ok(bRet
== FALSE
, "bin(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
344 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szSubstring
;
345 pvRight
.Value
.bin
.cb
= strlen(szSubstring
);
346 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
347 ok(bRet
== FALSE
, "bin(full,substr)[] match failed\n");
348 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
349 ok(bRet
== FALSE
, "bin(full,substr)[PREFIX] match failed\n");
350 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
351 ok(bRet
== TRUE
, "bin(full,substr)[SUBSTRING] match failed\n");
352 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szSubstringLower
;
353 pvRight
.Value
.bin
.cb
= strlen(szSubstringLower
);
354 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
355 ok(bRet
== FALSE
, "bin(full,substrlow)[PREFIX] match failed\n");
356 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
357 ok(bRet
== FALSE
, "bin(full,substrlow)[SUBSTRING] match failed\n");
358 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
359 ok(bRet
== FALSE
, "bin(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
360 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
361 ok(bRet
== FALSE
, "bin(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
362 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szFullLower
;
363 pvRight
.Value
.bin
.cb
= strlen(szFullLower
);
364 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
|FL_IGNORECASE
);
365 ok(bRet
== FALSE
, "bin(full,fulllow)[IGNORECASE] match failed\n");
368 typedef struct tagFPropCompareProp_Result
374 } FPropCompareProp_Result
;
376 static const FPropCompareProp_Result FPCProp_Results
[] =
378 { 1, 2, RELOP_LT
, TRUE
},
379 { 1, 1, RELOP_LT
, FALSE
},
380 { 2, 1, RELOP_LT
, FALSE
},
381 { 1, 2, RELOP_LE
, TRUE
},
382 { 1, 1, RELOP_LE
, TRUE
},
383 { 2, 1, RELOP_LE
, FALSE
},
384 { 1, 2, RELOP_GT
, FALSE
},
385 { 1, 1, RELOP_GT
, FALSE
},
386 { 2, 1, RELOP_GT
, TRUE
},
387 { 1, 2, RELOP_GE
, FALSE
},
388 { 1, 1, RELOP_GE
, TRUE
},
389 { 2, 1, RELOP_GE
, TRUE
},
390 { 1, 2, RELOP_EQ
, FALSE
},
391 { 1, 1, RELOP_EQ
, TRUE
},
392 { 2, 1, RELOP_EQ
, FALSE
}
395 static const char *relops
[] = { "RELOP_LT", "RELOP_LE", "RELOP_GT", "RELOP_GE", "RELOP_EQ" };
397 static void test_FPropCompareProp(void)
399 SPropValue pvLeft
, pvRight
;
401 char lbuffa
[2], rbuffa
[2];
402 WCHAR lbuffw
[2], rbuffw
[2];
406 pFPropCompareProp
= (void*)GetProcAddress(hMapi32
, "FPropCompareProp@12");
408 if (!pFPropCompareProp
)
416 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
418 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= ptTypes
[i
];
420 for (j
= 0; j
< sizeof(FPCProp_Results
)/sizeof(FPCProp_Results
[0]); j
++)
422 SHORT lVal
= FPCProp_Results
[j
].lVal
;
423 SHORT rVal
= FPCProp_Results
[j
].rVal
;
425 bExp
= FPCProp_Results
[j
].bRet
;
430 /* Boolean values have no concept of less or greater than, only equality */
431 if ((lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_LT
) ||
432 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_LE
)||
433 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_GT
)||
434 (lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_GE
)||
435 (lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_EQ
)||
436 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_EQ
))
438 /* Fall through ... */
440 pvLeft
.Value
.i
= lVal
;
441 pvRight
.Value
.i
= rVal
;
445 pvLeft
.Value
.l
= lVal
;
446 pvRight
.Value
.l
= rVal
;
449 pvLeft
.Value
.flt
= lVal
;
450 pvRight
.Value
.flt
= rVal
;
454 pvLeft
.Value
.dbl
= lVal
;
455 pvRight
.Value
.dbl
= rVal
;
458 pvLeft
.Value
.cur
.int64
= lVal
;
459 pvRight
.Value
.cur
.int64
= rVal
;
462 pvLeft
.Value
.ft
.dwLowDateTime
= lVal
;
463 pvLeft
.Value
.ft
.dwHighDateTime
= 0;
464 pvRight
.Value
.ft
.dwLowDateTime
= rVal
;
465 pvRight
.Value
.ft
.dwHighDateTime
= 0;
468 pvLeft
.Value
.li
.u
.LowPart
= lVal
;
469 pvLeft
.Value
.li
.u
.HighPart
= 0;
470 pvRight
.Value
.li
.u
.LowPart
= rVal
;
471 pvRight
.Value
.li
.u
.HighPart
= 0;
474 memset(&lguid
, 0, sizeof(GUID
));
475 memset(&rguid
, 0, sizeof(GUID
));
476 lguid
.Data4
[7] = lVal
;
477 rguid
.Data4
[7] = rVal
;
478 pvLeft
.Value
.lpguid
= &lguid
;
479 pvRight
.Value
.lpguid
= &rguid
;
482 pvLeft
.Value
.lpszA
= lbuffa
;
483 pvRight
.Value
.lpszA
= rbuffa
;
484 lbuffa
[0] = '0' + lVal
;
485 rbuffa
[0] = '0' + rVal
;
488 pvLeft
.Value
.lpszW
= lbuffw
;
489 pvRight
.Value
.lpszW
= rbuffw
;
490 lbuffw
[0] = '0' + lVal
;
491 rbuffw
[0] = '0' + rVal
;
494 pvLeft
.Value
.bin
.cb
= 1;
495 pvRight
.Value
.bin
.cb
= 1;
496 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)lbuffa
;
497 pvRight
.Value
.bin
.lpb
= (LPBYTE
)rbuffa
;
503 bRet
= pFPropCompareProp(&pvLeft
, FPCProp_Results
[j
].relOp
, &pvRight
);
504 ok(bRet
== bExp
, "pt %d (%d,%d,%s): expected %d, got %d\n", ptTypes
[i
],
505 FPCProp_Results
[j
].lVal
, FPCProp_Results
[j
].rVal
,
506 relops
[FPCProp_Results
[j
].relOp
], bExp
, bRet
);
511 typedef struct tagLPropCompareProp_Result
516 } LPropCompareProp_Result
;
518 static const LPropCompareProp_Result LPCProp_Results
[] =
525 static void test_LPropCompareProp(void)
527 SPropValue pvLeft
, pvRight
;
529 char lbuffa
[2], rbuffa
[2];
530 WCHAR lbuffw
[2], rbuffw
[2];
534 pLPropCompareProp
= (void*)GetProcAddress(hMapi32
, "LPropCompareProp@8");
536 if (!pLPropCompareProp
)
544 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
546 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= ptTypes
[i
];
548 for (j
= 0; j
< sizeof(LPCProp_Results
)/sizeof(LPCProp_Results
[0]); j
++)
550 SHORT lVal
= LPCProp_Results
[j
].lVal
;
551 SHORT rVal
= LPCProp_Results
[j
].rVal
;
553 iExp
= LPCProp_Results
[j
].iRet
;
558 /* Boolean values have no concept of less or greater than, only equality */
561 /* Fall through ... */
563 pvLeft
.Value
.i
= lVal
;
564 pvRight
.Value
.i
= rVal
;
568 pvLeft
.Value
.l
= lVal
;
569 pvRight
.Value
.l
= rVal
;
572 pvLeft
.Value
.flt
= lVal
;
573 pvRight
.Value
.flt
= rVal
;
577 pvLeft
.Value
.dbl
= lVal
;
578 pvRight
.Value
.dbl
= rVal
;
581 pvLeft
.Value
.cur
.int64
= lVal
;
582 pvRight
.Value
.cur
.int64
= rVal
;
585 pvLeft
.Value
.ft
.dwLowDateTime
= lVal
;
586 pvLeft
.Value
.ft
.dwHighDateTime
= 0;
587 pvRight
.Value
.ft
.dwLowDateTime
= rVal
;
588 pvRight
.Value
.ft
.dwHighDateTime
= 0;
591 pvLeft
.Value
.li
.u
.LowPart
= lVal
;
592 pvLeft
.Value
.li
.u
.HighPart
= 0;
593 pvRight
.Value
.li
.u
.LowPart
= rVal
;
594 pvRight
.Value
.li
.u
.HighPart
= 0;
597 memset(&lguid
, 0, sizeof(GUID
));
598 memset(&rguid
, 0, sizeof(GUID
));
599 lguid
.Data4
[7] = lVal
;
600 rguid
.Data4
[7] = rVal
;
601 pvLeft
.Value
.lpguid
= &lguid
;
602 pvRight
.Value
.lpguid
= &rguid
;
605 pvLeft
.Value
.lpszA
= lbuffa
;
606 pvRight
.Value
.lpszA
= rbuffa
;
607 lbuffa
[0] = '0' + lVal
;
608 rbuffa
[0] = '0' + rVal
;
611 pvLeft
.Value
.lpszW
= lbuffw
;
612 pvRight
.Value
.lpszW
= rbuffw
;
613 lbuffw
[0] = '0' + lVal
;
614 rbuffw
[0] = '0' + rVal
;
617 pvLeft
.Value
.bin
.cb
= 1;
618 pvRight
.Value
.bin
.cb
= 1;
619 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)lbuffa
;
620 pvRight
.Value
.bin
.lpb
= (LPBYTE
)rbuffa
;
626 iRet
= pLPropCompareProp(&pvLeft
, &pvRight
);
627 ok(iRet
== iExp
, "pt %d (%d,%d): expected %d, got %d\n", ptTypes
[i
],
628 LPCProp_Results
[j
].lVal
, LPCProp_Results
[j
].rVal
, iExp
, iRet
);
633 static void test_PpropFindProp(void)
635 SPropValue pvProp
, *pRet
;
638 pPpropFindProp
= (void*)GetProcAddress(hMapi32
, "PpropFindProp@12");
643 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
645 pvProp
.ulPropTag
= ptTypes
[i
];
647 pRet
= pPpropFindProp(&pvProp
, 1u, ptTypes
[i
]);
648 ok(pRet
== &pvProp
, "PpropFindProp[%d]: Didn't find existing propery\n",
651 pRet
= pPpropFindProp(&pvProp
, 1u, i
? ptTypes
[i
-1] : ptTypes
[i
+1]);
652 ok(pRet
== NULL
, "PpropFindProp[%d]: Found nonexistent propery\n",
656 pvProp
.ulPropTag
= PROP_TAG(PT_I2
, 1u);
657 pRet
= pPpropFindProp(&pvProp
, 1u, PROP_TAG(PT_UNSPECIFIED
, 0u));
658 ok(pRet
== NULL
, "PpropFindProp[UNSPECIFIED]: Matched on different id\n");
659 pRet
= pPpropFindProp(&pvProp
, 1u, PROP_TAG(PT_UNSPECIFIED
, 1u));
660 ok(pRet
== &pvProp
, "PpropFindProp[UNSPECIFIED]: Didn't match id\n");
663 static void test_ScCountProps(void)
665 static char szHiA
[] = "Hi!";
666 static WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
667 static const ULONG ULHILEN
= 4; /* chars in szHiA/W incl. NUL */
671 GUID iids
[4], *iid
= iids
;
673 ULONG pt
, exp
, ulRet
;
676 pScCountProps
= (void*)GetProcAddress(hMapi32
, "ScCountProps@12");
681 for (pt
= 0; pt
< PROP_ID_INVALID
&& success
; pt
++)
685 memset(&pv
, 0 ,sizeof(pv
));
686 pv
.ulPropTag
= PROP_TAG(pt
, 1u);
688 switch (PROP_TYPE(pt
))
704 pv
.Value
.lpguid
= iid
;
705 exp
= sizeof(GUID
) + sizeof(pv
);
708 pv
.Value
.lpszA
= szHiA
;
709 exp
= 4 + sizeof(pv
);
712 pv
.Value
.lpszW
= szHiW
;
713 exp
= 4 * sizeof(WCHAR
) + sizeof(pv
);
717 pv
.Value
.bin
.lpb
= (LPBYTE
)iid
;
718 exp
= 2 + sizeof(pv
);
721 pv
.Value
.MVi
.cValues
= 3;
722 pv
.Value
.MVi
.lpi
= (SHORT
*)iid
;
723 exp
= 3 * sizeof(SHORT
) + sizeof(pv
);
726 pv
.Value
.MVl
.cValues
= 3;
727 pv
.Value
.MVl
.lpl
= (LONG
*)iid
;
728 exp
= 3 * sizeof(LONG
) + sizeof(pv
);
731 pv
.Value
.MVli
.cValues
= 3;
732 pv
.Value
.MVli
.lpli
= (LARGE_INTEGER
*)iid
;
733 exp
= 3 * sizeof(LARGE_INTEGER
) + sizeof(pv
);
736 pv
.Value
.MVflt
.cValues
= 3;
737 pv
.Value
.MVflt
.lpflt
= (float*)iid
;
738 exp
= 3 * sizeof(float) + sizeof(pv
);
742 pv
.Value
.MVdbl
.cValues
= 3;
743 pv
.Value
.MVdbl
.lpdbl
= (double*)iid
;
744 exp
= 3 * sizeof(double) + sizeof(pv
);
747 pv
.Value
.MVcur
.cValues
= 3;
748 pv
.Value
.MVcur
.lpcur
= (CY
*)iid
;
749 exp
= 3 * sizeof(CY
) + sizeof(pv
);
752 pv
.Value
.MVft
.cValues
= 3;
753 pv
.Value
.MVft
.lpft
= (FILETIME
*)iid
;
754 exp
= 3 * sizeof(CY
) + sizeof(pv
);
757 pv
.Value
.MVszA
.cValues
= 3;
758 pv
.Value
.MVszA
.lppszA
= buffa
;
762 exp
= ULHILEN
* 3 + 3 * sizeof(char*) + sizeof(pv
);
765 pv
.Value
.MVszW
.cValues
= 3;
766 pv
.Value
.MVszW
.lppszW
= buffw
;
770 exp
= ULHILEN
* 3 * sizeof(WCHAR
) + 3 * sizeof(WCHAR
*) + sizeof(pv
);
773 pv
.Value
.MVbin
.cValues
= 3;
774 pv
.Value
.MVbin
.lpbin
= buffbin
;
776 buffbin
[0].lpb
= (LPBYTE
)&iid
;
778 buffbin
[1].lpb
= (LPBYTE
)&iid
;
780 buffbin
[2].lpb
= (LPBYTE
)&iid
;
781 exp
= 20 + sizeof(pv
) + sizeof(SBinary
) * 3;
788 res
= pScCountProps(1, &pv
, &ulRet
);
790 success
= res
== MAPI_E_INVALID_PARAMETER
&& ulRet
== 0xffffffff;
791 ok(success
, "pt= %d: Expected failure, got %d, ret=0x%08X\n",
795 success
= res
== S_OK
&& ulRet
== exp
;
796 ok(success
, "pt= %d: Expected %d, got %d, ret=0x%08X\n",
797 pt
, exp
, ulRet
, res
);
803 static void test_ScCopyRelocProps(void)
805 static char szTestA
[] = "Test";
806 char buffer
[512], buffer2
[512], *lppszA
[1];
807 SPropValue pvProp
, *lpResProp
= (LPSPropValue
)buffer
;
811 pScCopyProps
= (void*)GetProcAddress(hMapi32
, "ScCopyProps@16");
812 pScRelocProps
= (void*)GetProcAddress(hMapi32
, "ScRelocProps@20");
814 if (!pScCopyProps
|| !pScRelocProps
)
817 pvProp
.ulPropTag
= PROP_TAG(PT_MV_STRING8
, 1u);
820 pvProp
.Value
.MVszA
.cValues
= 1;
821 pvProp
.Value
.MVszA
.lppszA
= lppszA
;
824 sc
= pScCopyProps(1, &pvProp
, buffer
, &ulCount
);
825 ok(sc
== S_OK
, "wrong ret %d\n", sc
);
826 ok(lpResProp
->ulPropTag
== pvProp
.ulPropTag
, "wrong tag %x\n",lpResProp
->ulPropTag
);
827 ok(lpResProp
->Value
.MVszA
.cValues
== 1, "wrong cValues %d\n", lpResProp
->Value
.MVszA
.cValues
);
828 ok(lpResProp
->Value
.MVszA
.lppszA
[0] == buffer
+ sizeof(SPropValue
) + sizeof(char*),
829 "wrong lppszA[0] %p\n",lpResProp
->Value
.MVszA
.lppszA
[0]);
830 ok(ulCount
== sizeof(SPropValue
) + sizeof(char*) + 5, "wrong count %d\n", ulCount
);
831 ok(!strcmp(lpResProp
->Value
.MVszA
.lppszA
[0], szTestA
),
832 "wrong string '%s'\n", lpResProp
->Value
.MVszA
.lppszA
[0]);
834 memcpy(buffer2
, buffer
, sizeof(buffer
));
836 /* Clear the data in the source buffer. Since pointers in the copied buffer
837 * refer to the source buffer, this proves that native always assumes that
838 * the copied buffers pointers are bad (needing to be relocated first).
840 memset(buffer
, 0, sizeof(buffer
));
843 sc
= pScRelocProps(1, (LPSPropValue
)buffer2
, buffer
, buffer2
, &ulCount
);
844 lpResProp
= (LPSPropValue
)buffer2
;
846 ok(sc
== S_OK
, "wrong ret %d\n", sc
);
847 ok(lpResProp
->ulPropTag
== pvProp
.ulPropTag
, "wrong tag %x\n",lpResProp
->ulPropTag
);
848 ok(lpResProp
->Value
.MVszA
.cValues
== 1, "wrong cValues %d\n", lpResProp
->Value
.MVszA
.cValues
);
849 ok(lpResProp
->Value
.MVszA
.lppszA
[0] == buffer2
+ sizeof(SPropValue
) + sizeof(char*),
850 "wrong lppszA[0] %p\n",lpResProp
->Value
.MVszA
.lppszA
[0]);
851 /* Native has a bug whereby it calculates the size correctly when copying
852 * but when relocating does not (presumably it uses UlPropSize() which
853 * ignores multivalue pointers). Wine returns the correct value.
855 ok(ulCount
== sizeof(SPropValue
) + sizeof(char*) + 5 || ulCount
== sizeof(SPropValue
) + 5,
856 "wrong count %d\n", ulCount
);
857 ok(!strcmp(lpResProp
->Value
.MVszA
.lppszA
[0], szTestA
),
858 "wrong string '%s'\n", lpResProp
->Value
.MVszA
.lppszA
[0]);
860 /* Native crashes with lpNew or lpOld set to NULL so skip testing this */
863 static void test_LpValFindProp(void)
865 SPropValue pvProp
, *pRet
;
868 pLpValFindProp
= (void*)GetProcAddress(hMapi32
, "LpValFindProp@12");
873 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
875 pvProp
.ulPropTag
= PROP_TAG(ptTypes
[i
], 1u);
877 pRet
= pLpValFindProp(PROP_TAG(ptTypes
[i
], 1u), 1u, &pvProp
);
878 ok(pRet
== &pvProp
, "LpValFindProp[%d]: Didn't find existing propery id/type\n",
881 pRet
= pLpValFindProp(PROP_TAG(ptTypes
[i
], 0u), 1u, &pvProp
);
882 ok(pRet
== NULL
, "LpValFindProp[%d]: Found nonexistent propery id\n",
885 pRet
= pLpValFindProp(PROP_TAG(PT_NULL
, 0u), 1u, &pvProp
);
886 ok(pRet
== NULL
, "LpValFindProp[%d]: Found nonexistent propery id/type\n",
889 pRet
= pLpValFindProp(PROP_TAG(PT_NULL
, 1u), 1u, &pvProp
);
890 ok(pRet
== &pvProp
, "LpValFindProp[%d]: Didn't find existing propery id\n",
895 static void test_FBadRglpszA(void)
898 static CHAR szString
[] = "A String";
901 pFBadRglpszA
= (void*)GetProcAddress(hMapi32
, "FBadRglpszA@8");
905 bRet
= pFBadRglpszA(NULL
, 10);
906 ok(bRet
== TRUE
, "FBadRglpszA(Null): expected TRUE, got FALSE\n");
908 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = lpStrs
[3] = NULL
;
909 bRet
= pFBadRglpszA(lpStrs
, 4);
910 ok(bRet
== TRUE
, "FBadRglpszA(Nulls): expected TRUE, got FALSE\n");
912 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = szString
;
913 bRet
= pFBadRglpszA(lpStrs
, 3);
914 ok(bRet
== FALSE
, "FBadRglpszA(valid): expected FALSE, got TRUE\n");
916 bRet
= pFBadRglpszA(lpStrs
, 4);
917 ok(bRet
== TRUE
, "FBadRglpszA(1 invalid): expected TRUE, got FALSE\n");
920 static void test_FBadRglpszW(void)
923 static WCHAR szString
[] = { 'A',' ','S','t','r','i','n','g','\0' };
926 pFBadRglpszW
= (void*)GetProcAddress(hMapi32
, "FBadRglpszW@8");
930 bRet
= pFBadRglpszW(NULL
, 10);
931 ok(bRet
== TRUE
, "FBadRglpszW(Null): expected TRUE, got FALSE\n");
933 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = lpStrs
[3] = NULL
;
934 bRet
= pFBadRglpszW(lpStrs
, 4);
935 ok(bRet
== TRUE
, "FBadRglpszW(Nulls): expected TRUE, got FALSE\n");
937 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = szString
;
938 bRet
= pFBadRglpszW(lpStrs
, 3);
939 ok(bRet
== FALSE
, "FBadRglpszW(valid): expected FALSE, got TRUE\n");
941 bRet
= pFBadRglpszW(lpStrs
, 4);
942 ok(bRet
== TRUE
, "FBadRglpszW(1 invalid): expected TRUE, got FALSE\n");
945 static void test_FBadRowSet(void)
949 pFBadRowSet
= (void*)GetProcAddress(hMapi32
, "FBadRowSet@4");
953 ulRet
= pFBadRowSet(NULL
);
954 ok(ulRet
!= 0, "FBadRow(null): Expected non-zero, got 0\n");
959 static void test_FBadPropTag(void)
963 pFBadPropTag
= (void*)GetProcAddress(hMapi32
, "FBadPropTag@4");
967 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
971 switch (pt
& (~MV_FLAG
& PROP_TYPE_MASK
))
974 case PT_NULL
: case PT_I2
: case PT_I4
: case PT_R4
:
975 case PT_R8
: case PT_CURRENCY
: case PT_APPTIME
:
976 case PT_ERROR
: case PT_BOOLEAN
: case PT_OBJECT
:
977 case PT_I8
: case PT_STRING8
: case PT_UNICODE
:
978 case PT_SYSTIME
: case PT_CLSID
: case PT_BINARY
:
982 res
= pFBadPropTag(pt
);
984 ok(res
!= 0, "pt= %d: Expected non-zero, got 0\n", pt
);
986 ok(res
== 0, "pt= %d: Expected zero, got %d\n", pt
, res
);
990 static void test_FBadRow(void)
994 pFBadRow
= (void*)GetProcAddress(hMapi32
, "FBadRow@4");
998 ulRet
= pFBadRow(NULL
);
999 ok(ulRet
!= 0, "FBadRow(null): Expected non-zero, got 0\n");
1004 static void test_FBadProp(void)
1006 static WCHAR szEmpty
[] = { '\0' };
1011 pFBadProp
= (void*)GetProcAddress(hMapi32
, "FBadProp@4");
1015 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1019 memset(&pv
, 0, sizeof(pv
));
1022 /* Note that MV values are valid below because their array count is 0,
1023 * so no pointers are validated.
1025 switch (PROP_TYPE(pt
))
1027 case (MV_FLAG
|PT_UNSPECIFIED
):
1028 case PT_UNSPECIFIED
:
1029 case (MV_FLAG
|PT_NULL
):
1041 case PT_MV_CURRENCY
:
1045 case (MV_FLAG
|PT_ERROR
):
1047 case (MV_FLAG
|PT_BOOLEAN
):
1049 case (MV_FLAG
|PT_OBJECT
):
1062 pv
.Value
.lpszW
= szEmpty
;
1066 pv
.Value
.lpguid
= &iid
;
1071 res
= pFBadProp(&pv
);
1073 ok(res
!= 0, "pt= %d: Expected non-zero, got 0\n", pt
);
1075 ok(res
== 0, "pt= %d: Expected zero, got %d\n", pt
, res
);
1079 static void test_FBadColumnSet(void)
1084 pFBadColumnSet
= (void*)GetProcAddress(hMapi32
, "FBadColumnSet@4");
1085 if (!pFBadColumnSet
)
1088 res
= pFBadColumnSet(NULL
);
1089 ok(res
!= 0, "(null): Expected non-zero, got 0\n");
1093 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1097 pta
.aulPropTag
[0] = pt
;
1099 switch (pt
& (~MV_FLAG
& PROP_TYPE_MASK
))
1101 case PT_UNSPECIFIED
:
1119 if (pt
== (MV_FLAG
|PT_ERROR
))
1122 res
= pFBadColumnSet(&pta
);
1124 ok(res
!= 0, "pt= %d: Expected non-zero, got 0\n", pt
);
1126 ok(res
== 0, "pt= %d: Expected zero, got %d\n", pt
, res
);
1131 static void test_IProp(void)
1134 LPMAPIERROR lpError
;
1135 LPSPropProblemArray lpProbs
;
1136 LPSPropValue lpProps
;
1137 LPSPropTagArray lpTags
;
1139 SizedSPropTagArray(2,tags
);
1140 ULONG access
[2], count
;
1143 pCreateIProp
= (void*)GetProcAddress(hMapi32
, "CreateIProp@24");
1148 memset(&tags
, 0 , sizeof(tags
));
1150 /* Create the object */
1152 sc
= pCreateIProp(&IID_IMAPIPropData
, (ALLOCATEBUFFER
*)pMAPIAllocateBuffer
, (ALLOCATEMORE
*)pMAPIAllocateMore
,
1153 (FREEBUFFER
*)pMAPIFreeBuffer
, NULL
, &lpIProp
);
1154 ok(sc
== S_OK
&& lpIProp
,
1155 "CreateIProp: expected S_OK, non-null, got 0x%08X,%p\n", sc
, lpIProp
);
1157 if (sc
!= S_OK
|| !lpIProp
)
1160 /* GetLastError - No errors set */
1162 IPropData_GetLastError(lpIProp
, E_INVALIDARG
, 0, &lpError
);
1163 ok(sc
== S_OK
&& !lpError
,
1164 "GetLastError: Expected S_OK, null, got 0x%08X,%p\n", sc
, lpError
);
1166 /* Get prop tags - succeeds returning 0 items */
1168 sc
= IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1169 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 0,
1170 "GetPropList(empty): Expected S_OK, non-null, 0, got 0x%08X,%p,%d\n",
1171 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1173 pMAPIFreeBuffer(lpTags
);
1175 /* Get props - succeeds returning 0 items */
1179 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1180 sc
= IPropData_GetProps(lpIProp
, (LPSPropTagArray
)&tags
, 0, &count
, &lpProps
);
1181 ok(sc
== MAPI_W_ERRORS_RETURNED
&& lpProps
&& count
== 1,
1182 "GetProps(empty): Expected ERRORS_RETURNED, non-null, 1, got 0x%08X,%p,%d\n",
1183 sc
, lpProps
, count
);
1184 if (lpProps
&& count
> 0)
1186 ok(lpProps
[0].ulPropTag
== CHANGE_PROP_TYPE(PR_IMPORTANCE
,PT_ERROR
),
1187 "GetProps(empty): Expected %x, got %x\n",
1188 CHANGE_PROP_TYPE(PR_IMPORTANCE
,PT_ERROR
), lpProps
[0].ulPropTag
);
1190 pMAPIFreeBuffer(lpProps
);
1193 /* Add (NULL) - Can't add NULLs */
1195 pvs
[0].ulPropTag
= PROP_TAG(PT_NULL
,0x01);
1196 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1197 ok(sc
== MAPI_E_INVALID_PARAMETER
&& !lpProbs
,
1198 "SetProps(): Expected INVALID_PARAMETER, null, got 0x%08X,%p\n",
1201 /* Add (OBJECT) - Can't add OBJECTs */
1203 pvs
[0].ulPropTag
= PROP_TAG(PT_OBJECT
,0x01);
1204 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1205 ok(sc
== MAPI_E_INVALID_PARAMETER
&& !lpProbs
,
1206 "SetProps(OBJECT): Expected INVALID_PARAMETER, null, got 0x%08X,%p\n",
1209 /* Add - Adds value */
1211 pvs
[0].ulPropTag
= PR_IMPORTANCE
;
1212 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1213 ok(sc
== S_OK
&& !lpProbs
,
1214 "SetProps(ERROR): Expected S_OK, null, got 0x%08X,%p\n", sc
, lpProbs
);
1216 /* Get prop list - returns 1 item */
1218 IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1219 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 1,
1220 "GetPropList: Expected S_OK, non-null, 1, got 0x%08X,%p,%d\n",
1221 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1222 if (lpTags
&& lpTags
->cValues
> 0)
1224 ok(lpTags
->aulPropTag
[0] == PR_IMPORTANCE
,
1225 "GetPropList: Expected %x, got %x\n",
1226 PR_IMPORTANCE
, lpTags
->aulPropTag
[0]);
1227 pMAPIFreeBuffer(lpTags
);
1230 /* Set access to read and write */
1231 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READWRITE
);
1232 ok(sc
== S_OK
, "SetObjAcess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1235 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1237 /* Set item access (bad access) - Fails */
1239 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1240 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1241 "SetPropAcess(0): Expected INVALID_PARAMETER got 0x%08X\n",sc
);
1242 access
[0] = IPROP_READWRITE
;
1243 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1244 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1245 "SetPropAcess(RW): Expected INVALID_PARAMETER got 0x%08X\n",sc
);
1246 access
[0] = IPROP_CLEAN
;
1247 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1248 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1249 "SetPropAcess(C): Expected INVALID_PARAMETER got 0x%08X\n",sc
);
1251 /* Set item access to read/write/clean */
1253 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1254 access
[0] = IPROP_READWRITE
|IPROP_CLEAN
;
1255 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1256 ok(sc
== S_OK
, "SetPropAcess(RW/C): Expected S_OK got 0x%08X\n",sc
);
1258 /* Set object access to read only */
1259 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READONLY
);
1260 ok(sc
== S_OK
, "SetObjAcess(READ): Expected S_OK got 0x%08X\n", sc
);
1262 /* Set item access to read/write/dirty - doesn't care about RO object */
1263 access
[0] = IPROP_READONLY
|IPROP_DIRTY
;
1264 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1265 ok(sc
== S_OK
, "SetPropAcess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1267 /* Delete any item when set to read only - Error */
1269 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1270 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1271 ok(sc
== E_ACCESSDENIED
&& !lpProbs
,
1272 "DeleteProps(nonexistent): Expected E_ACCESSDENIED null got 0x%08X %p\n",
1275 /* Set access to read and write */
1276 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READWRITE
);
1277 ok(sc
== S_OK
, "SetObjAcess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1279 /* Delete nonexistent item - No error */
1281 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1282 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1283 ok(sc
== S_OK
&& !lpProbs
,
1284 "DeleteProps(nonexistent): Expected S_OK null got 0x%08X %p\n",
1287 /* Delete existing item (r/o) - No error, but lpProbs populated */
1289 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1290 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1291 ok(sc
== S_OK
&& lpProbs
,
1292 "DeleteProps(RO): Expected S_OK non-null got 0x%08X %p\n", sc
, lpProbs
);
1294 if (lpProbs
&& lpProbs
->cProblem
> 0)
1296 ok(lpProbs
->cProblem
== 1 &&
1297 lpProbs
->aProblem
[0].ulIndex
== 0 &&
1298 lpProbs
->aProblem
[0].ulPropTag
== PR_IMPORTANCE
&&
1299 lpProbs
->aProblem
[0].scode
== E_ACCESSDENIED
,
1300 "DeleteProps(RO): Expected (1,0,%x,%x) got (%d,%x,%x)\n",
1301 PR_IMPORTANCE
, E_ACCESSDENIED
,
1302 lpProbs
->aProblem
[0].ulIndex
, lpProbs
->aProblem
[0].ulPropTag
,
1303 lpProbs
->aProblem
[0].scode
);
1304 pMAPIFreeBuffer(lpProbs
);
1309 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1310 IPropData_HrAddObjProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1311 ok(sc
== S_OK
&& !lpProbs
,
1312 "AddObjProps(RO): Expected S_OK null got 0x%08X %p\n", sc
, lpProbs
);
1314 /* Get prop list - returns 1 item */
1316 IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1317 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 1,
1318 "GetPropList: Expected S_OK, non-null, 1, got 0x%08X,%p,%d\n",
1319 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1320 if (lpTags
&& lpTags
->cValues
> 0)
1322 ok(lpTags
->aulPropTag
[0] == PR_IMPORTANCE
,
1323 "GetPropList: Expected %x, got %x\n",
1324 PR_IMPORTANCE
, lpTags
->aulPropTag
[0]);
1325 pMAPIFreeBuffer(lpTags
);
1328 /* Set item to r/w again */
1329 access
[0] = IPROP_READWRITE
|IPROP_DIRTY
;
1330 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1331 ok(sc
== S_OK
, "SetPropAcess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1333 /* Delete existing item (r/w) - No error, no problems */
1335 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1336 ok(sc
== S_OK
&& !lpProbs
,
1337 "DeleteProps(RO): Expected S_OK null got 0x%08X %p\n", sc
, lpProbs
);
1340 IPropData_Release(lpIProp
);
1349 skip("Needed functions are not available\n");
1353 SetLastError(0xdeadbeef);
1354 ret
= pScInitMapiUtil(0);
1355 if ((ret
!= S_OK
) && (GetLastError() == ERROR_PROC_NOT_FOUND
))
1357 skip("ScInitMapiUtil is not implemented\n");
1358 FreeLibrary(hMapi32
);
1362 test_PropCopyMore();
1364 test_FPropContainsProp();
1365 test_FPropCompareProp();
1366 test_LPropCompareProp();
1367 test_PpropFindProp();
1368 test_ScCountProps();
1369 test_ScCopyRelocProps();
1370 test_LpValFindProp();
1377 test_FBadColumnSet();
1380 FreeLibrary(hMapi32
);