diff --git a/configure b/configure index d777ef38b13..755829de6f6 100755 --- a/configure +++ b/configure @@ -20031,7 +20031,7 @@ MAKE_LIB_RULES=libs/Makelib.rules MAKE_PROG_RULES=programs/Makeprog.rules - ac_config_files="$ac_config_files Make.rules dlls/Makedll.rules dlls/Maketest.rules libs/Makelib.rules programs/Makeprog.rules Makefile dlls/Makefile dlls/advapi32/Makefile dlls/advapi32/tests/Makefile dlls/amstream/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/cabinet/Makefile dlls/capi2032/Makefile dlls/cards/Makefile dlls/cfgmgr32/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/comctl32/tests/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/ctl3d/Makefile dlls/d3d8/Makefile dlls/d3d9/Makefile dlls/d3dim/Makefile dlls/d3dx8/Makefile dlls/dbghelp/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/ddraw/tests/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput8/Makefile dlls/dmband/Makefile dlls/dmcompos/Makefile dlls/dmime/Makefile dlls/dmloader/Makefile dlls/dmscript/Makefile dlls/dmstyle/Makefile dlls/dmsynth/Makefile dlls/dmusic/Makefile dlls/dmusic32/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dpnet/Makefile dlls/dpnhpast/Makefile dlls/dsound/Makefile dlls/dsound/tests/Makefile dlls/dswave/Makefile dlls/dxdiagn/Makefile dlls/dxerr8/Makefile dlls/dxerr9/Makefile dlls/dxguid/Makefile dlls/gdi/Makefile dlls/gdi/tests/Makefile dlls/glu32/Makefile dlls/glut32/Makefile dlls/hhctrl.ocx/Makefile dlls/iccvid/Makefile dlls/icmp/Makefile dlls/ifsmgr.vxd/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/iphlpapi/Makefile dlls/iphlpapi/tests/Makefile dlls/kernel/Makefile dlls/kernel/tests/Makefile dlls/lzexpand/Makefile dlls/mapi32/Makefile dlls/mmdevldr.vxd/Makefile dlls/monodebg.vxd/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msdmo/Makefile dlls/mshtml/Makefile dlls/msi/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msrle32/Makefile dlls/msvcrt/Makefile dlls/msvcrt/tests/Makefile dlls/msvcrt20/Makefile dlls/msvcrt40/Makefile dlls/msvcrtd/Makefile dlls/msvidc32/Makefile dlls/msvideo/Makefile dlls/mswsock/Makefile dlls/netapi32/Makefile dlls/netapi32/tests/Makefile dlls/newdev/Makefile dlls/ntdll/Makefile dlls/ntdll/tests/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile dlls/oleacc/Makefile dlls/oleaut32/Makefile dlls/oleaut32/tests/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/psapi/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/rasapi32/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/rpcrt4/tests/Makefile dlls/rsabase/Makefile dlls/secur32/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shell32/tests/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/shlwapi/tests/Makefile dlls/snmpapi/Makefile dlls/sti/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/unicows/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/urlmon/tests/Makefile dlls/user/Makefile dlls/user/tests/Makefile dlls/uuid/Makefile dlls/uxtheme/Makefile dlls/vdhcp.vxd/Makefile dlls/vdmdbg/Makefile dlls/version/Makefile dlls/version/tests/Makefile dlls/vmm.vxd/Makefile dlls/vnbt.vxd/Makefile dlls/vnetbios.vxd/Makefile dlls/vtdapi.vxd/Makefile dlls/vwin32.vxd/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/wined3d/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/wininet/tests/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/midimap/Makefile dlls/winmm/tests/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineaudioio/Makefile dlls/winmm/winejack/Makefile dlls/winmm/winenas/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winsock/tests/Makefile dlls/winspool/Makefile dlls/winspool/tests/Makefile dlls/wintab32/Makefile dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/x11drv/Makefile documentation/Makefile include/Makefile libs/Makefile libs/port/Makefile libs/unicode/Makefile libs/wine/Makefile libs/wpp/Makefile loader/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/notepad/Makefile programs/progman/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/rpcss/Makefile programs/rundll32/Makefile programs/start/Makefile programs/taskmgr/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineboot/Makefile programs/winebrowser/Makefile programs/winecfg/Makefile programs/wineconsole/Makefile programs/winedbg/Makefile programs/winefile/Makefile programs/winemenubuilder/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winetest/Makefile programs/winevdm/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/widl/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/winegcc/Makefile tools/wmc/Makefile tools/wrc/Makefile" + ac_config_files="$ac_config_files Make.rules dlls/Makedll.rules dlls/Maketest.rules libs/Makelib.rules programs/Makeprog.rules Makefile dlls/Makefile dlls/advapi32/Makefile dlls/advapi32/tests/Makefile dlls/amstream/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/cabinet/Makefile dlls/capi2032/Makefile dlls/cards/Makefile dlls/cfgmgr32/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/comctl32/tests/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/ctl3d/Makefile dlls/d3d8/Makefile dlls/d3d9/Makefile dlls/d3dim/Makefile dlls/d3dx8/Makefile dlls/dbghelp/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/ddraw/tests/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput8/Makefile dlls/dmband/Makefile dlls/dmcompos/Makefile dlls/dmime/Makefile dlls/dmloader/Makefile dlls/dmscript/Makefile dlls/dmstyle/Makefile dlls/dmsynth/Makefile dlls/dmusic/Makefile dlls/dmusic32/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dpnet/Makefile dlls/dpnhpast/Makefile dlls/dsound/Makefile dlls/dsound/tests/Makefile dlls/dswave/Makefile dlls/dxdiagn/Makefile dlls/dxerr8/Makefile dlls/dxerr9/Makefile dlls/dxguid/Makefile dlls/gdi/Makefile dlls/gdi/tests/Makefile dlls/glu32/Makefile dlls/glut32/Makefile dlls/hhctrl.ocx/Makefile dlls/iccvid/Makefile dlls/icmp/Makefile dlls/ifsmgr.vxd/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/iphlpapi/Makefile dlls/iphlpapi/tests/Makefile dlls/kernel/Makefile dlls/kernel/tests/Makefile dlls/lzexpand/Makefile dlls/mapi32/Makefile dlls/mapi32/tests/Makefile dlls/mmdevldr.vxd/Makefile dlls/monodebg.vxd/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msdmo/Makefile dlls/mshtml/Makefile dlls/msi/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msrle32/Makefile dlls/msvcrt/Makefile dlls/msvcrt/tests/Makefile dlls/msvcrt20/Makefile dlls/msvcrt40/Makefile dlls/msvcrtd/Makefile dlls/msvidc32/Makefile dlls/msvideo/Makefile dlls/mswsock/Makefile dlls/netapi32/Makefile dlls/netapi32/tests/Makefile dlls/newdev/Makefile dlls/ntdll/Makefile dlls/ntdll/tests/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile dlls/oleacc/Makefile dlls/oleaut32/Makefile dlls/oleaut32/tests/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/psapi/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/rasapi32/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/rpcrt4/tests/Makefile dlls/rsabase/Makefile dlls/secur32/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shell32/tests/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/shlwapi/tests/Makefile dlls/snmpapi/Makefile dlls/sti/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/unicows/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/urlmon/tests/Makefile dlls/user/Makefile dlls/user/tests/Makefile dlls/uuid/Makefile dlls/uxtheme/Makefile dlls/vdhcp.vxd/Makefile dlls/vdmdbg/Makefile dlls/version/Makefile dlls/version/tests/Makefile dlls/vmm.vxd/Makefile dlls/vnbt.vxd/Makefile dlls/vnetbios.vxd/Makefile dlls/vtdapi.vxd/Makefile dlls/vwin32.vxd/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/wined3d/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/wininet/tests/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/midimap/Makefile dlls/winmm/tests/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineaudioio/Makefile dlls/winmm/winejack/Makefile dlls/winmm/winenas/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winsock/tests/Makefile dlls/winspool/Makefile dlls/winspool/tests/Makefile dlls/wintab32/Makefile dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/x11drv/Makefile documentation/Makefile include/Makefile libs/Makefile libs/port/Makefile libs/unicode/Makefile libs/wine/Makefile libs/wpp/Makefile loader/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/notepad/Makefile programs/progman/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/rpcss/Makefile programs/rundll32/Makefile programs/start/Makefile programs/taskmgr/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineboot/Makefile programs/winebrowser/Makefile programs/winecfg/Makefile programs/wineconsole/Makefile programs/winedbg/Makefile programs/winefile/Makefile programs/winemenubuilder/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winetest/Makefile programs/winevdm/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/widl/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/winegcc/Makefile tools/wmc/Makefile tools/wrc/Makefile" cat >confcache <<\_ACEOF @@ -20632,6 +20632,7 @@ do "dlls/kernel/tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/kernel/tests/Makefile" ;; "dlls/lzexpand/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/lzexpand/Makefile" ;; "dlls/mapi32/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/mapi32/Makefile" ;; + "dlls/mapi32/tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/mapi32/tests/Makefile" ;; "dlls/mmdevldr.vxd/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/mmdevldr.vxd/Makefile" ;; "dlls/monodebg.vxd/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/monodebg.vxd/Makefile" ;; "dlls/mpr/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/mpr/Makefile" ;; diff --git a/configure.ac b/configure.ac index d08842452ce..fba45a34676 100644 --- a/configure.ac +++ b/configure.ac @@ -1557,6 +1557,7 @@ dlls/kernel/Makefile dlls/kernel/tests/Makefile dlls/lzexpand/Makefile dlls/mapi32/Makefile +dlls/mapi32/tests/Makefile dlls/mmdevldr.vxd/Makefile dlls/monodebg.vxd/Makefile dlls/mpr/Makefile diff --git a/dlls/mapi32/tests/.cvsignore b/dlls/mapi32/tests/.cvsignore new file mode 100644 index 00000000000..526e3c48625 --- /dev/null +++ b/dlls/mapi32/tests/.cvsignore @@ -0,0 +1,4 @@ +Makefile +prop.ok +testlist.c +util.ok diff --git a/dlls/mapi32/tests/Makefile.in b/dlls/mapi32/tests/Makefile.in new file mode 100644 index 00000000000..9b938766716 --- /dev/null +++ b/dlls/mapi32/tests/Makefile.in @@ -0,0 +1,15 @@ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +TESTDLL = mapi32.dll +IMPORTS = mapi32 +EXTRALIBS = -luuid + +CTESTS = \ + prop.c \ + util.c + +@MAKE_TEST_RULES@ + +### Dependencies: diff --git a/dlls/mapi32/tests/prop.c b/dlls/mapi32/tests/prop.c new file mode 100644 index 00000000000..f223c6cc082 --- /dev/null +++ b/dlls/mapi32/tests/prop.c @@ -0,0 +1,1073 @@ +/* + * Unit test suite for MAPI property functions + * + * Copyright 2004 Jon Griffiths + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "wine/test.h" +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winerror.h" +#include "winnt.h" +#include "mapiutil.h" +#include "mapitags.h" + +HRESULT WINAPI MAPIInitialize(LPVOID); + +static HMODULE hMapi32 = 0; + +static SCODE (WINAPI *pScInitMapiUtil)(ULONG); +static SCODE (WINAPI *pPropCopyMore)(LPSPropValue,LPSPropValue,ALLOCATEMORE*,LPVOID); +static ULONG (WINAPI *pUlPropSize)(LPSPropValue); +static BOOL (WINAPI *pFPropContainsProp)(LPSPropValue,LPSPropValue,ULONG); +static BOOL (WINAPI *pFPropCompareProp)(LPSPropValue,ULONG,LPSPropValue); +static LONG (WINAPI *pLPropCompareProp)(LPSPropValue,LPSPropValue); +static LPSPropValue (WINAPI *pPpropFindProp)(LPSPropValue,ULONG,ULONG); +static SCODE (WINAPI *pScCountProps)(INT,LPSPropValue,ULONG*); +static LPSPropValue (WINAPI *pLpValFindProp)(ULONG,ULONG,LPSPropValue); +static BOOL (WINAPI *pFBadRglpszA)(LPSTR*,ULONG); +static BOOL (WINAPI *pFBadRglpszW)(LPWSTR*,ULONG); +static BOOL (WINAPI *pFBadRowSet)(LPSRowSet); +static ULONG (WINAPI *pFBadPropTag)(ULONG); +static ULONG (WINAPI *pFBadRow)(LPSRow); +static ULONG (WINAPI *pFBadProp)(LPSPropValue); +static ULONG (WINAPI *pFBadColumnSet)(LPSPropTagArray); + +static ULONG ptTypes[] = { + PT_I2, PT_I4, PT_R4, PT_R8, PT_CURRENCY, PT_APPTIME, PT_SYSTIME, + PT_ERROR, PT_BOOLEAN, PT_I8, PT_CLSID, PT_STRING8, PT_BINARY, + PT_UNICODE +}; + +static inline int strcmpW(const WCHAR *str1, const WCHAR *str2) +{ + while (*str1 && (*str1 == *str2)) { str1++; str2++; } + return *str1 - *str2; +} + +static void test_PropCopyMore(void) +{ + static const char *szHiA = "Hi!"; + static const WCHAR szHiW[] = { 'H', 'i', '!', '\0' }; + SPropValue *lpDest = NULL, *lpSrc = NULL; + ULONG i; + SCODE scode; + + pPropCopyMore = (void*)GetProcAddress(hMapi32, "PropCopyMore@16"); + + if (!pPropCopyMore) + return; + + scode = MAPIAllocateBuffer(sizeof(LPSPropValue), (LPVOID *)lpDest); + if (FAILED(scode)) + return; + + scode = MAPIAllocateMore(sizeof(LPSPropValue), lpDest, (LPVOID *)lpSrc); + if (FAILED(scode)) + return; + + for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++) + { + lpSrc->ulPropTag = ptTypes[i]; + + switch (ptTypes[i]) + { + case PT_STRING8: + lpSrc->Value.lpszA = (char*)szHiA; + break; + case PT_UNICODE: + lpSrc->Value.lpszW = (WCHAR*)szHiW; + break; + case PT_BINARY: + lpSrc->Value.bin.cb = 4; + lpSrc->Value.bin.lpb = (LPBYTE)szHiA; + break; + } + + memset(lpDest, 0xff, sizeof(SPropValue)); + + scode = pPropCopyMore(lpDest, lpSrc, MAPIAllocateMore, lpDest); + ok(!scode && lpDest->ulPropTag == lpSrc->ulPropTag, + "PropCopyMore: Expected 0x0,%ld, got 0x%08lx,%ld\n", + lpSrc->ulPropTag, scode, lpDest->ulPropTag); + if (SUCCEEDED(scode)) + { + switch (ptTypes[i]) + { + case PT_STRING8: + ok(lstrcmpA(lpDest->Value.lpszA, lpSrc->Value.lpszA) == 0, + "PropCopyMore: Ascii string differs\n"); + break; + case PT_UNICODE: + ok(strcmpW(lpDest->Value.lpszW, lpSrc->Value.lpszW) == 0, + "PropCopyMore: Unicode string differs\n"); + break; + case PT_BINARY: + ok(lpDest->Value.bin.cb == 4 && + !memcmp(lpSrc->Value.bin.lpb, lpDest->Value.bin.lpb, 4), + "PropCopyMore: Binary array differs\n"); + break; + } + } + } + + /* Since all allocations are linked, freeing lpDest frees everything */ + MAPIFreeBuffer(lpDest); +} + +static void test_UlPropSize(void) +{ + static const char *szHiA = "Hi!"; + static const WCHAR szHiW[] = { 'H', 'i', '!', '\0' }; + LPSTR buffa[2]; + LPWSTR buffw[2]; + SBinary buffbin[2]; + ULONG pt, exp, res; + + pUlPropSize = (void*)GetProcAddress(hMapi32, "UlPropSize@4"); + + if (!pUlPropSize) + return; + + for (pt = 0; pt < PROP_ID_INVALID; pt++) + { + SPropValue pv; + + memset(&pv, 0 ,sizeof(pv)); + pv.ulPropTag = pt; + + exp = 1u; /* Default to one item for non-MV properties */ + + switch (PROP_TYPE(pt)) + { + case PT_MV_I2: pv.Value.MVi.cValues = exp = 2; + case PT_I2: exp *= sizeof(USHORT); break; + case PT_MV_I4: pv.Value.MVl.cValues = exp = 2; + case PT_I4: exp *= sizeof(LONG); break; + case PT_MV_R4: pv.Value.MVflt.cValues = exp = 2; + case PT_R4: exp *= sizeof(float); break; + case PT_MV_DOUBLE: pv.Value.MVdbl.cValues = exp = 2; + case PT_R8: exp *= sizeof(double); break; + case PT_MV_CURRENCY: pv.Value.MVcur.cValues = exp = 2; + case PT_CURRENCY: exp *= sizeof(CY); break; + case PT_MV_APPTIME: pv.Value.MVat.cValues = exp = 2; + case PT_APPTIME: exp *= sizeof(double); break; + case PT_MV_SYSTIME: pv.Value.MVft.cValues = exp = 2; + case PT_SYSTIME: exp *= sizeof(FILETIME); break; + case PT_ERROR: exp = sizeof(SCODE); break; + case PT_BOOLEAN: exp = sizeof(USHORT); break; + case PT_OBJECT: exp = 0; break; + case PT_MV_I8: pv.Value.MVli.cValues = exp = 2; + case PT_I8: exp *= sizeof(LONG64); break; +#if 0 + /* My version of native mapi returns 0 for PT_MV_CLSID even if a valid + * array is given. This _has_ to be a bug, so Wine does + * the right thing(tm) and we don't test it here. + */ + case PT_MV_CLSID: pv.Value.MVguid.cValues = exp = 2; +#endif + case PT_CLSID: exp *= sizeof(GUID); break; + case PT_STRING8: + pv.Value.lpszA = (LPSTR)szHiA; + exp = 4; + break; + case PT_UNICODE: + pv.Value.lpszW = (LPWSTR)szHiW; + exp = 4 * sizeof(WCHAR); + break; + case PT_BINARY: + pv.Value.bin.cb = exp = 19; + break; + case PT_MV_STRING8: + pv.Value.MVszA.cValues = 2; + pv.Value.MVszA.lppszA = buffa; + buffa[0] = (LPSTR)szHiA; + buffa[1] = (LPSTR)szHiA; + exp = 8; + break; + case PT_MV_UNICODE: + pv.Value.MVszW.cValues = 2; + pv.Value.MVszW.lppszW = buffw; + buffw[0] = (LPWSTR)szHiW; + buffw[1] = (LPWSTR)szHiW; + exp = 8 * sizeof(WCHAR); + break; + case PT_MV_BINARY: + pv.Value.MVbin.cValues = 2; + pv.Value.MVbin.lpbin = buffbin; + buffbin[0].cb = 19; + buffbin[1].cb = 1; + exp = 20; + break; + default: + exp = 0; + } + + res = pUlPropSize(&pv); + ok(res == exp, "pt= %ld: Expected %ld, got %ld\n", pt, exp, res); + } +} + +static void test_FPropContainsProp(void) +{ + static const char *szFull = "Full String"; + static const char *szFullLower = "full string"; + static const char *szPrefix = "Full"; + static const char *szPrefixLower = "full"; + static const char *szSubstring = "ll St"; + static const char *szSubstringLower = "ll st"; + SPropValue pvLeft, pvRight; + ULONG pt; + BOOL bRet; + + pFPropContainsProp = (void*)GetProcAddress(hMapi32, "FPropContainsProp@12"); + + if (!pFPropContainsProp) + return; + + /* Ensure that only PT_STRING8 and PT_BINARY are handled */ + for (pt = 0; pt < PROP_ID_INVALID; pt++) + { + if (pt == PT_STRING8 || pt == PT_BINARY) + continue; /* test these later */ + + memset(&pvLeft, 0 ,sizeof(pvLeft)); + memset(&pvRight, 0 ,sizeof(pvRight)); + pvLeft.ulPropTag = pvRight.ulPropTag = pt; + + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING); + ok(bRet == FALSE, "pt= %ld: Expected FALSE, got %d\n", pt, bRet); + } + + /* test the various flag combinations */ + pvLeft.ulPropTag = pvRight.ulPropTag = PT_STRING8; + pvLeft.Value.lpszA = (LPSTR)szFull; + pvRight.Value.lpszA = (LPSTR)szFull; + + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING); + ok(bRet == TRUE, "(full,full)[] match failed\n"); + pvRight.Value.lpszA = (LPSTR)szPrefix; + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING); + ok(bRet == FALSE, "(full,prefix)[] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX); + ok(bRet == TRUE, "(full,prefix)[PREFIX] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING); + ok(bRet == TRUE, "(full,prefix)[SUBSTRING] match failed\n"); + pvRight.Value.lpszA = (LPSTR)szPrefixLower; + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX); + ok(bRet == FALSE, "(full,prefixlow)[PREFIX] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING); + ok(bRet == FALSE, "(full,prefixlow)[SUBSTRING] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE); + ok(bRet == TRUE, "(full,prefixlow)[PREFIX|IGNORECASE] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE); + ok(bRet == TRUE, "(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n"); + pvRight.Value.lpszA = (LPSTR)szSubstring; + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING); + ok(bRet == FALSE, "(full,substr)[] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX); + ok(bRet == FALSE, "(full,substr)[PREFIX] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING); + ok(bRet == TRUE, "(full,substr)[SUBSTRING] match failed\n"); + pvRight.Value.lpszA = (LPSTR)szSubstringLower; + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX); + ok(bRet == FALSE, "(full,substrlow)[PREFIX] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING); + ok(bRet == FALSE, "(full,substrlow)[SUBSTRING] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE); + ok(bRet == FALSE, "(full,substrlow)[PREFIX|IGNORECASE] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE); + ok(bRet == TRUE, "(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n"); + pvRight.Value.lpszA = (LPSTR)szFullLower; + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING|FL_IGNORECASE); + ok(bRet == TRUE, "(full,fulllow)[IGNORECASE] match failed\n"); + + pvLeft.ulPropTag = pvRight.ulPropTag = PT_BINARY; + pvLeft.Value.bin.lpb = (LPBYTE)szFull; + pvRight.Value.bin.lpb = (LPBYTE)szFull; + pvLeft.Value.bin.cb = pvRight.Value.bin.cb = strlen(szFull); + + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING); + ok(bRet == TRUE, "bin(full,full)[] match failed\n"); + pvRight.Value.bin.lpb = (LPBYTE)szPrefix; + pvRight.Value.bin.cb = strlen(szPrefix); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING); + ok(bRet == FALSE, "bin(full,prefix)[] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX); + ok(bRet == TRUE, "bin(full,prefix)[PREFIX] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING); + ok(bRet == TRUE, "bin(full,prefix)[SUBSTRING] match failed\n"); + pvRight.Value.bin.lpb = (LPBYTE)szPrefixLower; + pvRight.Value.bin.cb = strlen(szPrefixLower); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX); + ok(bRet == FALSE, "bin(full,prefixlow)[PREFIX] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING); + ok(bRet == FALSE, "bin(full,prefixlow)[SUBSTRING] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE); + ok(bRet == FALSE, "bin(full,prefixlow)[PREFIX|IGNORECASE] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE); + ok(bRet == FALSE, "bin(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n"); + pvRight.Value.bin.lpb = (LPBYTE)szSubstring; + pvRight.Value.bin.cb = strlen(szSubstring); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING); + ok(bRet == FALSE, "bin(full,substr)[] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX); + ok(bRet == FALSE, "bin(full,substr)[PREFIX] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING); + ok(bRet == TRUE, "bin(full,substr)[SUBSTRING] match failed\n"); + pvRight.Value.bin.lpb = (LPBYTE)szSubstringLower; + pvRight.Value.bin.cb = strlen(szSubstringLower); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX); + ok(bRet == FALSE, "bin(full,substrlow)[PREFIX] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING); + ok(bRet == FALSE, "bin(full,substrlow)[SUBSTRING] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE); + ok(bRet == FALSE, "bin(full,substrlow)[PREFIX|IGNORECASE] match failed\n"); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE); + ok(bRet == FALSE, "bin(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n"); + pvRight.Value.bin.lpb = (LPBYTE)szFullLower; + pvRight.Value.bin.cb = strlen(szFullLower); + bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING|FL_IGNORECASE); + ok(bRet == FALSE, "bin(full,fulllow)[IGNORECASE] match failed\n"); +} + +typedef struct tagFPropCompareProp_Result +{ + SHORT lVal; + SHORT rVal; + ULONG relOp; + BOOL bRet; +} FPropCompareProp_Result; + +static const FPropCompareProp_Result FPCProp_Results[] = +{ + { 1, 2, RELOP_LT, TRUE }, + { 1, 1, RELOP_LT, FALSE }, + { 2, 1, RELOP_LT, FALSE }, + { 1, 2, RELOP_LE, TRUE }, + { 1, 1, RELOP_LE, TRUE }, + { 2, 1, RELOP_LE, FALSE }, + { 1, 2, RELOP_GT, FALSE }, + { 1, 1, RELOP_GT, FALSE }, + { 2, 1, RELOP_GT, TRUE }, + { 1, 2, RELOP_GE, FALSE }, + { 1, 1, RELOP_GE, TRUE }, + { 2, 1, RELOP_GE, TRUE }, + { 1, 2, RELOP_EQ, FALSE }, + { 1, 1, RELOP_EQ, TRUE }, + { 2, 1, RELOP_EQ, FALSE } +}; + +static const char *relops[] = { "RELOP_LT", "RELOP_LE", "RELOP_GT", "RELOP_GE", "RELOP_EQ" }; + +static void test_FPropCompareProp(void) +{ + SPropValue pvLeft, pvRight; + GUID lguid, rguid; + char lbuffa[2], rbuffa[2]; + WCHAR lbuffw[2], rbuffw[2]; + ULONG i, j; + BOOL bRet, bExp; + + pFPropCompareProp = (void*)GetProcAddress(hMapi32, "FPropCompareProp@12"); + + if (!pFPropCompareProp) + return; + + lbuffa[1] = '\0'; + rbuffa[1] = '\0'; + lbuffw[1] = '\0'; + rbuffw[1] = '\0'; + + for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++) + { + pvLeft.ulPropTag = pvRight.ulPropTag = ptTypes[i]; + + for (j = 0; j < sizeof(FPCProp_Results)/sizeof(FPCProp_Results[0]); j++) + { + SHORT lVal = FPCProp_Results[j].lVal; + SHORT rVal = FPCProp_Results[j].rVal; + + bExp = FPCProp_Results[j].bRet; + + switch (ptTypes[i]) + { + case PT_BOOLEAN: + /* Boolean values have no concept of less or greater than, only equality */ + if ((lVal == 1 && rVal == 2 && FPCProp_Results[j].relOp == RELOP_LT) || + (lVal == 2 && rVal == 1 && FPCProp_Results[j].relOp == RELOP_LE)|| + (lVal == 2 && rVal == 1 && FPCProp_Results[j].relOp == RELOP_GT)|| + (lVal == 1 && rVal == 2 && FPCProp_Results[j].relOp == RELOP_GE)|| + (lVal == 1 && rVal == 2 && FPCProp_Results[j].relOp == RELOP_EQ)|| + (lVal == 2 && rVal == 1 && FPCProp_Results[j].relOp == RELOP_EQ)) + bExp = !bExp; + /* Fall through ... */ + case PT_I2: + pvLeft.Value.i = lVal; + pvRight.Value.i = rVal; + break; + case PT_ERROR: + case PT_I4: + pvLeft.Value.l = lVal; + pvRight.Value.l = rVal; + break; + case PT_R4: + pvLeft.Value.flt = lVal; + pvRight.Value.flt = rVal; + break; + case PT_APPTIME: + case PT_R8: + pvLeft.Value.dbl = lVal; + pvRight.Value.dbl = rVal; + break; + case PT_CURRENCY: + pvLeft.Value.cur.int64 = lVal; + pvRight.Value.cur.int64 = rVal; + break; + case PT_SYSTIME: + pvLeft.Value.ft.dwLowDateTime = lVal; + pvLeft.Value.ft.dwHighDateTime = 0; + pvRight.Value.ft.dwLowDateTime = rVal; + pvRight.Value.ft.dwHighDateTime = 0; + break; + case PT_I8: + pvLeft.Value.li.u.LowPart = lVal; + pvLeft.Value.li.u.HighPart = 0; + pvRight.Value.li.u.LowPart = rVal; + pvRight.Value.li.u.HighPart = 0; + break; + case PT_CLSID: + memset(&lguid, 0, sizeof(GUID)); + memset(&rguid, 0, sizeof(GUID)); + lguid.Data4[7] = lVal; + rguid.Data4[7] = rVal; + pvLeft.Value.lpguid = &lguid; + pvRight.Value.lpguid = &rguid; + break; + case PT_STRING8: + pvLeft.Value.lpszA = lbuffa; + pvRight.Value.lpszA = rbuffa; + lbuffa[0] = '0' + lVal; + rbuffa[0] = '0' + rVal; + break; + case PT_UNICODE: + pvLeft.Value.lpszW = lbuffw; + pvRight.Value.lpszW = rbuffw; + lbuffw[0] = '0' + lVal; + rbuffw[0] = '0' + rVal; + break; + case PT_BINARY: + pvLeft.Value.bin.cb = 1; + pvRight.Value.bin.cb = 1; + pvLeft.Value.bin.lpb = lbuffa; + pvRight.Value.bin.lpb = rbuffa; + lbuffa[0] = lVal; + rbuffa[0] = rVal; + break; + } + + bRet = pFPropCompareProp(&pvLeft, FPCProp_Results[j].relOp, &pvRight); + ok(bRet == bExp, "pt %ld (%d,%d,%s): expected %d, got %d\n", ptTypes[i], + FPCProp_Results[j].lVal, FPCProp_Results[j].rVal, + relops[FPCProp_Results[j].relOp], bExp, bRet); + } + } +} + +typedef struct tagLPropCompareProp_Result +{ + SHORT lVal; + SHORT rVal; + INT iRet; +} LPropCompareProp_Result; + +static const LPropCompareProp_Result LPCProp_Results[] = +{ + { 1, 2, -1 }, + { 1, 1, 0 }, + { 2, 1, 1 }, +}; + +static void test_LPropCompareProp(void) +{ + SPropValue pvLeft, pvRight; + GUID lguid, rguid; + char lbuffa[2], rbuffa[2]; + WCHAR lbuffw[2], rbuffw[2]; + ULONG i, j; + INT iRet, iExp; + + pLPropCompareProp = (void*)GetProcAddress(hMapi32, "LPropCompareProp@8"); + + if (!pLPropCompareProp) + return; + + lbuffa[1] = '\0'; + rbuffa[1] = '\0'; + lbuffw[1] = '\0'; + rbuffw[1] = '\0'; + + for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++) + { + pvLeft.ulPropTag = pvRight.ulPropTag = ptTypes[i]; + + for (j = 0; j < sizeof(LPCProp_Results)/sizeof(LPCProp_Results[0]); j++) + { + SHORT lVal = LPCProp_Results[j].lVal; + SHORT rVal = LPCProp_Results[j].rVal; + + iExp = LPCProp_Results[j].iRet; + + switch (ptTypes[i]) + { + case PT_BOOLEAN: + /* Boolean values have no concept of less or greater than, only equality */ + if (lVal && rVal) + iExp = 0; + /* Fall through ... */ + case PT_I2: + pvLeft.Value.i = lVal; + pvRight.Value.i = rVal; + break; + case PT_ERROR: + case PT_I4: + pvLeft.Value.l = lVal; + pvRight.Value.l = rVal; + break; + case PT_R4: + pvLeft.Value.flt = lVal; + pvRight.Value.flt = rVal; + break; + case PT_APPTIME: + case PT_R8: + pvLeft.Value.dbl = lVal; + pvRight.Value.dbl = rVal; + break; + case PT_CURRENCY: + pvLeft.Value.cur.int64 = lVal; + pvRight.Value.cur.int64 = rVal; + break; + case PT_SYSTIME: + pvLeft.Value.ft.dwLowDateTime = lVal; + pvLeft.Value.ft.dwHighDateTime = 0; + pvRight.Value.ft.dwLowDateTime = rVal; + pvRight.Value.ft.dwHighDateTime = 0; + break; + case PT_I8: + pvLeft.Value.li.u.LowPart = lVal; + pvLeft.Value.li.u.HighPart = 0; + pvRight.Value.li.u.LowPart = rVal; + pvRight.Value.li.u.HighPart = 0; + break; + case PT_CLSID: + memset(&lguid, 0, sizeof(GUID)); + memset(&rguid, 0, sizeof(GUID)); + lguid.Data4[7] = lVal; + rguid.Data4[7] = rVal; + pvLeft.Value.lpguid = &lguid; + pvRight.Value.lpguid = &rguid; + break; + case PT_STRING8: + pvLeft.Value.lpszA = lbuffa; + pvRight.Value.lpszA = rbuffa; + lbuffa[0] = '0' + lVal; + rbuffa[0] = '0' + rVal; + break; + case PT_UNICODE: + pvLeft.Value.lpszW = lbuffw; + pvRight.Value.lpszW = rbuffw; + lbuffw[0] = '0' + lVal; + rbuffw[0] = '0' + rVal; + break; + case PT_BINARY: + pvLeft.Value.bin.cb = 1; + pvRight.Value.bin.cb = 1; + pvLeft.Value.bin.lpb = lbuffa; + pvRight.Value.bin.lpb = rbuffa; + lbuffa[0] = lVal; + rbuffa[0] = rVal; + break; + } + + iRet = pLPropCompareProp(&pvLeft, &pvRight); + ok(iRet == iExp, "pt %ld (%d,%d): expected %d, got %d\n", ptTypes[i], + LPCProp_Results[j].lVal, LPCProp_Results[j].rVal, iExp, iRet); + } + } +} + +static void test_PpropFindProp(void) +{ + SPropValue pvProp, *pRet; + ULONG i; + + pPpropFindProp = (void*)GetProcAddress(hMapi32, "PpropFindProp@12"); + + if (!pPpropFindProp) + return; + + for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++) + { + pvProp.ulPropTag = ptTypes[i]; + + pRet = pPpropFindProp(&pvProp, 1u, ptTypes[i]); + ok(pRet == &pvProp, "PpropFindProp[%ld]: Didn't find existing propery\n", + ptTypes[i]); + + pRet = pPpropFindProp(&pvProp, 1u, i ? ptTypes[i-1] : ptTypes[i+1]); + ok(pRet == NULL, "PpropFindProp[%ld]: Found non-existing propery\n", + ptTypes[i]); + } + + pvProp.ulPropTag = PROP_TAG(PT_I2, 1u); + pRet = pPpropFindProp(&pvProp, 1u, PROP_TAG(PT_UNSPECIFIED, 0u)); + ok(pRet == NULL, "PpropFindProp[UNSPECIFIED]: Matched on different id\n"); + pRet = pPpropFindProp(&pvProp, 1u, PROP_TAG(PT_UNSPECIFIED, 1u)); + ok(pRet == &pvProp, "PpropFindProp[UNSPECIFIED]: Didn't match id\n"); +} + +static void test_ScCountProps(void) +{ + static const char *szHiA = "Hi!"; + static const WCHAR szHiW[] = { 'H', 'i', '!', '\0' }; + static const ULONG ULHILEN = 4; /* chars in szHiA/W incl. NUL */ + LPSTR buffa[3]; + LPWSTR buffw[3]; + SBinary buffbin[3]; + GUID iids[4], *iid = iids; + SCODE res; + ULONG pt, exp, ulRet; + + pScCountProps = (void*)GetProcAddress(hMapi32, "ScCountProps@12"); + + if (!pScCountProps) + return; + + for (pt = 0; pt < PROP_ID_INVALID; pt++) + { + SPropValue pv; + + memset(&pv, 0 ,sizeof(pv)); + pv.ulPropTag = PROP_TAG(pt, 1u); + + switch (PROP_TYPE(pt)) + { + case PT_I2: + case PT_I4: + case PT_R4: + case PT_R8: + case PT_CURRENCY: + case PT_APPTIME: + case PT_SYSTIME: + case PT_ERROR: + case PT_BOOLEAN: + case PT_OBJECT: + case PT_I8: + exp = sizeof(pv); + break; + case PT_CLSID: + pv.Value.lpguid = iid; + exp = sizeof(GUID) + sizeof(pv); + break; + case PT_STRING8: + pv.Value.lpszA = (LPSTR)szHiA; + exp = 4 + sizeof(pv); + break; + case PT_UNICODE: + pv.Value.lpszW = (LPWSTR)szHiW; + exp = 4 * sizeof(WCHAR) + sizeof(pv); + break; + case PT_BINARY: + pv.Value.bin.cb = 2; + pv.Value.bin.lpb = (LPBYTE)iid; + exp = 2 + sizeof(pv); + break; + case PT_MV_I2: + pv.Value.MVi.cValues = 3; + pv.Value.MVi.lpi = (SHORT*)iid; + exp = 3 * sizeof(SHORT) + sizeof(pv); + break; + case PT_MV_I4: + pv.Value.MVl.cValues = 3; + pv.Value.MVl.lpl = (LONG*)iid; + exp = 3 * sizeof(LONG) + sizeof(pv); + break; + case PT_MV_I8: + pv.Value.MVli.cValues = 3; + pv.Value.MVli.lpli = (LARGE_INTEGER*)iid; + exp = 3 * sizeof(LARGE_INTEGER) + sizeof(pv); + break; + case PT_MV_R4: + pv.Value.MVflt.cValues = 3; + pv.Value.MVflt.lpflt = (float*)iid; + exp = 3 * sizeof(float) + sizeof(pv); + break; + case PT_MV_APPTIME: + case PT_MV_R8: + pv.Value.MVdbl.cValues = 3; + pv.Value.MVdbl.lpdbl = (double*)iid; + exp = 3 * sizeof(double) + sizeof(pv); + break; + case PT_MV_CURRENCY: + pv.Value.MVcur.cValues = 3; + pv.Value.MVcur.lpcur = (CY*)iid; + exp = 3 * sizeof(CY) + sizeof(pv); + break; + case PT_MV_SYSTIME: + pv.Value.MVft.cValues = 3; + pv.Value.MVft.lpft = (FILETIME*)iid; + exp = 3 * sizeof(CY) + sizeof(pv); + break; + break; + case PT_MV_STRING8: + pv.Value.MVszA.cValues = 3; + pv.Value.MVszA.lppszA = buffa; + buffa[0] = (LPSTR)szHiA; + buffa[1] = (LPSTR)szHiA; + buffa[2] = (LPSTR)szHiA; + exp = ULHILEN * 3 + 3 * sizeof(char*) + sizeof(pv); + break; + case PT_MV_UNICODE: + pv.Value.MVszW.cValues = 3; + pv.Value.MVszW.lppszW = buffw; + buffw[0] = (LPWSTR)szHiW; + buffw[1] = (LPWSTR)szHiW; + buffw[2] = (LPWSTR)szHiW; + exp = ULHILEN * 3 * sizeof(WCHAR) + 3 * sizeof(WCHAR*) + sizeof(pv); + break; + case PT_MV_BINARY: + pv.Value.MVbin.cValues = 3; + pv.Value.MVbin.lpbin = buffbin; + buffbin[0].cb = 17; + buffbin[0].lpb = (LPBYTE)&iid; + buffbin[1].cb = 2; + buffbin[1].lpb = (LPBYTE)&iid; + buffbin[2].cb = 1; + buffbin[2].lpb = (LPBYTE)&iid; + exp = 20 + sizeof(pv) + sizeof(SBinary) * 3; + break; + default: + exp = 0; + } + + ulRet = 0xffffffff; + res = pScCountProps(1, &pv, &ulRet); + if (!exp) + ok(res == MAPI_E_INVALID_PARAMETER && ulRet == 0xffffffff, + "pt= %ld: Expected failure, got %ld, ret=0x%08lX\n", pt, ulRet, res); + else + ok(res == S_OK && ulRet == exp, "pt= %ld: Expected %ld, got %ld, ret=0x%08lX\n", + pt, exp, ulRet, res); + } + +} + +static void test_LpValFindProp(void) +{ + SPropValue pvProp, *pRet; + ULONG i; + + pLpValFindProp = (void*)GetProcAddress(hMapi32, "LpValFindProp@12"); + + if (!pLpValFindProp) + return; + + for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++) + { + pvProp.ulPropTag = PROP_TAG(ptTypes[i], 1u); + + pRet = pLpValFindProp(PROP_TAG(ptTypes[i], 1u), 1u, &pvProp); + ok(pRet == &pvProp, "LpValFindProp[%ld]: Didn't find existing propery id/type\n", + ptTypes[i]); + + pRet = pLpValFindProp(PROP_TAG(ptTypes[i], 0u), 1u, &pvProp); + ok(pRet == NULL, "LpValFindProp[%ld]: Found non-existing propery id\n", + ptTypes[i]); + + pRet = pLpValFindProp(PROP_TAG(PT_NULL, 0u), 1u, &pvProp); + ok(pRet == NULL, "LpValFindProp[%ld]: Found non-existing propery id/type\n", + ptTypes[i]); + + pRet = pLpValFindProp(PROP_TAG(PT_NULL, 1u), 1u, &pvProp); + ok(pRet == &pvProp, "LpValFindProp[%ld]: Didn't find existing propery id\n", + ptTypes[i]); + } +} + +static void test_FBadRglpszA(void) +{ + LPSTR lpStrs[4]; + char *szString = "A String"; + BOOL bRet; + + pFBadRglpszA = (void*)GetProcAddress(hMapi32, "FBadRglpszA@8"); + if (!pFBadRglpszA) + return; + + bRet = pFBadRglpszA(NULL, 10); + ok(bRet == TRUE, "FBadRglpszA(Null): expected TRUE, got FALSE\n"); + + lpStrs[0] = lpStrs[1] = lpStrs[2] = lpStrs[3] = NULL; + bRet = pFBadRglpszA(lpStrs, 4); + ok(bRet == TRUE, "FBadRglpszA(Nulls): expected TRUE, got FALSE\n"); + + lpStrs[0] = lpStrs[1] = lpStrs[2] = szString; + bRet = pFBadRglpszA(lpStrs, 3); + ok(bRet == FALSE, "FBadRglpszA(valid): expected FALSE, got TRUE\n"); + + bRet = pFBadRglpszA(lpStrs, 4); + ok(bRet == TRUE, "FBadRglpszA(1 invalid): expected TRUE, got FALSE\n"); +} + +static void test_FBadRglpszW(void) +{ + LPWSTR lpStrs[4]; + WCHAR szString[] = { 'A',' ','S','t','r','i','n','g','\0' }; + BOOL bRet; + + pFBadRglpszW = (void*)GetProcAddress(hMapi32, "FBadRglpszW@8"); + if (!pFBadRglpszW) + return; + + bRet = pFBadRglpszW(NULL, 10); + ok(bRet == TRUE, "FBadRglpszW(Null): expected TRUE, got FALSE\n"); + + lpStrs[0] = lpStrs[1] = lpStrs[2] = lpStrs[3] = NULL; + bRet = pFBadRglpszW(lpStrs, 4); + ok(bRet == TRUE, "FBadRglpszW(Nulls): expected TRUE, got FALSE\n"); + + lpStrs[0] = lpStrs[1] = lpStrs[2] = szString; + bRet = pFBadRglpszW(lpStrs, 3); + ok(bRet == FALSE, "FBadRglpszW(valid): expected FALSE, got TRUE\n"); + + bRet = pFBadRglpszW(lpStrs, 4); + ok(bRet == TRUE, "FBadRglpszW(1 invalid): expected TRUE, got FALSE\n"); +} + +static void test_FBadRowSet(void) +{ + ULONG ulRet; + + pFBadRowSet = (void*)GetProcAddress(hMapi32, "FBadRowSet@4"); + if (!pFBadRowSet) + return; + + ulRet = pFBadRowSet(NULL); + ok(ulRet != 0, "FBadRow(null): Expected non-zero, got 0\n"); + + /* FIXME */ +} + +static void test_FBadPropTag(void) +{ + ULONG pt, res; + + pFBadPropTag = (void*)GetProcAddress(hMapi32, "FBadPropTag@4"); + if (!pFBadPropTag) + return; + + for (pt = 0; pt < PROP_ID_INVALID; pt++) + { + BOOL bBad = TRUE; + + switch (pt & (~MV_FLAG & PROP_TYPE_MASK)) + { + case PT_UNSPECIFIED: + case PT_NULL: case PT_I2: case PT_I4: case PT_R4: + case PT_R8: case PT_CURRENCY: case PT_APPTIME: + case PT_ERROR: case PT_BOOLEAN: case PT_OBJECT: + case PT_I8: case PT_STRING8: case PT_UNICODE: + case PT_SYSTIME: case PT_CLSID: case PT_BINARY: + bBad = FALSE; + } + + res = pFBadPropTag(pt); + if (bBad) + ok(res != 0, "pt= %ld: Expected non-zero, got 0\n", pt); + else + ok(res == 0, "pt= %ld: Expected zero, got %ld\n", pt, res); + } +} + +static void test_FBadRow(void) +{ + ULONG ulRet; + + pFBadRow = (void*)GetProcAddress(hMapi32, "FBadRow@4"); + if (!pFBadRow) + return; + + ulRet = pFBadRow(NULL); + ok(ulRet != 0, "FBadRow(null): Expected non-zero, got 0\n"); + + /* FIXME */ +} + +static void test_FBadProp(void) +{ + WCHAR szEmpty[] = { '\0' }; + GUID iid; + ULONG pt, res; + SPropValue pv; + + pFBadProp = (void*)GetProcAddress(hMapi32, "FBadProp@4"); + if (!pFBadProp) + return; + + for (pt = 0; pt < PROP_ID_INVALID; pt++) + { + BOOL bBad = TRUE; + + memset(&pv, 0, sizeof(pv)); + pv.ulPropTag = pt; + + /* Note that MV values are valid below because their array count is 0, + * so no pointers are validated. + */ + switch (PROP_TYPE(pt)) + { + case (MV_FLAG|PT_UNSPECIFIED): + case PT_UNSPECIFIED: + case (MV_FLAG|PT_NULL): + case PT_NULL: + case PT_MV_I2: + case PT_I2: + case PT_MV_I4: + case PT_I4: + case PT_MV_I8: + case PT_I8: + case PT_MV_R4: + case PT_R4: + case PT_MV_R8: + case PT_R8: + case PT_MV_CURRENCY: + case PT_CURRENCY: + case PT_MV_APPTIME: + case PT_APPTIME: + case (MV_FLAG|PT_ERROR): + case PT_ERROR: + case (MV_FLAG|PT_BOOLEAN): + case PT_BOOLEAN: + case (MV_FLAG|PT_OBJECT): + case PT_OBJECT: + case PT_MV_STRING8: + case PT_MV_UNICODE: + case PT_MV_SYSTIME: + case PT_SYSTIME: + case PT_MV_BINARY: + case PT_BINARY: + case PT_MV_CLSID: + bBad = FALSE; + break; + case PT_STRING8: + case PT_UNICODE: + pv.Value.lpszW = szEmpty; + bBad = FALSE; + break; + case PT_CLSID: + pv.Value.lpguid = &iid; + bBad = FALSE; + break; + } + + res = pFBadProp(&pv); + if (bBad) + ok(res != 0, "pt= %ld: Expected non-zero, got 0\n", pt); + else + ok(res == 0, "pt= %ld: Expected zero, got %ld\n", pt, res); + } +} + +static void test_FBadColumnSet(void) +{ + SPropTagArray pta; + ULONG pt, res; + + pFBadColumnSet = (void*)GetProcAddress(hMapi32, "FBadColumnSet@4"); + if (!pFBadColumnSet) + return; + + res = pFBadColumnSet(NULL); + ok(res != 0, "(null): Expected non-zero, got 0\n"); + + pta.cValues = 1; + + for (pt = 0; pt < PROP_ID_INVALID; pt++) + { + BOOL bBad = TRUE; + + pta.aulPropTag[0] = pt; + + switch (pt & (~MV_FLAG & PROP_TYPE_MASK)) + { + case PT_UNSPECIFIED: + case PT_NULL: + case PT_I2: + case PT_I4: + case PT_R4: + case PT_R8: + case PT_CURRENCY: + case PT_APPTIME: + case PT_BOOLEAN: + case PT_OBJECT: + case PT_I8: + case PT_STRING8: + case PT_UNICODE: + case PT_SYSTIME: + case PT_CLSID: + case PT_BINARY: + bBad = FALSE; + } + if (pt == (MV_FLAG|PT_ERROR)) + bBad = FALSE; + + res = pFBadColumnSet(&pta); + if (bBad) + ok(res != 0, "pt= %ld: Expected non-zero, got 0\n", pt); + else + ok(res == 0, "pt= %ld: Expected zero, got %ld\n", pt, res); + } +} + +START_TEST(prop) +{ + hMapi32 = LoadLibraryA("mapi32.dll"); + + pScInitMapiUtil = (void*)GetProcAddress(hMapi32, "ScInitMapiUtil@4"); + if (!pScInitMapiUtil) + return; + pScInitMapiUtil(0); + + test_PropCopyMore(); + test_UlPropSize(); + test_FPropContainsProp(); + test_FPropCompareProp(); + test_LPropCompareProp(); + test_PpropFindProp(); + test_ScCountProps(); + test_LpValFindProp(); + test_FBadRglpszA(); + test_FBadRglpszW(); + test_FBadRowSet(); + test_FBadPropTag(); + test_FBadRow(); + test_FBadProp(); + test_FBadColumnSet(); +} diff --git a/dlls/mapi32/tests/util.c b/dlls/mapi32/tests/util.c new file mode 100644 index 00000000000..4aaf98da0f2 --- /dev/null +++ b/dlls/mapi32/tests/util.c @@ -0,0 +1,83 @@ +/* + * Unit test suite for MAPI utility functions + * + * Copyright 2004 Jon Griffiths + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "wine/test.h" +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winerror.h" +#include "winnt.h" +#include "mapiutil.h" +#include "mapitags.h" + +static HMODULE hMapi32 = 0; + +static SCODE (WINAPI *pScInitMapiUtil)(ULONG); +static void (WINAPI *pSwapPword)(PUSHORT,ULONG); +static void (WINAPI *pSwapPlong)(PULONG,ULONG); + +static void test_SwapPword(void) +{ + USHORT shorts[3]; + + pSwapPword = (void*)GetProcAddress(hMapi32, "SwapPword@8"); + if (!pSwapPword) + return; + + shorts[0] = 0xff01; + shorts[1] = 0x10ff; + shorts[2] = 0x2001; + pSwapPword(shorts, 2); + ok(shorts[0] == 0x01ff && shorts[1] == 0xff10 && shorts[2] == 0x2001, + "Expected {0x01ff,0xff10,0x2001}, got {0x%04x,0x%04x,0x%04x}\n", + shorts[0], shorts[1], shorts[2]); +} + +static void test_SwapPlong(void) +{ + ULONG longs[3]; + + pSwapPlong = (void*)GetProcAddress(hMapi32, "SwapPlong@8"); + if (!pSwapPlong) + return; + + longs[0] = 0xffff0001; + longs[1] = 0x1000ffff; + longs[2] = 0x20000001; + pSwapPlong(longs, 2); + ok(longs[0] == 0x0100ffff && longs[1] == 0xffff0010 && longs[2] == 0x20000001, + "Expected {0x0100ffff,0xffff0010,0x20000001}, got {0x%08lx,0x%08lx,0x%08lx}\n", + longs[0], longs[1], longs[2]); +} + +START_TEST(util) +{ + hMapi32 = LoadLibraryA("mapi32.dll"); + + pScInitMapiUtil = (void*)GetProcAddress(hMapi32, "ScInitMapiUtil@4"); + if (!pScInitMapiUtil) + return; + pScInitMapiUtil(0); + + test_SwapPword(); + test_SwapPlong(); +}