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 void (WINAPI
*pDeinitMapiUtil
)(void);
36 static SCODE (WINAPI
*pPropCopyMore
)(LPSPropValue
,LPSPropValue
,ALLOCATEMORE
*,LPVOID
);
37 static ULONG (WINAPI
*pUlPropSize
)(LPSPropValue
);
38 static BOOL (WINAPI
*pFPropContainsProp
)(LPSPropValue
,LPSPropValue
,ULONG
);
39 static BOOL (WINAPI
*pFPropCompareProp
)(LPSPropValue
,ULONG
,LPSPropValue
);
40 static LONG (WINAPI
*pLPropCompareProp
)(LPSPropValue
,LPSPropValue
);
41 static LPSPropValue (WINAPI
*pPpropFindProp
)(LPSPropValue
,ULONG
,ULONG
);
42 static SCODE (WINAPI
*pScCountProps
)(INT
,LPSPropValue
,ULONG
*);
43 static SCODE (WINAPI
*pScCopyProps
)(int,LPSPropValue
,LPVOID
,ULONG
*);
44 static SCODE (WINAPI
*pScRelocProps
)(int,LPSPropValue
,LPVOID
,LPVOID
,ULONG
*);
45 static LPSPropValue (WINAPI
*pLpValFindProp
)(ULONG
,ULONG
,LPSPropValue
);
46 static BOOL (WINAPI
*pFBadRglpszA
)(LPSTR
*,ULONG
);
47 static BOOL (WINAPI
*pFBadRglpszW
)(LPWSTR
*,ULONG
);
48 static BOOL (WINAPI
*pFBadRowSet
)(LPSRowSet
);
49 static ULONG (WINAPI
*pFBadPropTag
)(ULONG
);
50 static ULONG (WINAPI
*pFBadRow
)(LPSRow
);
51 static ULONG (WINAPI
*pFBadProp
)(LPSPropValue
);
52 static ULONG (WINAPI
*pFBadColumnSet
)(LPSPropTagArray
);
53 static SCODE (WINAPI
*pCreateIProp
)(LPCIID
,ALLOCATEBUFFER
*,ALLOCATEMORE
*,
54 FREEBUFFER
*,LPVOID
,LPPROPDATA
*);
55 static SCODE (WINAPI
*pMAPIAllocateBuffer
)(ULONG
, LPVOID
);
56 static SCODE (WINAPI
*pMAPIAllocateMore
)(ULONG
, LPVOID
, LPVOID
);
57 static SCODE (WINAPI
*pMAPIInitialize
)(LPVOID
);
58 static SCODE (WINAPI
*pMAPIFreeBuffer
)(LPVOID
);
59 static void (WINAPI
*pMAPIUninitialize
)(void);
61 static BOOL
InitFuncPtrs(void)
63 hMapi32
= LoadLibraryA("mapi32.dll");
65 pPropCopyMore
= (void*)GetProcAddress(hMapi32
, "PropCopyMore@16");
66 pUlPropSize
= (void*)GetProcAddress(hMapi32
, "UlPropSize@4");
67 pFPropContainsProp
= (void*)GetProcAddress(hMapi32
, "FPropContainsProp@12");
68 pFPropCompareProp
= (void*)GetProcAddress(hMapi32
, "FPropCompareProp@12");
69 pLPropCompareProp
= (void*)GetProcAddress(hMapi32
, "LPropCompareProp@8");
70 pPpropFindProp
= (void*)GetProcAddress(hMapi32
, "PpropFindProp@12");
71 pScCountProps
= (void*)GetProcAddress(hMapi32
, "ScCountProps@12");
72 pScCopyProps
= (void*)GetProcAddress(hMapi32
, "ScCopyProps@16");
73 pScRelocProps
= (void*)GetProcAddress(hMapi32
, "ScRelocProps@20");
74 pLpValFindProp
= (void*)GetProcAddress(hMapi32
, "LpValFindProp@12");
75 pFBadRglpszA
= (void*)GetProcAddress(hMapi32
, "FBadRglpszA@8");
76 pFBadRglpszW
= (void*)GetProcAddress(hMapi32
, "FBadRglpszW@8");
77 pFBadRowSet
= (void*)GetProcAddress(hMapi32
, "FBadRowSet@4");
78 pFBadPropTag
= (void*)GetProcAddress(hMapi32
, "FBadPropTag@4");
79 pFBadRow
= (void*)GetProcAddress(hMapi32
, "FBadRow@4");
80 pFBadProp
= (void*)GetProcAddress(hMapi32
, "FBadProp@4");
81 pFBadColumnSet
= (void*)GetProcAddress(hMapi32
, "FBadColumnSet@4");
82 pCreateIProp
= (void*)GetProcAddress(hMapi32
, "CreateIProp@24");
84 pScInitMapiUtil
= (void*)GetProcAddress(hMapi32
, "ScInitMapiUtil@4");
85 pDeinitMapiUtil
= (void*)GetProcAddress(hMapi32
, "DeinitMapiUtil@0");
86 pMAPIAllocateBuffer
= (void*)GetProcAddress(hMapi32
, "MAPIAllocateBuffer");
87 pMAPIAllocateMore
= (void*)GetProcAddress(hMapi32
, "MAPIAllocateMore");
88 pMAPIFreeBuffer
= (void*)GetProcAddress(hMapi32
, "MAPIFreeBuffer");
89 pMAPIInitialize
= (void*)GetProcAddress(hMapi32
, "MAPIInitialize");
90 pMAPIUninitialize
= (void*)GetProcAddress(hMapi32
, "MAPIUninitialize");
92 return pMAPIAllocateBuffer
&& pMAPIAllocateMore
&& pMAPIFreeBuffer
&&
93 pScInitMapiUtil
&& pDeinitMapiUtil
;
96 /* FIXME: Test PT_I2, PT_I4, PT_R4, PT_R8, PT_CURRENCY, PT_APPTIME, PT_SYSTIME,
97 * PT_ERROR, PT_BOOLEAN, PT_I8, and PT_CLSID. */
98 static ULONG ptTypes
[] = {
99 PT_STRING8
, PT_BINARY
, PT_UNICODE
102 static inline int strcmpW(const WCHAR
*str1
, const WCHAR
*str2
)
104 while (*str1
&& (*str1
== *str2
)) { str1
++; str2
++; }
105 return *str1
- *str2
;
108 static void test_PropCopyMore(void)
110 static char szHiA
[] = "Hi!";
111 static WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
112 SPropValue
*lpDest
= NULL
, *lpSrc
= NULL
;
118 win_skip("PropCopyMore is not available\n");
122 scode
= pMAPIAllocateBuffer(sizeof(SPropValue
), &lpDest
);
123 ok(scode
== S_OK
, "Expected MAPIAllocateBuffer to return S_OK, got 0x%x\n", scode
);
126 skip("MAPIAllocateBuffer failed\n");
130 scode
= pMAPIAllocateMore(sizeof(SPropValue
), lpDest
, &lpSrc
);
131 ok(scode
== S_OK
, "Expected MAPIAllocateMore to return S_OK, got 0x%x\n", scode
);
134 skip("MAPIAllocateMore failed\n");
138 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
140 lpSrc
->ulPropTag
= ptTypes
[i
];
145 lpSrc
->Value
.lpszA
= szHiA
;
148 lpSrc
->Value
.lpszW
= szHiW
;
151 lpSrc
->Value
.bin
.cb
= 4;
152 lpSrc
->Value
.bin
.lpb
= (LPBYTE
)szHiA
;
156 memset(lpDest
, 0xff, sizeof(SPropValue
));
158 scode
= pPropCopyMore(lpDest
, lpSrc
, (ALLOCATEMORE
*)pMAPIAllocateMore
, lpDest
);
159 ok(!scode
&& lpDest
->ulPropTag
== lpSrc
->ulPropTag
,
160 "PropCopyMore: Expected 0x0,%d, got 0x%08x,%d\n",
161 lpSrc
->ulPropTag
, scode
, lpDest
->ulPropTag
);
162 if (SUCCEEDED(scode
))
167 ok(lstrcmpA(lpDest
->Value
.lpszA
, lpSrc
->Value
.lpszA
) == 0,
168 "PropCopyMore: Ascii string differs\n");
171 ok(strcmpW(lpDest
->Value
.lpszW
, lpSrc
->Value
.lpszW
) == 0,
172 "PropCopyMore: Unicode string differs\n");
175 ok(lpDest
->Value
.bin
.cb
== 4 &&
176 !memcmp(lpSrc
->Value
.bin
.lpb
, lpDest
->Value
.bin
.lpb
, 4),
177 "PropCopyMore: Binary array differs\n");
183 /* Since all allocations are linked, freeing lpDest frees everything */
184 scode
= pMAPIFreeBuffer(lpDest
);
185 ok(scode
== S_OK
, "Expected MAPIFreeBuffer to return S_OK, got 0x%x\n", scode
);
188 static void test_UlPropSize(void)
190 static char szHiA
[] = "Hi!";
191 static WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
199 win_skip("UlPropSize is not available\n");
203 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
207 memset(&pv
, 0 ,sizeof(pv
));
210 exp
= 1u; /* Default to one item for non-MV properties */
212 switch (PROP_TYPE(pt
))
214 case PT_MV_I2
: pv
.Value
.MVi
.cValues
= exp
= 2;
215 case PT_I2
: exp
*= sizeof(USHORT
); break;
216 case PT_MV_I4
: pv
.Value
.MVl
.cValues
= exp
= 2;
217 case PT_I4
: exp
*= sizeof(LONG
); break;
218 case PT_MV_R4
: pv
.Value
.MVflt
.cValues
= exp
= 2;
219 case PT_R4
: exp
*= sizeof(float); break;
220 case PT_MV_DOUBLE
: pv
.Value
.MVdbl
.cValues
= exp
= 2;
221 case PT_R8
: exp
*= sizeof(double); break;
222 case PT_MV_CURRENCY
: pv
.Value
.MVcur
.cValues
= exp
= 2;
223 case PT_CURRENCY
: exp
*= sizeof(CY
); break;
224 case PT_MV_APPTIME
: pv
.Value
.MVat
.cValues
= exp
= 2;
225 case PT_APPTIME
: exp
*= sizeof(double); break;
226 case PT_MV_SYSTIME
: pv
.Value
.MVft
.cValues
= exp
= 2;
227 case PT_SYSTIME
: exp
*= sizeof(FILETIME
); break;
228 case PT_ERROR
: exp
= sizeof(SCODE
); break;
229 case PT_BOOLEAN
: exp
= sizeof(USHORT
); break;
230 case PT_OBJECT
: exp
= 0; break;
231 case PT_MV_I8
: pv
.Value
.MVli
.cValues
= exp
= 2;
232 case PT_I8
: exp
*= sizeof(LONG64
); break;
234 /* My version of native mapi returns 0 for PT_MV_CLSID even if a valid
235 * array is given. This _has_ to be a bug, so Wine does
236 * the right thing(tm) and we don't test it here.
238 case PT_MV_CLSID
: pv
.Value
.MVguid
.cValues
= exp
= 2;
240 case PT_CLSID
: exp
*= sizeof(GUID
); break;
242 pv
.Value
.lpszA
= szHiA
;
246 pv
.Value
.lpszW
= szHiW
;
247 exp
= 4 * sizeof(WCHAR
);
250 pv
.Value
.bin
.cb
= exp
= 19;
253 pv
.Value
.MVszA
.cValues
= 2;
254 pv
.Value
.MVszA
.lppszA
= buffa
;
260 pv
.Value
.MVszW
.cValues
= 2;
261 pv
.Value
.MVszW
.lppszW
= buffw
;
264 exp
= 8 * sizeof(WCHAR
);
267 pv
.Value
.MVbin
.cValues
= 2;
268 pv
.Value
.MVbin
.lpbin
= buffbin
;
277 res
= pUlPropSize(&pv
);
279 "pt= %d: Expected %d, got %d\n", pt
, exp
, res
);
283 static void test_FPropContainsProp(void)
285 static char szFull
[] = "Full String";
286 static char szFullLower
[] = "full string";
287 static char szPrefix
[] = "Full";
288 static char szPrefixLower
[] = "full";
289 static char szSubstring
[] = "ll St";
290 static char szSubstringLower
[] = "ll st";
291 SPropValue pvLeft
, pvRight
;
295 if (!pFPropContainsProp
)
297 win_skip("FPropContainsProp is not available\n");
301 /* Ensure that only PT_STRING8 and PT_BINARY are handled */
302 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
304 if (pt
== PT_STRING8
|| pt
== PT_BINARY
)
305 continue; /* test these later */
307 memset(&pvLeft
, 0 ,sizeof(pvLeft
));
308 memset(&pvRight
, 0 ,sizeof(pvRight
));
309 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= pt
;
311 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
312 ok(bRet
== FALSE
, "pt= %d: Expected FALSE, got %d\n", pt
, bRet
);
315 /* test the various flag combinations */
316 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= PT_STRING8
;
317 pvLeft
.Value
.lpszA
= szFull
;
318 pvRight
.Value
.lpszA
= szFull
;
320 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
321 ok(bRet
== TRUE
, "(full,full)[] match failed\n");
322 pvRight
.Value
.lpszA
= szPrefix
;
323 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
324 ok(bRet
== FALSE
, "(full,prefix)[] match failed\n");
325 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
326 ok(bRet
== TRUE
, "(full,prefix)[PREFIX] match failed\n");
327 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
328 ok(bRet
== TRUE
, "(full,prefix)[SUBSTRING] match failed\n");
329 pvRight
.Value
.lpszA
= szPrefixLower
;
330 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
331 ok(bRet
== FALSE
, "(full,prefixlow)[PREFIX] match failed\n");
332 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
333 ok(bRet
== FALSE
, "(full,prefixlow)[SUBSTRING] match failed\n");
334 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
335 ok(bRet
== TRUE
, "(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
336 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
337 ok(bRet
== TRUE
, "(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
338 pvRight
.Value
.lpszA
= szSubstring
;
339 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
340 ok(bRet
== FALSE
, "(full,substr)[] match failed\n");
341 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
342 ok(bRet
== FALSE
, "(full,substr)[PREFIX] match failed\n");
343 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
344 ok(bRet
== TRUE
, "(full,substr)[SUBSTRING] match failed\n");
345 pvRight
.Value
.lpszA
= szSubstringLower
;
346 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
347 ok(bRet
== FALSE
, "(full,substrlow)[PREFIX] match failed\n");
348 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
349 ok(bRet
== FALSE
, "(full,substrlow)[SUBSTRING] match failed\n");
350 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
351 ok(bRet
== FALSE
, "(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
352 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
353 ok(bRet
== TRUE
, "(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
354 pvRight
.Value
.lpszA
= szFullLower
;
355 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
|FL_IGNORECASE
);
356 ok(bRet
== TRUE
, "(full,fulllow)[IGNORECASE] match failed\n");
358 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= PT_BINARY
;
359 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)szFull
;
360 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szFull
;
361 pvLeft
.Value
.bin
.cb
= pvRight
.Value
.bin
.cb
= strlen(szFull
);
363 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
364 ok(bRet
== TRUE
, "bin(full,full)[] match failed\n");
365 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szPrefix
;
366 pvRight
.Value
.bin
.cb
= strlen(szPrefix
);
367 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
368 ok(bRet
== FALSE
, "bin(full,prefix)[] match failed\n");
369 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
370 ok(bRet
== TRUE
, "bin(full,prefix)[PREFIX] match failed\n");
371 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
372 ok(bRet
== TRUE
, "bin(full,prefix)[SUBSTRING] match failed\n");
373 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szPrefixLower
;
374 pvRight
.Value
.bin
.cb
= strlen(szPrefixLower
);
375 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
376 ok(bRet
== FALSE
, "bin(full,prefixlow)[PREFIX] match failed\n");
377 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
378 ok(bRet
== FALSE
, "bin(full,prefixlow)[SUBSTRING] match failed\n");
379 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
380 ok(bRet
== FALSE
, "bin(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
381 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
382 ok(bRet
== FALSE
, "bin(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
383 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szSubstring
;
384 pvRight
.Value
.bin
.cb
= strlen(szSubstring
);
385 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
386 ok(bRet
== FALSE
, "bin(full,substr)[] match failed\n");
387 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
388 ok(bRet
== FALSE
, "bin(full,substr)[PREFIX] match failed\n");
389 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
390 ok(bRet
== TRUE
, "bin(full,substr)[SUBSTRING] match failed\n");
391 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szSubstringLower
;
392 pvRight
.Value
.bin
.cb
= strlen(szSubstringLower
);
393 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
394 ok(bRet
== FALSE
, "bin(full,substrlow)[PREFIX] match failed\n");
395 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
396 ok(bRet
== FALSE
, "bin(full,substrlow)[SUBSTRING] match failed\n");
397 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
398 ok(bRet
== FALSE
, "bin(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
399 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
400 ok(bRet
== FALSE
, "bin(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
401 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szFullLower
;
402 pvRight
.Value
.bin
.cb
= strlen(szFullLower
);
403 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
|FL_IGNORECASE
);
404 ok(bRet
== FALSE
, "bin(full,fulllow)[IGNORECASE] match failed\n");
407 typedef struct tagFPropCompareProp_Result
413 } FPropCompareProp_Result
;
415 static const FPropCompareProp_Result FPCProp_Results
[] =
417 { 1, 2, RELOP_LT
, TRUE
},
418 { 1, 1, RELOP_LT
, FALSE
},
419 { 2, 1, RELOP_LT
, FALSE
},
420 { 1, 2, RELOP_LE
, TRUE
},
421 { 1, 1, RELOP_LE
, TRUE
},
422 { 2, 1, RELOP_LE
, FALSE
},
423 { 1, 2, RELOP_GT
, FALSE
},
424 { 1, 1, RELOP_GT
, FALSE
},
425 { 2, 1, RELOP_GT
, TRUE
},
426 { 1, 2, RELOP_GE
, FALSE
},
427 { 1, 1, RELOP_GE
, TRUE
},
428 { 2, 1, RELOP_GE
, TRUE
},
429 { 1, 2, RELOP_EQ
, FALSE
},
430 { 1, 1, RELOP_EQ
, TRUE
},
431 { 2, 1, RELOP_EQ
, FALSE
}
434 static const char *relops
[] = { "RELOP_LT", "RELOP_LE", "RELOP_GT", "RELOP_GE", "RELOP_EQ" };
436 static void test_FPropCompareProp(void)
438 SPropValue pvLeft
, pvRight
;
440 char lbuffa
[2], rbuffa
[2];
441 WCHAR lbuffw
[2], rbuffw
[2];
445 if (!pFPropCompareProp
)
447 win_skip("FPropCompareProp is not available\n");
456 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
458 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= ptTypes
[i
];
460 for (j
= 0; j
< sizeof(FPCProp_Results
)/sizeof(FPCProp_Results
[0]); j
++)
462 SHORT lVal
= FPCProp_Results
[j
].lVal
;
463 SHORT rVal
= FPCProp_Results
[j
].rVal
;
465 bExp
= FPCProp_Results
[j
].bRet
;
470 /* Boolean values have no concept of less or greater than, only equality */
471 if ((lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_LT
) ||
472 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_LE
)||
473 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_GT
)||
474 (lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_GE
)||
475 (lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_EQ
)||
476 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_EQ
))
478 /* Fall through ... */
480 pvLeft
.Value
.i
= lVal
;
481 pvRight
.Value
.i
= rVal
;
485 pvLeft
.Value
.l
= lVal
;
486 pvRight
.Value
.l
= rVal
;
489 pvLeft
.Value
.flt
= lVal
;
490 pvRight
.Value
.flt
= rVal
;
494 pvLeft
.Value
.dbl
= lVal
;
495 pvRight
.Value
.dbl
= rVal
;
498 pvLeft
.Value
.cur
.int64
= lVal
;
499 pvRight
.Value
.cur
.int64
= rVal
;
502 pvLeft
.Value
.ft
.dwLowDateTime
= lVal
;
503 pvLeft
.Value
.ft
.dwHighDateTime
= 0;
504 pvRight
.Value
.ft
.dwLowDateTime
= rVal
;
505 pvRight
.Value
.ft
.dwHighDateTime
= 0;
508 pvLeft
.Value
.li
.u
.LowPart
= lVal
;
509 pvLeft
.Value
.li
.u
.HighPart
= 0;
510 pvRight
.Value
.li
.u
.LowPart
= rVal
;
511 pvRight
.Value
.li
.u
.HighPart
= 0;
514 memset(&lguid
, 0, sizeof(GUID
));
515 memset(&rguid
, 0, sizeof(GUID
));
516 lguid
.Data4
[7] = lVal
;
517 rguid
.Data4
[7] = rVal
;
518 pvLeft
.Value
.lpguid
= &lguid
;
519 pvRight
.Value
.lpguid
= &rguid
;
522 pvLeft
.Value
.lpszA
= lbuffa
;
523 pvRight
.Value
.lpszA
= rbuffa
;
524 lbuffa
[0] = '0' + lVal
;
525 rbuffa
[0] = '0' + rVal
;
528 pvLeft
.Value
.lpszW
= lbuffw
;
529 pvRight
.Value
.lpszW
= rbuffw
;
530 lbuffw
[0] = '0' + lVal
;
531 rbuffw
[0] = '0' + rVal
;
534 pvLeft
.Value
.bin
.cb
= 1;
535 pvRight
.Value
.bin
.cb
= 1;
536 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)lbuffa
;
537 pvRight
.Value
.bin
.lpb
= (LPBYTE
)rbuffa
;
543 bRet
= pFPropCompareProp(&pvLeft
, FPCProp_Results
[j
].relOp
, &pvRight
);
545 "pt %d (%d,%d,%s): expected %d, got %d\n", ptTypes
[i
],
546 FPCProp_Results
[j
].lVal
, FPCProp_Results
[j
].rVal
,
547 relops
[FPCProp_Results
[j
].relOp
], bExp
, bRet
);
552 typedef struct tagLPropCompareProp_Result
557 } LPropCompareProp_Result
;
559 static const LPropCompareProp_Result LPCProp_Results
[] =
566 static void test_LPropCompareProp(void)
568 SPropValue pvLeft
, pvRight
;
570 char lbuffa
[2], rbuffa
[2];
571 WCHAR lbuffw
[2], rbuffw
[2];
575 if (!pLPropCompareProp
)
577 win_skip("LPropCompareProp is not available\n");
586 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
588 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= ptTypes
[i
];
590 for (j
= 0; j
< sizeof(LPCProp_Results
)/sizeof(LPCProp_Results
[0]); j
++)
592 SHORT lVal
= LPCProp_Results
[j
].lVal
;
593 SHORT rVal
= LPCProp_Results
[j
].rVal
;
595 iExp
= LPCProp_Results
[j
].iRet
;
600 /* Boolean values have no concept of less or greater than, only equality */
603 /* Fall through ... */
605 pvLeft
.Value
.i
= lVal
;
606 pvRight
.Value
.i
= rVal
;
610 pvLeft
.Value
.l
= lVal
;
611 pvRight
.Value
.l
= rVal
;
614 pvLeft
.Value
.flt
= lVal
;
615 pvRight
.Value
.flt
= rVal
;
619 pvLeft
.Value
.dbl
= lVal
;
620 pvRight
.Value
.dbl
= rVal
;
623 pvLeft
.Value
.cur
.int64
= lVal
;
624 pvRight
.Value
.cur
.int64
= rVal
;
627 pvLeft
.Value
.ft
.dwLowDateTime
= lVal
;
628 pvLeft
.Value
.ft
.dwHighDateTime
= 0;
629 pvRight
.Value
.ft
.dwLowDateTime
= rVal
;
630 pvRight
.Value
.ft
.dwHighDateTime
= 0;
633 pvLeft
.Value
.li
.u
.LowPart
= lVal
;
634 pvLeft
.Value
.li
.u
.HighPart
= 0;
635 pvRight
.Value
.li
.u
.LowPart
= rVal
;
636 pvRight
.Value
.li
.u
.HighPart
= 0;
639 memset(&lguid
, 0, sizeof(GUID
));
640 memset(&rguid
, 0, sizeof(GUID
));
641 lguid
.Data4
[7] = lVal
;
642 rguid
.Data4
[7] = rVal
;
643 pvLeft
.Value
.lpguid
= &lguid
;
644 pvRight
.Value
.lpguid
= &rguid
;
647 pvLeft
.Value
.lpszA
= lbuffa
;
648 pvRight
.Value
.lpszA
= rbuffa
;
649 lbuffa
[0] = '0' + lVal
;
650 rbuffa
[0] = '0' + rVal
;
653 pvLeft
.Value
.lpszW
= lbuffw
;
654 pvRight
.Value
.lpszW
= rbuffw
;
655 lbuffw
[0] = '0' + lVal
;
656 rbuffw
[0] = '0' + rVal
;
659 pvLeft
.Value
.bin
.cb
= 1;
660 pvRight
.Value
.bin
.cb
= 1;
661 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)lbuffa
;
662 pvRight
.Value
.bin
.lpb
= (LPBYTE
)rbuffa
;
668 iRet
= pLPropCompareProp(&pvLeft
, &pvRight
);
670 "pt %d (%d,%d): expected %d, got %d\n", ptTypes
[i
],
671 LPCProp_Results
[j
].lVal
, LPCProp_Results
[j
].rVal
, iExp
, iRet
);
676 static void test_PpropFindProp(void)
678 SPropValue pvProp
, *pRet
;
683 win_skip("PpropFindProp is not available\n");
687 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
689 pvProp
.ulPropTag
= ptTypes
[i
];
691 pRet
= pPpropFindProp(&pvProp
, 1u, ptTypes
[i
]);
693 "PpropFindProp[%d]: Didn't find existing property\n",
696 pRet
= pPpropFindProp(&pvProp
, 1u, i
? ptTypes
[i
-1] : ptTypes
[i
+1]);
697 ok(pRet
== NULL
, "PpropFindProp[%d]: Found nonexistent property\n",
701 pvProp
.ulPropTag
= PROP_TAG(PT_I2
, 1u);
702 pRet
= pPpropFindProp(&pvProp
, 1u, PROP_TAG(PT_UNSPECIFIED
, 0u));
703 ok(pRet
== NULL
, "PpropFindProp[UNSPECIFIED]: Matched on different id\n");
704 pRet
= pPpropFindProp(&pvProp
, 1u, PROP_TAG(PT_UNSPECIFIED
, 1u));
705 ok(pRet
== &pvProp
, "PpropFindProp[UNSPECIFIED]: Didn't match id\n");
708 static void test_ScCountProps(void)
710 static char szHiA
[] = "Hi!";
711 static WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
712 static const ULONG ULHILEN
= 4; /* chars in szHiA/W incl. NUL */
716 GUID iids
[4], *iid
= iids
;
718 ULONG pt
, exp
, ulRet
;
723 win_skip("ScCountProps is not available\n");
727 for (pt
= 0; pt
< PROP_ID_INVALID
&& success
; pt
++)
731 memset(&pv
, 0 ,sizeof(pv
));
732 pv
.ulPropTag
= PROP_TAG(pt
, 1u);
734 switch (PROP_TYPE(pt
))
750 pv
.Value
.lpguid
= iid
;
751 exp
= sizeof(GUID
) + sizeof(pv
);
754 pv
.Value
.lpszA
= szHiA
;
755 exp
= 4 + sizeof(pv
);
758 pv
.Value
.lpszW
= szHiW
;
759 exp
= 4 * sizeof(WCHAR
) + sizeof(pv
);
763 pv
.Value
.bin
.lpb
= (LPBYTE
)iid
;
764 exp
= 2 + sizeof(pv
);
767 pv
.Value
.MVi
.cValues
= 3;
768 pv
.Value
.MVi
.lpi
= (SHORT
*)iid
;
769 exp
= 3 * sizeof(SHORT
) + sizeof(pv
);
772 pv
.Value
.MVl
.cValues
= 3;
773 pv
.Value
.MVl
.lpl
= (LONG
*)iid
;
774 exp
= 3 * sizeof(LONG
) + sizeof(pv
);
777 pv
.Value
.MVli
.cValues
= 3;
778 pv
.Value
.MVli
.lpli
= (LARGE_INTEGER
*)iid
;
779 exp
= 3 * sizeof(LARGE_INTEGER
) + sizeof(pv
);
782 pv
.Value
.MVflt
.cValues
= 3;
783 pv
.Value
.MVflt
.lpflt
= (float*)iid
;
784 exp
= 3 * sizeof(float) + sizeof(pv
);
788 pv
.Value
.MVdbl
.cValues
= 3;
789 pv
.Value
.MVdbl
.lpdbl
= (double*)iid
;
790 exp
= 3 * sizeof(double) + sizeof(pv
);
793 pv
.Value
.MVcur
.cValues
= 3;
794 pv
.Value
.MVcur
.lpcur
= (CY
*)iid
;
795 exp
= 3 * sizeof(CY
) + sizeof(pv
);
798 pv
.Value
.MVft
.cValues
= 3;
799 pv
.Value
.MVft
.lpft
= (FILETIME
*)iid
;
800 exp
= 3 * sizeof(CY
) + sizeof(pv
);
803 pv
.Value
.MVszA
.cValues
= 3;
804 pv
.Value
.MVszA
.lppszA
= buffa
;
808 exp
= ULHILEN
* 3 + 3 * sizeof(char*) + sizeof(pv
);
811 pv
.Value
.MVszW
.cValues
= 3;
812 pv
.Value
.MVszW
.lppszW
= buffw
;
816 exp
= ULHILEN
* 3 * sizeof(WCHAR
) + 3 * sizeof(WCHAR
*) + sizeof(pv
);
819 pv
.Value
.MVbin
.cValues
= 3;
820 pv
.Value
.MVbin
.lpbin
= buffbin
;
822 buffbin
[0].lpb
= (LPBYTE
)&iid
;
824 buffbin
[1].lpb
= (LPBYTE
)&iid
;
826 buffbin
[2].lpb
= (LPBYTE
)&iid
;
827 exp
= 20 + sizeof(pv
) + sizeof(SBinary
) * 3;
834 res
= pScCountProps(1, &pv
, &ulRet
);
836 success
= res
== MAPI_E_INVALID_PARAMETER
&& ulRet
== 0xffffffff;
837 ok(success
, "pt= %d: Expected failure, got %d, ret=0x%08X\n",
841 success
= res
== S_OK
&& ulRet
== exp
;
842 ok(success
, "pt= %d: Expected %d, got %d, ret=0x%08X\n",
843 pt
, exp
, ulRet
, res
);
849 static void test_ScCopyRelocProps(void)
851 static char szTestA
[] = "Test";
852 char buffer
[512], buffer2
[512], *lppszA
[1];
853 SPropValue pvProp
, *lpResProp
= (LPSPropValue
)buffer
;
857 if (!pScCopyProps
|| !pScRelocProps
)
859 win_skip("SPropValue copy functions are not available\n");
863 pvProp
.ulPropTag
= PROP_TAG(PT_MV_STRING8
, 1u);
866 pvProp
.Value
.MVszA
.cValues
= 1;
867 pvProp
.Value
.MVszA
.lppszA
= lppszA
;
870 sc
= pScCopyProps(1, &pvProp
, buffer
, &ulCount
);
871 ok(sc
== S_OK
, "wrong ret %d\n", sc
);
874 ok(lpResProp
->ulPropTag
== pvProp
.ulPropTag
, "wrong tag %x\n",lpResProp
->ulPropTag
);
875 ok(lpResProp
->Value
.MVszA
.cValues
== 1, "wrong cValues %d\n", lpResProp
->Value
.MVszA
.cValues
);
876 ok(lpResProp
->Value
.MVszA
.lppszA
[0] == buffer
+ sizeof(SPropValue
) + sizeof(char*),
877 "wrong lppszA[0] %p\n",lpResProp
->Value
.MVszA
.lppszA
[0]);
878 ok(ulCount
== sizeof(SPropValue
) + sizeof(char*) + 5, "wrong count %d\n", ulCount
);
879 ok(!strcmp(lpResProp
->Value
.MVszA
.lppszA
[0], szTestA
),
880 "wrong string '%s'\n", lpResProp
->Value
.MVszA
.lppszA
[0]);
883 memcpy(buffer2
, buffer
, sizeof(buffer
));
885 /* Clear the data in the source buffer. Since pointers in the copied buffer
886 * refer to the source buffer, this proves that native always assumes that
887 * the copied buffers pointers are bad (needing to be relocated first).
889 memset(buffer
, 0, sizeof(buffer
));
892 sc
= pScRelocProps(1, (LPSPropValue
)buffer2
, buffer
, buffer2
, &ulCount
);
893 lpResProp
= (LPSPropValue
)buffer2
;
895 ok(sc
== S_OK
, "wrong ret %d\n", sc
);
898 ok(lpResProp
->ulPropTag
== pvProp
.ulPropTag
, "wrong tag %x\n",lpResProp
->ulPropTag
);
899 ok(lpResProp
->Value
.MVszA
.cValues
== 1, "wrong cValues %d\n", lpResProp
->Value
.MVszA
.cValues
);
900 ok(lpResProp
->Value
.MVszA
.lppszA
[0] == buffer2
+ sizeof(SPropValue
) + sizeof(char*),
901 "wrong lppszA[0] %p\n",lpResProp
->Value
.MVszA
.lppszA
[0]);
902 /* Native has a bug whereby it calculates the size correctly when copying
903 * but when relocating does not (presumably it uses UlPropSize() which
904 * ignores multivalue pointers). Wine returns the correct value.
906 ok(ulCount
== sizeof(SPropValue
) + sizeof(char*) + 5 || ulCount
== sizeof(SPropValue
) + 5,
907 "wrong count %d\n", ulCount
);
908 ok(!strcmp(lpResProp
->Value
.MVszA
.lppszA
[0], szTestA
),
909 "wrong string '%s'\n", lpResProp
->Value
.MVszA
.lppszA
[0]);
912 /* Native crashes with lpNew or lpOld set to NULL so skip testing this */
915 static void test_LpValFindProp(void)
917 SPropValue pvProp
, *pRet
;
922 win_skip("LpValFindProp is not available\n");
926 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
928 pvProp
.ulPropTag
= PROP_TAG(ptTypes
[i
], 1u);
930 pRet
= pLpValFindProp(PROP_TAG(ptTypes
[i
], 1u), 1u, &pvProp
);
932 "LpValFindProp[%d]: Didn't find existing property id/type\n",
935 pRet
= pLpValFindProp(PROP_TAG(ptTypes
[i
], 0u), 1u, &pvProp
);
936 ok(pRet
== NULL
, "LpValFindProp[%d]: Found nonexistent property id\n",
939 pRet
= pLpValFindProp(PROP_TAG(PT_NULL
, 0u), 1u, &pvProp
);
940 ok(pRet
== NULL
, "LpValFindProp[%d]: Found nonexistent property id/type\n",
943 pRet
= pLpValFindProp(PROP_TAG(PT_NULL
, 1u), 1u, &pvProp
);
945 "LpValFindProp[%d]: Didn't find existing property id\n",
950 static void test_FBadRglpszA(void)
953 static CHAR szString
[] = "A String";
958 win_skip("FBadRglpszA is not available\n");
962 bRet
= pFBadRglpszA(NULL
, 10);
963 ok(bRet
== TRUE
, "FBadRglpszA(Null): expected TRUE, got FALSE\n");
965 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = lpStrs
[3] = NULL
;
966 bRet
= pFBadRglpszA(lpStrs
, 4);
967 ok(bRet
== TRUE
, "FBadRglpszA(Nulls): expected TRUE, got FALSE\n");
969 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = szString
;
970 bRet
= pFBadRglpszA(lpStrs
, 3);
971 ok(bRet
== FALSE
, "FBadRglpszA(valid): expected FALSE, got TRUE\n");
973 bRet
= pFBadRglpszA(lpStrs
, 4);
974 ok(bRet
== TRUE
, "FBadRglpszA(1 invalid): expected TRUE, got FALSE\n");
977 static void test_FBadRglpszW(void)
980 static WCHAR szString
[] = { 'A',' ','S','t','r','i','n','g','\0' };
985 win_skip("FBadRglpszW is not available\n");
989 bRet
= pFBadRglpszW(NULL
, 10);
990 ok(bRet
== TRUE
, "FBadRglpszW(Null): expected TRUE, got FALSE\n");
992 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = lpStrs
[3] = NULL
;
993 bRet
= pFBadRglpszW(lpStrs
, 4);
994 ok(bRet
== TRUE
, "FBadRglpszW(Nulls): expected TRUE, got FALSE\n");
996 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = szString
;
997 bRet
= pFBadRglpszW(lpStrs
, 3);
998 ok(bRet
== FALSE
, "FBadRglpszW(valid): expected FALSE, got TRUE\n");
1000 bRet
= pFBadRglpszW(lpStrs
, 4);
1001 ok(bRet
== TRUE
, "FBadRglpszW(1 invalid): expected TRUE, got FALSE\n");
1004 static void test_FBadRowSet(void)
1010 win_skip("FBadRowSet is not available\n");
1014 ulRet
= pFBadRowSet(NULL
);
1015 ok(ulRet
!= 0, "FBadRow(null): Expected non-zero, got 0\n");
1020 static void test_FBadPropTag(void)
1026 win_skip("FBadPropTag is not available\n");
1030 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1034 switch (pt
& (~MV_FLAG
& PROP_TYPE_MASK
))
1036 case PT_UNSPECIFIED
:
1037 case PT_NULL
: case PT_I2
: case PT_I4
: case PT_R4
:
1038 case PT_R8
: case PT_CURRENCY
: case PT_APPTIME
:
1039 case PT_ERROR
: case PT_BOOLEAN
: case PT_OBJECT
:
1040 case PT_I8
: case PT_STRING8
: case PT_UNICODE
:
1041 case PT_SYSTIME
: case PT_CLSID
: case PT_BINARY
:
1045 res
= pFBadPropTag(pt
);
1047 ok(res
!= 0, "pt= %d: Expected non-zero, got 0\n", pt
);
1050 "pt= %d: Expected zero, got %d\n", pt
, res
);
1054 static void test_FBadRow(void)
1060 win_skip("FBadRow is not available\n");
1064 ulRet
= pFBadRow(NULL
);
1065 ok(ulRet
!= 0, "FBadRow(null): Expected non-zero, got 0\n");
1070 static void test_FBadProp(void)
1072 static WCHAR szEmpty
[] = { '\0' };
1079 win_skip("FBadProp is not available\n");
1083 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1087 memset(&pv
, 0, sizeof(pv
));
1090 /* Note that MV values are valid below because their array count is 0,
1091 * so no pointers are validated.
1093 switch (PROP_TYPE(pt
))
1095 case (MV_FLAG
|PT_UNSPECIFIED
):
1096 case PT_UNSPECIFIED
:
1097 case (MV_FLAG
|PT_NULL
):
1109 case PT_MV_CURRENCY
:
1113 case (MV_FLAG
|PT_ERROR
):
1115 case (MV_FLAG
|PT_BOOLEAN
):
1117 case (MV_FLAG
|PT_OBJECT
):
1130 pv
.Value
.lpszW
= szEmpty
;
1134 pv
.Value
.lpguid
= &iid
;
1139 res
= pFBadProp(&pv
);
1141 ok(res
!= 0, "pt= %d: Expected non-zero, got 0\n", pt
);
1144 "pt= %d: Expected zero, got %d\n", pt
, res
);
1148 static void test_FBadColumnSet(void)
1153 if (!pFBadColumnSet
)
1155 win_skip("FBadColumnSet is not available\n");
1159 res
= pFBadColumnSet(NULL
);
1160 ok(res
!= 0, "(null): Expected non-zero, got 0\n");
1164 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1168 pta
.aulPropTag
[0] = pt
;
1170 switch (pt
& (~MV_FLAG
& PROP_TYPE_MASK
))
1172 case PT_UNSPECIFIED
:
1190 if (pt
== (MV_FLAG
|PT_ERROR
))
1193 res
= pFBadColumnSet(&pta
);
1195 ok(res
!= 0, "pt= %d: Expected non-zero, got 0\n", pt
);
1198 "pt= %d: Expected zero, got %d\n", pt
, res
);
1203 static void test_IProp(void)
1206 LPMAPIERROR lpError
;
1207 LPSPropProblemArray lpProbs
;
1208 LPSPropValue lpProps
;
1209 LPSPropTagArray lpTags
;
1211 SizedSPropTagArray(2,tags
);
1212 ULONG access
[2], count
;
1217 win_skip("CreateIProp is not available\n");
1221 memset(&tags
, 0 , sizeof(tags
));
1223 /* Create the object */
1225 sc
= pCreateIProp(&IID_IMAPIPropData
, (ALLOCATEBUFFER
*)pMAPIAllocateBuffer
, (ALLOCATEMORE
*)pMAPIAllocateMore
,
1226 (FREEBUFFER
*)pMAPIFreeBuffer
, NULL
, &lpIProp
);
1227 ok(sc
== S_OK
&& lpIProp
,
1228 "CreateIProp: expected S_OK, non-null, got 0x%08X,%p\n", sc
, lpIProp
);
1230 if (sc
!= S_OK
|| !lpIProp
)
1233 /* GetLastError - No errors set */
1235 sc
= IPropData_GetLastError(lpIProp
, E_INVALIDARG
, 0, &lpError
);
1236 ok(sc
== S_OK
&& !lpError
,
1237 "GetLastError: Expected S_OK, null, got 0x%08X,%p\n", sc
, lpError
);
1239 /* Get prop tags - succeeds returning 0 items */
1241 sc
= IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1242 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 0,
1243 "GetPropList(empty): Expected S_OK, non-null, 0, got 0x%08X,%p,%d\n",
1244 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1246 pMAPIFreeBuffer(lpTags
);
1248 /* Get props - succeeds returning 0 items */
1252 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1253 sc
= IPropData_GetProps(lpIProp
, (LPSPropTagArray
)&tags
, 0, &count
, &lpProps
);
1254 ok(sc
== MAPI_W_ERRORS_RETURNED
&& lpProps
&& count
== 1,
1255 "GetProps(empty): Expected ERRORS_RETURNED, non-null, 1, got 0x%08X,%p,%d\n",
1256 sc
, lpProps
, count
);
1257 if (lpProps
&& count
> 0)
1259 ok(lpProps
[0].ulPropTag
== CHANGE_PROP_TYPE(PR_IMPORTANCE
,PT_ERROR
),
1260 "GetProps(empty): Expected %x, got %x\n",
1261 CHANGE_PROP_TYPE(PR_IMPORTANCE
,PT_ERROR
), lpProps
[0].ulPropTag
);
1263 pMAPIFreeBuffer(lpProps
);
1266 /* Add (NULL) - Can't add NULLs */
1268 pvs
[0].ulPropTag
= PROP_TAG(PT_NULL
,0x01);
1269 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1270 ok(sc
== MAPI_E_INVALID_PARAMETER
&& !lpProbs
,
1271 "SetProps(): Expected INVALID_PARAMETER, null, got 0x%08X,%p\n",
1274 /* Add (OBJECT) - Can't add OBJECTs */
1276 pvs
[0].ulPropTag
= PROP_TAG(PT_OBJECT
,0x01);
1277 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1278 ok(sc
== MAPI_E_INVALID_PARAMETER
&& !lpProbs
,
1279 "SetProps(OBJECT): Expected INVALID_PARAMETER, null, got 0x%08X,%p\n",
1282 /* Add - Adds value */
1284 pvs
[0].ulPropTag
= PR_IMPORTANCE
;
1285 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1286 ok(sc
== S_OK
&& !lpProbs
,
1287 "SetProps(ERROR): Expected S_OK, null, got 0x%08X,%p\n", sc
, lpProbs
);
1289 /* Get prop list - returns 1 item */
1291 IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1292 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 1,
1293 "GetPropList: Expected S_OK, non-null, 1, got 0x%08X,%p,%d\n",
1294 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1295 if (lpTags
&& lpTags
->cValues
> 0)
1297 ok(lpTags
->aulPropTag
[0] == PR_IMPORTANCE
,
1298 "GetPropList: Expected %x, got %x\n",
1299 PR_IMPORTANCE
, lpTags
->aulPropTag
[0]);
1300 pMAPIFreeBuffer(lpTags
);
1303 /* Set access to read and write */
1304 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READWRITE
);
1305 ok(sc
== S_OK
, "SetObjAccess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1308 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1310 /* Set item access (bad access) - Fails */
1312 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1313 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1314 "SetPropAccess(0): Expected INVALID_PARAMETER got 0x%08X\n",sc
);
1315 access
[0] = IPROP_READWRITE
;
1316 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1317 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1318 "SetPropAccess(RW): Expected INVALID_PARAMETER got 0x%08X\n",sc
);
1319 access
[0] = IPROP_CLEAN
;
1320 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1321 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1322 "SetPropAccess(C): Expected INVALID_PARAMETER got 0x%08X\n",sc
);
1324 /* Set item access to read/write/clean */
1326 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1327 access
[0] = IPROP_READWRITE
|IPROP_CLEAN
;
1328 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1329 ok(sc
== S_OK
, "SetPropAccess(RW/C): Expected S_OK got 0x%08X\n",sc
);
1331 /* Set object access to read only */
1332 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READONLY
);
1333 ok(sc
== S_OK
, "SetObjAccess(READ): Expected S_OK got 0x%08X\n", sc
);
1335 /* Set item access to read/write/dirty - doesn't care about RO object */
1336 access
[0] = IPROP_READONLY
|IPROP_DIRTY
;
1337 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1338 ok(sc
== S_OK
, "SetPropAccess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1340 /* Delete any item when set to read only - Error */
1342 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1343 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1344 ok(sc
== E_ACCESSDENIED
&& !lpProbs
,
1345 "DeleteProps(nonexistent): Expected E_ACCESSDENIED null got 0x%08X %p\n",
1348 /* Set access to read and write */
1349 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READWRITE
);
1350 ok(sc
== S_OK
, "SetObjAccess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1352 /* Delete nonexistent item - No error */
1354 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1355 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1356 ok(sc
== S_OK
&& !lpProbs
,
1357 "DeleteProps(nonexistent): Expected S_OK null got 0x%08X %p\n",
1360 /* Delete existing item (r/o) - No error, but lpProbs populated */
1362 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1363 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1364 ok(sc
== S_OK
&& lpProbs
,
1365 "DeleteProps(RO): Expected S_OK non-null got 0x%08X %p\n", sc
, lpProbs
);
1367 if (lpProbs
&& lpProbs
->cProblem
> 0)
1369 ok(lpProbs
->cProblem
== 1 &&
1370 lpProbs
->aProblem
[0].ulIndex
== 0 &&
1371 lpProbs
->aProblem
[0].ulPropTag
== PR_IMPORTANCE
&&
1372 lpProbs
->aProblem
[0].scode
== E_ACCESSDENIED
,
1373 "DeleteProps(RO): Expected (1,0,%x,%x) got (%d,%x,%x)\n",
1374 PR_IMPORTANCE
, E_ACCESSDENIED
,
1375 lpProbs
->aProblem
[0].ulIndex
, lpProbs
->aProblem
[0].ulPropTag
,
1376 lpProbs
->aProblem
[0].scode
);
1377 pMAPIFreeBuffer(lpProbs
);
1382 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1383 IPropData_HrAddObjProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1384 ok(sc
== S_OK
&& !lpProbs
,
1385 "AddObjProps(RO): Expected S_OK null got 0x%08X %p\n", sc
, lpProbs
);
1387 /* Get prop list - returns 1 item */
1389 IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1390 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 1,
1391 "GetPropList: Expected S_OK, non-null, 1, got 0x%08X,%p,%d\n",
1392 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1393 if (lpTags
&& lpTags
->cValues
> 0)
1395 ok(lpTags
->aulPropTag
[0] == PR_IMPORTANCE
,
1396 "GetPropList: Expected %x, got %x\n",
1397 PR_IMPORTANCE
, lpTags
->aulPropTag
[0]);
1398 pMAPIFreeBuffer(lpTags
);
1401 /* Set item to r/w again */
1402 access
[0] = IPROP_READWRITE
|IPROP_DIRTY
;
1403 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1404 ok(sc
== S_OK
, "SetPropAccess(WRITE): Expected S_OK got 0x%08X\n", sc
);
1406 /* Delete existing item (r/w) - No error, no problems */
1408 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1409 ok(sc
== S_OK
&& !lpProbs
,
1410 "DeleteProps(RO): Expected S_OK null got 0x%08X %p\n", sc
, lpProbs
);
1413 IPropData_Release(lpIProp
);
1420 if (!HaveDefaultMailClient())
1422 win_skip("No default mail client installed\n");
1428 win_skip("Needed functions are not available\n");
1432 SetLastError(0xdeadbeef);
1433 ret
= pScInitMapiUtil(0);
1434 if ((ret
!= S_OK
) && (GetLastError() == ERROR_PROC_NOT_FOUND
))
1436 win_skip("ScInitMapiUtil is not implemented\n");
1437 FreeLibrary(hMapi32
);
1440 else if ((ret
== E_FAIL
) && (GetLastError() == ERROR_INVALID_HANDLE
))
1442 win_skip("ScInitMapiUtil doesn't work on some Win98 and WinME systems\n");
1443 FreeLibrary(hMapi32
);
1447 test_PropCopyMore();
1450 /* We call MAPIInitialize here for the benefit of native extended MAPI
1451 * providers which crash in the FPropContainsProp tests when MAPIInitialize
1452 * has not been called. Since MAPIInitialize is irrelevant for FPropContainsProp
1453 * on Wine, we do not care whether MAPIInitialize succeeds. */
1454 if (pMAPIInitialize
)
1455 ret
= pMAPIInitialize(NULL
);
1456 test_FPropContainsProp();
1457 if (pMAPIUninitialize
&& ret
== S_OK
)
1458 pMAPIUninitialize();
1460 test_FPropCompareProp();
1461 test_LPropCompareProp();
1462 test_PpropFindProp();
1463 test_ScCountProps();
1464 test_ScCopyRelocProps();
1465 test_LpValFindProp();
1472 test_FBadColumnSet();
1477 FreeLibrary(hMapi32
);