2 * Unit test suite for MAPI property functions
4 * Copyright 2004 Jon Griffiths
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "wine/test.h"
30 #include "mapi32_test.h"
32 static HMODULE hMapi32
= 0;
34 static SCODE (WINAPI
*pScInitMapiUtil
)(ULONG
);
35 static SCODE (WINAPI
*pPropCopyMore
)(LPSPropValue
,LPSPropValue
,ALLOCATEMORE
*,LPVOID
);
36 static ULONG (WINAPI
*pUlPropSize
)(LPSPropValue
);
37 static BOOL (WINAPI
*pFPropContainsProp
)(LPSPropValue
,LPSPropValue
,ULONG
);
38 static BOOL (WINAPI
*pFPropCompareProp
)(LPSPropValue
,ULONG
,LPSPropValue
);
39 static LONG (WINAPI
*pLPropCompareProp
)(LPSPropValue
,LPSPropValue
);
40 static LPSPropValue (WINAPI
*pPpropFindProp
)(LPSPropValue
,ULONG
,ULONG
);
41 static SCODE (WINAPI
*pScCountProps
)(INT
,LPSPropValue
,ULONG
*);
42 static SCODE (WINAPI
*pScCopyProps
)(int,LPSPropValue
,LPVOID
,ULONG
*);
43 static SCODE (WINAPI
*pScRelocProps
)(int,LPSPropValue
,LPVOID
,LPVOID
,ULONG
*);
44 static LPSPropValue (WINAPI
*pLpValFindProp
)(ULONG
,ULONG
,LPSPropValue
);
45 static BOOL (WINAPI
*pFBadRglpszA
)(LPSTR
*,ULONG
);
46 static BOOL (WINAPI
*pFBadRglpszW
)(LPWSTR
*,ULONG
);
47 static BOOL (WINAPI
*pFBadRowSet
)(LPSRowSet
);
48 static ULONG (WINAPI
*pFBadPropTag
)(ULONG
);
49 static ULONG (WINAPI
*pFBadRow
)(LPSRow
);
50 static ULONG (WINAPI
*pFBadProp
)(LPSPropValue
);
51 static ULONG (WINAPI
*pFBadColumnSet
)(LPSPropTagArray
);
52 static SCODE (WINAPI
*pCreateIProp
)(LPCIID
,ALLOCATEBUFFER
*,ALLOCATEMORE
*,
53 FREEBUFFER
*,LPVOID
,LPPROPDATA
*);
54 static SCODE (WINAPI
*pMAPIAllocateBuffer
)(ULONG
, LPVOID
);
55 static SCODE (WINAPI
*pMAPIAllocateMore
)(ULONG
, LPVOID
, LPVOID
);
56 static SCODE (WINAPI
*pMAPIFreeBuffer
)(LPVOID
);
58 static BOOL
InitFuncPtrs(void)
60 hMapi32
= LoadLibraryA("mapi32.dll");
62 pScInitMapiUtil
= (void*)GetProcAddress(hMapi32
, "ScInitMapiUtil@4");
63 pMAPIAllocateBuffer
= (void*)GetProcAddress(hMapi32
, "MAPIAllocateBuffer");
64 pMAPIAllocateMore
= (void*)GetProcAddress(hMapi32
, "MAPIAllocateMore");
65 pMAPIFreeBuffer
= (void*)GetProcAddress(hMapi32
, "MAPIFreeBuffer");
66 if(pScInitMapiUtil
&& pMAPIAllocateBuffer
&& pMAPIAllocateMore
&& pMAPIFreeBuffer
)
72 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 char szHiA
[] = "Hi!";
87 static WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
88 SPropValue
*lpDest
= NULL
, *lpSrc
= NULL
;
92 pPropCopyMore
= (void*)GetProcAddress(hMapi32
, "PropCopyMore@16");
97 scode
= pMAPIAllocateBuffer(sizeof(LPSPropValue
), lpDest
);
101 scode
= pMAPIAllocateMore(sizeof(LPSPropValue
), lpDest
, lpSrc
);
105 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
107 lpSrc
->ulPropTag
= ptTypes
[i
];
112 lpSrc
->Value
.lpszA
= szHiA
;
115 lpSrc
->Value
.lpszW
= 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,%d, got 0x%08x,%d\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 char szHiA
[] = "Hi!";
157 static 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
= szHiA
;
211 pv
.Value
.lpszW
= 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
;
225 pv
.Value
.MVszW
.cValues
= 2;
226 pv
.Value
.MVszW
.lppszW
= buffw
;
229 exp
= 8 * sizeof(WCHAR
);
232 pv
.Value
.MVbin
.cValues
= 2;
233 pv
.Value
.MVbin
.lpbin
= buffbin
;
242 res
= pUlPropSize(&pv
);
244 "pt= %d: Expected %d, got %d\n", pt
, exp
, res
);
248 static void test_FPropContainsProp(void)
250 static char szFull
[] = "Full String";
251 static char szFullLower
[] = "full string";
252 static char szPrefix
[] = "Full";
253 static char szPrefixLower
[] = "full";
254 static char szSubstring
[] = "ll St";
255 static char szSubstringLower
[] = "ll st";
256 SPropValue pvLeft
, pvRight
;
260 pFPropContainsProp
= (void*)GetProcAddress(hMapi32
, "FPropContainsProp@12");
262 if (!pFPropContainsProp
)
265 /* Ensure that only PT_STRING8 and PT_BINARY are handled */
266 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
268 if (pt
== PT_STRING8
|| pt
== PT_BINARY
)
269 continue; /* test these later */
271 memset(&pvLeft
, 0 ,sizeof(pvLeft
));
272 memset(&pvRight
, 0 ,sizeof(pvRight
));
273 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= pt
;
275 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
276 ok(bRet
== FALSE
, "pt= %d: Expected FALSE, got %d\n", pt
, bRet
);
279 /* test the various flag combinations */
280 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= PT_STRING8
;
281 pvLeft
.Value
.lpszA
= szFull
;
282 pvRight
.Value
.lpszA
= szFull
;
284 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
285 ok(bRet
== TRUE
, "(full,full)[] match failed\n");
286 pvRight
.Value
.lpszA
= szPrefix
;
287 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
288 ok(bRet
== FALSE
, "(full,prefix)[] match failed\n");
289 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
290 ok(bRet
== TRUE
, "(full,prefix)[PREFIX] match failed\n");
291 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
292 ok(bRet
== TRUE
, "(full,prefix)[SUBSTRING] match failed\n");
293 pvRight
.Value
.lpszA
= szPrefixLower
;
294 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
295 ok(bRet
== FALSE
, "(full,prefixlow)[PREFIX] match failed\n");
296 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
297 ok(bRet
== FALSE
, "(full,prefixlow)[SUBSTRING] match failed\n");
298 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
299 ok(bRet
== TRUE
, "(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
300 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
301 ok(bRet
== TRUE
, "(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
302 pvRight
.Value
.lpszA
= szSubstring
;
303 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
304 ok(bRet
== FALSE
, "(full,substr)[] match failed\n");
305 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
306 ok(bRet
== FALSE
, "(full,substr)[PREFIX] match failed\n");
307 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
308 ok(bRet
== TRUE
, "(full,substr)[SUBSTRING] match failed\n");
309 pvRight
.Value
.lpszA
= szSubstringLower
;
310 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
311 ok(bRet
== FALSE
, "(full,substrlow)[PREFIX] match failed\n");
312 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
313 ok(bRet
== FALSE
, "(full,substrlow)[SUBSTRING] match failed\n");
314 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
315 ok(bRet
== FALSE
, "(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
316 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
317 ok(bRet
== TRUE
, "(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
318 pvRight
.Value
.lpszA
= szFullLower
;
319 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
|FL_IGNORECASE
);
320 ok(bRet
== TRUE
, "(full,fulllow)[IGNORECASE] match failed\n");
322 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= PT_BINARY
;
323 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)szFull
;
324 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szFull
;
325 pvLeft
.Value
.bin
.cb
= pvRight
.Value
.bin
.cb
= strlen(szFull
);
327 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
328 ok(bRet
== TRUE
, "bin(full,full)[] match failed\n");
329 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szPrefix
;
330 pvRight
.Value
.bin
.cb
= strlen(szPrefix
);
331 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
332 ok(bRet
== FALSE
, "bin(full,prefix)[] match failed\n");
333 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
334 ok(bRet
== TRUE
, "bin(full,prefix)[PREFIX] match failed\n");
335 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
336 ok(bRet
== TRUE
, "bin(full,prefix)[SUBSTRING] match failed\n");
337 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szPrefixLower
;
338 pvRight
.Value
.bin
.cb
= strlen(szPrefixLower
);
339 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
340 ok(bRet
== FALSE
, "bin(full,prefixlow)[PREFIX] match failed\n");
341 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
342 ok(bRet
== FALSE
, "bin(full,prefixlow)[SUBSTRING] match failed\n");
343 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
344 ok(bRet
== FALSE
, "bin(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
345 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
346 ok(bRet
== FALSE
, "bin(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
347 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szSubstring
;
348 pvRight
.Value
.bin
.cb
= strlen(szSubstring
);
349 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
350 ok(bRet
== FALSE
, "bin(full,substr)[] match failed\n");
351 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
352 ok(bRet
== FALSE
, "bin(full,substr)[PREFIX] match failed\n");
353 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
354 ok(bRet
== TRUE
, "bin(full,substr)[SUBSTRING] match failed\n");
355 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szSubstringLower
;
356 pvRight
.Value
.bin
.cb
= strlen(szSubstringLower
);
357 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
358 ok(bRet
== FALSE
, "bin(full,substrlow)[PREFIX] match failed\n");
359 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
360 ok(bRet
== FALSE
, "bin(full,substrlow)[SUBSTRING] match failed\n");
361 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
362 ok(bRet
== FALSE
, "bin(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
363 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
364 ok(bRet
== FALSE
, "bin(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
365 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szFullLower
;
366 pvRight
.Value
.bin
.cb
= strlen(szFullLower
);
367 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
|FL_IGNORECASE
);
368 ok(bRet
== FALSE
, "bin(full,fulllow)[IGNORECASE] match failed\n");
371 typedef struct tagFPropCompareProp_Result
377 } FPropCompareProp_Result
;
379 static const FPropCompareProp_Result FPCProp_Results
[] =
381 { 1, 2, RELOP_LT
, TRUE
},
382 { 1, 1, RELOP_LT
, FALSE
},
383 { 2, 1, RELOP_LT
, FALSE
},
384 { 1, 2, RELOP_LE
, TRUE
},
385 { 1, 1, RELOP_LE
, TRUE
},
386 { 2, 1, RELOP_LE
, FALSE
},
387 { 1, 2, RELOP_GT
, FALSE
},
388 { 1, 1, RELOP_GT
, FALSE
},
389 { 2, 1, RELOP_GT
, TRUE
},
390 { 1, 2, RELOP_GE
, FALSE
},
391 { 1, 1, RELOP_GE
, TRUE
},
392 { 2, 1, RELOP_GE
, TRUE
},
393 { 1, 2, RELOP_EQ
, FALSE
},
394 { 1, 1, RELOP_EQ
, TRUE
},
395 { 2, 1, RELOP_EQ
, FALSE
}
398 static const char *relops
[] = { "RELOP_LT", "RELOP_LE", "RELOP_GT", "RELOP_GE", "RELOP_EQ" };
400 static void test_FPropCompareProp(void)
402 SPropValue pvLeft
, pvRight
;
404 char lbuffa
[2], rbuffa
[2];
405 WCHAR lbuffw
[2], rbuffw
[2];
409 pFPropCompareProp
= (void*)GetProcAddress(hMapi32
, "FPropCompareProp@12");
411 if (!pFPropCompareProp
)
419 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
421 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= ptTypes
[i
];
423 for (j
= 0; j
< sizeof(FPCProp_Results
)/sizeof(FPCProp_Results
[0]); j
++)
425 SHORT lVal
= FPCProp_Results
[j
].lVal
;
426 SHORT rVal
= FPCProp_Results
[j
].rVal
;
428 bExp
= FPCProp_Results
[j
].bRet
;
433 /* Boolean values have no concept of less or greater than, only equality */
434 if ((lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_LT
) ||
435 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_LE
)||
436 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_GT
)||
437 (lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_GE
)||
438 (lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_EQ
)||
439 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_EQ
))
441 /* Fall through ... */
443 pvLeft
.Value
.i
= lVal
;
444 pvRight
.Value
.i
= rVal
;
448 pvLeft
.Value
.l
= lVal
;
449 pvRight
.Value
.l
= rVal
;
452 pvLeft
.Value
.flt
= lVal
;
453 pvRight
.Value
.flt
= rVal
;
457 pvLeft
.Value
.dbl
= lVal
;
458 pvRight
.Value
.dbl
= rVal
;
461 pvLeft
.Value
.cur
.int64
= lVal
;
462 pvRight
.Value
.cur
.int64
= rVal
;
465 pvLeft
.Value
.ft
.dwLowDateTime
= lVal
;
466 pvLeft
.Value
.ft
.dwHighDateTime
= 0;
467 pvRight
.Value
.ft
.dwLowDateTime
= rVal
;
468 pvRight
.Value
.ft
.dwHighDateTime
= 0;
471 pvLeft
.Value
.li
.u
.LowPart
= lVal
;
472 pvLeft
.Value
.li
.u
.HighPart
= 0;
473 pvRight
.Value
.li
.u
.LowPart
= rVal
;
474 pvRight
.Value
.li
.u
.HighPart
= 0;
477 memset(&lguid
, 0, sizeof(GUID
));
478 memset(&rguid
, 0, sizeof(GUID
));
479 lguid
.Data4
[7] = lVal
;
480 rguid
.Data4
[7] = rVal
;
481 pvLeft
.Value
.lpguid
= &lguid
;
482 pvRight
.Value
.lpguid
= &rguid
;
485 pvLeft
.Value
.lpszA
= lbuffa
;
486 pvRight
.Value
.lpszA
= rbuffa
;
487 lbuffa
[0] = '0' + lVal
;
488 rbuffa
[0] = '0' + rVal
;
491 pvLeft
.Value
.lpszW
= lbuffw
;
492 pvRight
.Value
.lpszW
= rbuffw
;
493 lbuffw
[0] = '0' + lVal
;
494 rbuffw
[0] = '0' + rVal
;
497 pvLeft
.Value
.bin
.cb
= 1;
498 pvRight
.Value
.bin
.cb
= 1;
499 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)lbuffa
;
500 pvRight
.Value
.bin
.lpb
= (LPBYTE
)rbuffa
;
506 bRet
= pFPropCompareProp(&pvLeft
, FPCProp_Results
[j
].relOp
, &pvRight
);
508 "pt %d (%d,%d,%s): expected %d, got %d\n", ptTypes
[i
],
509 FPCProp_Results
[j
].lVal
, FPCProp_Results
[j
].rVal
,
510 relops
[FPCProp_Results
[j
].relOp
], bExp
, bRet
);
515 typedef struct tagLPropCompareProp_Result
520 } LPropCompareProp_Result
;
522 static const LPropCompareProp_Result LPCProp_Results
[] =
529 static void test_LPropCompareProp(void)
531 SPropValue pvLeft
, pvRight
;
533 char lbuffa
[2], rbuffa
[2];
534 WCHAR lbuffw
[2], rbuffw
[2];
538 pLPropCompareProp
= (void*)GetProcAddress(hMapi32
, "LPropCompareProp@8");
540 if (!pLPropCompareProp
)
548 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
550 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= ptTypes
[i
];
552 for (j
= 0; j
< sizeof(LPCProp_Results
)/sizeof(LPCProp_Results
[0]); j
++)
554 SHORT lVal
= LPCProp_Results
[j
].lVal
;
555 SHORT rVal
= LPCProp_Results
[j
].rVal
;
557 iExp
= LPCProp_Results
[j
].iRet
;
562 /* Boolean values have no concept of less or greater than, only equality */
565 /* Fall through ... */
567 pvLeft
.Value
.i
= lVal
;
568 pvRight
.Value
.i
= rVal
;
572 pvLeft
.Value
.l
= lVal
;
573 pvRight
.Value
.l
= rVal
;
576 pvLeft
.Value
.flt
= lVal
;
577 pvRight
.Value
.flt
= rVal
;
581 pvLeft
.Value
.dbl
= lVal
;
582 pvRight
.Value
.dbl
= rVal
;
585 pvLeft
.Value
.cur
.int64
= lVal
;
586 pvRight
.Value
.cur
.int64
= rVal
;
589 pvLeft
.Value
.ft
.dwLowDateTime
= lVal
;
590 pvLeft
.Value
.ft
.dwHighDateTime
= 0;
591 pvRight
.Value
.ft
.dwLowDateTime
= rVal
;
592 pvRight
.Value
.ft
.dwHighDateTime
= 0;
595 pvLeft
.Value
.li
.u
.LowPart
= lVal
;
596 pvLeft
.Value
.li
.u
.HighPart
= 0;
597 pvRight
.Value
.li
.u
.LowPart
= rVal
;
598 pvRight
.Value
.li
.u
.HighPart
= 0;
601 memset(&lguid
, 0, sizeof(GUID
));
602 memset(&rguid
, 0, sizeof(GUID
));
603 lguid
.Data4
[7] = lVal
;
604 rguid
.Data4
[7] = rVal
;
605 pvLeft
.Value
.lpguid
= &lguid
;
606 pvRight
.Value
.lpguid
= &rguid
;
609 pvLeft
.Value
.lpszA
= lbuffa
;
610 pvRight
.Value
.lpszA
= rbuffa
;
611 lbuffa
[0] = '0' + lVal
;
612 rbuffa
[0] = '0' + rVal
;
615 pvLeft
.Value
.lpszW
= lbuffw
;
616 pvRight
.Value
.lpszW
= rbuffw
;
617 lbuffw
[0] = '0' + lVal
;
618 rbuffw
[0] = '0' + rVal
;
621 pvLeft
.Value
.bin
.cb
= 1;
622 pvRight
.Value
.bin
.cb
= 1;
623 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)lbuffa
;
624 pvRight
.Value
.bin
.lpb
= (LPBYTE
)rbuffa
;
630 iRet
= pLPropCompareProp(&pvLeft
, &pvRight
);
632 "pt %d (%d,%d): expected %d, got %d\n", ptTypes
[i
],
633 LPCProp_Results
[j
].lVal
, LPCProp_Results
[j
].rVal
, iExp
, iRet
);
638 static void test_PpropFindProp(void)
640 SPropValue pvProp
, *pRet
;
643 pPpropFindProp
= (void*)GetProcAddress(hMapi32
, "PpropFindProp@12");
648 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
650 pvProp
.ulPropTag
= ptTypes
[i
];
652 pRet
= pPpropFindProp(&pvProp
, 1u, ptTypes
[i
]);
654 "PpropFindProp[%d]: Didn't find existing propery\n",
657 pRet
= pPpropFindProp(&pvProp
, 1u, i
? ptTypes
[i
-1] : ptTypes
[i
+1]);
658 ok(pRet
== NULL
, "PpropFindProp[%d]: Found nonexistent propery\n",
662 pvProp
.ulPropTag
= PROP_TAG(PT_I2
, 1u);
663 pRet
= pPpropFindProp(&pvProp
, 1u, PROP_TAG(PT_UNSPECIFIED
, 0u));
664 ok(pRet
== NULL
, "PpropFindProp[UNSPECIFIED]: Matched on different id\n");
665 pRet
= pPpropFindProp(&pvProp
, 1u, PROP_TAG(PT_UNSPECIFIED
, 1u));
666 ok(pRet
== &pvProp
, "PpropFindProp[UNSPECIFIED]: Didn't match id\n");
669 static void test_ScCountProps(void)
671 static char szHiA
[] = "Hi!";
672 static WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
673 static const ULONG ULHILEN
= 4; /* chars in szHiA/W incl. NUL */
677 GUID iids
[4], *iid
= iids
;
679 ULONG pt
, exp
, ulRet
;
682 pScCountProps
= (void*)GetProcAddress(hMapi32
, "ScCountProps@12");
687 for (pt
= 0; pt
< PROP_ID_INVALID
&& success
; pt
++)
691 memset(&pv
, 0 ,sizeof(pv
));
692 pv
.ulPropTag
= PROP_TAG(pt
, 1u);
694 switch (PROP_TYPE(pt
))
710 pv
.Value
.lpguid
= iid
;
711 exp
= sizeof(GUID
) + sizeof(pv
);
714 pv
.Value
.lpszA
= szHiA
;
715 exp
= 4 + sizeof(pv
);
718 pv
.Value
.lpszW
= szHiW
;
719 exp
= 4 * sizeof(WCHAR
) + sizeof(pv
);
723 pv
.Value
.bin
.lpb
= (LPBYTE
)iid
;
724 exp
= 2 + sizeof(pv
);
727 pv
.Value
.MVi
.cValues
= 3;
728 pv
.Value
.MVi
.lpi
= (SHORT
*)iid
;
729 exp
= 3 * sizeof(SHORT
) + sizeof(pv
);
732 pv
.Value
.MVl
.cValues
= 3;
733 pv
.Value
.MVl
.lpl
= (LONG
*)iid
;
734 exp
= 3 * sizeof(LONG
) + sizeof(pv
);
737 pv
.Value
.MVli
.cValues
= 3;
738 pv
.Value
.MVli
.lpli
= (LARGE_INTEGER
*)iid
;
739 exp
= 3 * sizeof(LARGE_INTEGER
) + sizeof(pv
);
742 pv
.Value
.MVflt
.cValues
= 3;
743 pv
.Value
.MVflt
.lpflt
= (float*)iid
;
744 exp
= 3 * sizeof(float) + sizeof(pv
);
748 pv
.Value
.MVdbl
.cValues
= 3;
749 pv
.Value
.MVdbl
.lpdbl
= (double*)iid
;
750 exp
= 3 * sizeof(double) + sizeof(pv
);
753 pv
.Value
.MVcur
.cValues
= 3;
754 pv
.Value
.MVcur
.lpcur
= (CY
*)iid
;
755 exp
= 3 * sizeof(CY
) + sizeof(pv
);
758 pv
.Value
.MVft
.cValues
= 3;
759 pv
.Value
.MVft
.lpft
= (FILETIME
*)iid
;
760 exp
= 3 * sizeof(CY
) + sizeof(pv
);
763 pv
.Value
.MVszA
.cValues
= 3;
764 pv
.Value
.MVszA
.lppszA
= buffa
;
768 exp
= ULHILEN
* 3 + 3 * sizeof(char*) + sizeof(pv
);
771 pv
.Value
.MVszW
.cValues
= 3;
772 pv
.Value
.MVszW
.lppszW
= buffw
;
776 exp
= ULHILEN
* 3 * sizeof(WCHAR
) + 3 * sizeof(WCHAR
*) + sizeof(pv
);
779 pv
.Value
.MVbin
.cValues
= 3;
780 pv
.Value
.MVbin
.lpbin
= buffbin
;
782 buffbin
[0].lpb
= (LPBYTE
)&iid
;
784 buffbin
[1].lpb
= (LPBYTE
)&iid
;
786 buffbin
[2].lpb
= (LPBYTE
)&iid
;
787 exp
= 20 + sizeof(pv
) + sizeof(SBinary
) * 3;
794 res
= pScCountProps(1, &pv
, &ulRet
);
796 success
= res
== MAPI_E_INVALID_PARAMETER
&& ulRet
== 0xffffffff;
797 ok(success
, "pt= %d: Expected failure, got %d, ret=0x%08X\n",
801 success
= res
== S_OK
&& ulRet
== exp
;
802 ok(success
, "pt= %d: Expected %d, got %d, ret=0x%08X\n",
803 pt
, exp
, ulRet
, res
);
809 static void test_ScCopyRelocProps(void)
811 static char szTestA
[] = "Test";
812 char buffer
[512], buffer2
[512], *lppszA
[1];
813 SPropValue pvProp
, *lpResProp
= (LPSPropValue
)buffer
;
817 pScCopyProps
= (void*)GetProcAddress(hMapi32
, "ScCopyProps@16");
818 pScRelocProps
= (void*)GetProcAddress(hMapi32
, "ScRelocProps@20");
820 if (!pScCopyProps
|| !pScRelocProps
)
823 pvProp
.ulPropTag
= PROP_TAG(PT_MV_STRING8
, 1u);
826 pvProp
.Value
.MVszA
.cValues
= 1;
827 pvProp
.Value
.MVszA
.lppszA
= lppszA
;
830 sc
= pScCopyProps(1, &pvProp
, buffer
, &ulCount
);
831 ok(sc
== S_OK
, "wrong ret %d\n", sc
);
834 ok(lpResProp
->ulPropTag
== pvProp
.ulPropTag
, "wrong tag %x\n",lpResProp
->ulPropTag
);
835 ok(lpResProp
->Value
.MVszA
.cValues
== 1, "wrong cValues %d\n", lpResProp
->Value
.MVszA
.cValues
);
836 ok(lpResProp
->Value
.MVszA
.lppszA
[0] == buffer
+ sizeof(SPropValue
) + sizeof(char*),
837 "wrong lppszA[0] %p\n",lpResProp
->Value
.MVszA
.lppszA
[0]);
838 ok(ulCount
== sizeof(SPropValue
) + sizeof(char*) + 5, "wrong count %d\n", ulCount
);
839 ok(!strcmp(lpResProp
->Value
.MVszA
.lppszA
[0], szTestA
),
840 "wrong string '%s'\n", lpResProp
->Value
.MVszA
.lppszA
[0]);
843 memcpy(buffer2
, buffer
, sizeof(buffer
));
845 /* Clear the data in the source buffer. Since pointers in the copied buffer
846 * refer to the source buffer, this proves that native always assumes that
847 * the copied buffers pointers are bad (needing to be relocated first).
849 memset(buffer
, 0, sizeof(buffer
));
852 sc
= pScRelocProps(1, (LPSPropValue
)buffer2
, buffer
, buffer2
, &ulCount
);
853 lpResProp
= (LPSPropValue
)buffer2
;
855 ok(sc
== S_OK
, "wrong ret %d\n", sc
);
858 ok(lpResProp
->ulPropTag
== pvProp
.ulPropTag
, "wrong tag %x\n",lpResProp
->ulPropTag
);
859 ok(lpResProp
->Value
.MVszA
.cValues
== 1, "wrong cValues %d\n", lpResProp
->Value
.MVszA
.cValues
);
860 ok(lpResProp
->Value
.MVszA
.lppszA
[0] == buffer2
+ sizeof(SPropValue
) + sizeof(char*),
861 "wrong lppszA[0] %p\n",lpResProp
->Value
.MVszA
.lppszA
[0]);
862 /* Native has a bug whereby it calculates the size correctly when copying
863 * but when relocating does not (presumably it uses UlPropSize() which
864 * ignores multivalue pointers). Wine returns the correct value.
866 ok(ulCount
== sizeof(SPropValue
) + sizeof(char*) + 5 || ulCount
== sizeof(SPropValue
) + 5,
867 "wrong count %d\n", ulCount
);
868 ok(!strcmp(lpResProp
->Value
.MVszA
.lppszA
[0], szTestA
),
869 "wrong string '%s'\n", lpResProp
->Value
.MVszA
.lppszA
[0]);
872 /* Native crashes with lpNew or lpOld set to NULL so skip testing this */
875 static void test_LpValFindProp(void)
877 SPropValue pvProp
, *pRet
;
880 pLpValFindProp
= (void*)GetProcAddress(hMapi32
, "LpValFindProp@12");
885 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
887 pvProp
.ulPropTag
= PROP_TAG(ptTypes
[i
], 1u);
889 pRet
= pLpValFindProp(PROP_TAG(ptTypes
[i
], 1u), 1u, &pvProp
);
891 "LpValFindProp[%d]: Didn't find existing propery id/type\n",
894 pRet
= pLpValFindProp(PROP_TAG(ptTypes
[i
], 0u), 1u, &pvProp
);
895 ok(pRet
== NULL
, "LpValFindProp[%d]: Found nonexistent propery id\n",
898 pRet
= pLpValFindProp(PROP_TAG(PT_NULL
, 0u), 1u, &pvProp
);
899 ok(pRet
== NULL
, "LpValFindProp[%d]: Found nonexistent propery id/type\n",
902 pRet
= pLpValFindProp(PROP_TAG(PT_NULL
, 1u), 1u, &pvProp
);
904 "LpValFindProp[%d]: Didn't find existing propery id\n",
909 static void test_FBadRglpszA(void)
912 static CHAR szString
[] = "A String";
915 pFBadRglpszA
= (void*)GetProcAddress(hMapi32
, "FBadRglpszA@8");
919 bRet
= pFBadRglpszA(NULL
, 10);
920 ok(bRet
== TRUE
, "FBadRglpszA(Null): expected TRUE, got FALSE\n");
922 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = lpStrs
[3] = NULL
;
923 bRet
= pFBadRglpszA(lpStrs
, 4);
924 ok(bRet
== TRUE
, "FBadRglpszA(Nulls): expected TRUE, got FALSE\n");
926 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = szString
;
927 bRet
= pFBadRglpszA(lpStrs
, 3);
928 ok(bRet
== FALSE
, "FBadRglpszA(valid): expected FALSE, got TRUE\n");
930 bRet
= pFBadRglpszA(lpStrs
, 4);
931 ok(bRet
== TRUE
, "FBadRglpszA(1 invalid): expected TRUE, got FALSE\n");
934 static void test_FBadRglpszW(void)
937 static WCHAR szString
[] = { 'A',' ','S','t','r','i','n','g','\0' };
940 pFBadRglpszW
= (void*)GetProcAddress(hMapi32
, "FBadRglpszW@8");
944 bRet
= pFBadRglpszW(NULL
, 10);
945 ok(bRet
== TRUE
, "FBadRglpszW(Null): expected TRUE, got FALSE\n");
947 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = lpStrs
[3] = NULL
;
948 bRet
= pFBadRglpszW(lpStrs
, 4);
949 ok(bRet
== TRUE
, "FBadRglpszW(Nulls): expected TRUE, got FALSE\n");
951 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = szString
;
952 bRet
= pFBadRglpszW(lpStrs
, 3);
953 ok(bRet
== FALSE
, "FBadRglpszW(valid): expected FALSE, got TRUE\n");
955 bRet
= pFBadRglpszW(lpStrs
, 4);
956 ok(bRet
== TRUE
, "FBadRglpszW(1 invalid): expected TRUE, got FALSE\n");
959 static void test_FBadRowSet(void)
963 pFBadRowSet
= (void*)GetProcAddress(hMapi32
, "FBadRowSet@4");
967 ulRet
= pFBadRowSet(NULL
);
968 ok(ulRet
!= 0, "FBadRow(null): Expected non-zero, got 0\n");
973 static void test_FBadPropTag(void)
977 pFBadPropTag
= (void*)GetProcAddress(hMapi32
, "FBadPropTag@4");
981 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
985 switch (pt
& (~MV_FLAG
& PROP_TYPE_MASK
))
988 case PT_NULL
: case PT_I2
: case PT_I4
: case PT_R4
:
989 case PT_R8
: case PT_CURRENCY
: case PT_APPTIME
:
990 case PT_ERROR
: case PT_BOOLEAN
: case PT_OBJECT
:
991 case PT_I8
: case PT_STRING8
: case PT_UNICODE
:
992 case PT_SYSTIME
: case PT_CLSID
: case PT_BINARY
:
996 res
= pFBadPropTag(pt
);
998 ok(res
!= 0, "pt= %d: Expected non-zero, got 0\n", pt
);
1001 "pt= %d: Expected zero, got %d\n", pt
, res
);
1005 static void test_FBadRow(void)
1009 pFBadRow
= (void*)GetProcAddress(hMapi32
, "FBadRow@4");
1013 ulRet
= pFBadRow(NULL
);
1014 ok(ulRet
!= 0, "FBadRow(null): Expected non-zero, got 0\n");
1019 static void test_FBadProp(void)
1021 static WCHAR szEmpty
[] = { '\0' };
1026 pFBadProp
= (void*)GetProcAddress(hMapi32
, "FBadProp@4");
1030 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1034 memset(&pv
, 0, sizeof(pv
));
1037 /* Note that MV values are valid below because their array count is 0,
1038 * so no pointers are validated.
1040 switch (PROP_TYPE(pt
))
1042 case (MV_FLAG
|PT_UNSPECIFIED
):
1043 case PT_UNSPECIFIED
:
1044 case (MV_FLAG
|PT_NULL
):
1056 case PT_MV_CURRENCY
:
1060 case (MV_FLAG
|PT_ERROR
):
1062 case (MV_FLAG
|PT_BOOLEAN
):
1064 case (MV_FLAG
|PT_OBJECT
):
1077 pv
.Value
.lpszW
= szEmpty
;
1081 pv
.Value
.lpguid
= &iid
;
1086 res
= pFBadProp(&pv
);
1088 ok(res
!= 0, "pt= %d: Expected non-zero, got 0\n", pt
);
1091 "pt= %d: Expected zero, got %d\n", pt
, res
);
1095 static void test_FBadColumnSet(void)
1100 pFBadColumnSet
= (void*)GetProcAddress(hMapi32
, "FBadColumnSet@4");
1101 if (!pFBadColumnSet
)
1104 res
= pFBadColumnSet(NULL
);
1105 ok(res
!= 0, "(null): Expected non-zero, got 0\n");
1109 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1113 pta
.aulPropTag
[0] = pt
;
1115 switch (pt
& (~MV_FLAG
& PROP_TYPE_MASK
))
1117 case PT_UNSPECIFIED
:
1135 if (pt
== (MV_FLAG
|PT_ERROR
))
1138 res
= pFBadColumnSet(&pta
);
1140 ok(res
!= 0, "pt= %d: Expected non-zero, got 0\n", pt
);
1143 "pt= %d: Expected zero, got %d\n", pt
, res
);
1148 static void test_IProp(void)
1151 LPMAPIERROR lpError
;
1152 LPSPropProblemArray lpProbs
;
1153 LPSPropValue lpProps
;
1154 LPSPropTagArray lpTags
;
1156 SizedSPropTagArray(2,tags
);
1157 ULONG access
[2], count
;
1160 pCreateIProp
= (void*)GetProcAddress(hMapi32
, "CreateIProp@24");
1165 memset(&tags
, 0 , sizeof(tags
));
1167 /* Create the object */
1169 sc
= pCreateIProp(&IID_IMAPIPropData
, (ALLOCATEBUFFER
*)pMAPIAllocateBuffer
, (ALLOCATEMORE
*)pMAPIAllocateMore
,
1170 (FREEBUFFER
*)pMAPIFreeBuffer
, NULL
, &lpIProp
);
1171 ok(sc
== S_OK
&& lpIProp
,
1172 "CreateIProp: expected S_OK, non-null, got 0x%08X,%p\n", sc
, lpIProp
);
1174 if (sc
!= S_OK
|| !lpIProp
)
1177 /* GetLastError - No errors set */
1179 IPropData_GetLastError(lpIProp
, E_INVALIDARG
, 0, &lpError
);
1180 ok(sc
== S_OK
&& !lpError
,
1181 "GetLastError: Expected S_OK, null, got 0x%08X,%p\n", sc
, lpError
);
1183 /* Get prop tags - succeeds returning 0 items */
1185 sc
= IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1186 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 0,
1187 "GetPropList(empty): Expected S_OK, non-null, 0, got 0x%08X,%p,%d\n",
1188 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1190 pMAPIFreeBuffer(lpTags
);
1192 /* Get props - succeeds returning 0 items */
1196 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1197 sc
= IPropData_GetProps(lpIProp
, (LPSPropTagArray
)&tags
, 0, &count
, &lpProps
);
1198 ok(sc
== MAPI_W_ERRORS_RETURNED
&& lpProps
&& count
== 1,
1199 "GetProps(empty): Expected ERRORS_RETURNED, non-null, 1, got 0x%08X,%p,%d\n",
1200 sc
, lpProps
, count
);
1201 if (lpProps
&& count
> 0)
1203 ok(lpProps
[0].ulPropTag
== CHANGE_PROP_TYPE(PR_IMPORTANCE
,PT_ERROR
),
1204 "GetProps(empty): Expected %x, got %x\n",
1205 CHANGE_PROP_TYPE(PR_IMPORTANCE
,PT_ERROR
), lpProps
[0].ulPropTag
);
1207 pMAPIFreeBuffer(lpProps
);
1210 /* Add (NULL) - Can't add NULLs */
1212 pvs
[0].ulPropTag
= PROP_TAG(PT_NULL
,0x01);
1213 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1214 ok(sc
== MAPI_E_INVALID_PARAMETER
&& !lpProbs
,
1215 "SetProps(): Expected INVALID_PARAMETER, null, got 0x%08X,%p\n",
1218 /* Add (OBJECT) - Can't add OBJECTs */
1220 pvs
[0].ulPropTag
= PROP_TAG(PT_OBJECT
,0x01);
1221 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1222 ok(sc
== MAPI_E_INVALID_PARAMETER
&& !lpProbs
,
1223 "SetProps(OBJECT): Expected INVALID_PARAMETER, null, got 0x%08X,%p\n",
1226 /* Add - Adds value */
1228 pvs
[0].ulPropTag
= PR_IMPORTANCE
;
1229 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1230 ok(sc
== S_OK
&& !lpProbs
,
1231 "SetProps(ERROR): Expected S_OK, null, got 0x%08X,%p\n", sc
, lpProbs
);
1233 /* Get prop list - returns 1 item */
1235 IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1236 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 1,
1237 "GetPropList: Expected S_OK, non-null, 1, got 0x%08X,%p,%d\n",
1238 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1239 if (lpTags
&& lpTags
->cValues
> 0)
1241 ok(lpTags
->aulPropTag
[0] == PR_IMPORTANCE
,
1242 "GetPropList: Expected %x, got %x\n",
1243 PR_IMPORTANCE
, lpTags
->aulPropTag
[0]);
1244 pMAPIFreeBuffer(lpTags
);
1247 /* Set access to read and write */
1248 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READWRITE
);
1249 ok(sc
== S_OK
, "SetObjAcess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1252 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1254 /* Set item access (bad access) - Fails */
1256 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1257 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1258 "SetPropAcess(0): Expected INVALID_PARAMETER got 0x%08X\n",sc
);
1259 access
[0] = IPROP_READWRITE
;
1260 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1261 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1262 "SetPropAcess(RW): Expected INVALID_PARAMETER got 0x%08X\n",sc
);
1263 access
[0] = IPROP_CLEAN
;
1264 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1265 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1266 "SetPropAcess(C): Expected INVALID_PARAMETER got 0x%08X\n",sc
);
1268 /* Set item access to read/write/clean */
1270 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1271 access
[0] = IPROP_READWRITE
|IPROP_CLEAN
;
1272 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1273 ok(sc
== S_OK
, "SetPropAcess(RW/C): Expected S_OK got 0x%08X\n",sc
);
1275 /* Set object access to read only */
1276 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READONLY
);
1277 ok(sc
== S_OK
, "SetObjAcess(READ): Expected S_OK got 0x%08X\n", sc
);
1279 /* Set item access to read/write/dirty - doesn't care about RO object */
1280 access
[0] = IPROP_READONLY
|IPROP_DIRTY
;
1281 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1282 ok(sc
== S_OK
, "SetPropAcess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1284 /* Delete any item when set to read only - Error */
1286 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1287 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1288 ok(sc
== E_ACCESSDENIED
&& !lpProbs
,
1289 "DeleteProps(nonexistent): Expected E_ACCESSDENIED null got 0x%08X %p\n",
1292 /* Set access to read and write */
1293 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READWRITE
);
1294 ok(sc
== S_OK
, "SetObjAcess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1296 /* Delete nonexistent item - No error */
1298 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1299 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1300 ok(sc
== S_OK
&& !lpProbs
,
1301 "DeleteProps(nonexistent): Expected S_OK null got 0x%08X %p\n",
1304 /* Delete existing item (r/o) - No error, but lpProbs populated */
1306 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1307 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1308 ok(sc
== S_OK
&& lpProbs
,
1309 "DeleteProps(RO): Expected S_OK non-null got 0x%08X %p\n", sc
, lpProbs
);
1311 if (lpProbs
&& lpProbs
->cProblem
> 0)
1313 ok(lpProbs
->cProblem
== 1 &&
1314 lpProbs
->aProblem
[0].ulIndex
== 0 &&
1315 lpProbs
->aProblem
[0].ulPropTag
== PR_IMPORTANCE
&&
1316 lpProbs
->aProblem
[0].scode
== E_ACCESSDENIED
,
1317 "DeleteProps(RO): Expected (1,0,%x,%x) got (%d,%x,%x)\n",
1318 PR_IMPORTANCE
, E_ACCESSDENIED
,
1319 lpProbs
->aProblem
[0].ulIndex
, lpProbs
->aProblem
[0].ulPropTag
,
1320 lpProbs
->aProblem
[0].scode
);
1321 pMAPIFreeBuffer(lpProbs
);
1326 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1327 IPropData_HrAddObjProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1328 ok(sc
== S_OK
&& !lpProbs
,
1329 "AddObjProps(RO): Expected S_OK null got 0x%08X %p\n", sc
, lpProbs
);
1331 /* Get prop list - returns 1 item */
1333 IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1334 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 1,
1335 "GetPropList: Expected S_OK, non-null, 1, got 0x%08X,%p,%d\n",
1336 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1337 if (lpTags
&& lpTags
->cValues
> 0)
1339 ok(lpTags
->aulPropTag
[0] == PR_IMPORTANCE
,
1340 "GetPropList: Expected %x, got %x\n",
1341 PR_IMPORTANCE
, lpTags
->aulPropTag
[0]);
1342 pMAPIFreeBuffer(lpTags
);
1345 /* Set item to r/w again */
1346 access
[0] = IPROP_READWRITE
|IPROP_DIRTY
;
1347 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1348 ok(sc
== S_OK
, "SetPropAcess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1350 /* Delete existing item (r/w) - No error, no problems */
1352 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1353 ok(sc
== S_OK
&& !lpProbs
,
1354 "DeleteProps(RO): Expected S_OK null got 0x%08X %p\n", sc
, lpProbs
);
1357 IPropData_Release(lpIProp
);
1364 if (!HaveDefaultMailClient())
1366 win_skip("No default mail client installed\n");
1372 win_skip("Needed functions are not available\n");
1376 SetLastError(0xdeadbeef);
1377 ret
= pScInitMapiUtil(0);
1378 if ((ret
!= S_OK
) && (GetLastError() == ERROR_PROC_NOT_FOUND
))
1380 win_skip("ScInitMapiUtil is not implemented\n");
1381 FreeLibrary(hMapi32
);
1384 else if ((ret
== E_FAIL
) && (GetLastError() == ERROR_INVALID_HANDLE
))
1386 win_skip("ScInitMapiUtil doesn't work on some Win98 and WinME systems\n");
1387 FreeLibrary(hMapi32
);
1391 test_PropCopyMore();
1393 test_FPropContainsProp();
1394 test_FPropCompareProp();
1395 test_LPropCompareProp();
1396 test_PpropFindProp();
1397 test_ScCountProps();
1398 test_ScCopyRelocProps();
1399 test_LpValFindProp();
1406 test_FBadColumnSet();
1409 FreeLibrary(hMapi32
);