2 * Unit test suite for MAPI property functions
4 * Copyright 2004 Jon Griffiths
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define NONAMELESSUNION
22 #define NONAMELESSSTRUCT
23 #include "wine/test.h"
32 HRESULT WINAPI
MAPIInitialize(LPVOID
);
34 static HMODULE hMapi32
= 0;
36 static SCODE (WINAPI
*pScInitMapiUtil
)(ULONG
);
37 static SCODE (WINAPI
*pPropCopyMore
)(LPSPropValue
,LPSPropValue
,ALLOCATEMORE
*,LPVOID
);
38 static ULONG (WINAPI
*pUlPropSize
)(LPSPropValue
);
39 static BOOL (WINAPI
*pFPropContainsProp
)(LPSPropValue
,LPSPropValue
,ULONG
);
40 static BOOL (WINAPI
*pFPropCompareProp
)(LPSPropValue
,ULONG
,LPSPropValue
);
41 static LONG (WINAPI
*pLPropCompareProp
)(LPSPropValue
,LPSPropValue
);
42 static LPSPropValue (WINAPI
*pPpropFindProp
)(LPSPropValue
,ULONG
,ULONG
);
43 static SCODE (WINAPI
*pScCountProps
)(INT
,LPSPropValue
,ULONG
*);
44 static SCODE (WINAPI
*pScCopyProps
)(int,LPSPropValue
,LPVOID
,ULONG
*);
45 static SCODE (WINAPI
*pScRelocProps
)(int,LPSPropValue
,LPVOID
,LPVOID
,ULONG
*);
46 static LPSPropValue (WINAPI
*pLpValFindProp
)(ULONG
,ULONG
,LPSPropValue
);
47 static BOOL (WINAPI
*pFBadRglpszA
)(LPSTR
*,ULONG
);
48 static BOOL (WINAPI
*pFBadRglpszW
)(LPWSTR
*,ULONG
);
49 static BOOL (WINAPI
*pFBadRowSet
)(LPSRowSet
);
50 static ULONG (WINAPI
*pFBadPropTag
)(ULONG
);
51 static ULONG (WINAPI
*pFBadRow
)(LPSRow
);
52 static ULONG (WINAPI
*pFBadProp
)(LPSPropValue
);
53 static ULONG (WINAPI
*pFBadColumnSet
)(LPSPropTagArray
);
54 static SCODE (WINAPI
*pCreateIProp
)(LPCIID
,ALLOCATEBUFFER
*,ALLOCATEMORE
*,
55 FREEBUFFER
*,LPVOID
,LPPROPDATA
*);
57 static ULONG ptTypes
[] = {
58 PT_I2
, PT_I4
, PT_R4
, PT_R8
, PT_CURRENCY
, PT_APPTIME
, PT_SYSTIME
,
59 PT_ERROR
, PT_BOOLEAN
, PT_I8
, PT_CLSID
, PT_STRING8
, PT_BINARY
,
63 static inline int strcmpW(const WCHAR
*str1
, const WCHAR
*str2
)
65 while (*str1
&& (*str1
== *str2
)) { str1
++; str2
++; }
69 static void test_PropCopyMore(void)
71 static const char *szHiA
= "Hi!";
72 static const WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
73 SPropValue
*lpDest
= NULL
, *lpSrc
= NULL
;
77 pPropCopyMore
= (void*)GetProcAddress(hMapi32
, "PropCopyMore@16");
82 scode
= MAPIAllocateBuffer(sizeof(LPSPropValue
), (LPVOID
*)lpDest
);
86 scode
= MAPIAllocateMore(sizeof(LPSPropValue
), lpDest
, (LPVOID
*)lpSrc
);
90 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
92 lpSrc
->ulPropTag
= ptTypes
[i
];
97 lpSrc
->Value
.lpszA
= (char*)szHiA
;
100 lpSrc
->Value
.lpszW
= (WCHAR
*)szHiW
;
103 lpSrc
->Value
.bin
.cb
= 4;
104 lpSrc
->Value
.bin
.lpb
= (LPBYTE
)szHiA
;
108 memset(lpDest
, 0xff, sizeof(SPropValue
));
110 scode
= pPropCopyMore(lpDest
, lpSrc
, MAPIAllocateMore
, lpDest
);
111 ok(!scode
&& lpDest
->ulPropTag
== lpSrc
->ulPropTag
,
112 "PropCopyMore: Expected 0x0,%ld, got 0x%08lx,%ld\n",
113 lpSrc
->ulPropTag
, scode
, lpDest
->ulPropTag
);
114 if (SUCCEEDED(scode
))
119 ok(lstrcmpA(lpDest
->Value
.lpszA
, lpSrc
->Value
.lpszA
) == 0,
120 "PropCopyMore: Ascii string differs\n");
123 ok(strcmpW(lpDest
->Value
.lpszW
, lpSrc
->Value
.lpszW
) == 0,
124 "PropCopyMore: Unicode string differs\n");
127 ok(lpDest
->Value
.bin
.cb
== 4 &&
128 !memcmp(lpSrc
->Value
.bin
.lpb
, lpDest
->Value
.bin
.lpb
, 4),
129 "PropCopyMore: Binary array differs\n");
135 /* Since all allocations are linked, freeing lpDest frees everything */
136 MAPIFreeBuffer(lpDest
);
139 static void test_UlPropSize(void)
141 static const char *szHiA
= "Hi!";
142 static const WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
148 pUlPropSize
= (void*)GetProcAddress(hMapi32
, "UlPropSize@4");
153 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
157 memset(&pv
, 0 ,sizeof(pv
));
160 exp
= 1u; /* Default to one item for non-MV properties */
162 switch (PROP_TYPE(pt
))
164 case PT_MV_I2
: pv
.Value
.MVi
.cValues
= exp
= 2;
165 case PT_I2
: exp
*= sizeof(USHORT
); break;
166 case PT_MV_I4
: pv
.Value
.MVl
.cValues
= exp
= 2;
167 case PT_I4
: exp
*= sizeof(LONG
); break;
168 case PT_MV_R4
: pv
.Value
.MVflt
.cValues
= exp
= 2;
169 case PT_R4
: exp
*= sizeof(float); break;
170 case PT_MV_DOUBLE
: pv
.Value
.MVdbl
.cValues
= exp
= 2;
171 case PT_R8
: exp
*= sizeof(double); break;
172 case PT_MV_CURRENCY
: pv
.Value
.MVcur
.cValues
= exp
= 2;
173 case PT_CURRENCY
: exp
*= sizeof(CY
); break;
174 case PT_MV_APPTIME
: pv
.Value
.MVat
.cValues
= exp
= 2;
175 case PT_APPTIME
: exp
*= sizeof(double); break;
176 case PT_MV_SYSTIME
: pv
.Value
.MVft
.cValues
= exp
= 2;
177 case PT_SYSTIME
: exp
*= sizeof(FILETIME
); break;
178 case PT_ERROR
: exp
= sizeof(SCODE
); break;
179 case PT_BOOLEAN
: exp
= sizeof(USHORT
); break;
180 case PT_OBJECT
: exp
= 0; break;
181 case PT_MV_I8
: pv
.Value
.MVli
.cValues
= exp
= 2;
182 case PT_I8
: exp
*= sizeof(LONG64
); break;
184 /* My version of native mapi returns 0 for PT_MV_CLSID even if a valid
185 * array is given. This _has_ to be a bug, so Wine does
186 * the right thing(tm) and we don't test it here.
188 case PT_MV_CLSID
: pv
.Value
.MVguid
.cValues
= exp
= 2;
190 case PT_CLSID
: exp
*= sizeof(GUID
); break;
192 pv
.Value
.lpszA
= (LPSTR
)szHiA
;
196 pv
.Value
.lpszW
= (LPWSTR
)szHiW
;
197 exp
= 4 * sizeof(WCHAR
);
200 pv
.Value
.bin
.cb
= exp
= 19;
203 pv
.Value
.MVszA
.cValues
= 2;
204 pv
.Value
.MVszA
.lppszA
= buffa
;
205 buffa
[0] = (LPSTR
)szHiA
;
206 buffa
[1] = (LPSTR
)szHiA
;
210 pv
.Value
.MVszW
.cValues
= 2;
211 pv
.Value
.MVszW
.lppszW
= buffw
;
212 buffw
[0] = (LPWSTR
)szHiW
;
213 buffw
[1] = (LPWSTR
)szHiW
;
214 exp
= 8 * sizeof(WCHAR
);
217 pv
.Value
.MVbin
.cValues
= 2;
218 pv
.Value
.MVbin
.lpbin
= buffbin
;
227 res
= pUlPropSize(&pv
);
228 ok(res
== exp
, "pt= %ld: Expected %ld, got %ld\n", pt
, exp
, res
);
232 static void test_FPropContainsProp(void)
234 static const char *szFull
= "Full String";
235 static const char *szFullLower
= "full string";
236 static const char *szPrefix
= "Full";
237 static const char *szPrefixLower
= "full";
238 static const char *szSubstring
= "ll St";
239 static const char *szSubstringLower
= "ll st";
240 SPropValue pvLeft
, pvRight
;
244 pFPropContainsProp
= (void*)GetProcAddress(hMapi32
, "FPropContainsProp@12");
246 if (!pFPropContainsProp
)
249 /* Ensure that only PT_STRING8 and PT_BINARY are handled */
250 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
252 if (pt
== PT_STRING8
|| pt
== PT_BINARY
)
253 continue; /* test these later */
255 memset(&pvLeft
, 0 ,sizeof(pvLeft
));
256 memset(&pvRight
, 0 ,sizeof(pvRight
));
257 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= pt
;
259 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
260 ok(bRet
== FALSE
, "pt= %ld: Expected FALSE, got %d\n", pt
, bRet
);
263 /* test the various flag combinations */
264 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= PT_STRING8
;
265 pvLeft
.Value
.lpszA
= (LPSTR
)szFull
;
266 pvRight
.Value
.lpszA
= (LPSTR
)szFull
;
268 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
269 ok(bRet
== TRUE
, "(full,full)[] match failed\n");
270 pvRight
.Value
.lpszA
= (LPSTR
)szPrefix
;
271 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
272 ok(bRet
== FALSE
, "(full,prefix)[] match failed\n");
273 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
274 ok(bRet
== TRUE
, "(full,prefix)[PREFIX] match failed\n");
275 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
276 ok(bRet
== TRUE
, "(full,prefix)[SUBSTRING] match failed\n");
277 pvRight
.Value
.lpszA
= (LPSTR
)szPrefixLower
;
278 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
279 ok(bRet
== FALSE
, "(full,prefixlow)[PREFIX] match failed\n");
280 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
281 ok(bRet
== FALSE
, "(full,prefixlow)[SUBSTRING] match failed\n");
282 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
283 ok(bRet
== TRUE
, "(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
284 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
285 ok(bRet
== TRUE
, "(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
286 pvRight
.Value
.lpszA
= (LPSTR
)szSubstring
;
287 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
288 ok(bRet
== FALSE
, "(full,substr)[] match failed\n");
289 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
290 ok(bRet
== FALSE
, "(full,substr)[PREFIX] match failed\n");
291 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
292 ok(bRet
== TRUE
, "(full,substr)[SUBSTRING] match failed\n");
293 pvRight
.Value
.lpszA
= (LPSTR
)szSubstringLower
;
294 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
295 ok(bRet
== FALSE
, "(full,substrlow)[PREFIX] match failed\n");
296 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
297 ok(bRet
== FALSE
, "(full,substrlow)[SUBSTRING] match failed\n");
298 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
299 ok(bRet
== FALSE
, "(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
300 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
301 ok(bRet
== TRUE
, "(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
302 pvRight
.Value
.lpszA
= (LPSTR
)szFullLower
;
303 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
|FL_IGNORECASE
);
304 ok(bRet
== TRUE
, "(full,fulllow)[IGNORECASE] match failed\n");
306 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= PT_BINARY
;
307 pvLeft
.Value
.bin
.lpb
= (LPBYTE
)szFull
;
308 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szFull
;
309 pvLeft
.Value
.bin
.cb
= pvRight
.Value
.bin
.cb
= strlen(szFull
);
311 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
312 ok(bRet
== TRUE
, "bin(full,full)[] match failed\n");
313 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szPrefix
;
314 pvRight
.Value
.bin
.cb
= strlen(szPrefix
);
315 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
316 ok(bRet
== FALSE
, "bin(full,prefix)[] match failed\n");
317 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
318 ok(bRet
== TRUE
, "bin(full,prefix)[PREFIX] match failed\n");
319 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
320 ok(bRet
== TRUE
, "bin(full,prefix)[SUBSTRING] match failed\n");
321 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szPrefixLower
;
322 pvRight
.Value
.bin
.cb
= strlen(szPrefixLower
);
323 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
324 ok(bRet
== FALSE
, "bin(full,prefixlow)[PREFIX] match failed\n");
325 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
326 ok(bRet
== FALSE
, "bin(full,prefixlow)[SUBSTRING] match failed\n");
327 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
328 ok(bRet
== FALSE
, "bin(full,prefixlow)[PREFIX|IGNORECASE] match failed\n");
329 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
330 ok(bRet
== FALSE
, "bin(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n");
331 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szSubstring
;
332 pvRight
.Value
.bin
.cb
= strlen(szSubstring
);
333 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
);
334 ok(bRet
== FALSE
, "bin(full,substr)[] match failed\n");
335 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
336 ok(bRet
== FALSE
, "bin(full,substr)[PREFIX] match failed\n");
337 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
338 ok(bRet
== TRUE
, "bin(full,substr)[SUBSTRING] match failed\n");
339 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szSubstringLower
;
340 pvRight
.Value
.bin
.cb
= strlen(szSubstringLower
);
341 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
);
342 ok(bRet
== FALSE
, "bin(full,substrlow)[PREFIX] match failed\n");
343 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
);
344 ok(bRet
== FALSE
, "bin(full,substrlow)[SUBSTRING] match failed\n");
345 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_PREFIX
|FL_IGNORECASE
);
346 ok(bRet
== FALSE
, "bin(full,substrlow)[PREFIX|IGNORECASE] match failed\n");
347 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_SUBSTRING
|FL_IGNORECASE
);
348 ok(bRet
== FALSE
, "bin(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n");
349 pvRight
.Value
.bin
.lpb
= (LPBYTE
)szFullLower
;
350 pvRight
.Value
.bin
.cb
= strlen(szFullLower
);
351 bRet
= pFPropContainsProp(&pvLeft
, &pvRight
, FL_FULLSTRING
|FL_IGNORECASE
);
352 ok(bRet
== FALSE
, "bin(full,fulllow)[IGNORECASE] match failed\n");
355 typedef struct tagFPropCompareProp_Result
361 } FPropCompareProp_Result
;
363 static const FPropCompareProp_Result FPCProp_Results
[] =
365 { 1, 2, RELOP_LT
, TRUE
},
366 { 1, 1, RELOP_LT
, FALSE
},
367 { 2, 1, RELOP_LT
, FALSE
},
368 { 1, 2, RELOP_LE
, TRUE
},
369 { 1, 1, RELOP_LE
, TRUE
},
370 { 2, 1, RELOP_LE
, FALSE
},
371 { 1, 2, RELOP_GT
, FALSE
},
372 { 1, 1, RELOP_GT
, FALSE
},
373 { 2, 1, RELOP_GT
, TRUE
},
374 { 1, 2, RELOP_GE
, FALSE
},
375 { 1, 1, RELOP_GE
, TRUE
},
376 { 2, 1, RELOP_GE
, TRUE
},
377 { 1, 2, RELOP_EQ
, FALSE
},
378 { 1, 1, RELOP_EQ
, TRUE
},
379 { 2, 1, RELOP_EQ
, FALSE
}
382 static const char *relops
[] = { "RELOP_LT", "RELOP_LE", "RELOP_GT", "RELOP_GE", "RELOP_EQ" };
384 static void test_FPropCompareProp(void)
386 SPropValue pvLeft
, pvRight
;
388 char lbuffa
[2], rbuffa
[2];
389 WCHAR lbuffw
[2], rbuffw
[2];
393 pFPropCompareProp
= (void*)GetProcAddress(hMapi32
, "FPropCompareProp@12");
395 if (!pFPropCompareProp
)
403 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
405 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= ptTypes
[i
];
407 for (j
= 0; j
< sizeof(FPCProp_Results
)/sizeof(FPCProp_Results
[0]); j
++)
409 SHORT lVal
= FPCProp_Results
[j
].lVal
;
410 SHORT rVal
= FPCProp_Results
[j
].rVal
;
412 bExp
= FPCProp_Results
[j
].bRet
;
417 /* Boolean values have no concept of less or greater than, only equality */
418 if ((lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_LT
) ||
419 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_LE
)||
420 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_GT
)||
421 (lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_GE
)||
422 (lVal
== 1 && rVal
== 2 && FPCProp_Results
[j
].relOp
== RELOP_EQ
)||
423 (lVal
== 2 && rVal
== 1 && FPCProp_Results
[j
].relOp
== RELOP_EQ
))
425 /* Fall through ... */
427 pvLeft
.Value
.i
= lVal
;
428 pvRight
.Value
.i
= rVal
;
432 pvLeft
.Value
.l
= lVal
;
433 pvRight
.Value
.l
= rVal
;
436 pvLeft
.Value
.flt
= lVal
;
437 pvRight
.Value
.flt
= rVal
;
441 pvLeft
.Value
.dbl
= lVal
;
442 pvRight
.Value
.dbl
= rVal
;
445 pvLeft
.Value
.cur
.int64
= lVal
;
446 pvRight
.Value
.cur
.int64
= rVal
;
449 pvLeft
.Value
.ft
.dwLowDateTime
= lVal
;
450 pvLeft
.Value
.ft
.dwHighDateTime
= 0;
451 pvRight
.Value
.ft
.dwLowDateTime
= rVal
;
452 pvRight
.Value
.ft
.dwHighDateTime
= 0;
455 pvLeft
.Value
.li
.u
.LowPart
= lVal
;
456 pvLeft
.Value
.li
.u
.HighPart
= 0;
457 pvRight
.Value
.li
.u
.LowPart
= rVal
;
458 pvRight
.Value
.li
.u
.HighPart
= 0;
461 memset(&lguid
, 0, sizeof(GUID
));
462 memset(&rguid
, 0, sizeof(GUID
));
463 lguid
.Data4
[7] = lVal
;
464 rguid
.Data4
[7] = rVal
;
465 pvLeft
.Value
.lpguid
= &lguid
;
466 pvRight
.Value
.lpguid
= &rguid
;
469 pvLeft
.Value
.lpszA
= lbuffa
;
470 pvRight
.Value
.lpszA
= rbuffa
;
471 lbuffa
[0] = '0' + lVal
;
472 rbuffa
[0] = '0' + rVal
;
475 pvLeft
.Value
.lpszW
= lbuffw
;
476 pvRight
.Value
.lpszW
= rbuffw
;
477 lbuffw
[0] = '0' + lVal
;
478 rbuffw
[0] = '0' + rVal
;
481 pvLeft
.Value
.bin
.cb
= 1;
482 pvRight
.Value
.bin
.cb
= 1;
483 pvLeft
.Value
.bin
.lpb
= lbuffa
;
484 pvRight
.Value
.bin
.lpb
= rbuffa
;
490 bRet
= pFPropCompareProp(&pvLeft
, FPCProp_Results
[j
].relOp
, &pvRight
);
491 ok(bRet
== bExp
, "pt %ld (%d,%d,%s): expected %d, got %d\n", ptTypes
[i
],
492 FPCProp_Results
[j
].lVal
, FPCProp_Results
[j
].rVal
,
493 relops
[FPCProp_Results
[j
].relOp
], bExp
, bRet
);
498 typedef struct tagLPropCompareProp_Result
503 } LPropCompareProp_Result
;
505 static const LPropCompareProp_Result LPCProp_Results
[] =
512 static void test_LPropCompareProp(void)
514 SPropValue pvLeft
, pvRight
;
516 char lbuffa
[2], rbuffa
[2];
517 WCHAR lbuffw
[2], rbuffw
[2];
521 pLPropCompareProp
= (void*)GetProcAddress(hMapi32
, "LPropCompareProp@8");
523 if (!pLPropCompareProp
)
531 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
533 pvLeft
.ulPropTag
= pvRight
.ulPropTag
= ptTypes
[i
];
535 for (j
= 0; j
< sizeof(LPCProp_Results
)/sizeof(LPCProp_Results
[0]); j
++)
537 SHORT lVal
= LPCProp_Results
[j
].lVal
;
538 SHORT rVal
= LPCProp_Results
[j
].rVal
;
540 iExp
= LPCProp_Results
[j
].iRet
;
545 /* Boolean values have no concept of less or greater than, only equality */
548 /* Fall through ... */
550 pvLeft
.Value
.i
= lVal
;
551 pvRight
.Value
.i
= rVal
;
555 pvLeft
.Value
.l
= lVal
;
556 pvRight
.Value
.l
= rVal
;
559 pvLeft
.Value
.flt
= lVal
;
560 pvRight
.Value
.flt
= rVal
;
564 pvLeft
.Value
.dbl
= lVal
;
565 pvRight
.Value
.dbl
= rVal
;
568 pvLeft
.Value
.cur
.int64
= lVal
;
569 pvRight
.Value
.cur
.int64
= rVal
;
572 pvLeft
.Value
.ft
.dwLowDateTime
= lVal
;
573 pvLeft
.Value
.ft
.dwHighDateTime
= 0;
574 pvRight
.Value
.ft
.dwLowDateTime
= rVal
;
575 pvRight
.Value
.ft
.dwHighDateTime
= 0;
578 pvLeft
.Value
.li
.u
.LowPart
= lVal
;
579 pvLeft
.Value
.li
.u
.HighPart
= 0;
580 pvRight
.Value
.li
.u
.LowPart
= rVal
;
581 pvRight
.Value
.li
.u
.HighPart
= 0;
584 memset(&lguid
, 0, sizeof(GUID
));
585 memset(&rguid
, 0, sizeof(GUID
));
586 lguid
.Data4
[7] = lVal
;
587 rguid
.Data4
[7] = rVal
;
588 pvLeft
.Value
.lpguid
= &lguid
;
589 pvRight
.Value
.lpguid
= &rguid
;
592 pvLeft
.Value
.lpszA
= lbuffa
;
593 pvRight
.Value
.lpszA
= rbuffa
;
594 lbuffa
[0] = '0' + lVal
;
595 rbuffa
[0] = '0' + rVal
;
598 pvLeft
.Value
.lpszW
= lbuffw
;
599 pvRight
.Value
.lpszW
= rbuffw
;
600 lbuffw
[0] = '0' + lVal
;
601 rbuffw
[0] = '0' + rVal
;
604 pvLeft
.Value
.bin
.cb
= 1;
605 pvRight
.Value
.bin
.cb
= 1;
606 pvLeft
.Value
.bin
.lpb
= lbuffa
;
607 pvRight
.Value
.bin
.lpb
= rbuffa
;
613 iRet
= pLPropCompareProp(&pvLeft
, &pvRight
);
614 ok(iRet
== iExp
, "pt %ld (%d,%d): expected %d, got %d\n", ptTypes
[i
],
615 LPCProp_Results
[j
].lVal
, LPCProp_Results
[j
].rVal
, iExp
, iRet
);
620 static void test_PpropFindProp(void)
622 SPropValue pvProp
, *pRet
;
625 pPpropFindProp
= (void*)GetProcAddress(hMapi32
, "PpropFindProp@12");
630 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
632 pvProp
.ulPropTag
= ptTypes
[i
];
634 pRet
= pPpropFindProp(&pvProp
, 1u, ptTypes
[i
]);
635 ok(pRet
== &pvProp
, "PpropFindProp[%ld]: Didn't find existing propery\n",
638 pRet
= pPpropFindProp(&pvProp
, 1u, i
? ptTypes
[i
-1] : ptTypes
[i
+1]);
639 ok(pRet
== NULL
, "PpropFindProp[%ld]: Found nonexistent propery\n",
643 pvProp
.ulPropTag
= PROP_TAG(PT_I2
, 1u);
644 pRet
= pPpropFindProp(&pvProp
, 1u, PROP_TAG(PT_UNSPECIFIED
, 0u));
645 ok(pRet
== NULL
, "PpropFindProp[UNSPECIFIED]: Matched on different id\n");
646 pRet
= pPpropFindProp(&pvProp
, 1u, PROP_TAG(PT_UNSPECIFIED
, 1u));
647 ok(pRet
== &pvProp
, "PpropFindProp[UNSPECIFIED]: Didn't match id\n");
650 static void test_ScCountProps(void)
652 static const char *szHiA
= "Hi!";
653 static const WCHAR szHiW
[] = { 'H', 'i', '!', '\0' };
654 static const ULONG ULHILEN
= 4; /* chars in szHiA/W incl. NUL */
658 GUID iids
[4], *iid
= iids
;
660 ULONG pt
, exp
, ulRet
;
663 pScCountProps
= (void*)GetProcAddress(hMapi32
, "ScCountProps@12");
668 for (pt
= 0; pt
< PROP_ID_INVALID
&& success
; pt
++)
672 memset(&pv
, 0 ,sizeof(pv
));
673 pv
.ulPropTag
= PROP_TAG(pt
, 1u);
675 switch (PROP_TYPE(pt
))
691 pv
.Value
.lpguid
= iid
;
692 exp
= sizeof(GUID
) + sizeof(pv
);
695 pv
.Value
.lpszA
= (LPSTR
)szHiA
;
696 exp
= 4 + sizeof(pv
);
699 pv
.Value
.lpszW
= (LPWSTR
)szHiW
;
700 exp
= 4 * sizeof(WCHAR
) + sizeof(pv
);
704 pv
.Value
.bin
.lpb
= (LPBYTE
)iid
;
705 exp
= 2 + sizeof(pv
);
708 pv
.Value
.MVi
.cValues
= 3;
709 pv
.Value
.MVi
.lpi
= (SHORT
*)iid
;
710 exp
= 3 * sizeof(SHORT
) + sizeof(pv
);
713 pv
.Value
.MVl
.cValues
= 3;
714 pv
.Value
.MVl
.lpl
= (LONG
*)iid
;
715 exp
= 3 * sizeof(LONG
) + sizeof(pv
);
718 pv
.Value
.MVli
.cValues
= 3;
719 pv
.Value
.MVli
.lpli
= (LARGE_INTEGER
*)iid
;
720 exp
= 3 * sizeof(LARGE_INTEGER
) + sizeof(pv
);
723 pv
.Value
.MVflt
.cValues
= 3;
724 pv
.Value
.MVflt
.lpflt
= (float*)iid
;
725 exp
= 3 * sizeof(float) + sizeof(pv
);
729 pv
.Value
.MVdbl
.cValues
= 3;
730 pv
.Value
.MVdbl
.lpdbl
= (double*)iid
;
731 exp
= 3 * sizeof(double) + sizeof(pv
);
734 pv
.Value
.MVcur
.cValues
= 3;
735 pv
.Value
.MVcur
.lpcur
= (CY
*)iid
;
736 exp
= 3 * sizeof(CY
) + sizeof(pv
);
739 pv
.Value
.MVft
.cValues
= 3;
740 pv
.Value
.MVft
.lpft
= (FILETIME
*)iid
;
741 exp
= 3 * sizeof(CY
) + sizeof(pv
);
744 pv
.Value
.MVszA
.cValues
= 3;
745 pv
.Value
.MVszA
.lppszA
= buffa
;
746 buffa
[0] = (LPSTR
)szHiA
;
747 buffa
[1] = (LPSTR
)szHiA
;
748 buffa
[2] = (LPSTR
)szHiA
;
749 exp
= ULHILEN
* 3 + 3 * sizeof(char*) + sizeof(pv
);
752 pv
.Value
.MVszW
.cValues
= 3;
753 pv
.Value
.MVszW
.lppszW
= buffw
;
754 buffw
[0] = (LPWSTR
)szHiW
;
755 buffw
[1] = (LPWSTR
)szHiW
;
756 buffw
[2] = (LPWSTR
)szHiW
;
757 exp
= ULHILEN
* 3 * sizeof(WCHAR
) + 3 * sizeof(WCHAR
*) + sizeof(pv
);
760 pv
.Value
.MVbin
.cValues
= 3;
761 pv
.Value
.MVbin
.lpbin
= buffbin
;
763 buffbin
[0].lpb
= (LPBYTE
)&iid
;
765 buffbin
[1].lpb
= (LPBYTE
)&iid
;
767 buffbin
[2].lpb
= (LPBYTE
)&iid
;
768 exp
= 20 + sizeof(pv
) + sizeof(SBinary
) * 3;
775 res
= pScCountProps(1, &pv
, &ulRet
);
777 success
= res
== MAPI_E_INVALID_PARAMETER
&& ulRet
== 0xffffffff;
778 ok(success
, "pt= %ld: Expected failure, got %ld, ret=0x%08lX\n",
782 success
= res
== S_OK
&& ulRet
== exp
;
783 ok(success
, "pt= %ld: Expected %ld, got %ld, ret=0x%08lX\n",
784 pt
, exp
, ulRet
, res
);
790 static void test_ScCopyRelocProps(void)
792 static const char* szTestA
= "Test";
793 char buffer
[512], buffer2
[512], *lppszA
[1];
794 SPropValue pvProp
, *lpResProp
= (LPSPropValue
)buffer
;
798 pScCopyProps
= (void*)GetProcAddress(hMapi32
, "ScCopyProps@16");
799 pScRelocProps
= (void*)GetProcAddress(hMapi32
, "ScRelocProps@20");
801 if (!pScCopyProps
|| !pScRelocProps
)
804 pvProp
.ulPropTag
= PROP_TAG(PT_MV_STRING8
, 1u);
806 lppszA
[0] = (char *)szTestA
;
807 pvProp
.Value
.MVszA
.cValues
= 1;
808 pvProp
.Value
.MVszA
.lppszA
= lppszA
;
811 sc
= pScCopyProps(1, &pvProp
, buffer
, &ulCount
);
812 ok(sc
== S_OK
&& lpResProp
->ulPropTag
== pvProp
.ulPropTag
&&
813 lpResProp
->Value
.MVszA
.cValues
== 1 &&
814 lpResProp
->Value
.MVszA
.lppszA
[0] == buffer
+ sizeof(SPropValue
) + sizeof(char*) &&
815 !strcmp(lpResProp
->Value
.MVszA
.lppszA
[0], szTestA
) &&
816 ulCount
== sizeof(SPropValue
) + sizeof(char*) + 5,
817 "CopyProps(str): Expected 0 {1,%lx,%p,%s} %d got 0x%08lx {%ld,%lx,%p,%s} %ld\n",
818 pvProp
.ulPropTag
, buffer
+ sizeof(SPropValue
) + sizeof(char*),
819 szTestA
, sizeof(SPropValue
) + sizeof(char*) + 5, sc
,
820 lpResProp
->Value
.MVszA
.cValues
, lpResProp
->ulPropTag
,
821 lpResProp
->Value
.MVszA
.lppszA
[0], sc
==S_OK
?lpResProp
->Value
.MVszA
.lppszA
[0]:NULL
, ulCount
);
823 memcpy(buffer2
, buffer
, sizeof(buffer
));
825 /* Clear the data in the source buffer. Since pointers in the copied buffer
826 * refer to the source buffer, this proves that native always assumes that
827 * the copied buffers pointers are bad (needing to be relocated first).
829 memset(buffer
, 0, sizeof(buffer
));
832 sc
= pScRelocProps(1, (LPSPropValue
)buffer2
, buffer
, buffer2
, &ulCount
);
833 lpResProp
= (LPSPropValue
)buffer2
;
834 ok(sc
== S_OK
&& lpResProp
->ulPropTag
== pvProp
.ulPropTag
&&
835 lpResProp
->Value
.MVszA
.cValues
== 1 &&
836 lpResProp
->Value
.MVszA
.lppszA
[0] == buffer2
+ sizeof(SPropValue
) + sizeof(char*) &&
837 !strcmp(lpResProp
->Value
.MVszA
.lppszA
[0], szTestA
) &&
838 /* Native has a bug whereby it calculates the size correctly when copying
839 * but when relocating does not (presumably it uses UlPropSize() which
840 * ignores multivalue pointers). Wine returns the correct value.
842 (ulCount
== sizeof(SPropValue
) + sizeof(char*) + 5 || ulCount
== sizeof(SPropValue
) + 5),
843 "RelocProps(str): Expected 0 {1,%lx,%p,%s} %d got 0x%08lx {%ld,%lx,%p,%s} %ld\n",
844 pvProp
.ulPropTag
, buffer2
+ sizeof(SPropValue
) + sizeof(char*),
845 szTestA
, sizeof(SPropValue
) + sizeof(char*) + 5, sc
,
846 lpResProp
->Value
.MVszA
.cValues
, lpResProp
->ulPropTag
,
847 lpResProp
->Value
.MVszA
.lppszA
[0], sc
==S_OK
?lpResProp
->Value
.MVszA
.lppszA
[0]:NULL
, ulCount
);
849 /* Native crashes with lpNew or lpOld set to NULL so skip testing this */
852 static void test_LpValFindProp(void)
854 SPropValue pvProp
, *pRet
;
857 pLpValFindProp
= (void*)GetProcAddress(hMapi32
, "LpValFindProp@12");
862 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
864 pvProp
.ulPropTag
= PROP_TAG(ptTypes
[i
], 1u);
866 pRet
= pLpValFindProp(PROP_TAG(ptTypes
[i
], 1u), 1u, &pvProp
);
867 ok(pRet
== &pvProp
, "LpValFindProp[%ld]: Didn't find existing propery id/type\n",
870 pRet
= pLpValFindProp(PROP_TAG(ptTypes
[i
], 0u), 1u, &pvProp
);
871 ok(pRet
== NULL
, "LpValFindProp[%ld]: Found nonexistent propery id\n",
874 pRet
= pLpValFindProp(PROP_TAG(PT_NULL
, 0u), 1u, &pvProp
);
875 ok(pRet
== NULL
, "LpValFindProp[%ld]: Found nonexistent propery id/type\n",
878 pRet
= pLpValFindProp(PROP_TAG(PT_NULL
, 1u), 1u, &pvProp
);
879 ok(pRet
== &pvProp
, "LpValFindProp[%ld]: Didn't find existing propery id\n",
884 static void test_FBadRglpszA(void)
887 char *szString
= "A String";
890 pFBadRglpszA
= (void*)GetProcAddress(hMapi32
, "FBadRglpszA@8");
894 bRet
= pFBadRglpszA(NULL
, 10);
895 ok(bRet
== TRUE
, "FBadRglpszA(Null): expected TRUE, got FALSE\n");
897 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = lpStrs
[3] = NULL
;
898 bRet
= pFBadRglpszA(lpStrs
, 4);
899 ok(bRet
== TRUE
, "FBadRglpszA(Nulls): expected TRUE, got FALSE\n");
901 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = szString
;
902 bRet
= pFBadRglpszA(lpStrs
, 3);
903 ok(bRet
== FALSE
, "FBadRglpszA(valid): expected FALSE, got TRUE\n");
905 bRet
= pFBadRglpszA(lpStrs
, 4);
906 ok(bRet
== TRUE
, "FBadRglpszA(1 invalid): expected TRUE, got FALSE\n");
909 static void test_FBadRglpszW(void)
912 WCHAR szString
[] = { 'A',' ','S','t','r','i','n','g','\0' };
915 pFBadRglpszW
= (void*)GetProcAddress(hMapi32
, "FBadRglpszW@8");
919 bRet
= pFBadRglpszW(NULL
, 10);
920 ok(bRet
== TRUE
, "FBadRglpszW(Null): expected TRUE, got FALSE\n");
922 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = lpStrs
[3] = NULL
;
923 bRet
= pFBadRglpszW(lpStrs
, 4);
924 ok(bRet
== TRUE
, "FBadRglpszW(Nulls): expected TRUE, got FALSE\n");
926 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = szString
;
927 bRet
= pFBadRglpszW(lpStrs
, 3);
928 ok(bRet
== FALSE
, "FBadRglpszW(valid): expected FALSE, got TRUE\n");
930 bRet
= pFBadRglpszW(lpStrs
, 4);
931 ok(bRet
== TRUE
, "FBadRglpszW(1 invalid): expected TRUE, got FALSE\n");
934 static void test_FBadRowSet(void)
938 pFBadRowSet
= (void*)GetProcAddress(hMapi32
, "FBadRowSet@4");
942 ulRet
= pFBadRowSet(NULL
);
943 ok(ulRet
!= 0, "FBadRow(null): Expected non-zero, got 0\n");
948 static void test_FBadPropTag(void)
952 pFBadPropTag
= (void*)GetProcAddress(hMapi32
, "FBadPropTag@4");
956 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
960 switch (pt
& (~MV_FLAG
& PROP_TYPE_MASK
))
963 case PT_NULL
: case PT_I2
: case PT_I4
: case PT_R4
:
964 case PT_R8
: case PT_CURRENCY
: case PT_APPTIME
:
965 case PT_ERROR
: case PT_BOOLEAN
: case PT_OBJECT
:
966 case PT_I8
: case PT_STRING8
: case PT_UNICODE
:
967 case PT_SYSTIME
: case PT_CLSID
: case PT_BINARY
:
971 res
= pFBadPropTag(pt
);
973 ok(res
!= 0, "pt= %ld: Expected non-zero, got 0\n", pt
);
975 ok(res
== 0, "pt= %ld: Expected zero, got %ld\n", pt
, res
);
979 static void test_FBadRow(void)
983 pFBadRow
= (void*)GetProcAddress(hMapi32
, "FBadRow@4");
987 ulRet
= pFBadRow(NULL
);
988 ok(ulRet
!= 0, "FBadRow(null): Expected non-zero, got 0\n");
993 static void test_FBadProp(void)
995 WCHAR szEmpty
[] = { '\0' };
1000 pFBadProp
= (void*)GetProcAddress(hMapi32
, "FBadProp@4");
1004 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1008 memset(&pv
, 0, sizeof(pv
));
1011 /* Note that MV values are valid below because their array count is 0,
1012 * so no pointers are validated.
1014 switch (PROP_TYPE(pt
))
1016 case (MV_FLAG
|PT_UNSPECIFIED
):
1017 case PT_UNSPECIFIED
:
1018 case (MV_FLAG
|PT_NULL
):
1030 case PT_MV_CURRENCY
:
1034 case (MV_FLAG
|PT_ERROR
):
1036 case (MV_FLAG
|PT_BOOLEAN
):
1038 case (MV_FLAG
|PT_OBJECT
):
1051 pv
.Value
.lpszW
= szEmpty
;
1055 pv
.Value
.lpguid
= &iid
;
1060 res
= pFBadProp(&pv
);
1062 ok(res
!= 0, "pt= %ld: Expected non-zero, got 0\n", pt
);
1064 ok(res
== 0, "pt= %ld: Expected zero, got %ld\n", pt
, res
);
1068 static void test_FBadColumnSet(void)
1073 pFBadColumnSet
= (void*)GetProcAddress(hMapi32
, "FBadColumnSet@4");
1074 if (!pFBadColumnSet
)
1077 res
= pFBadColumnSet(NULL
);
1078 ok(res
!= 0, "(null): Expected non-zero, got 0\n");
1082 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1086 pta
.aulPropTag
[0] = pt
;
1088 switch (pt
& (~MV_FLAG
& PROP_TYPE_MASK
))
1090 case PT_UNSPECIFIED
:
1108 if (pt
== (MV_FLAG
|PT_ERROR
))
1111 res
= pFBadColumnSet(&pta
);
1113 ok(res
!= 0, "pt= %ld: Expected non-zero, got 0\n", pt
);
1115 ok(res
== 0, "pt= %ld: Expected zero, got %ld\n", pt
, res
);
1120 static void test_IProp(void)
1123 LPMAPIERROR lpError
;
1124 LPSPropProblemArray lpProbs
;
1125 LPSPropValue lpProps
;
1126 LPSPropTagArray lpTags
;
1128 SizedSPropTagArray(2,tags
);
1129 ULONG access
[2], count
;
1132 pCreateIProp
= (void*)GetProcAddress(hMapi32
, "CreateIProp@24");
1136 memset(&tags
, 0 , sizeof(tags
));
1138 /* Create the object */
1140 sc
= pCreateIProp(&IID_IMAPIPropData
, MAPIAllocateBuffer
, MAPIAllocateMore
,
1141 MAPIFreeBuffer
, NULL
, &lpIProp
);
1142 ok(sc
== S_OK
&& lpIProp
,
1143 "CreateIProp: expected S_OK, non-null, got 0x%08lX,%p\n", sc
, lpIProp
);
1145 if (sc
!= S_OK
|| !lpIProp
)
1148 /* GetLastError - No errors set */
1150 IPropData_GetLastError(lpIProp
, E_INVALIDARG
, 0, &lpError
);
1151 ok(sc
== S_OK
&& !lpError
,
1152 "GetLastError: Expected S_OK, null, got 0x%08lX,%p\n", sc
, lpError
);
1154 /* Get prop tags - succeeds returning 0 items */
1156 sc
= IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1157 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 0,
1158 "GetPropList(empty): Expected S_OK, non-null, 0, got 0x%08lX,%p,%ld\n",
1159 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1161 MAPIFreeBuffer(lpTags
);
1163 /* Get props - succeeds returning 0 items */
1167 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1168 sc
= IPropData_GetProps(lpIProp
, (LPSPropTagArray
)&tags
, 0, &count
, &lpProps
);
1169 ok(sc
== MAPI_W_ERRORS_RETURNED
&& lpProps
&& count
== 1,
1170 "GetProps(empty): Expected ERRORS_RETURNED, non-null, 1, got 0x%08lX,%p,%ld\n",
1171 sc
, lpProps
, count
);
1172 if (lpProps
&& count
> 0)
1174 ok(lpProps
[0].ulPropTag
== CHANGE_PROP_TYPE(PR_IMPORTANCE
,PT_ERROR
),
1175 "GetProps(empty): Expected %x, got %lx\n",
1176 CHANGE_PROP_TYPE(PR_IMPORTANCE
,PT_ERROR
), lpProps
[0].ulPropTag
);
1178 MAPIFreeBuffer(lpProps
);
1181 /* Add (NULL) - Can't add NULL's */
1183 pvs
[0].ulPropTag
= PROP_TAG(PT_NULL
,0x01);
1184 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1185 ok(sc
== MAPI_E_INVALID_PARAMETER
&& !lpProbs
,
1186 "SetProps(): Expected INVALID_PARAMETER, null, got 0x%08lX,%p\n",
1189 /* Add (OBJECT) - Can't add OBJECTS's */
1191 pvs
[0].ulPropTag
= PROP_TAG(PT_OBJECT
,0x01);
1192 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1193 ok(sc
== MAPI_E_INVALID_PARAMETER
&& !lpProbs
,
1194 "SetProps(OBJECT): Expected INVALID_PARAMETER, null, got 0x%08lX,%p\n",
1197 /* Add - Adds value */
1199 pvs
[0].ulPropTag
= PR_IMPORTANCE
;
1200 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1201 ok(sc
== S_OK
&& !lpProbs
,
1202 "SetProps(ERROR): Expected S_OK, null, got 0x%08lX,%p\n", sc
, lpProbs
);
1204 /* Get prop list - returns 1 item */
1206 IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1207 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 1,
1208 "GetPropList: Expected S_OK, non-null, 1, got 0x%08lX,%p,%ld\n",
1209 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1210 if (lpTags
&& lpTags
->cValues
> 0)
1212 ok(lpTags
->aulPropTag
[0] == PR_IMPORTANCE
,
1213 "GetPropList: Expected %x, got %lx\n",
1214 PR_IMPORTANCE
, lpTags
->aulPropTag
[0]);
1215 MAPIFreeBuffer(lpTags
);
1218 /* Set access to read and write */
1219 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READWRITE
);
1220 ok(sc
== S_OK
, "SetObjAcess(WRITE): Expected S_OK got 0x%08lX\n", sc
);
1223 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1225 /* Set item access (bad access) - Fails */
1227 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1228 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1229 "SetPropAcess(0): Expected INVALID_PARAMETER got 0x%08lX\n",sc
);
1230 access
[0] = IPROP_READWRITE
;
1231 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1232 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1233 "SetPropAcess(RW): Expected INVALID_PARAMETER got 0x%08lX\n",sc
);
1234 access
[0] = IPROP_CLEAN
;
1235 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1236 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1237 "SetPropAcess(C): Expected INVALID_PARAMETER got 0x%08lX\n",sc
);
1239 /* Set item access to read/write/clean */
1241 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1242 access
[0] = IPROP_READWRITE
|IPROP_CLEAN
;
1243 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1244 ok(sc
== S_OK
, "SetPropAcess(RW/C): Expected S_OK got 0x%08lX\n",sc
);
1246 /* Set object access to read only */
1247 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READONLY
);
1248 ok(sc
== S_OK
, "SetObjAcess(READ): Expected S_OK got 0x%08lX\n", sc
);
1250 /* Set item access to read/write/dirty - doesn't care about RO object */
1251 access
[0] = IPROP_READONLY
|IPROP_DIRTY
;
1252 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1253 ok(sc
== S_OK
, "SetPropAcess(WRITE): Expected S_OK got 0x%08lX\n", sc
);
1255 /* Delete any item when set to read only - Error */
1257 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1258 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1259 ok(sc
== E_ACCESSDENIED
&& !lpProbs
,
1260 "DeleteProps(nonexistent): Expected E_ACCESSDENIED null got 0x%08lX %p\n",
1263 /* Set access to read and write */
1264 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READWRITE
);
1265 ok(sc
== S_OK
, "SetObjAcess(WRITE): Expected S_OK got 0x%08lX\n", sc
);
1267 /* Delete nonexistent item - No error */
1269 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1270 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1271 ok(sc
== S_OK
&& !lpProbs
,
1272 "DeleteProps(nonexistent): Expected S_OK null got 0x%08lX %p\n",
1275 /* Delete existing item (r/o) - No error, but lpProbs populated */
1277 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1278 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1279 ok(sc
== S_OK
&& lpProbs
,
1280 "DeleteProps(RO): Expected S_OK non-null got 0x%08lX %p\n", sc
, lpProbs
);
1282 if (lpProbs
&& lpProbs
->cProblem
> 0)
1284 ok(lpProbs
->cProblem
== 1 &&
1285 lpProbs
->aProblem
[0].ulIndex
== 0 &&
1286 lpProbs
->aProblem
[0].ulPropTag
== PR_IMPORTANCE
&&
1287 lpProbs
->aProblem
[0].scode
== E_ACCESSDENIED
,
1288 "DeleteProps(RO): Expected (1,0,%x,%lx) got (%ld,%lx,%lx)\n",
1289 PR_IMPORTANCE
, E_ACCESSDENIED
,
1290 lpProbs
->aProblem
[0].ulIndex
, lpProbs
->aProblem
[0].ulPropTag
,
1291 lpProbs
->aProblem
[0].scode
);
1292 MAPIFreeBuffer(lpProbs
);
1297 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1298 IPropData_HrAddObjProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1299 ok(sc
== S_OK
&& !lpProbs
,
1300 "AddObjProps(RO): Expected S_OK null got 0x%08lX %p\n", sc
, lpProbs
);
1302 /* Get prop list - returns 1 item */
1304 IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1305 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 1,
1306 "GetPropList: Expected S_OK, non-null, 1, got 0x%08lX,%p,%ld\n",
1307 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1308 if (lpTags
&& lpTags
->cValues
> 0)
1310 ok(lpTags
->aulPropTag
[0] == PR_IMPORTANCE
,
1311 "GetPropList: Expected %x, got %lx\n",
1312 PR_IMPORTANCE
, lpTags
->aulPropTag
[0]);
1313 MAPIFreeBuffer(lpTags
);
1316 /* Set item to r/w again */
1317 access
[0] = IPROP_READWRITE
|IPROP_DIRTY
;
1318 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1319 ok(sc
== S_OK
, "SetPropAcess(WRITE): Expected S_OK got 0x%08lX\n", sc
);
1321 /* Delete existing item (r/w) - No error, no problems */
1323 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1324 ok(sc
== S_OK
&& !lpProbs
,
1325 "DeleteProps(RO): Expected S_OK null got 0x%08lX %p\n", sc
, lpProbs
);
1328 IPropData_Release(lpIProp
);
1333 hMapi32
= LoadLibraryA("mapi32.dll");
1335 pScInitMapiUtil
= (void*)GetProcAddress(hMapi32
, "ScInitMapiUtil@4");
1336 if (!pScInitMapiUtil
)
1340 test_PropCopyMore();
1342 test_FPropContainsProp();
1343 test_FPropCompareProp();
1344 test_LPropCompareProp();
1345 test_PpropFindProp();
1346 test_ScCountProps();
1347 test_ScCopyRelocProps();
1348 test_LpValFindProp();
1355 test_FBadColumnSet();