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
= (LPBYTE
)lbuffa
;
484 pvRight
.Value
.bin
.lpb
= (LPBYTE
)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
= (LPBYTE
)lbuffa
;
607 pvRight
.Value
.bin
.lpb
= (LPBYTE
)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 ulCount
== sizeof(SPropValue
) + sizeof(char*) + 5 &&
816 !strcmp(lpResProp
->Value
.MVszA
.lppszA
[0], szTestA
),
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 sc
==S_OK
?lpResProp
->Value
.MVszA
.lppszA
[0]:NULL
,
822 sc
==S_OK
?lpResProp
->Value
.MVszA
.lppszA
[0]:NULL
, ulCount
);
824 memcpy(buffer2
, buffer
, sizeof(buffer
));
826 /* Clear the data in the source buffer. Since pointers in the copied buffer
827 * refer to the source buffer, this proves that native always assumes that
828 * the copied buffers pointers are bad (needing to be relocated first).
830 memset(buffer
, 0, sizeof(buffer
));
833 sc
= pScRelocProps(1, (LPSPropValue
)buffer2
, buffer
, buffer2
, &ulCount
);
834 lpResProp
= (LPSPropValue
)buffer2
;
835 ok(sc
== S_OK
&& lpResProp
->ulPropTag
== pvProp
.ulPropTag
&&
836 lpResProp
->Value
.MVszA
.cValues
== 1 &&
837 lpResProp
->Value
.MVszA
.lppszA
[0] == buffer2
+ sizeof(SPropValue
) + sizeof(char*) &&
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 !strcmp(lpResProp
->Value
.MVszA
.lppszA
[0], szTestA
),
844 "RelocProps(str): Expected 0 {1,%lx,%p,%s} %d got 0x%08lx {%ld,%lx,%p,%s} %ld\n",
845 pvProp
.ulPropTag
, buffer2
+ sizeof(SPropValue
) + sizeof(char*),
846 szTestA
, sizeof(SPropValue
) + sizeof(char*) + 5, sc
,
847 lpResProp
->Value
.MVszA
.cValues
, lpResProp
->ulPropTag
,
848 sc
==S_OK
?lpResProp
->Value
.MVszA
.lppszA
[0]:NULL
,
849 sc
==S_OK
?lpResProp
->Value
.MVszA
.lppszA
[0]:NULL
, ulCount
);
851 /* Native crashes with lpNew or lpOld set to NULL so skip testing this */
854 static void test_LpValFindProp(void)
856 SPropValue pvProp
, *pRet
;
859 pLpValFindProp
= (void*)GetProcAddress(hMapi32
, "LpValFindProp@12");
864 for (i
= 0; i
< sizeof(ptTypes
)/sizeof(ptTypes
[0]); i
++)
866 pvProp
.ulPropTag
= PROP_TAG(ptTypes
[i
], 1u);
868 pRet
= pLpValFindProp(PROP_TAG(ptTypes
[i
], 1u), 1u, &pvProp
);
869 ok(pRet
== &pvProp
, "LpValFindProp[%ld]: Didn't find existing propery id/type\n",
872 pRet
= pLpValFindProp(PROP_TAG(ptTypes
[i
], 0u), 1u, &pvProp
);
873 ok(pRet
== NULL
, "LpValFindProp[%ld]: Found nonexistent propery id\n",
876 pRet
= pLpValFindProp(PROP_TAG(PT_NULL
, 0u), 1u, &pvProp
);
877 ok(pRet
== NULL
, "LpValFindProp[%ld]: Found nonexistent propery id/type\n",
880 pRet
= pLpValFindProp(PROP_TAG(PT_NULL
, 1u), 1u, &pvProp
);
881 ok(pRet
== &pvProp
, "LpValFindProp[%ld]: Didn't find existing propery id\n",
886 static void test_FBadRglpszA(void)
889 char *szString
= "A String";
892 pFBadRglpszA
= (void*)GetProcAddress(hMapi32
, "FBadRglpszA@8");
896 bRet
= pFBadRglpszA(NULL
, 10);
897 ok(bRet
== TRUE
, "FBadRglpszA(Null): expected TRUE, got FALSE\n");
899 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = lpStrs
[3] = NULL
;
900 bRet
= pFBadRglpszA(lpStrs
, 4);
901 ok(bRet
== TRUE
, "FBadRglpszA(Nulls): expected TRUE, got FALSE\n");
903 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = szString
;
904 bRet
= pFBadRglpszA(lpStrs
, 3);
905 ok(bRet
== FALSE
, "FBadRglpszA(valid): expected FALSE, got TRUE\n");
907 bRet
= pFBadRglpszA(lpStrs
, 4);
908 ok(bRet
== TRUE
, "FBadRglpszA(1 invalid): expected TRUE, got FALSE\n");
911 static void test_FBadRglpszW(void)
914 WCHAR szString
[] = { 'A',' ','S','t','r','i','n','g','\0' };
917 pFBadRglpszW
= (void*)GetProcAddress(hMapi32
, "FBadRglpszW@8");
921 bRet
= pFBadRglpszW(NULL
, 10);
922 ok(bRet
== TRUE
, "FBadRglpszW(Null): expected TRUE, got FALSE\n");
924 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = lpStrs
[3] = NULL
;
925 bRet
= pFBadRglpszW(lpStrs
, 4);
926 ok(bRet
== TRUE
, "FBadRglpszW(Nulls): expected TRUE, got FALSE\n");
928 lpStrs
[0] = lpStrs
[1] = lpStrs
[2] = szString
;
929 bRet
= pFBadRglpszW(lpStrs
, 3);
930 ok(bRet
== FALSE
, "FBadRglpszW(valid): expected FALSE, got TRUE\n");
932 bRet
= pFBadRglpszW(lpStrs
, 4);
933 ok(bRet
== TRUE
, "FBadRglpszW(1 invalid): expected TRUE, got FALSE\n");
936 static void test_FBadRowSet(void)
940 pFBadRowSet
= (void*)GetProcAddress(hMapi32
, "FBadRowSet@4");
944 ulRet
= pFBadRowSet(NULL
);
945 ok(ulRet
!= 0, "FBadRow(null): Expected non-zero, got 0\n");
950 static void test_FBadPropTag(void)
954 pFBadPropTag
= (void*)GetProcAddress(hMapi32
, "FBadPropTag@4");
958 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
962 switch (pt
& (~MV_FLAG
& PROP_TYPE_MASK
))
965 case PT_NULL
: case PT_I2
: case PT_I4
: case PT_R4
:
966 case PT_R8
: case PT_CURRENCY
: case PT_APPTIME
:
967 case PT_ERROR
: case PT_BOOLEAN
: case PT_OBJECT
:
968 case PT_I8
: case PT_STRING8
: case PT_UNICODE
:
969 case PT_SYSTIME
: case PT_CLSID
: case PT_BINARY
:
973 res
= pFBadPropTag(pt
);
975 ok(res
!= 0, "pt= %ld: Expected non-zero, got 0\n", pt
);
977 ok(res
== 0, "pt= %ld: Expected zero, got %ld\n", pt
, res
);
981 static void test_FBadRow(void)
985 pFBadRow
= (void*)GetProcAddress(hMapi32
, "FBadRow@4");
989 ulRet
= pFBadRow(NULL
);
990 ok(ulRet
!= 0, "FBadRow(null): Expected non-zero, got 0\n");
995 static void test_FBadProp(void)
997 WCHAR szEmpty
[] = { '\0' };
1002 pFBadProp
= (void*)GetProcAddress(hMapi32
, "FBadProp@4");
1006 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1010 memset(&pv
, 0, sizeof(pv
));
1013 /* Note that MV values are valid below because their array count is 0,
1014 * so no pointers are validated.
1016 switch (PROP_TYPE(pt
))
1018 case (MV_FLAG
|PT_UNSPECIFIED
):
1019 case PT_UNSPECIFIED
:
1020 case (MV_FLAG
|PT_NULL
):
1032 case PT_MV_CURRENCY
:
1036 case (MV_FLAG
|PT_ERROR
):
1038 case (MV_FLAG
|PT_BOOLEAN
):
1040 case (MV_FLAG
|PT_OBJECT
):
1053 pv
.Value
.lpszW
= szEmpty
;
1057 pv
.Value
.lpguid
= &iid
;
1062 res
= pFBadProp(&pv
);
1064 ok(res
!= 0, "pt= %ld: Expected non-zero, got 0\n", pt
);
1066 ok(res
== 0, "pt= %ld: Expected zero, got %ld\n", pt
, res
);
1070 static void test_FBadColumnSet(void)
1075 pFBadColumnSet
= (void*)GetProcAddress(hMapi32
, "FBadColumnSet@4");
1076 if (!pFBadColumnSet
)
1079 res
= pFBadColumnSet(NULL
);
1080 ok(res
!= 0, "(null): Expected non-zero, got 0\n");
1084 for (pt
= 0; pt
< PROP_ID_INVALID
; pt
++)
1088 pta
.aulPropTag
[0] = pt
;
1090 switch (pt
& (~MV_FLAG
& PROP_TYPE_MASK
))
1092 case PT_UNSPECIFIED
:
1110 if (pt
== (MV_FLAG
|PT_ERROR
))
1113 res
= pFBadColumnSet(&pta
);
1115 ok(res
!= 0, "pt= %ld: Expected non-zero, got 0\n", pt
);
1117 ok(res
== 0, "pt= %ld: Expected zero, got %ld\n", pt
, res
);
1122 static void test_IProp(void)
1125 LPMAPIERROR lpError
;
1126 LPSPropProblemArray lpProbs
;
1127 LPSPropValue lpProps
;
1128 LPSPropTagArray lpTags
;
1130 SizedSPropTagArray(2,tags
);
1131 ULONG access
[2], count
;
1134 pCreateIProp
= (void*)GetProcAddress(hMapi32
, "CreateIProp@24");
1138 memset(&tags
, 0 , sizeof(tags
));
1140 /* Create the object */
1142 sc
= pCreateIProp(&IID_IMAPIPropData
, MAPIAllocateBuffer
, MAPIAllocateMore
,
1143 MAPIFreeBuffer
, NULL
, &lpIProp
);
1144 ok(sc
== S_OK
&& lpIProp
,
1145 "CreateIProp: expected S_OK, non-null, got 0x%08lX,%p\n", sc
, lpIProp
);
1147 if (sc
!= S_OK
|| !lpIProp
)
1150 /* GetLastError - No errors set */
1152 IPropData_GetLastError(lpIProp
, E_INVALIDARG
, 0, &lpError
);
1153 ok(sc
== S_OK
&& !lpError
,
1154 "GetLastError: Expected S_OK, null, got 0x%08lX,%p\n", sc
, lpError
);
1156 /* Get prop tags - succeeds returning 0 items */
1158 sc
= IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1159 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 0,
1160 "GetPropList(empty): Expected S_OK, non-null, 0, got 0x%08lX,%p,%ld\n",
1161 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1163 MAPIFreeBuffer(lpTags
);
1165 /* Get props - succeeds returning 0 items */
1169 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1170 sc
= IPropData_GetProps(lpIProp
, (LPSPropTagArray
)&tags
, 0, &count
, &lpProps
);
1171 ok(sc
== MAPI_W_ERRORS_RETURNED
&& lpProps
&& count
== 1,
1172 "GetProps(empty): Expected ERRORS_RETURNED, non-null, 1, got 0x%08lX,%p,%ld\n",
1173 sc
, lpProps
, count
);
1174 if (lpProps
&& count
> 0)
1176 ok(lpProps
[0].ulPropTag
== CHANGE_PROP_TYPE(PR_IMPORTANCE
,PT_ERROR
),
1177 "GetProps(empty): Expected %x, got %lx\n",
1178 CHANGE_PROP_TYPE(PR_IMPORTANCE
,PT_ERROR
), lpProps
[0].ulPropTag
);
1180 MAPIFreeBuffer(lpProps
);
1183 /* Add (NULL) - Can't add NULL's */
1185 pvs
[0].ulPropTag
= PROP_TAG(PT_NULL
,0x01);
1186 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1187 ok(sc
== MAPI_E_INVALID_PARAMETER
&& !lpProbs
,
1188 "SetProps(): Expected INVALID_PARAMETER, null, got 0x%08lX,%p\n",
1191 /* Add (OBJECT) - Can't add OBJECTS's */
1193 pvs
[0].ulPropTag
= PROP_TAG(PT_OBJECT
,0x01);
1194 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1195 ok(sc
== MAPI_E_INVALID_PARAMETER
&& !lpProbs
,
1196 "SetProps(OBJECT): Expected INVALID_PARAMETER, null, got 0x%08lX,%p\n",
1199 /* Add - Adds value */
1201 pvs
[0].ulPropTag
= PR_IMPORTANCE
;
1202 sc
= IPropData_SetProps(lpIProp
, 1, pvs
, &lpProbs
);
1203 ok(sc
== S_OK
&& !lpProbs
,
1204 "SetProps(ERROR): Expected S_OK, null, got 0x%08lX,%p\n", sc
, lpProbs
);
1206 /* Get prop list - returns 1 item */
1208 IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1209 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 1,
1210 "GetPropList: Expected S_OK, non-null, 1, got 0x%08lX,%p,%ld\n",
1211 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1212 if (lpTags
&& lpTags
->cValues
> 0)
1214 ok(lpTags
->aulPropTag
[0] == PR_IMPORTANCE
,
1215 "GetPropList: Expected %x, got %lx\n",
1216 PR_IMPORTANCE
, lpTags
->aulPropTag
[0]);
1217 MAPIFreeBuffer(lpTags
);
1220 /* Set access to read and write */
1221 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READWRITE
);
1222 ok(sc
== S_OK
, "SetObjAcess(WRITE): Expected S_OK got 0x%08lX\n", sc
);
1225 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1227 /* Set item access (bad access) - Fails */
1229 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1230 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1231 "SetPropAcess(0): Expected INVALID_PARAMETER got 0x%08lX\n",sc
);
1232 access
[0] = IPROP_READWRITE
;
1233 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1234 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1235 "SetPropAcess(RW): Expected INVALID_PARAMETER got 0x%08lX\n",sc
);
1236 access
[0] = IPROP_CLEAN
;
1237 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1238 ok(sc
== MAPI_E_INVALID_PARAMETER
,
1239 "SetPropAcess(C): Expected INVALID_PARAMETER got 0x%08lX\n",sc
);
1241 /* Set item access to read/write/clean */
1243 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1244 access
[0] = IPROP_READWRITE
|IPROP_CLEAN
;
1245 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1246 ok(sc
== S_OK
, "SetPropAcess(RW/C): Expected S_OK got 0x%08lX\n",sc
);
1248 /* Set object access to read only */
1249 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READONLY
);
1250 ok(sc
== S_OK
, "SetObjAcess(READ): Expected S_OK got 0x%08lX\n", sc
);
1252 /* Set item access to read/write/dirty - doesn't care about RO object */
1253 access
[0] = IPROP_READONLY
|IPROP_DIRTY
;
1254 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1255 ok(sc
== S_OK
, "SetPropAcess(WRITE): Expected S_OK got 0x%08lX\n", sc
);
1257 /* Delete any item when set to read only - Error */
1259 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1260 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1261 ok(sc
== E_ACCESSDENIED
&& !lpProbs
,
1262 "DeleteProps(nonexistent): Expected E_ACCESSDENIED null got 0x%08lX %p\n",
1265 /* Set access to read and write */
1266 sc
= IPropData_HrSetObjAccess(lpIProp
, IPROP_READWRITE
);
1267 ok(sc
== S_OK
, "SetObjAcess(WRITE): Expected S_OK got 0x%08lX\n", sc
);
1269 /* Delete nonexistent item - No error */
1271 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1272 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1273 ok(sc
== S_OK
&& !lpProbs
,
1274 "DeleteProps(nonexistent): Expected S_OK null got 0x%08lX %p\n",
1277 /* Delete existing item (r/o) - No error, but lpProbs populated */
1279 tags
.aulPropTag
[0] = PR_IMPORTANCE
;
1280 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1281 ok(sc
== S_OK
&& lpProbs
,
1282 "DeleteProps(RO): Expected S_OK non-null got 0x%08lX %p\n", sc
, lpProbs
);
1284 if (lpProbs
&& lpProbs
->cProblem
> 0)
1286 ok(lpProbs
->cProblem
== 1 &&
1287 lpProbs
->aProblem
[0].ulIndex
== 0 &&
1288 lpProbs
->aProblem
[0].ulPropTag
== PR_IMPORTANCE
&&
1289 lpProbs
->aProblem
[0].scode
== E_ACCESSDENIED
,
1290 "DeleteProps(RO): Expected (1,0,%x,%lx) got (%ld,%lx,%lx)\n",
1291 PR_IMPORTANCE
, E_ACCESSDENIED
,
1292 lpProbs
->aProblem
[0].ulIndex
, lpProbs
->aProblem
[0].ulPropTag
,
1293 lpProbs
->aProblem
[0].scode
);
1294 MAPIFreeBuffer(lpProbs
);
1299 tags
.aulPropTag
[0] = PR_RESPONSE_REQUESTED
;
1300 IPropData_HrAddObjProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1301 ok(sc
== S_OK
&& !lpProbs
,
1302 "AddObjProps(RO): Expected S_OK null got 0x%08lX %p\n", sc
, lpProbs
);
1304 /* Get prop list - returns 1 item */
1306 IPropData_GetPropList(lpIProp
, 0, &lpTags
);
1307 ok(sc
== S_OK
&& lpTags
&& lpTags
->cValues
== 1,
1308 "GetPropList: Expected S_OK, non-null, 1, got 0x%08lX,%p,%ld\n",
1309 sc
, lpTags
, lpTags
? lpTags
->cValues
: 0);
1310 if (lpTags
&& lpTags
->cValues
> 0)
1312 ok(lpTags
->aulPropTag
[0] == PR_IMPORTANCE
,
1313 "GetPropList: Expected %x, got %lx\n",
1314 PR_IMPORTANCE
, lpTags
->aulPropTag
[0]);
1315 MAPIFreeBuffer(lpTags
);
1318 /* Set item to r/w again */
1319 access
[0] = IPROP_READWRITE
|IPROP_DIRTY
;
1320 sc
= IPropData_HrSetPropAccess(lpIProp
, (LPSPropTagArray
)&tags
, access
);
1321 ok(sc
== S_OK
, "SetPropAcess(WRITE): Expected S_OK got 0x%08lX\n", sc
);
1323 /* Delete existing item (r/w) - No error, no problems */
1325 sc
= IPropData_DeleteProps(lpIProp
, (LPSPropTagArray
)&tags
, &lpProbs
);
1326 ok(sc
== S_OK
&& !lpProbs
,
1327 "DeleteProps(RO): Expected S_OK null got 0x%08lX %p\n", sc
, lpProbs
);
1330 IPropData_Release(lpIProp
);
1335 hMapi32
= LoadLibraryA("mapi32.dll");
1337 pScInitMapiUtil
= (void*)GetProcAddress(hMapi32
, "ScInitMapiUtil@4");
1338 if (!pScInitMapiUtil
)
1342 test_PropCopyMore();
1344 test_FPropContainsProp();
1345 test_FPropCompareProp();
1346 test_LPropCompareProp();
1347 test_PpropFindProp();
1348 test_ScCountProps();
1349 test_ScCopyRelocProps();
1350 test_LpValFindProp();
1357 test_FBadColumnSet();