Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2018
- 68 participants
- 1149 messages
Re: [PATCH 1/3] comctl32/taskdialog: Fix buttons might disappear.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
June 25, 2018
Re: [PATCH v2] comctl32/imagelist: fix ImageList_Read/Write.
by Nikolay Sivov
On 06/21/2018 05:53 PM, Denis Malikov wrote:
> diff --git a/dlls/comctl32/imagelist.c b/dlls/comctl32/imagelist.c
> index a08d60752e..eadbf134b4 100644
> --- a/dlls/comctl32/imagelist.c
> +++ b/dlls/comctl32/imagelist.c
> @@ -80,9 +80,11 @@ struct _IMAGELIST
> BOOL color_table_set;
>
> LONG ref; /* reference count */
> + USHORT usVersion; /* keep stream version here */
> };
Now this new field is not used anywhere.
June 25, 2018
[PATCH] user.exe16: Fix handling of DDL_DRIVES flag in DlgDirList.
by Alistair Leslie-Hughes
From: Alex Villacís Lasso <a_villacis(a)palosanto.com>
Fixes: https://bugs.winehq.org/show_bug.cgi?id=18734
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/user.exe16/dialog.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/user.exe16/dialog.c b/dlls/user.exe16/dialog.c
index e5bf7b9..385e859 100644
--- a/dlls/user.exe16/dialog.c
+++ b/dlls/user.exe16/dialog.c
@@ -636,7 +636,7 @@ INT16 WINAPI DlgDirList16( HWND16 hDlg, LPSTR spec, INT16 idLBox,
* be set automatically (this is different in Win32, and
* DIALOG_DlgDirList sends Win32 messages to the control,
* so do it here) */
- if (attrib & DDL_DRIVES) attrib |= DDL_EXCLUSIVE;
+ if (attrib == DDL_DRIVES) attrib |= DDL_EXCLUSIVE;
return DlgDirListA( WIN_Handle32(hDlg), spec, idLBox, idStatic, attrib );
}
--
1.9.1
June 25, 2018
[PATCH] hnetcfg: Store the full path in INetFwAuthorizedApplication_put_ProcessImageFileName().
by Zebediah Figura
Should hopefully fix test failures on Windows.
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/hnetcfg/apps.c | 17 ++++++++++++-----
dlls/hnetcfg/tests/policy.c | 5 ++++-
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/dlls/hnetcfg/apps.c b/dlls/hnetcfg/apps.c
index 34ef108..fe47721 100644
--- a/dlls/hnetcfg/apps.c
+++ b/dlls/hnetcfg/apps.c
@@ -268,7 +268,7 @@ static HRESULT WINAPI fw_app_put_ProcessImageFileName(
{
fw_app *This = impl_from_INetFwAuthorizedApplication( iface );
UNIVERSAL_NAME_INFOW *info;
- WCHAR *netpath;
+ WCHAR *path;
DWORD res;
DWORD sz;
@@ -281,22 +281,29 @@ static HRESULT WINAPI fw_app_put_ProcessImageFileName(
res = WNetGetUniversalNameW(image, UNIVERSAL_NAME_INFO_LEVEL, NULL, &sz);
if (res == WN_MORE_DATA)
{
- if (!(netpath = heap_alloc(sz)))
+ if (!(path = heap_alloc(sz)))
return E_OUTOFMEMORY;
- info = (UNIVERSAL_NAME_INFOW *)&netpath;
+ info = (UNIVERSAL_NAME_INFOW *)&path;
res = WNetGetUniversalNameW(image, UNIVERSAL_NAME_INFO_LEVEL, &info, &sz);
if (res == NO_ERROR)
{
SysFreeString(This->filename);
This->filename = SysAllocString(info->lpUniversalName);
}
- heap_free(netpath);
+ heap_free(path);
return HRESULT_FROM_WIN32(res);
}
+ sz = GetFullPathNameW(image, 0, NULL, NULL);
+ if (!(path = heap_alloc(++sz)))
+ return E_OUTOFMEMORY;
+
+ GetFullPathNameW(image, sz, path, NULL);
+
SysFreeString( This->filename );
- This->filename = SysAllocString(image);
+ This->filename = SysAllocString(path);
+ heap_free(path);
return This->filename ? S_OK : E_OUTOFMEMORY;
}
diff --git a/dlls/hnetcfg/tests/policy.c b/dlls/hnetcfg/tests/policy.c
index f2d1372..7791926 100644
--- a/dlls/hnetcfg/tests/policy.c
+++ b/dlls/hnetcfg/tests/policy.c
@@ -107,6 +107,7 @@ static void test_NetFwAuthorizedApplication(void)
INetFwAuthorizedApplication *app;
static WCHAR empty[] = {0};
UNIVERSAL_NAME_INFOW *info;
+ WCHAR fullpath[MAX_PATH];
WCHAR netpath[MAX_PATH];
WCHAR image[MAX_PATH];
HRESULT hr;
@@ -138,13 +139,15 @@ static void test_NetFwAuthorizedApplication(void)
ok(hr == S_OK, "got: %08x\n", hr);
SysFreeString(bstr);
+ GetFullPathNameW(image, sizeof(fullpath), fullpath, NULL);
+
info = (UNIVERSAL_NAME_INFOW *)&netpath;
sz = sizeof(netpath);
hr = WNetGetUniversalNameW(image, UNIVERSAL_NAME_INFO_LEVEL, &info, &sz);
if (hr != NO_ERROR)
{
info->lpUniversalName = netpath + sizeof(*info)/sizeof(WCHAR);
- lstrcpyW(info->lpUniversalName, image);
+ lstrcpyW(info->lpUniversalName, fullpath);
}
hr = INetFwAuthorizedApplication_get_ProcessImageFileName(app, &bstr);
--
2.7.4
June 25, 2018
[PATCH] loader: Register mp3dmod DMO.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
loader/wine.inf.in | 1 +
1 file changed, 1 insertion(+)
diff --git a/loader/wine.inf.in b/loader/wine.inf.in
index 90fb151..e844d65 100644
--- a/loader/wine.inf.in
+++ b/loader/wine.inf.in
@@ -2511,6 +2511,7 @@ HKLM,%CurrentVersion%\Telephony\Country List\998,"SameAreaRule",,"G"
11,,cryptdlg.dll,1
11,,cryptnet.dll,1
11,,devenum.dll,1
+11,,mp3dmod.dll,1
11,,mscoree.dll,1
11,,mshtml.dll,1
11,,msisip.dll,1
--
2.7.4
June 24, 2018
[PATCH 2/2] devenum: Implement enumerating DMOs.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/devenum/mediacatenum.c | 57 ++++++++++++++++++++++++++++++++++++--------
dlls/devenum/tests/devenum.c | 2 ++
2 files changed, 49 insertions(+), 10 deletions(-)
diff --git a/dlls/devenum/mediacatenum.c b/dlls/devenum/mediacatenum.c
index c0efae0..c4338a2 100644
--- a/dlls/devenum/mediacatenum.c
+++ b/dlls/devenum/mediacatenum.c
@@ -36,6 +36,7 @@ typedef struct
IEnumMoniker IEnumMoniker_iface;
CLSID class;
LONG ref;
+ IEnumDMO *dmo_enum;
HKEY sw_key;
DWORD sw_index;
HKEY cm_key;
@@ -845,6 +846,7 @@ static ULONG WINAPI DEVENUM_IEnumMoniker_Release(IEnumMoniker *iface)
if (!ref)
{
+ IEnumDMO_Release(This->dmo_enum);
RegCloseKey(This->sw_key);
RegCloseKey(This->cm_key);
CoTaskMemFree(This);
@@ -862,16 +864,31 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(IEnumMoniker *iface, ULONG celt,
LONG res;
ULONG fetched = 0;
MediaCatMoniker * pMoniker;
+ WCHAR *name;
+ CLSID clsid;
+ HRESULT hr;
HKEY hkey;
TRACE("(%p)->(%d, %p, %p)\n", iface, celt, rgelt, pceltFetched);
while (fetched < celt)
{
- /* FIXME: try PNP devices and DMOs first */
+ /* FIXME: try PNP devices first */
+ /* try DMOs */
+ if ((hr = IEnumDMO_Next(This->dmo_enum, 1, &clsid, &name, NULL)) == S_OK)
+ {
+ if (!(pMoniker = DEVENUM_IMediaCatMoniker_Construct()))
+ return E_OUTOFMEMORY;
+
+ pMoniker->type = DEVICE_DMO;
+ pMoniker->clsid = clsid;
+
+ StringFromGUID2(&clsid, buffer, CHARS_IN_GUID);
+ StringFromGUID2(&This->class, buffer + CHARS_IN_GUID - 1, CHARS_IN_GUID);
+ }
/* try DirectShow filters */
- if (!(res = RegEnumKeyW(This->sw_key, This->sw_index, buffer, sizeof(buffer)/sizeof(WCHAR))))
+ else if (!(res = RegEnumKeyW(This->sw_key, This->sw_index, buffer, sizeof(buffer)/sizeof(WCHAR))))
{
This->sw_index++;
if ((res = RegOpenKeyExW(This->sw_key, buffer, 0, KEY_QUERY_VALUE, &hkey)))
@@ -881,6 +898,13 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(IEnumMoniker *iface, ULONG celt,
return E_OUTOFMEMORY;
pMoniker->type = DEVICE_FILTER;
+
+ if (!(pMoniker->name = CoTaskMemAlloc((strlenW(buffer) + 1) * sizeof(WCHAR))))
+ {
+ IMoniker_Release(&pMoniker->IMoniker_iface);
+ return E_OUTOFMEMORY;
+ }
+ strcpyW(pMoniker->name, buffer);
}
/* then try codecs */
else if (!(res = RegEnumKeyW(This->cm_key, This->cm_index, buffer, sizeof(buffer)/sizeof(WCHAR))))
@@ -894,16 +918,17 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(IEnumMoniker *iface, ULONG celt,
return E_OUTOFMEMORY;
pMoniker->type = DEVICE_CODEC;
+
+ if (!(pMoniker->name = CoTaskMemAlloc((strlenW(buffer) + 1) * sizeof(WCHAR))))
+ {
+ IMoniker_Release(&pMoniker->IMoniker_iface);
+ return E_OUTOFMEMORY;
+ }
+ strcpyW(pMoniker->name, buffer);
}
else
break;
- if (!(pMoniker->name = CoTaskMemAlloc((strlenW(buffer) + 1) * sizeof(WCHAR))))
- {
- IMoniker_Release(&pMoniker->IMoniker_iface);
- return E_OUTOFMEMORY;
- }
- strcpyW(pMoniker->name, buffer);
pMoniker->has_class = TRUE;
pMoniker->class = This->class;
@@ -930,10 +955,13 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Skip(IEnumMoniker *iface, ULONG celt)
while (celt--)
{
- /* FIXME: try PNP devices and DMOs first */
+ /* FIXME: try PNP devices first */
+ /* try DMOs */
+ if (IEnumDMO_Skip(This->dmo_enum, 1) == S_OK)
+ ;
/* try DirectShow filters */
- if (RegEnumKeyW(This->sw_key, This->sw_index, NULL, 0) != ERROR_NO_MORE_ITEMS)
+ else if (RegEnumKeyW(This->sw_key, This->sw_index, NULL, 0) != ERROR_NO_MORE_ITEMS)
{
This->sw_index++;
}
@@ -955,6 +983,7 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Reset(IEnumMoniker *iface)
TRACE("(%p)->()\n", iface);
+ IEnumDMO_Reset(This->dmo_enum);
This->sw_index = 0;
This->cm_index = 0;
@@ -986,6 +1015,7 @@ HRESULT create_EnumMoniker(REFCLSID class, IEnumMoniker **ppEnumMoniker)
{
EnumMonikerImpl * pEnumMoniker = CoTaskMemAlloc(sizeof(EnumMonikerImpl));
WCHAR buffer[78];
+ HRESULT hr;
if (!pEnumMoniker)
return E_OUTOFMEMORY;
@@ -1007,6 +1037,13 @@ HRESULT create_EnumMoniker(REFCLSID class, IEnumMoniker **ppEnumMoniker)
if (RegOpenKeyExW(HKEY_CURRENT_USER, buffer, 0, KEY_ENUMERATE_SUB_KEYS, &pEnumMoniker->cm_key))
pEnumMoniker->cm_key = NULL;
+ hr = DMOEnum(class, 0, 0, NULL, 0, NULL, &pEnumMoniker->dmo_enum);
+ if (FAILED(hr))
+ {
+ IEnumMoniker_Release(&pEnumMoniker->IEnumMoniker_iface);
+ return hr;
+ }
+
*ppEnumMoniker = &pEnumMoniker->IEnumMoniker_iface;
DEVENUM_LockModule();
diff --git a/dlls/devenum/tests/devenum.c b/dlls/devenum/tests/devenum.c
index 2f66907..6d4ce2d 100644
--- a/dlls/devenum/tests/devenum.c
+++ b/dlls/devenum/tests/devenum.c
@@ -525,6 +525,8 @@ static void test_dmo(void)
{
ok(hr == S_OK, "got %#x\n", hr);
+ ok(find_moniker(&CLSID_AudioRendererCategory, mon), "DMO should be registered\n");
+
VariantClear(&var);
hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
ok(hr == S_OK, "got %#x\n", hr);
--
2.7.4
June 24, 2018
[PATCH 1/2] devenum: Implement parsing and reading DMO monikers.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/devenum/Makefile.in | 2 +-
dlls/devenum/devenum_private.h | 10 ++++-
dlls/devenum/mediacatenum.c | 99 ++++++++++++++++++++++++++++++-----------
dlls/devenum/parsedisplayname.c | 52 ++++++++++++++++------
dlls/devenum/tests/Makefile.in | 2 +-
dlls/devenum/tests/devenum.c | 64 ++++++++++++++++++++++++++
6 files changed, 186 insertions(+), 43 deletions(-)
diff --git a/dlls/devenum/Makefile.in b/dlls/devenum/Makefile.in
index 8f81f93..ae138b6 100644
--- a/dlls/devenum/Makefile.in
+++ b/dlls/devenum/Makefile.in
@@ -1,5 +1,5 @@
MODULE = devenum.dll
-IMPORTS = strmiids uuid ole32 oleaut32 avicap32 winmm user32 advapi32 dsound
+IMPORTS = strmiids uuid ole32 oleaut32 avicap32 winmm user32 advapi32 dsound msdmo
DELAYIMPORTS = msvfw32
C_SRCS = \
diff --git a/dlls/devenum/devenum_private.h b/dlls/devenum/devenum_private.h
index d4e1141..df0080d 100644
--- a/dlls/devenum/devenum_private.h
+++ b/dlls/devenum/devenum_private.h
@@ -64,6 +64,7 @@ enum device_type
{
DEVICE_FILTER,
DEVICE_CODEC,
+ DEVICE_DMO,
};
typedef struct
@@ -73,7 +74,11 @@ typedef struct
CLSID class;
BOOL has_class;
enum device_type type;
- WCHAR *name;
+ union
+ {
+ WCHAR *name; /* for filters and codecs */
+ CLSID clsid; /* for DMOs */
+ };
} MediaCatMoniker;
MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void) DECLSPEC_HIDDEN;
@@ -95,5 +100,8 @@ static const WCHAR wszActiveMovieKey[] = {'S','o','f','t','w','a','r','e','\\',
'A','c','t','i','v','e','M','o','v','i','e','\\',
'd','e','v','e','n','u','m','\\',0};
static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':',0};
+static const WCHAR dmoW[] = {'d','m','o',':',0};
+static const WCHAR swW[] = {'s','w',':',0};
+static const WCHAR cmW[] = {'c','m',':',0};
extern const WCHAR clsid_keyname[6] DECLSPEC_HIDDEN;
diff --git a/dlls/devenum/mediacatenum.c b/dlls/devenum/mediacatenum.c
index a76c7be..c0efae0 100644
--- a/dlls/devenum/mediacatenum.c
+++ b/dlls/devenum/mediacatenum.c
@@ -25,6 +25,7 @@
#include "devenum_private.h"
#include "oleauto.h"
#include "ocidl.h"
+#include "dmoreg.h"
#include "wine/debug.h"
@@ -46,7 +47,11 @@ typedef struct
IPropertyBag IPropertyBag_iface;
LONG ref;
enum device_type type;
- WCHAR path[MAX_PATH];
+ union
+ {
+ WCHAR path[MAX_PATH]; /* for filters and codecs */
+ CLSID clsid; /* for DMOs */
+ };
} RegPropBagImpl;
@@ -114,12 +119,14 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
VARIANT* pVar,
IErrorLog* pErrorLog)
{
+ static const WCHAR FriendlyNameW[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
LPVOID pData = NULL;
DWORD received;
DWORD type = 0;
RegPropBagImpl *This = impl_from_IPropertyBag(iface);
HRESULT res = S_OK;
LONG reswin32 = ERROR_SUCCESS;
+ WCHAR name[80];
HKEY hkey;
TRACE("(%p)->(%s, %p, %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog);
@@ -127,6 +134,21 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
if (!pszPropName || !pVar)
return E_POINTER;
+ if (This->type == DEVICE_DMO)
+ {
+ if (!strcmpW(pszPropName, FriendlyNameW))
+ {
+ res = DMOGetName(&This->clsid, name);
+ if (SUCCEEDED(res))
+ {
+ V_VT(pVar) = VT_BSTR;
+ V_BSTR(pVar) = SysAllocString(name);
+ }
+ return res;
+ }
+ return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+ }
+
if (This->type == DEVICE_FILTER)
reswin32 = RegOpenKeyW(HKEY_CLASSES_ROOT, This->path, &hkey);
else if (This->type == DEVICE_CODEC)
@@ -246,6 +268,9 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Write(
TRACE("(%p)->(%s, %p)\n", This, debugstr_w(pszPropName), pVar);
+ if (This->type == DEVICE_DMO)
+ return E_ACCESSDENIED;
+
switch (V_VT(pVar))
{
case VT_BSTR:
@@ -316,18 +341,29 @@ static HRESULT create_PropertyBag(MediaCatMoniker *mon, IPropertyBag **ppBag)
rpb->ref = 1;
rpb->type = mon->type;
- if (rpb->type == DEVICE_FILTER)
- strcpyW(rpb->path, clsidW);
- else if (rpb->type == DEVICE_CODEC)
- strcpyW(rpb->path, wszActiveMovieKey);
- if (mon->has_class)
+ if (rpb->type == DEVICE_DMO)
+ rpb->clsid = mon->clsid;
+ else if (rpb->type == DEVICE_FILTER)
{
- StringFromGUID2(&mon->class, rpb->path + strlenW(rpb->path), CHARS_IN_GUID);
- if (rpb->type == DEVICE_FILTER)
+ strcpyW(rpb->path, clsidW);
+ if (mon->has_class)
+ {
+ StringFromGUID2(&mon->class, rpb->path + strlenW(rpb->path), CHARS_IN_GUID);
strcatW(rpb->path, instanceW);
- strcatW(rpb->path, backslashW);
+ strcatW(rpb->path, backslashW);
+ }
+ strcatW(rpb->path, mon->name);
+ }
+ else if (rpb->type == DEVICE_CODEC)
+ {
+ strcpyW(rpb->path, wszActiveMovieKey);
+ if (mon->has_class)
+ {
+ StringFromGUID2(&mon->class, rpb->path + strlenW(rpb->path), CHARS_IN_GUID);
+ strcatW(rpb->path, backslashW);
+ }
+ strcatW(rpb->path, mon->name);
}
- strcatW(rpb->path, mon->name);
*ppBag = &rpb->IPropertyBag_iface;
DEVENUM_LockModule();
@@ -658,8 +694,6 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_RelativePathTo(IMoniker *iface, I
static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
{
- static const WCHAR swW[] = {'s','w',':',0};
- static const WCHAR cmW[] = {'c','m',':',0};
MediaCatMoniker *This = impl_from_IMoniker(iface);
WCHAR *buffer;
@@ -667,23 +701,36 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetDisplayName(IMoniker *iface, I
*ppszDisplayName = NULL;
- buffer = CoTaskMemAlloc((strlenW(deviceW) + 4 + (This->has_class ? CHARS_IN_GUID : 0)
- + strlenW(This->name) + 1) * sizeof(WCHAR));
- if (!buffer)
- return E_OUTOFMEMORY;
-
- strcpyW(buffer, deviceW);
- if (This->type == DEVICE_FILTER)
- strcatW(buffer, swW);
- else if (This->type == DEVICE_CODEC)
- strcatW(buffer, cmW);
-
- if (This->has_class)
+ if (This->type == DEVICE_DMO)
{
+ buffer = CoTaskMemAlloc((strlenW(deviceW) + strlenW(dmoW)
+ + 2 * CHARS_IN_GUID + 1) * sizeof(WCHAR));
+ if (!buffer) return E_OUTOFMEMORY;
+
+ strcpyW(buffer, deviceW);
+ strcatW(buffer, dmoW);
+ StringFromGUID2(&This->clsid, buffer + strlenW(buffer), CHARS_IN_GUID);
StringFromGUID2(&This->class, buffer + strlenW(buffer), CHARS_IN_GUID);
- strcatW(buffer, backslashW);
}
- strcatW(buffer, This->name);
+ else
+ {
+ buffer = CoTaskMemAlloc((strlenW(deviceW) + 3 + (This->has_class ? CHARS_IN_GUID : 0)
+ + strlenW(This->name) + 1) * sizeof(WCHAR));
+ if (!buffer) return E_OUTOFMEMORY;
+
+ strcpyW(buffer, deviceW);
+ if (This->type == DEVICE_FILTER)
+ strcatW(buffer, swW);
+ else if (This->type == DEVICE_CODEC)
+ strcatW(buffer, cmW);
+
+ if (This->has_class)
+ {
+ StringFromGUID2(&This->class, buffer + strlenW(buffer), CHARS_IN_GUID);
+ strcatW(buffer, backslashW);
+ }
+ strcatW(buffer, This->name);
+ }
*ppszDisplayName = buffer;
return S_OK;
diff --git a/dlls/devenum/parsedisplayname.c b/dlls/devenum/parsedisplayname.c
index 0f3ef3b..2992af0 100644
--- a/dlls/devenum/parsedisplayname.c
+++ b/dlls/devenum/parsedisplayname.c
@@ -91,16 +91,21 @@ static HRESULT WINAPI DEVENUM_IParseDisplayName_ParseDisplayName(IParseDisplayNa
name = strchrW(name, ':') + 1;
- if (name[0] == 's' && name[1] == 'w' && name[2] == ':')
+ if (!strncmpW(name, swW, 3))
{
type = DEVICE_FILTER;
name += 3;
}
- else if (name[0] == 'c' && name[1] == 'm' && name[2] == ':')
+ else if (!strncmpW(name, cmW, 3))
{
type = DEVICE_CODEC;
name += 3;
}
+ else if (!strncmpW(name, dmoW, 4))
+ {
+ type = DEVICE_DMO;
+ name += 4;
+ }
else
{
FIXME("unhandled device type %s\n", debugstr_w(name));
@@ -110,23 +115,42 @@ static HRESULT WINAPI DEVENUM_IParseDisplayName_ParseDisplayName(IParseDisplayNa
if (!(mon = DEVENUM_IMediaCatMoniker_Construct()))
return E_OUTOFMEMORY;
- lstrcpynW(buffer, name, CHARS_IN_GUID);
- if (CLSIDFromString(buffer, &class) == S_OK)
+ if (type == DEVICE_DMO)
{
- mon->has_class = TRUE;
- mon->class = class;
- name += CHARS_IN_GUID;
+ lstrcpynW(buffer, name, CHARS_IN_GUID);
+ if (FAILED(CLSIDFromString(buffer, &mon->clsid)))
+ {
+ IMoniker_Release(&mon->IMoniker_iface);
+ return MK_E_SYNTAX;
+ }
+
+ lstrcpynW(buffer, name + CHARS_IN_GUID - 1, CHARS_IN_GUID);
+ if (FAILED(CLSIDFromString(buffer, &mon->class)))
+ {
+ IMoniker_Release(&mon->IMoniker_iface);
+ return MK_E_SYNTAX;
+ }
+ }
+ else
+ {
+ lstrcpynW(buffer, name, CHARS_IN_GUID);
+ if (CLSIDFromString(buffer, &class) == S_OK)
+ {
+ mon->has_class = TRUE;
+ mon->class = class;
+ name += CHARS_IN_GUID;
+ }
+
+ if (!(mon->name = CoTaskMemAlloc((strlenW(name) + 1) * sizeof(WCHAR))))
+ {
+ IMoniker_Release(&mon->IMoniker_iface);
+ return E_OUTOFMEMORY;
+ }
+ strcpyW(mon->name, name);
}
mon->type = type;
- if (!(mon->name = CoTaskMemAlloc((strlenW(name) + 1) * sizeof(WCHAR))))
- {
- IMoniker_Release(&mon->IMoniker_iface);
- return E_OUTOFMEMORY;
- }
- strcpyW(mon->name, name);
-
*ret = &mon->IMoniker_iface;
return S_OK;
diff --git a/dlls/devenum/tests/Makefile.in b/dlls/devenum/tests/Makefile.in
index b268adf..2d6ec2d 100644
--- a/dlls/devenum/tests/Makefile.in
+++ b/dlls/devenum/tests/Makefile.in
@@ -1,5 +1,5 @@
TESTDLL = devenum.dll
-IMPORTS = advapi32 dsound msvfw32 oleaut32 ole32 winmm
+IMPORTS = advapi32 dsound msdmo msvfw32 oleaut32 ole32 winmm
C_SRCS = \
devenum.c
diff --git a/dlls/devenum/tests/devenum.c b/dlls/devenum/tests/devenum.c
index 383619c..2f66907 100644
--- a/dlls/devenum/tests/devenum.c
+++ b/dlls/devenum/tests/devenum.c
@@ -32,6 +32,7 @@
#include "dsound.h"
#include "mmddk.h"
#include "vfw.h"
+#include "dmoreg.h"
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
@@ -41,6 +42,7 @@ static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':',0};
static const WCHAR clsidW[] = {'C','L','S','I','D',0};
static const WCHAR waveW[] = {'w','a','v','e',':',0};
static const WCHAR mrleW[] = {'m','r','l','e',0};
+static const WCHAR dmoW[] = {'d','m','o',':',0};
static const WCHAR swW[] = {'s','w',':',0};
static const WCHAR cmW[] = {'c','m',':',0};
static const WCHAR backslashW[] = {'\\',0};
@@ -485,6 +487,67 @@ static void test_codec(void)
IParseDisplayName_Release(parser);
}
+static void test_dmo(void)
+{
+ static const WCHAR name[] = {'d','e','v','e','n','u','m',' ','t','e','s','t',0};
+ IParseDisplayName *parser;
+ IPropertyBag *prop_bag;
+ WCHAR buffer[200];
+ IMoniker *mon;
+ VARIANT var;
+ HRESULT hr;
+
+ hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser);
+ ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);
+
+ lstrcpyW(buffer, deviceW);
+ lstrcatW(buffer, dmoW);
+ StringFromGUID2(&CLSID_TestFilter, buffer + lstrlenW(buffer), CHARS_IN_GUID);
+ StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
+ mon = check_display_name(parser, buffer);
+
+ ok(!find_moniker(&CLSID_AudioRendererCategory, mon), "DMO should not be registered\n");
+
+ hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
+ ok(hr == S_OK, "got %#x\n", hr);
+
+ VariantInit(&var);
+ hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
+ ok(hr == E_FAIL, "got %#x\n", hr);
+
+ V_VT(&var) = VT_BSTR;
+ V_BSTR(&var) = SysAllocString(name);
+ hr = IPropertyBag_Write(prop_bag, friendly_name, &var);
+ ok(hr == E_ACCESSDENIED, "Write failed: %#x\n", hr);
+
+ hr = DMORegister(name, &CLSID_TestFilter, &CLSID_AudioRendererCategory, 0, 0, NULL, 0, NULL);
+ if (hr != E_ACCESSDENIED)
+ {
+ ok(hr == S_OK, "got %#x\n", hr);
+
+ VariantClear(&var);
+ hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
+ ok(hr == S_OK, "got %#x\n", hr);
+ ok(!lstrcmpW(V_BSTR(&var), name), "got %s\n", wine_dbgstr_w(V_BSTR(&var)));
+
+ VariantClear(&var);
+ V_VT(&var) = VT_BSTR;
+ V_BSTR(&var) = SysAllocString(name);
+ hr = IPropertyBag_Write(prop_bag, friendly_name, &var);
+ ok(hr == E_ACCESSDENIED, "Write failed: %#x\n", hr);
+
+ VariantClear(&var);
+ hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL);
+ ok(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "got %#x\n", hr);
+
+ hr = DMOUnregister(&CLSID_TestFilter, &CLSID_AudioRendererCategory);
+ ok(hr == S_OK, "got %#x\n", hr);
+ }
+ IPropertyBag_Release(prop_bag);
+ IMoniker_Release(mon);
+ IParseDisplayName_Release(parser);
+}
+
static void test_legacy_filter(void)
{
static const WCHAR nameW[] = {'t','e','s','t',0};
@@ -974,6 +1037,7 @@ START_TEST(devenum)
test_register_filter();
test_directshow_filter();
test_codec();
+ test_dmo();
test_legacy_filter();
hr = DirectSoundEnumerateW(test_dsound, NULL);
--
2.7.4
June 24, 2018
[PATCH 5/5] [programs\xcopy] Fix copying empty directories
by Jason Edmeades
Found whilst fixing bug#44967
When a directory is searched with /e, an equivalent destination
directory is created immediately, not just when contents are found.
Signed-off-by: Jason Edmeades <us(a)edmeades.me.uk>
---
programs/xcopy/tests/xcopy.c | 1 -
programs/xcopy/xcopy.c | 13 +++++++------
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/programs/xcopy/tests/xcopy.c b/programs/xcopy/tests/xcopy.c
index 0991d49769..94cede6f67 100644
--- a/programs/xcopy/tests/xcopy.c
+++ b/programs/xcopy/tests/xcopy.c
@@ -103,7 +103,6 @@ static void test_parms_syntax(void)
rc = runcmd("xcopy /D/S/E xcopytest xcopytest2\\");
ok(rc == 0, "xcopy /D/S/E test failed rc=%u\n", rc);
- todo_wine
ok(GetFileAttributesA("xcopytest2") != INVALID_FILE_ATTRIBUTES,
"xcopy failed to copy empty directory\n");
RemoveDirectoryA("xcopytest2");
diff --git a/programs/xcopy/xcopy.c b/programs/xcopy/xcopy.c
index 97b0538e57..e380cde226 100644
--- a/programs/xcopy/xcopy.c
+++ b/programs/xcopy/xcopy.c
@@ -590,6 +590,13 @@ static int XCOPY_DoCopy(WCHAR *srcstem, WCHAR *srcspec,
/* Search 2 - do subdirs */
if (flags & OPT_RECURSIVE) {
+
+ /* If /E is supplied, create the directory now */
+ if ((flags & OPT_EMPTYDIR) &&
+ !(flags & OPT_SIMULATE)) {
+ XCOPY_CreateDirectory(deststem);
+ }
+
lstrcpyW(inputpath, srcstem);
lstrcatW(inputpath, wchr_star);
findres = TRUE;
@@ -613,12 +620,6 @@ static int XCOPY_DoCopy(WCHAR *srcstem, WCHAR *srcspec,
lstrcpyW(outputpath, deststem);
if (*destspec == 0x00) {
lstrcatW(outputpath, finddata->cFileName);
-
- /* If /E is supplied, create the directory now */
- if ((flags & OPT_EMPTYDIR) &&
- !(flags & OPT_SIMULATE))
- XCOPY_CreateDirectory(outputpath);
-
lstrcatW(outputpath, wchr_slash);
}
--
2.17.1
June 24, 2018
[PATCH 4/5] [programs/xcopy] Return code 1 for no files is never returned
by Jason Edmeades
Found whilst fixing bug#44967
Testing, and confirmed on the internet (*1) shows xcopy never
returns 1 to indicate no files were copied.
(*1) e.g. https://superuser.com/questions/1180180/is-it-possible-to-get-an-errorlevel…
Signed-off-by: Jason Edmeades <us(a)edmeades.me.uk>
---
programs/xcopy/tests/xcopy.c | 4 +---
programs/xcopy/xcopy.c | 7 ++++---
2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/programs/xcopy/tests/xcopy.c b/programs/xcopy/tests/xcopy.c
index 7ca32d6c33..0991d49769 100644
--- a/programs/xcopy/tests/xcopy.c
+++ b/programs/xcopy/tests/xcopy.c
@@ -97,17 +97,15 @@ static void test_parms_syntax(void)
DeleteFileA("xcopytest\\xcopy1"); */
rc = runcmd("xcopy /D/S xcopytest xcopytest2\\");
- todo_wine
ok(rc == 0, "xcopy /D/S test failed rc=%u\n", rc);
ok(GetFileAttributesA("xcopytest2") == INVALID_FILE_ATTRIBUTES,
"xcopy copied empty directory incorrectly\n");
rc = runcmd("xcopy /D/S/E xcopytest xcopytest2\\");
- todo_wine {
ok(rc == 0, "xcopy /D/S/E test failed rc=%u\n", rc);
+ todo_wine
ok(GetFileAttributesA("xcopytest2") != INVALID_FILE_ATTRIBUTES,
"xcopy failed to copy empty directory\n");
- }
RemoveDirectoryA("xcopytest2");
}
diff --git a/programs/xcopy/xcopy.c b/programs/xcopy/xcopy.c
index 461104a8da..97b0538e57 100644
--- a/programs/xcopy/xcopy.c
+++ b/programs/xcopy/xcopy.c
@@ -31,12 +31,14 @@
/*
* Notes:
- * Apparently, valid return codes are:
+ * Documented valid return codes are:
* 0 - OK
- * 1 - No files found to copy
+ * 1 - No files found to copy (*1)
* 2 - CTRL+C during copy
* 4 - Initialization error, or invalid source specification
* 5 - Disk write error
+ *
+ * (*1) Testing shows return code 1 is never returned
*/
@@ -1165,7 +1167,6 @@ int wmain (int argc, WCHAR *argvW[])
} else if (!(flags & OPT_NOCOPY)) {
XCOPY_wprintf(XCOPY_LoadMessage(STRING_COPY), filesCopied);
}
- if (rc == RC_OK && filesCopied == 0) rc = RC_NOFILES;
return rc;
}
--
2.17.1
June 24, 2018
[PATCH 3/5] [programes/xcopy] Handle multiple switches concatenated without whitespace
by Jason Edmeades
Fixes bug#44967
This changes xcopy to support flags supplied like /S/E without spaces
between them. Tests supplied but in writing the tests I found a few
other problems left as todo in this patch.
(Note the majority of this patch is just changing the indenting of
a large code block)
Signed-off-by: Jason Edmeades <us(a)edmeades.me.uk>
---
programs/xcopy/tests/xcopy.c | 39 +++++++
programs/xcopy/xcopy.c | 208 ++++++++++++++++++++---------------
2 files changed, 159 insertions(+), 88 deletions(-)
diff --git a/programs/xcopy/tests/xcopy.c b/programs/xcopy/tests/xcopy.c
index ec7683aecc..7ca32d6c33 100644
--- a/programs/xcopy/tests/xcopy.c
+++ b/programs/xcopy/tests/xcopy.c
@@ -73,6 +73,44 @@ static void test_date_format(void)
DeleteFileA("xcopytest\\xcopy1");
}
+static void test_parms_syntax(void)
+{
+ DWORD rc;
+
+ rc = runcmd("xcopy /H/D:20-01-2000 xcopy1 xcopytest");
+ ok(rc == 4, "xcopy /H/D:d-m-y test returned rc=%u\n", rc);
+ ok(GetFileAttributesA("xcopytest\\xcopy1") == INVALID_FILE_ATTRIBUTES,
+ "xcopy should not have created xcopytest\\xcopy1\n");
+
+ rc = runcmd("xcopy /D:01-20-2000/H xcopy1 xcopytest");
+ ok(rc == 0, "xcopy /H/D:m-d-y test failed rc=%u\n", rc);
+ ok(GetFileAttributesA("xcopytest\\xcopy1") != INVALID_FILE_ATTRIBUTES,
+ "xcopy did not create xcopytest\\xcopy1\n");
+ DeleteFileA("xcopytest\\xcopy1");
+
+ /* The following test is commented out as under wine it generates
+ a recursively deep directory tree (todo_wine)
+ rc = runcmd("xcopy /D:1-20-2000/E xcopy1 xcopytest");
+ ok(rc == 0, "xcopy /D:m-d-y/E test failed rc=%u\n", rc);
+ ok(GetFileAttributesA("xcopytest\\xcopy1") != INVALID_FILE_ATTRIBUTES,
+ "xcopy did not create xcopytest\\xcopy1\n");
+ DeleteFileA("xcopytest\\xcopy1"); */
+
+ rc = runcmd("xcopy /D/S xcopytest xcopytest2\\");
+ todo_wine
+ ok(rc == 0, "xcopy /D/S test failed rc=%u\n", rc);
+ ok(GetFileAttributesA("xcopytest2") == INVALID_FILE_ATTRIBUTES,
+ "xcopy copied empty directory incorrectly\n");
+
+ rc = runcmd("xcopy /D/S/E xcopytest xcopytest2\\");
+ todo_wine {
+ ok(rc == 0, "xcopy /D/S/E test failed rc=%u\n", rc);
+ ok(GetFileAttributesA("xcopytest2") != INVALID_FILE_ATTRIBUTES,
+ "xcopy failed to copy empty directory\n");
+ }
+ RemoveDirectoryA("xcopytest2");
+}
+
START_TEST(xcopy)
{
char tmpdir[MAX_PATH];
@@ -94,6 +132,7 @@ START_TEST(xcopy)
CloseHandle(hfile);
test_date_format();
+ test_parms_syntax();
DeleteFileA("xcopy1");
RemoveDirectoryA("xcopytest");
diff --git a/programs/xcopy/xcopy.c b/programs/xcopy/xcopy.c
index a173cc14c7..461104a8da 100644
--- a/programs/xcopy/xcopy.c
+++ b/programs/xcopy/xcopy.c
@@ -743,101 +743,133 @@ static int XCOPY_ParseCommandLine(WCHAR *suppliedsource,
Note: Windows docs say /P prompts when dest is created
but tests show it is done for each src file
regardless of the destination */
- switch (toupper(word[1])) {
- case 'I': flags |= OPT_ASSUMEDIR; break;
- case 'S': flags |= OPT_RECURSIVE; break;
- case 'Q': flags |= OPT_QUIET; break;
- case 'F': flags |= OPT_FULL; break;
- case 'L': flags |= OPT_SIMULATE; break;
- case 'W': flags |= OPT_PAUSE; break;
- case 'T': flags |= OPT_NOCOPY | OPT_RECURSIVE; break;
- case 'Y': flags |= OPT_NOPROMPT; break;
- case 'N': flags |= OPT_SHORTNAME; break;
- case 'U': flags |= OPT_MUSTEXIST; break;
- case 'R': flags |= OPT_REPLACEREAD; break;
- case 'H': flags |= OPT_COPYHIDSYS; break;
- case 'C': flags |= OPT_IGNOREERRORS; break;
- case 'P': flags |= OPT_SRCPROMPT; break;
- case 'A': flags |= OPT_ARCHIVEONLY; break;
- case 'M': flags |= OPT_ARCHIVEONLY |
- OPT_REMOVEARCH; break;
-
- /* E can be /E or /EXCLUDE */
- case 'E': if (CompareStringW(LOCALE_USER_DEFAULT,
- NORM_IGNORECASE | SORT_STRINGSORT,
- &word[1], 8,
- EXCLUDE, -1) == CSTR_EQUAL) {
- if (XCOPY_ProcessExcludeList(&word[9])) {
- XCOPY_FailMessage(ERROR_INVALID_PARAMETER);
- goto out;
- } else flags |= OPT_EXCLUDELIST;
- } else flags |= OPT_EMPTYDIR | OPT_RECURSIVE;
- break;
-
- /* D can be /D or /D: */
- case 'D': if (word[2]==':' && is_digit(word[3])) {
- SYSTEMTIME st;
- WCHAR *pos = &word[3];
- BOOL isError = FALSE;
- memset(&st, 0x00, sizeof(st));
-
- /* Microsoft xcopy's usage message implies that the date
- * format depends on the locale, but that is false.
- * It is hardcoded to month-day-year.
- */
- st.wMonth = _wtol(pos);
- while (*pos && is_digit(*pos)) pos++;
- if (*pos++ != '-') isError = TRUE;
-
- if (!isError) {
- st.wDay = _wtol(pos);
- while (*pos && is_digit(*pos)) pos++;
- if (*pos++ != '-') isError = TRUE;
- }
+ int skip=0;
+ WCHAR *rest;
+
+ while (word[0]) {
+ rest = NULL;
+
+ switch (toupper(word[1])) {
+ case 'I': flags |= OPT_ASSUMEDIR; break;
+ case 'S': flags |= OPT_RECURSIVE; break;
+ case 'Q': flags |= OPT_QUIET; break;
+ case 'F': flags |= OPT_FULL; break;
+ case 'L': flags |= OPT_SIMULATE; break;
+ case 'W': flags |= OPT_PAUSE; break;
+ case 'T': flags |= OPT_NOCOPY | OPT_RECURSIVE; break;
+ case 'Y': flags |= OPT_NOPROMPT; break;
+ case 'N': flags |= OPT_SHORTNAME; break;
+ case 'U': flags |= OPT_MUSTEXIST; break;
+ case 'R': flags |= OPT_REPLACEREAD; break;
+ case 'H': flags |= OPT_COPYHIDSYS; break;
+ case 'C': flags |= OPT_IGNOREERRORS; break;
+ case 'P': flags |= OPT_SRCPROMPT; break;
+ case 'A': flags |= OPT_ARCHIVEONLY; break;
+ case 'M': flags |= OPT_ARCHIVEONLY |
+ OPT_REMOVEARCH; break;
+
+ /* E can be /E or /EXCLUDE */
+ case 'E': if (CompareStringW(LOCALE_USER_DEFAULT,
+ NORM_IGNORECASE | SORT_STRINGSORT,
+ &word[1], 8,
+ EXCLUDE, -1) == CSTR_EQUAL) {
+ if (XCOPY_ProcessExcludeList(&word[9])) {
+ XCOPY_FailMessage(ERROR_INVALID_PARAMETER);
+ goto out;
+ } else {
+ flags |= OPT_EXCLUDELIST;
- if (!isError) {
- st.wYear = _wtol(pos);
- while (*pos && is_digit(*pos)) pos++;
- if (st.wYear < 100) st.wYear+=2000;
+ /* Do not support concatenated switches onto exclude lists yet */
+ rest = end;
+ }
+ } else {
+ flags |= OPT_EMPTYDIR | OPT_RECURSIVE;
}
+ break;
- if (!isError && SystemTimeToFileTime(&st, &dateRange)) {
+ /* D can be /D or /D: */
+ case 'D': if (word[2]==':' && is_digit(word[3])) {
SYSTEMTIME st;
- WCHAR datestring[32], timestring[32];
-
- flags |= OPT_DATERANGE;
-
- /* Debug info: */
- FileTimeToSystemTime (&dateRange, &st);
- GetDateFormatW(0, DATE_SHORTDATE, &st, NULL, datestring,
- sizeof(datestring)/sizeof(WCHAR));
- GetTimeFormatW(0, TIME_NOSECONDS, &st,
- NULL, timestring, sizeof(timestring)/sizeof(WCHAR));
+ WCHAR *pos = &word[3];
+ BOOL isError = FALSE;
+ memset(&st, 0x00, sizeof(st));
+
+ /* Microsoft xcopy's usage message implies that the date
+ * format depends on the locale, but that is false.
+ * It is hardcoded to month-day-year.
+ */
+ st.wMonth = _wtol(pos);
+ while (*pos && is_digit(*pos)) pos++;
+ if (*pos++ != '-') isError = TRUE;
- WINE_TRACE("Date being used is: %s %s\n",
- wine_dbgstr_w(datestring), wine_dbgstr_w(timestring));
+ if (!isError) {
+ st.wDay = _wtol(pos);
+ while (*pos && is_digit(*pos)) pos++;
+ if (*pos++ != '-') isError = TRUE;
+ }
+
+ if (!isError) {
+ st.wYear = _wtol(pos);
+ while (*pos && is_digit(*pos)) pos++;
+ if (st.wYear < 100) st.wYear+=2000;
+ }
+
+ /* Handle switches straight after the supplied date */
+ rest = pos;
+
+ if (!isError && SystemTimeToFileTime(&st, &dateRange)) {
+ SYSTEMTIME st;
+ WCHAR datestring[32], timestring[32];
+
+ flags |= OPT_DATERANGE;
+
+ /* Debug info: */
+ FileTimeToSystemTime (&dateRange, &st);
+ GetDateFormatW(0, DATE_SHORTDATE, &st, NULL, datestring,
+ sizeof(datestring)/sizeof(WCHAR));
+ GetTimeFormatW(0, TIME_NOSECONDS, &st,
+ NULL, timestring, sizeof(timestring)/sizeof(WCHAR));
+
+ WINE_TRACE("Date being used is: %s %s\n",
+ wine_dbgstr_w(datestring), wine_dbgstr_w(timestring));
+ } else {
+ XCOPY_FailMessage(ERROR_INVALID_PARAMETER);
+ goto out;
+ }
} else {
- XCOPY_FailMessage(ERROR_INVALID_PARAMETER);
- goto out;
+ flags |= OPT_DATENEWER;
}
- } else {
- flags |= OPT_DATENEWER;
- }
- break;
-
- case '-': if (toupper(word[2])=='Y')
- flags &= ~OPT_NOPROMPT;
- break;
- case '?': XCOPY_wprintf(XCOPY_LoadMessage(STRING_HELP));
- rc = RC_HELP;
- goto out;
- case 'V':
- WINE_FIXME("ignoring /V\n");
- break;
- default:
- WINE_TRACE("Unhandled parameter '%s'\n", wine_dbgstr_w(word));
- XCOPY_wprintf(XCOPY_LoadMessage(STRING_INVPARM), word);
- goto out;
+ break;
+
+ case '-': if (toupper(word[2])=='Y') {
+ flags &= ~OPT_NOPROMPT;
+ rest = &word[3]; /* Skip over 3 characters */
+ }
+ break;
+ case '?': XCOPY_wprintf(XCOPY_LoadMessage(STRING_HELP));
+ rc = RC_HELP;
+ goto out;
+ case 'V':
+ WINE_FIXME("ignoring /V\n");
+ break;
+ default:
+ WINE_TRACE("Unhandled parameter '%s'\n", wine_dbgstr_w(word));
+ XCOPY_wprintf(XCOPY_LoadMessage(STRING_INVPARM), word);
+ goto out;
+ }
+
+ /* Unless overriden above, skip over the '/' and the first character */
+ if (rest == NULL) rest = &word[2];
+
+ /* By now, rest should point either to the null after the
+ switch, or the beginning of the next switch if there
+ was no whitespace between them */
+ if (!skip && *rest && *rest != '/') {
+ WINE_FIXME("Unexpected characters found and ignored '%s'\n", wine_dbgstr_w(rest));
+ skip=1;
+ } else {
+ word = rest;
+ }
}
}
word = next;
--
2.17.1
June 24, 2018
[PATCH 2/5] [programs/cmd] for loops lose subdirectory prefix
by Jason Edmeades
Fixes bug 45051
A for loop can be working through a wildcarded subdirectory, but when
processing the first file in the subdirectory, it stores the prefix in
a static variable which gets overwritten during the 'for' body
processing. Take a copy on the stack to free up the static buffer
Signed-off-by: Jason Edmeades <us(a)edmeades.me.uk>
---
programs/cmd/builtins.c | 10 ++++++++--
programs/cmd/tests/test_builtins.cmd | 7 +++++++
programs/cmd/tests/test_builtins.cmd.exp | 4 ++++
3 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 541915df67..56c50790ca 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -2261,19 +2261,25 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
thisSet->bracketDepth >= thisDepth) {
/* Loop through all entries on the same line */
- WCHAR *item;
+ WCHAR *staticitem;
WCHAR *itemStart;
WCHAR buffer[MAXSTRING];
WINE_TRACE("Processing for set %p\n", thisSet);
i = 0;
- while (*(item = WCMD_parameter (thisSet->command, i, &itemStart, TRUE, FALSE))) {
+ while (*(staticitem = WCMD_parameter (thisSet->command, i, &itemStart, TRUE, FALSE))) {
/*
* If the parameter within the set has a wildcard then search for matching files
* otherwise do a literal substitution.
*/
static const WCHAR wildcards[] = {'*','?','\0'};
+
+ /* Take a copy of the item returned from WCMD_parameter as it is held in a
+ static buffer which can be overwritten during parsing of the for body */
+ WCHAR item[MAXSTRING];
+ strcpyW(item, staticitem);
+
thisCmdStart = cmdStart;
itemNum++;
diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd
index d6edc5fff1..6f2ef4a843 100644
--- a/programs/cmd/tests/test_builtins.cmd
+++ b/programs/cmd/tests/test_builtins.cmd
@@ -1155,9 +1155,16 @@ mkdir foobar & cd foobar
mkdir foo
mkdir bar
mkdir baz
+mkdir pop
echo > bazbaz
echo --- basic wildcards
for %%i in (ba*) do echo %%i
+echo --- wildcards in subdirs
+echo something>pop\bar1
+echo something>pop\bar2.txt
+echo something>pop\bar3
+for %%f in (pop\ba*) do ( call echo %%f )
+rmdir /s/q pop
echo --- for /d
for /d %%i in (baz foo bar) do echo %%i 2>&1
rem Confirm we don't match files:
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index 22d83c3b19..0eb5b966e8 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -917,6 +917,10 @@ B C
B D
--- basic wildcards
bazbaz
+--- wildcards in subdirs
+pop\bar1(a)space@
+pop\bar2.txt(a)space@
+pop\bar3(a)space@
--- for /d
baz(a)space@
foo(a)space@
--
2.17.1
June 24, 2018
[PATCH 1/5] [programs/cmd] Add support for wildcards in if exist
by Jason Edmeades
Fixes bug 45052
Add support for 'if exist filenam*' style statments with associated tests
Signed-off-by: Jason Edmeades <us(a)edmeades.me.uk>
---
programs/cmd/builtins.c | 8 +++--
programs/cmd/tests/test_builtins.cmd | 43 ++++++++++++++++++++++++
programs/cmd/tests/test_builtins.cmd.exp | 8 +++++
3 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 04b098e98d..541915df67 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -2804,8 +2804,12 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList)
WCMD_parameter(p, 2+negate, &command, FALSE, FALSE);
}
else if (!lstrcmpiW (condition, existW)) {
- test = (GetFileAttributesW(WCMD_parameter(p, 1+negate, NULL, FALSE, FALSE))
- != INVALID_FILE_ATTRIBUTES);
+ HANDLE hff = INVALID_HANDLE_VALUE;
+ WIN32_FIND_DATAW fd;
+ hff = FindFirstFileW(WCMD_parameter(p, 1+negate, NULL, FALSE, FALSE), &fd);
+ test = (hff != INVALID_HANDLE_VALUE );
+ if (!test) FindClose(hff);
+
WCMD_parameter(p, 2+negate, &command, FALSE, FALSE);
}
else if (!lstrcmpiW (condition, defdW)) {
diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd
index 63ec3cacb1..d6edc5fff1 100644
--- a/programs/cmd/tests/test_builtins.cmd
+++ b/programs/cmd/tests/test_builtins.cmd
@@ -979,6 +979,49 @@ for %%i in (%WINE_STR_PARMS%) do (
for %%i in (%WINE_STR_PARMS%) do (
for %%j in (%WINE_STR_PARMS%) do (
call :GTRtest %%i %%j))
+
+echo ------------ Testing if/exist ------------
+mkdir subdir
+echo something>subdir\bar
+echo something else>foo
+if exist foo (
+ echo exist explicit works
+) else (
+ echo ERROR exist explicit broken
+)
+if exist bar (
+ echo ERROR exist explicit unknown file broken
+) else (
+ echo exist explicit unknown file works
+)
+if exist subdir\bar (
+ echo exist explicit in subdir works
+) else (
+ echo ERROR exist explicit in subdir broken
+)
+if exist fo* (
+ echo exist simple wildcard works
+) else (
+ echo ERROR exist simple wildcard broken
+)
+if exist subdir\ba* (
+ echo exist wildcard works
+) else (
+ echo ERROR exist wildcard broken
+)
+if not exist subdir\ba* (
+ echo ERROR negate exist wildcard broken
+) else (
+ echo negate exist wildcard works
+)
+if exist idontexist\ba* (
+ echo ERROR exist wildcard bad subdir broken
+) else (
+ echo exist wildcard bad subdir broken works
+)
+del foo subdir\bar
+rd subdir
+
echo ------ for numbers
if -1 LSS 1 (echo negative numbers handled)
if not -1 LSS -10 (echo negative numbers handled)
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index dcc96299b9..22d83c3b19 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -768,6 +768,14 @@ BA GTR B
BA GTR AB
BA GTR AA
AA GTR A
+------------ Testing if/exist ------------
+exist explicit works
+exist explicit unknown file works
+exist explicit in subdir works
+exist simple wildcard works
+exist wildcard works
+negate exist wildcard works
+exist wildcard bad subdir broken works
------ for numbers
negative numbers handled
negative numbers handled
--
2.17.1
June 24, 2018
[PATCH] include: Add definitions of SERVICES_*_DATABASEW for generic compilers
by Alex Henrie
Signed-off-by: Alex Henrie <alexhenrie24(a)gmail.com>
---
include/winsvc.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/include/winsvc.h b/include/winsvc.h
index 7d768f5ae2..9db35dd4fe 100644
--- a/include/winsvc.h
+++ b/include/winsvc.h
@@ -39,6 +39,9 @@ extern "C" {
#elif defined(_MSC_VER)
# define SERVICES_ACTIVE_DATABASEW L"ServicesActive"
# define SERVICES_FAILED_DATABASEW L"ServicesFailed"
+#else
+static const WCHAR SERVICES_ACTIVE_DATABASEW[] = { 'S','e','r','v','i','c','e','s','A','c','t','i','v','e',0 };
+static const WCHAR SERVICES_FAILED_DATABASEW[] = { 'S','e','r','v','i','c','e','s','F','a','i','l','e','d',0 };
#endif
#define SERVICES_ACTIVE_DATABASE WINELIB_NAME_AW( SERVICES_ACTIVE_DATABASE )
--
2.17.1
June 24, 2018
[PATCH] include: Add missing type declaration to CERT_EFSBLOB_VALUE_NAME
by Alex Henrie
Signed-off-by: Alex Henrie <alexhenrie24(a)gmail.com>
---
include/wincrypt.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/wincrypt.h b/include/wincrypt.h
index 373acacd26..8e8c258157 100644
--- a/include/wincrypt.h
+++ b/include/wincrypt.h
@@ -2216,7 +2216,7 @@ static const WCHAR CERT_EFSBLOB_REGPATH[] =
{'S','o','f','t','w','a','r','e','\\','P','o','l','i','c','i','e','s','\\',
'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
't','i','f','i','c','a','t','e','s','\\','E','F','S',0 };
-static const CERT_EFSBLOB_VALUE_NAME[] = { 'E','F','S','B','l','o','b',0 };
+static const WCHAR CERT_EFSBLOB_VALUE_NAME[] = { 'E','F','S','B','l','o','b',0 };
#endif
#if defined(__GNUC__)
--
2.17.1
June 24, 2018
[PATCH] winetest: Allow hyphens in test filenames.
by Zebediah Figura
For vulkan-1:vulkan.
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
winetest/dissect | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/winetest/dissect b/winetest/dissect
index 7416317..4db4f85 100755
--- a/winetest/dissect
+++ b/winetest/dissect
@@ -583,7 +583,7 @@ while ($line = <IN>) {
next if ($line =~ /^\s*$/);
chomp $line;
$line =~ s/\r+$//;
- if ($line =~ m%^([_.a-z0-9-]+):([_a-z0-9]+) (start|skipped) (-|[/_.a-z0-9]+) (-|[.0-9a-f]+)\r?$%)
+ if ($line =~ m%^([_.a-z0-9-]+):([_a-z0-9]+) (start|skipped) (-|[/_.a-z0-9-]+) (-|[.0-9a-f]+)\r?$%)
{
my ($l_dll, $l_unit, $l_type, $l_source, $l_rev) = ($1, $2, $3, $4, $5);
--
2.7.4
June 24, 2018
Re: [PATCH] kernel32: Always start debugger on WinSta0.
by Zebediah Figura
On 14/06/18 23:12, Alistair Leslie-Hughes wrote:
> From: Sebastian Lackner <sebastian(a)fds-team.de>
>
> Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
> ---
> dlls/kernel32/except.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/dlls/kernel32/except.c b/dlls/kernel32/except.c
> index de244fc..5f2166e 100644
> --- a/dlls/kernel32/except.c
> +++ b/dlls/kernel32/except.c
> @@ -304,6 +304,7 @@ static BOOL start_debugger(PEXCEPTION_POINTERS epointers, HANDLE hEvent)
> TRACE("Starting debugger %s\n", debugstr_a(cmdline));
> memset(&startup, 0, sizeof(startup));
> startup.cb = sizeof(startup);
> + startup.lpDesktop = (char *)"WinSta0";
> startup.dwFlags = STARTF_USESHOWWINDOW;
> startup.wShowWindow = SW_SHOWNORMAL;
> ret = CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, 0, env, NULL, &startup, &info);
>
I guess one potential problem with this is bugs like 45369; perhaps it
would be better to suppress creating a window at all in such a case.
June 24, 2018
[PATCH v3 2/2] d3d9/tests: Add new test for DXTn volume textures.
by Connor McAdams
To properly test the functionality of DXTn volume textures, I have added
new tests for DXT1, DXT3, and DXT5 replacing the old DXT5 test. I also
check for alpha values, which the previous test did not do.
Signed-off-by: Connor McAdams <conmanx360(a)gmail.com>
---
dlls/d3d9/tests/visual.c | 183 +++++++++++++++++++++++++++++++----------------
1 file changed, 123 insertions(+), 60 deletions(-)
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index b36c189..190ea1b 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -17741,26 +17741,73 @@ done:
DestroyWindow(window);
}
-static void volume_dxt5_test(void)
+static void volume_dxtn_test(void)
{
IDirect3DVolumeTexture9 *texture;
IDirect3DDevice9 *device;
D3DLOCKED_BOX box;
IDirect3D9 *d3d;
- unsigned int i;
+ struct surface_readback rb;
+ IDirect3DSurface9 *rt;
+ DWORD i, x;
ULONG refcount;
DWORD color;
HWND window;
HRESULT hr;
- static const char texture_data[] =
+ static const BYTE dxt1_texture_data[] =
+ {
+ 0x00, 0xF8, 0x00, 0xF8, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xE0, 0x07, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x1F, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00
+ };
+ static const BYTE dxt3_texture_data[] =
+ {
+ 0xFF, 0xEE, 0xFF, 0xEE, 0xFF, 0xEE, 0xFF, 0xEE, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xDD, 0xFF, 0xDD, 0xFF, 0xDD, 0xFF, 0xDD, 0xe0, 0x07, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xBB, 0xFF, 0xBB, 0xFF, 0xBB, 0xFF, 0xBB, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
+ };
+ static const BYTE dxt5_texture_data[] =
{
/* A 8x4x2 texture consisting of 4 4x4 blocks. The colors of the blocks are red, green, blue and white. */
- 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x80, 0x0D, 0xD8, 0x80, 0x0D, 0xD8, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
};
+ static const DWORD dxt1_expected_colors[] =
+ {
+ 0xFFFF0000, 0x00000000, 0xFF00FF00, 0xFF00FF00,
+ 0xFF0000FF, 0xFF0000FF, 0xFFFFFFFF, 0xFFFFFFFF,
+ };
+ static const DWORD dxt3_expected_colors[] =
+ {
+ 0xFFFF0000, 0xEEFF0000, 0xFF00FF00, 0xDD00FF00,
+ 0xFF0000FF, 0xCC0000FF, 0xFFFFFFFF, 0xBBFFFFFF,
+ };
+ static const DWORD dxt5_expected_colors[] =
+ {
+ 0xFFFF0000, 0x00FF0000, 0xFF00FF00, 0xFF00FF00,
+ 0xFF0000FF, 0xFF0000FF, 0xFFFFFFFF, 0xFFFFFFFF
+ };
+
+ static const struct
+ {
+ const char *dxtn;
+ const BYTE *tex_data;
+ DWORD tex_size;
+ D3DFORMAT fmt;
+ const DWORD *expected_colors;
+ }
+ dxtn_tex[] =
+ {
+ {"DXT1", dxt1_texture_data, sizeof(dxt1_texture_data), D3DFMT_DXT1, dxt1_expected_colors},
+ {"DXT3", dxt3_texture_data, sizeof(dxt3_texture_data), D3DFMT_DXT3, dxt3_expected_colors},
+ {"DXT5", dxt5_texture_data, sizeof(dxt5_texture_data), D3DFMT_DXT5, dxt5_expected_colors},
+ };
+
static const struct
{
struct vec3 position;
@@ -17778,70 +17825,86 @@ static void volume_dxt5_test(void)
{{ 1.0f, -1.0f, 1.0f}, { 1.0f, 0.0f, 0.75f}},
{{ 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 0.75f}},
};
- static const DWORD expected_colors[] = {0x00ff0000, 0x0000ff00, 0x000000ff, 0x00ffffff};
- window = create_window();
- d3d = Direct3DCreate9(D3D_SDK_VERSION);
- ok(!!d3d, "Failed to create a D3D object.\n");
- if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
- D3DFMT_X8R8G8B8, 0, D3DRTYPE_VOLUMETEXTURE, D3DFMT_DXT5)))
+ for (x = 0; x < ARRAY_SIZE(dxtn_tex); ++x)
{
- skip("DXT5 volume textures are not supported, skipping test.\n");
- goto done;
- }
- if (!(device = create_device(d3d, window, window, TRUE)))
- {
- skip("Failed to create a D3D device, skipping tests.\n");
- goto done;
- }
+ window = create_window();
+ d3d = Direct3DCreate9(D3D_SDK_VERSION);
+ ok(!!d3d, "Failed to create a D3D object.\n");
+ if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
+ D3DFMT_A8B8G8R8, 0, D3DRTYPE_VOLUMETEXTURE, dxtn_tex[x].fmt)))
+ {
+ skip("%s volume textures are not supported, skipping test.\n", dxtn_tex[x].dxtn);
+ continue;
+ }
+ if (!(device = create_device(d3d, window, window, TRUE)))
+ {
+ skip("Failed to create a D3D device, skipping tests.\n");
+ continue;
+ }
- hr = IDirect3DDevice9_CreateVolumeTexture(device, 8, 4, 2, 1, 0, D3DFMT_DXT5,
- D3DPOOL_MANAGED, &texture, NULL);
- ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_CreateVolumeTexture(device, 8, 4, 2, 1, 0, dxtn_tex[x].fmt,
+ D3DPOOL_MANAGED, &texture, NULL);
+ ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
- hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &box, NULL, 0);
- ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
- memcpy(box.pBits, texture_data, sizeof(texture_data));
- hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
- ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
+ hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &box, NULL, 0);
+ ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
+ memcpy(box.pBits, dxtn_tex[x].tex_data, dxtn_tex[x].tex_size);
- hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0));
- ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
- hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
- ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
- hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
- ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
- hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
- hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
- ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
- hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
- ok(SUCCEEDED(hr), "Failed to set mag filter, hr %#x.\n", hr);
+ hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
+ ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
- hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00ff00ff, 1.0f, 0);
- ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
- hr = IDirect3DDevice9_BeginScene(device);
- ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
- hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[0], sizeof(*quads));
- ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
- hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[4], sizeof(*quads));
- ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
- hr = IDirect3DDevice9_EndScene(device);
- ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0));
+ ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
+ ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+ ok(SUCCEEDED(hr), "Failed to set mag filter, hr %#x.\n", hr);
- for (i = 0; i < 4; i++)
- {
- color = getPixelColor(device, 80 + 160 * i, 240);
- ok (color_match(color, expected_colors[i], 1),
- "Expected color 0x%08x, got 0x%08x, case %u.\n", expected_colors[i], color, i);
+ hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00ff00ff, 1.0f, 0);
+ ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_BeginScene(device);
+ ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[0], sizeof(*quads));
+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[4], sizeof(*quads));
+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_EndScene(device);
+ ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
+
+ for (i = 0; i < ARRAY_SIZE(dxt1_expected_colors); ++i)
+ {
+ hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
+ if(FAILED(hr))
+ {
+ trace("Can't get the render target, hr %#x.\n", hr);
+ color = 0x00000000;
+ }
+ else
+ {
+ get_rt_readback(rt, &rb);
+ color = get_readback_color(&rb, 40 + 80 * i, 240);
+ release_surface_readback(&rb);
+ IDirect3DSurface9_Release(rt);
+ }
+ ok (color_match(color, dxtn_tex[x].expected_colors[i], 1),
+ "Expected color 0x%08x, got 0x%08x, case %u.\n", dxtn_tex[x].expected_colors[i], color, i);
+ }
+
+ hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
+ ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
+ IDirect3DVolumeTexture9_Release(texture);
+
+ refcount = IDirect3DDevice9_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
}
- hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
- ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
- IDirect3DVolumeTexture9_Release(texture);
- refcount = IDirect3DDevice9_Release(device);
- ok(!refcount, "Device has %u references left.\n", refcount);
-done:
IDirect3D9_Release(d3d);
DestroyWindow(window);
}
@@ -24131,7 +24194,7 @@ START_TEST(visual)
zenable_test();
fog_special_test();
volume_srgb_test();
- volume_dxt5_test();
+ volume_dxtn_test();
add_dirty_rect_test();
multisampled_depth_buffer_test();
resz_test();
--
2.7.4
June 23, 2018
[PATCH v3 1/2] wined3d: convert 3D DXTn textures
by Connor McAdams
This adds decompression functions for DXT1, DXT3, and DXT5 formats,
which covers all the possible DXT formats. These are used for
decompressing DXTn volume textures, and converting them to b8g8r8a8.
This patch also makes sure only 3D DXTn textures are uploaded by
performing a check in the wined3d_texture_upload_data function.
Signed-off-by: Connor McAdams <conmanx360(a)gmail.com>
---
dlls/wined3d/texture.c | 27 ++++++
dlls/wined3d/utils.c | 240 ++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 236 insertions(+), 31 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index c316906..0d03ea9 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -1948,6 +1948,33 @@ void wined3d_texture_upload_data(struct wined3d_texture *texture, unsigned int s
bo.addr += src_box->left * format->byte_count;
}
+ if (format->id == WINED3DFMT_DXT5 || format->id == WINED3DFMT_DXT4 ||
+ format->id == WINED3DFMT_DXT3 || format->id == WINED3DFMT_DXT2 ||
+ format->id == WINED3DFMT_DXT1 || format->id == WINED3DFMT_BC3_UNORM ||
+ format->id == WINED3DFMT_BC2_UNORM || format->id == WINED3DFMT_BC1_UNORM)
+ {
+ if (target == GL_TEXTURE_3D)
+ {
+ struct wined3d_format temp;
+
+ f = *format;
+ temp.upload = f.upload;
+ format = &f;
+ format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM, WINED3DUSAGE_TEXTURE);
+ f = *format;
+ f.upload = temp.upload;
+ f.conv_byte_count = 4;
+ format = &f;
+ texture->resource.format_flags &= ~WINED3DFMT_FLAG_BLOCKS;
+ }
+ else
+ {
+ f = *format;
+ f.upload = NULL;
+ format = &f;
+ }
+ }
+
if (format->upload)
{
unsigned int dst_row_pitch, dst_slice_pitch;
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 937c1bc..df6fef1 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -840,6 +840,206 @@ static void convert_s8_uint_d24_float(const BYTE *src, BYTE *dst, UINT src_row_p
}
}
+static void dxtn_decompress_block(const BYTE *src, BYTE *dst, UINT width, UINT height, UINT depth,
+ UINT x_pos, UINT y_pos, UINT z_pos, UINT dst_slice_pitch, UINT64 cur_block, UINT fmt, BYTE block_offset)
+{
+ UINT64 alpha_block, alpha_index, color_block, color_index;
+ const UINT64 *source;
+ DWORD *dest;
+ DWORD alpha_lookup;
+ DWORD bgra;
+ DWORD temp;
+ DWORD i, x, y;
+ WORD color[2];
+ BYTE alpha_val, color_val;
+ BYTE alpha[8];
+ BYTE r[4];
+ BYTE g[4];
+ BYTE b[4];
+
+ source = (const UINT64 *)(src + cur_block * block_offset);
+ if (fmt == WINED3DFMT_DXT1)
+ {
+ color_block = source[0];
+ alpha_block = 0;
+ }
+ else
+ {
+ alpha_block = source[0];
+ color_block = source[1];
+ }
+
+ color[0] = color_block & 0xffff;
+ color[1] = (color_block >> 16) & 0xffff;
+ for (i = 0; i < 2; ++i)
+ {
+ temp = (color[i] >> 11) * 255 + 16;
+ r[i] = (temp / 32 + temp) / 32;
+ temp = ((color[i] >> 5) & 0x3f) * 255 + 32;
+ g[i] = (temp / 64 + temp) / 64;
+ temp = (color[i] & 0x1f) * 255 + 16;
+ b[i] = (temp / 32 + temp) / 32;
+ }
+
+ if (fmt == WINED3DFMT_DXT3 || fmt == WINED3DFMT_DXT5 || color[0] > color[1])
+ {
+ for (i = 0; i < 2; ++i)
+ {
+ r[2 + i] = (2 * r[0 + i] + r[1 - i]) / 3;
+ g[2 + i] = (2 * g[0 + i] + g[1 - i]) / 3;
+ b[2 + i] = (2 * b[0 + i] + b[1 - i]) / 3;
+ }
+ }
+ else if (fmt == WINED3DFMT_DXT1 && color[0] <= color[1])
+ {
+ r[2] = (r[0] + r[1]) / 2;
+ g[2] = (g[0] + g[1]) / 2;
+ b[2] = (b[0] + b[1]) / 2;
+
+ r[3] = 0;
+ g[3] = 0;
+ b[3] = 0;
+ }
+
+ switch (fmt)
+ {
+ case WINED3DFMT_DXT1:
+ alpha_index = 0;
+ for (i = 0; i < ARRAY_SIZE(alpha); ++i)
+ alpha[i] = 255;
+ if (color[0] <= color[1])
+ alpha[3] = 0;
+ break;
+ case WINED3DFMT_DXT3:
+ alpha_index = alpha_block;
+ for (i = 0; i < ARRAY_SIZE(alpha); ++i)
+ alpha[i] = 0;
+ break;
+ case WINED3DFMT_DXT5:
+ alpha_index = (alpha_block >> 16);
+ alpha[0] = alpha_block & 0xff;
+ alpha[1] = (alpha_block >> 8) & 0xff;
+ if (alpha[0] > alpha[1])
+ {
+ for (i = 0; i < 6; ++i)
+ alpha[2 + i] = (((6 - i) * alpha[0]) + ((1 + i) * alpha[1])) / 7;
+ }
+ else if (alpha[0] <= alpha[1])
+ {
+ for (i = 0; i < 4; ++i)
+ alpha[2 + i] = (((4 - i) * alpha[0]) + ((1 + i) * alpha[1])) / 5;
+ alpha[6] = 0;
+ alpha[7] = 255;
+ }
+ break;
+ default:
+ alpha_index = 0;
+ break;
+ }
+
+ color_index = (color_block >> 32) & 0xffffffff;
+ dest = (DWORD *)(dst + z_pos * dst_slice_pitch);
+ for (y = 0; y < 4; ++y)
+ {
+ if (y_pos + y >= height)
+ break;
+ for (x = 0; x < 4; ++x)
+ {
+ if (x_pos + x >= width)
+ break;
+
+ color_val = 0;
+ alpha_val = 0;
+ bgra = 0;
+
+ color_val = (color_index >> (y * 8));
+ color_val = (color_val >> (x * 2)) & 0x3;
+ switch (fmt)
+ {
+ case WINED3DFMT_DXT1:
+ alpha_val = color_val;
+ break;
+ case WINED3DFMT_DXT3:
+ alpha_lookup = (alpha_index >> (y * 16)) & 0xffff;
+ alpha_val = (alpha_lookup >> (x * 4)) & 0xf;
+ temp = alpha_val * 255 + 8;
+ alpha[0] = (temp / 16 + temp) / 16;
+ alpha_val = 0;
+ break;
+ case WINED3DFMT_DXT5:
+ alpha_lookup = (alpha_index >> (y * 12)) & 0xfff;
+ alpha_val = (alpha_lookup >> (x * 3)) & 0x7;
+ break;
+ }
+ bgra = ((alpha[alpha_val] << 24) | (r[color_val] << 16) | (g[color_val] << 8) | b[color_val]);
+ dest[(y_pos + y) * width + (x_pos + x)] = bgra;
+ }
+ }
+}
+
+static void convert_dxt5_b8g8r8a8_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
+ UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
+{
+ UINT64 current_block;
+ DWORD x, y, z;
+
+ current_block = 0;
+
+ for (z = 0; z < depth; ++z)
+ {
+ for (y = 0; y < height; y += 4)
+ {
+ for (x = 0; x < width; x += 4)
+ {
+ dxtn_decompress_block(src, dst, width, height, depth, x, y, z, dst_slice_pitch, current_block, WINED3DFMT_DXT5, 16);
+ current_block++;
+ }
+ }
+ }
+}
+
+static void convert_dxt3_b8g8r8a8_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
+ UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
+{
+ UINT64 current_block;
+ DWORD x, y, z;
+
+ current_block = 0;
+
+ for (z = 0; z < depth; ++z)
+ {
+ for (y = 0; y < height; y += 4)
+ {
+ for (x = 0; x < width; x += 4)
+ {
+ dxtn_decompress_block(src, dst, width, height, depth, x, y, z, dst_slice_pitch, current_block, WINED3DFMT_DXT3, 16);
+ current_block++;
+ }
+ }
+ }
+}
+
+static void convert_dxt1_b8g8r8a8_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
+ UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
+{
+ UINT64 current_block;
+ DWORD x, y, z;
+
+ current_block = 0;
+
+ for (z = 0; z < depth; ++z)
+ {
+ for (y = 0; y < height; y += 4)
+ {
+ for (x = 0; x < width; x += 4)
+ {
+ dxtn_decompress_block(src, dst, width, height, depth, x, y, z, dst_slice_pitch, current_block, WINED3DFMT_DXT1, 8);
+ current_block++;
+ }
+ }
+ }
+}
+
static void x8_d24_unorm_upload(const BYTE *src, BYTE *dst,
unsigned int src_row_pitch, unsigned int src_slice_pitch,
unsigned int dst_row_pitch, unsigned int dst_slice_pitch,
@@ -1118,42 +1318,42 @@ static const struct wined3d_format_texture_info format_texture_info[] =
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt1_b8g8r8a8_unorm},
{WINED3DFMT_DXT2, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt3_b8g8r8a8_unorm},
{WINED3DFMT_DXT3, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt3_b8g8r8a8_unorm},
{WINED3DFMT_DXT4, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt5_b8g8r8a8_unorm},
{WINED3DFMT_DXT5, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt5_b8g8r8a8_unorm},
{WINED3DFMT_BC1_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt1_b8g8r8a8_unorm},
{WINED3DFMT_BC2_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt3_b8g8r8a8_unorm},
{WINED3DFMT_BC3_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt5_b8g8r8a8_unorm},
{WINED3DFMT_BC4_UNORM, GL_COMPRESSED_RED_RGTC1, GL_COMPRESSED_RED_RGTC1, 0,
GL_RED, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
@@ -3394,29 +3594,7 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_
* for dx9 GPUs support it, some do not, so not supporting DXTn volumes is OK for d3d9.
*
* Note that GL_NV_texture_compression_vtc adds this functionality to OpenGL, but the
- * block layout is not compatible with the one used by d3d. See volume_dxt5_test. */
- idx = get_format_idx(WINED3DFMT_DXT1);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_DXT2);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_DXT3);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_DXT4);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_DXT5);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_BC1_UNORM);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_BC1_UNORM_SRGB);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_BC2_UNORM);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_BC2_UNORM_SRGB);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_BC3_UNORM);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_BC3_UNORM_SRGB);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
+ * block layout is not compatible with the one used by d3d. See volume_dxtn_test. */
/* Similarly with ATI1N / ATI2N and GL_ARB_texture_compression_rgtc. */
idx = get_format_idx(WINED3DFMT_ATI1N);
gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
--
2.7.4
June 23, 2018
[PATCH v3 0/2] DXTn 3D Texture support
by Connor McAdams
This patch series adds support for DXTn volume textures by using the
CPU to decompress and convert them before upload.
It has been tested and works, but recently I included the BC1-BC3
formats as they use the same DXTn compression. However, I was unsure
about handling the WINED3DFMT_BCn_UNORM_SRGB. It may need to be added
to the list of formats in texture.c to prevent conversion if it's a
2D texture. Let me know if it needs changed.
Thanks,
Connor.
Connor McAdams (2):
wined3d: convert 3D DXTn textures
d3d9/tests: Add new test for DXTn volume textures.
dlls/d3d9/tests/visual.c | 183 ++++++++++++++++++++++++------------
dlls/wined3d/texture.c | 27 ++++++
dlls/wined3d/utils.c | 240 +++++++++++++++++++++++++++++++++++++++++------
3 files changed, 359 insertions(+), 91 deletions(-)
--
2.7.4
June 23, 2018
[PATCH] comctl32/listview: Don't send LVN_ENDLABELEDIT twice under some circumstances
by Fabian Maurer
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
---
dlls/comctl32/listview.c | 10 +++++++++
dlls/comctl32/tests/listview.c | 41 ++++++++++++++++++++++++++++++++++
2 files changed, 51 insertions(+)
diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index 200bf93be55..0193c038ebb 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -326,6 +326,7 @@ typedef struct tagLISTVIEW_INFO
/* misc */
DWORD iVersion; /* CCM_[G,S]ETVERSION */
+ BOOL inEndEditLabel; /* To prevent sending LVN_ENDLABELEDIT during LVN_ENDLABELEDIT */
} LISTVIEW_INFO;
/*
@@ -5869,6 +5870,9 @@ static BOOL LISTVIEW_EndEditLabelT(LISTVIEW_INFO *infoPtr, BOOL storeText, BOOL
WCHAR *pszText = NULL;
BOOL res;
+ if (infoPtr->inEndEditLabel)
+ return FALSE;
+
if (storeText)
{
DWORD len = isW ? GetWindowTextLengthW(infoPtr->hwndEdit) : GetWindowTextLengthA(infoPtr->hwndEdit);
@@ -5914,9 +5918,14 @@ static BOOL LISTVIEW_EndEditLabelT(LISTVIEW_INFO *infoPtr, BOOL storeText, BOOL
dispInfo.item.pszText = same ? NULL : pszText;
dispInfo.item.cchTextMax = textlenT(dispInfo.item.pszText, isW);
+ /* Sending LVN_ENDLABELEDITW might trigger EN_KILLFOCUS which would call this function again */
+ infoPtr->inEndEditLabel = TRUE;
+
/* Do we need to update the Item Text */
res = notify_dispinfoT(infoPtr, LVN_ENDLABELEDITW, &dispInfo, isW);
+ infoPtr->inEndEditLabel = FALSE;
+
infoPtr->nEditLabelItem = -1;
infoPtr->hwndEdit = 0;
@@ -9497,6 +9506,7 @@ static LRESULT LISTVIEW_NCCreate(HWND hwnd, WPARAM wParam, const CREATESTRUCTW *
infoPtr->itemEdit.fEnabled = FALSE;
infoPtr->iVersion = COMCTL32_VERSION;
infoPtr->colRectsDirty = FALSE;
+ infoPtr->inEndEditLabel = FALSE;
/* get default font (icon title) */
SystemParametersInfoW(SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c
index e9b715ee412..3e9e9697a4f 100644
--- a/dlls/comctl32/tests/listview.c
+++ b/dlls/comctl32/tests/listview.c
@@ -75,6 +75,10 @@ static BOOL g_disp_A_to_W;
static NMLVDISPINFOA g_editbox_disp_info;
/* when this is set focus will be tested on LVN_DELETEITEM */
static BOOL g_focus_test_LVN_DELETEITEM;
+/* Whether to send WM_KILLFOCUS to the edit control during LVN_ENDLABELEDIT */
+static BOOL do_LVN_ENDLABELEDIT_killfocus = FALSE;
+/* Number of LVN_ENDLABELEDIT notifications received */
+static BOOL LVN_ENDLABELEDITA_count = 0;
static HWND subclass_editbox(HWND hwndListview);
@@ -510,6 +514,11 @@ static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LP
ok(IsWindow(edit), "expected valid edit control handle\n");
ok((GetWindowLongA(edit, GWL_STYLE) & ES_MULTILINE) == 0, "edit is multiline\n");
+ LVN_ENDLABELEDITA_count++;
+
+ if (do_LVN_ENDLABELEDIT_killfocus)
+ SendMessageA(edit, WM_KILLFOCUS, 0, 0);
+
return TRUE;
}
case LVN_BEGINSCROLL:
@@ -6322,6 +6331,37 @@ static void test_LVSCW_AUTOSIZE(void)
DestroyWindow(hwnd);
}
+static void test_LVN_ENDLABELEDITW(void)
+{
+ HWND hwnd, hwndedit;
+ LVITEMW item = {0};
+ WCHAR text[] = {'l','a','l','a',0};
+ DWORD ret;
+
+ hwnd = create_listview_control(LVS_REPORT | LVS_EDITLABELS);
+
+ insert_column(hwnd, 0);
+
+ item.mask = LVIF_TEXT;
+ item.pszText = text;
+ ListView_InsertItemW(hwnd, &item);
+
+ SetFocus(hwnd);
+ hwndedit = (HWND)SendMessageW(hwnd, LVM_EDITLABELW, 0, 0);
+
+ ret = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)"test");
+ expect(TRUE, ret);
+
+ LVN_ENDLABELEDITA_count = 0;
+ do_LVN_ENDLABELEDIT_killfocus = TRUE;
+ ret = SendMessageA(hwndedit, WM_KEYDOWN, VK_RETURN, 0);
+ do_LVN_ENDLABELEDIT_killfocus = FALSE;
+ ok(LVN_ENDLABELEDITA_count == 1,
+ "messagebox during LVN_ENDLABELEDIT gave wrong number of LVN_ENDLABELEDITA: %d\n", LVN_ENDLABELEDITA_count);
+
+ DestroyWindow(hwnd);
+}
+
START_TEST(listview)
{
ULONG_PTR ctx_cookie;
@@ -6425,6 +6465,7 @@ START_TEST(listview)
test_oneclickactivate();
test_state_image();
test_LVSCW_AUTOSIZE();
+ test_LVN_ENDLABELEDITW();
unload_v6_module(ctx_cookie, hCtx);
--
2.18.0
June 23, 2018
[PATCH v4] msvcrt: Use already existent oneexit_table functions for _onexit and _c_exit
by Piotr Caban
From: Fabian Maurer <dark.shadow4(a)web.de>
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
Signed-off-by: Piotr Caban <piotr(a)codeweavers.com>
v4:
- don't use __MSVCRT_ prefix for internal functions
- simplified atexit functions order test
---
dlls/msvcrt/exit.c | 201
+++++++++++++++++++++------------------------
dlls/ucrtbase/tests/misc.c | 56 ++++++++++++-
2 files changed, 149 insertions(+), 108 deletions(-)
June 23, 2018
[PATCH v2 2/2] wined3d: Add new test for DXTn volume textures.
by Connor McAdams
To properly test the functionality of DXTn volume textures, I have added
new tests for DXT1, DXT3, and DXT5 replacing the old DXT5 test. I also
check for alpha values, which the previous test did not do.
Signed-off-by: Connor McAdams <conmanx360(a)gmail.com>
---
dlls/d3d9/tests/visual.c | 183 +++++++++++++++++++++++++++++++----------------
1 file changed, 123 insertions(+), 60 deletions(-)
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index b36c189..29fd27b 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -17741,26 +17741,73 @@ done:
DestroyWindow(window);
}
-static void volume_dxt5_test(void)
+static void volume_dxtn_test(void)
{
IDirect3DVolumeTexture9 *texture;
IDirect3DDevice9 *device;
D3DLOCKED_BOX box;
IDirect3D9 *d3d;
- unsigned int i;
+ struct surface_readback rb;
+ IDirect3DSurface9 *rt;
+ DWORD i, x;
ULONG refcount;
DWORD color;
HWND window;
HRESULT hr;
- static const char texture_data[] =
+ static const BYTE dxt1_texture_data[] =
+ {
+ 0x00, 0xF8, 0x00, 0xF8, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xE0, 0x07, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x1F, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00
+ };
+ static const BYTE dxt3_texture_data[] =
+ {
+ 0xFF, 0xEE, 0xFF, 0xEE, 0xFF, 0xEE, 0xFF, 0xEE, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xDD, 0xFF, 0xDD, 0xFF, 0xDD, 0xFF, 0xDD, 0xe0, 0x07, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xBB, 0xFF, 0xBB, 0xFF, 0xBB, 0xFF, 0xBB, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
+ };
+ static const BYTE dxt5_texture_data[] =
{
/* A 8x4x2 texture consisting of 4 4x4 blocks. The colors of the blocks are red, green, blue and white. */
- 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x80, 0x0D, 0xD8, 0x80, 0x0D, 0xD8, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
};
+ static const DWORD dxt1_expected_colors[] =
+ {
+ 0xFFFF0000, 0x00000000, 0xFF00FF00, 0xFF00FF00,
+ 0xFF0000FF, 0xFF0000FF, 0xFFFFFFFF, 0xFFFFFFFF,
+ };
+ static const DWORD dxt3_expected_colors[] =
+ {
+ 0xFFFF0000, 0xEEFF0000, 0xFF00FF00, 0xDD00FF00,
+ 0xFF0000FF, 0xCC0000FF, 0xFFFFFFFF, 0xBBFFFFFF,
+ };
+ static const DWORD dxt5_expected_colors[] =
+ {
+ 0xFFFF0000, 0x00FF0000, 0xFF00FF00, 0xFF00FF00,
+ 0xFF0000FF, 0xFF0000FF, 0xFFFFFFFF, 0xFFFFFFFF
+ };
+
+ static const struct
+ {
+ const char *dxtn;
+ const BYTE *tex_data;
+ DWORD tex_size;
+ D3DFORMAT fmt;
+ const DWORD *expected_colors;
+ }
+ dxtn_tex[] =
+ {
+ {"DXT1", dxt1_texture_data, sizeof(dxt1_texture_data), D3DFMT_DXT1, dxt1_expected_colors},
+ {"DXT3", dxt3_texture_data, sizeof(dxt3_texture_data), D3DFMT_DXT3, dxt3_expected_colors},
+ {"DXT5", dxt5_texture_data, sizeof(dxt5_texture_data), D3DFMT_DXT5, dxt5_expected_colors},
+ };
+
static const struct
{
struct vec3 position;
@@ -17778,70 +17825,86 @@ static void volume_dxt5_test(void)
{{ 1.0f, -1.0f, 1.0f}, { 1.0f, 0.0f, 0.75f}},
{{ 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 0.75f}},
};
- static const DWORD expected_colors[] = {0x00ff0000, 0x0000ff00, 0x000000ff, 0x00ffffff};
- window = create_window();
- d3d = Direct3DCreate9(D3D_SDK_VERSION);
- ok(!!d3d, "Failed to create a D3D object.\n");
- if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
- D3DFMT_X8R8G8B8, 0, D3DRTYPE_VOLUMETEXTURE, D3DFMT_DXT5)))
- {
- skip("DXT5 volume textures are not supported, skipping test.\n");
- goto done;
- }
- if (!(device = create_device(d3d, window, window, TRUE)))
+ for (x = 0; x < 3; ++x)
{
- skip("Failed to create a D3D device, skipping tests.\n");
- goto done;
- }
+ window = create_window();
+ d3d = Direct3DCreate9(D3D_SDK_VERSION);
+ ok(!!d3d, "Failed to create a D3D object.\n");
+ if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
+ D3DFMT_A8B8G8R8, 0, D3DRTYPE_VOLUMETEXTURE, dxtn_tex[x].fmt)))
+ {
+ skip("%s volume textures are not supported, skipping test.\n", dxtn_tex[x].dxtn);
+ continue;
+ }
+ if (!(device = create_device(d3d, window, window, TRUE)))
+ {
+ skip("Failed to create a D3D device, skipping tests.\n");
+ continue;
+ }
- hr = IDirect3DDevice9_CreateVolumeTexture(device, 8, 4, 2, 1, 0, D3DFMT_DXT5,
- D3DPOOL_MANAGED, &texture, NULL);
- ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_CreateVolumeTexture(device, 8, 4, 2, 1, 0, dxtn_tex[x].fmt,
+ D3DPOOL_MANAGED, &texture, NULL);
+ ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
- hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &box, NULL, 0);
- ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
- memcpy(box.pBits, texture_data, sizeof(texture_data));
- hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
- ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
+ hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &box, NULL, 0);
+ ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
+ memcpy(box.pBits, dxtn_tex[x].tex_data, dxtn_tex[x].tex_size);
- hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0));
- ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
- hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
- ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
- hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
- ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
- hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
- hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
- ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
- hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
- ok(SUCCEEDED(hr), "Failed to set mag filter, hr %#x.\n", hr);
+ hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
+ ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
- hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00ff00ff, 1.0f, 0);
- ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
- hr = IDirect3DDevice9_BeginScene(device);
- ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
- hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[0], sizeof(*quads));
- ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
- hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[4], sizeof(*quads));
- ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
- hr = IDirect3DDevice9_EndScene(device);
- ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0));
+ ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
+ ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+ ok(SUCCEEDED(hr), "Failed to set mag filter, hr %#x.\n", hr);
- for (i = 0; i < 4; i++)
- {
- color = getPixelColor(device, 80 + 160 * i, 240);
- ok (color_match(color, expected_colors[i], 1),
- "Expected color 0x%08x, got 0x%08x, case %u.\n", expected_colors[i], color, i);
+ hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00ff00ff, 1.0f, 0);
+ ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_BeginScene(device);
+ ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[0], sizeof(*quads));
+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[4], sizeof(*quads));
+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
+ hr = IDirect3DDevice9_EndScene(device);
+ ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
+
+ for (i = 0; i < 8; ++i)
+ {
+ hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
+ if(FAILED(hr))
+ {
+ trace("Can't get the render target, hr %#x.\n", hr);
+ color = 0x00000000;
+ }
+ else
+ {
+ get_rt_readback(rt, &rb);
+ color = get_readback_color(&rb, 40 + 80 * i, 240);
+ release_surface_readback(&rb);
+ IDirect3DSurface9_Release(rt);
+ }
+ ok (color_match(color, dxtn_tex[x].expected_colors[i], 1),
+ "Expected color 0x%08x, got 0x%08x, case %u.\n", dxtn_tex[x].expected_colors[i], color, i);
+ }
+
+ hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
+ ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
+ IDirect3DVolumeTexture9_Release(texture);
+
+ refcount = IDirect3DDevice9_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
}
- hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
- ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
- IDirect3DVolumeTexture9_Release(texture);
- refcount = IDirect3DDevice9_Release(device);
- ok(!refcount, "Device has %u references left.\n", refcount);
-done:
IDirect3D9_Release(d3d);
DestroyWindow(window);
}
@@ -24131,7 +24194,7 @@ START_TEST(visual)
zenable_test();
fog_special_test();
volume_srgb_test();
- volume_dxt5_test();
+ volume_dxtn_test();
add_dirty_rect_test();
multisampled_depth_buffer_test();
resz_test();
--
2.7.4
June 22, 2018
[PATCH v2 1/2] wined3d: Add decompression functions for DXT1, DXT3, and DXT5
by Connor McAdams
This adds decompression functions for DXT1, DXT3, and DXT5 formats,
which covers all the possible DXT formats. These are used for
decompressing DXTn volume textures, and converting them to b8g8r8a8.
This patch also makes sure only 3D DXTn textures are uploaded by
performing a check in the wined3d_texture_upload_data function.
Signed-off-by: Connor McAdams <conmanx360(a)gmail.com>
---
dlls/wined3d/texture.c | 26 ++++
dlls/wined3d/utils.c | 323 ++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 333 insertions(+), 16 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index c316906..a998b9c 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -1948,6 +1948,32 @@ void wined3d_texture_upload_data(struct wined3d_texture *texture, unsigned int s
bo.addr += src_box->left * format->byte_count;
}
+ if (format->id == WINED3DFMT_DXT5 || format->id == WINED3DFMT_DXT4 ||
+ format->id == WINED3DFMT_DXT3 || format->id == WINED3DFMT_DXT2 ||
+ format->id == WINED3DFMT_DXT1)
+ {
+ if (target == GL_TEXTURE_3D)
+ {
+ struct wined3d_format temp;
+
+ f = *format;
+ temp.upload = f.upload;
+ format = &f;
+ format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM, WINED3DUSAGE_TEXTURE);
+ f = *format;
+ f.upload = temp.upload;
+ f.conv_byte_count = 4;
+ format = &f;
+ texture->resource.format_flags &= ~WINED3DFMT_FLAG_BLOCKS;
+ }
+ else
+ {
+ f = *format;
+ f.upload = NULL;
+ format = &f;
+ }
+ }
+
if (format->upload)
{
unsigned int dst_row_pitch, dst_slice_pitch;
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 937c1bc..719f23e 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -840,6 +840,307 @@ static void convert_s8_uint_d24_float(const BYTE *src, BYTE *dst, UINT src_row_p
}
}
+static void dxt5_decompress_block(const BYTE *src, BYTE *dst, UINT width, UINT height, UINT depth,
+ UINT x_pos, UINT y_pos, UINT z_pos, UINT dst_slice_pitch, UINT64 cur_block)
+{
+ UINT64 alpha_block, alpha_index, color_block, color_index;
+ const UINT64 *source;
+ DWORD *dest;
+ DWORD alpha_lookup;
+ DWORD bgra;
+ DWORD temp;
+ DWORD i, x, y;
+ WORD color[2];
+ BYTE alpha_val, color_val;
+ BYTE alpha[8];
+ BYTE r[4];
+ BYTE g[4];
+ BYTE b[4];
+
+ source = (const UINT64 *)(src + cur_block * 16);
+ alpha_block = source[0];
+ color_block = source[1];
+
+ alpha[0] = alpha_block & 0xff;
+ alpha[1] = (alpha_block >> 8) & 0xff;
+
+ if (alpha[0] > alpha[1])
+ {
+ for (i = 0; i < 6; ++i)
+ alpha[2 + i] = (((6 - i) * alpha[0]) + ((1 + i) * alpha[1])) / 7;
+ }
+ else if (alpha[0] <= alpha[1])
+ {
+ for (i = 0; i < 4; ++i)
+ alpha[2 + i] = (((4 - i) * alpha[0]) + ((1 + i) * alpha[1])) / 5;
+ alpha[6] = 0;
+ alpha[7] = 255;
+ }
+
+ color[0] = color_block & 0xffff;
+ color[1] = (color_block >> 16) & 0xffff;
+
+ for (i = 0; i < 2; ++i)
+ {
+ temp = (color[i] >> 11) * 255 + 16;
+ r[i] = (temp / 32 + temp) / 32;
+ temp = ((color[i] >> 5) & 0x3f) * 255 + 32;
+ g[i] = (temp / 64 + temp) / 64;
+ temp = (color[i] & 0x1f) * 255 + 16;
+ b[i] = (temp / 32 + temp) / 32;
+ }
+
+ for (i = 0; i < 2; ++i)
+ {
+ r[2 + i] = (2 * r[0 + i] + r[1 - i]) / 3;
+ g[2 + i] = (2 * g[0 + i] + g[1 - i]) / 3;
+ b[2 + i] = (2 * b[0 + i] + b[1 - i]) / 3;
+ }
+
+ color_index = (color_block >> 32) & 0xffffffff;
+ alpha_index = (alpha_block >> 16);
+
+ dest = (DWORD *)(dst + z_pos * dst_slice_pitch);
+
+ for (y = 0; y < 4; ++y)
+ {
+ if (y_pos + y >= height)
+ break;
+ for (x = 0; x < 4; ++x)
+ {
+ if (x_pos + x >= width)
+ break;
+
+ color_val = 0;
+ alpha_val = 0;
+ bgra = 0;
+
+ color_val = (color_index >> (y * 8));
+ color_val = (color_val >> (x * 2)) & 0x3;
+ alpha_lookup = (alpha_index >> (y * 12)) & 0xfff;
+ alpha_val = (alpha_lookup >> (x * 3)) & 0x7;
+ bgra = ((alpha[alpha_val] << 24) | (r[color_val] << 16) | (g[color_val] << 8) | b[color_val]);
+ dest[(y_pos + y) * width + (x_pos + x)] = bgra;
+ }
+ }
+}
+
+static void convert_dxt5_b8g8r8a8_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
+ UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
+{
+ UINT64 current_block;
+ DWORD x, y, z;
+
+ current_block = 0;
+
+ for (z = 0; z < depth; ++z)
+ {
+ for (y = 0; y < height; y += 4)
+ {
+ for (x = 0; x < width; x += 4)
+ {
+ dxt5_decompress_block(src, dst, width, height, depth, x, y, z, dst_slice_pitch, current_block);
+ current_block++;
+ }
+ }
+ }
+}
+
+static void dxt3_decompress_block(const BYTE *src, BYTE *dst, UINT width, UINT height, UINT depth,
+ UINT x_pos, UINT y_pos, UINT z_pos, UINT dst_slice_pitch, UINT64 cur_block)
+{
+ UINT64 alpha_block, alpha_lookup, color_block, color_index;
+ const UINT64 *source;
+ DWORD *dest;
+ DWORD bgra;
+ DWORD temp;
+ DWORD i, x, y;
+ WORD color[2];
+ BYTE alpha_val, color_val;
+ BYTE r[4];
+ BYTE g[4];
+ BYTE b[4];
+
+ source = (const UINT64 *)(src + cur_block * 16);
+ alpha_block = source[0];
+ color_block = source[1];
+
+ color[0] = color_block & 0xffff;
+ color[1] = (color_block >> 16) & 0xffff;
+
+ for (i = 0; i < 2; ++i)
+ {
+ temp = (color[i] >> 11) * 255 + 16;
+ r[i] = (temp / 32 + temp) / 32;
+ temp = ((color[i] >> 5) & 0x3f) * 255 + 32;
+ g[i] = (temp / 64 + temp) / 64;
+ temp = (color[i] & 0x1f) * 255 + 16;
+ b[i] = (temp / 32 + temp) / 32;
+ }
+
+ for (i = 0; i < 2; ++i)
+ {
+ r[2 + i] = (2 * r[0 + i] + r[1 - i]) / 3;
+ g[2 + i] = (2 * g[0 + i] + g[1 - i]) / 3;
+ b[2 + i] = (2 * b[0 + i] + b[1 - i]) / 3;
+ }
+
+ color_index = (color_block >> 32) & 0xffffffff;
+ dest = (DWORD *)(dst + z_pos * dst_slice_pitch);
+
+ for (y = 0; y < 4; ++y)
+ {
+ if (y_pos + y >= height)
+ break;
+ for (x = 0; x < 4; ++x)
+ {
+ if (x_pos + x >= width)
+ break;
+
+ color_val = 0;
+ alpha_val = 0;
+ bgra = 0;
+
+ color_val = (color_index >> (y * 8));
+ color_val = (color_val >> (x * 2)) & 0x3;
+
+ alpha_lookup = (alpha_block >> (y * 16)) & 0xffff;
+ alpha_val = (alpha_lookup >> (x * 4)) & 0xf;
+ temp = alpha_val * 255 + 8;
+ alpha_val = (temp / 16 + temp) / 16;
+
+ bgra = ((alpha_val << 24) | (r[color_val] << 16) | (g[color_val] << 8) | b[color_val]);
+ dest[(y_pos + y) * width + (x_pos + x)] = bgra;
+ }
+ }
+}
+
+static void convert_dxt3_b8g8r8a8_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
+ UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
+{
+ UINT64 current_block;
+ DWORD x, y, z;
+
+ current_block = 0;
+
+ for (z = 0; z < depth; ++z)
+ {
+ for (y = 0; y < height; y += 4)
+ {
+ for (x = 0; x < width; x += 4)
+ {
+ dxt3_decompress_block(src, dst, width, height, depth, x, y, z, dst_slice_pitch, current_block);
+ current_block++;
+ }
+ }
+ }
+}
+
+static void dxt1_decompress_block(const BYTE *src, BYTE *dst, UINT width, UINT height, UINT depth,
+ UINT x_pos, UINT y_pos, UINT z_pos, UINT dst_slice_pitch, UINT64 cur_block)
+{
+ UINT64 color_block, color_index;
+ const UINT64 *source;
+ DWORD *dest;
+ DWORD bgra;
+ DWORD temp;
+ DWORD i, x, y;
+ WORD color[2];
+ BYTE color_val;
+ BYTE alpha;
+ BYTE r[4];
+ BYTE g[4];
+ BYTE b[4];
+ BYTE use_alpha;
+
+ source = (const UINT64 *)(src + cur_block * 8);
+ color_block = source[0];
+
+ color[0] = color_block & 0xffff;
+ color[1] = (color_block >> 16) & 0xffff;
+
+ for (i = 0; i < 2; ++i)
+ {
+ temp = (color[i] >> 11) * 255 + 16;
+ r[i] = (temp / 32 + temp) / 32;
+ temp = ((color[i] >> 5) & 0x3f) * 255 + 32;
+ g[i] = (temp / 64 + temp) / 64;
+ temp = (color[i] & 0x1f) * 255 + 16;
+ b[i] = (temp / 32 + temp) / 32;
+ }
+
+ if (color[0] > color[1])
+ {
+ for (i = 0; i < 2; ++i)
+ {
+ r[2 + i] = (2 * r[0 + i] + r[1 - i]) / 3;
+ g[2 + i] = (2 * g[0 + i] + g[1 - i]) / 3;
+ b[2 + i] = (2 * b[0 + i] + b[1 - i]) / 3;
+ }
+ use_alpha = 0;
+ }
+ else if (color[0] <= color[1])
+ {
+ r[2] = (r[0] + r[1]) / 2;
+ g[2] = (g[0] + g[1]) / 2;
+ b[2] = (b[0] + b[1]) / 2;
+
+ r[3] = 0;
+ g[3] = 0;
+ b[3] = 0;
+
+ use_alpha = 1;
+ }
+
+ color_index = (color_block >> 32) & 0xffffffff;
+ dest = (DWORD *)(dst + z_pos * dst_slice_pitch);
+
+ for (y = 0; y < 4; ++y)
+ {
+ if (y_pos + y >= height)
+ break;
+ for (x = 0; x < 4; ++x)
+ {
+ if (x_pos + x >= width)
+ break;
+
+ color_val = 0;
+ bgra = 0;
+
+ color_val = (color_index >> (y * 8));
+ color_val = (color_val >> (x * 2)) & 0x3;
+ if (color_val == 3 && use_alpha == 1)
+ alpha = 0;
+ else
+ alpha = 255;
+
+ bgra = ((alpha << 24) | (r[color_val] << 16) | (g[color_val] << 8) | b[color_val]);
+ dest[(y_pos + y) * width + (x_pos + x)] = bgra;
+ }
+ }
+}
+
+static void convert_dxt1_b8g8r8a8_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
+ UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
+{
+ UINT64 current_block;
+ DWORD x, y, z;
+
+ current_block = 0;
+
+ for (z = 0; z < depth; ++z)
+ {
+ for (y = 0; y < height; y += 4)
+ {
+ for (x = 0; x < width; x += 4)
+ {
+ dxt1_decompress_block(src, dst, width, height, depth, x, y, z, dst_slice_pitch, current_block);
+ current_block++;
+ }
+ }
+ }
+}
+
static void x8_d24_unorm_upload(const BYTE *src, BYTE *dst,
unsigned int src_row_pitch, unsigned int src_slice_pitch,
unsigned int dst_row_pitch, unsigned int dst_slice_pitch,
@@ -1118,27 +1419,27 @@ static const struct wined3d_format_texture_info format_texture_info[] =
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt1_b8g8r8a8_unorm},
{WINED3DFMT_DXT2, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt3_b8g8r8a8_unorm},
{WINED3DFMT_DXT3, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt3_b8g8r8a8_unorm},
{WINED3DFMT_DXT4, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt5_b8g8r8a8_unorm},
{WINED3DFMT_DXT5, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
| WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
- EXT_TEXTURE_COMPRESSION_S3TC, NULL},
+ EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt5_b8g8r8a8_unorm},
{WINED3DFMT_BC1_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0,
WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
@@ -3394,17 +3695,7 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_
* for dx9 GPUs support it, some do not, so not supporting DXTn volumes is OK for d3d9.
*
* Note that GL_NV_texture_compression_vtc adds this functionality to OpenGL, but the
- * block layout is not compatible with the one used by d3d. See volume_dxt5_test. */
- idx = get_format_idx(WINED3DFMT_DXT1);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_DXT2);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_DXT3);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_DXT4);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
- idx = get_format_idx(WINED3DFMT_DXT5);
- gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
+ * block layout is not compatible with the one used by d3d. See volume_dxtn_test. */
idx = get_format_idx(WINED3DFMT_BC1_UNORM);
gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
idx = get_format_idx(WINED3DFMT_BC1_UNORM_SRGB);
--
2.7.4
June 22, 2018
[PATCH v2 0/2] wined3d: Add DXTn Volume Texture Support
by Connor McAdams
This patchset adds support for DXTn volume textures by using the CPU to
decompress and convert them into a format the GPU can handle. It only
decompresses DXTn volume textures, and leaves regular 2D DXTn textures
alone.
Connor McAdams (2):
wined3d: Add decompression functions for DXT1, DXT3, and DXT5
wined3d: Add new test for DXTn volume textures.
dlls/d3d9/tests/visual.c | 183 ++++++++++++++++++---------
dlls/wined3d/texture.c | 26 ++++
dlls/wined3d/utils.c | 323 ++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 456 insertions(+), 76 deletions(-)
--
2.7.4
June 22, 2018
Re: [PATCH 3/4] shell32/tests: Add tests for SHGetKnownFolderPath() flags.
by Fabian Maurer
While probably not very relevant, when doing something like
----------
SHSetKnownFolderPath(&FOLDERID_SavedGames, KF_FLAG_DONT_UNEXPAND,
NULL, new_path);
SHGetKnownFolderPath(&FOLDERID_SavedGames, KF_FLAG_DONT_UNEXPAND, 0,
&path2);
----------
then KF_FLAG_DONT_UNEXPAND still doesn't seem to do anything.I figured that's
where the flag was useful, but it is completely ignored.
Do we want a testcase for that too?
Regards,
Fabian Maurer
June 22, 2018
[PATCH v3] msvcrt: Use already existent oneexit_table functions for _onexit and _c_exit
by Fabian Maurer
For that to work, MSVCRT__register_onexit_function and
MSVCRT__execute_onexit_table have to available all the time,
not only when _MSVCR_VER>=140
tests based on code by Piotr Caban
v2:
Create exit_event2 in test function, so it exists in child process
v3:
Keep exitlock
Keep _MSVCR_VER>=140 functions _MSVCR_VER>=140
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
---
dlls/msvcrt/exit.c | 195 ++++++++++++++++++-------------------
dlls/ucrtbase/tests/misc.c | 74 +++++++++++++-
2 files changed, 166 insertions(+), 103 deletions(-)
diff --git a/dlls/msvcrt/exit.c b/dlls/msvcrt/exit.c
index 7e1805569c4..602a80a0513 100644
--- a/dlls/msvcrt/exit.c
+++ b/dlls/msvcrt/exit.c
@@ -29,9 +29,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
#define LOCK_EXIT _mlock(_EXIT_LOCK1)
#define UNLOCK_EXIT _munlock(_EXIT_LOCK1)
-static MSVCRT__onexit_t *MSVCRT_atexit_table = NULL;
-static int MSVCRT_atexit_table_size = 0;
-static int MSVCRT_atexit_registered = 0; /* Points to free slot */
static MSVCRT_purecall_handler purecall_handler = NULL;
typedef struct MSVCRT__onexit_table_t
@@ -41,6 +38,8 @@ typedef struct MSVCRT__onexit_table_t
MSVCRT__onexit_t *_end;
} MSVCRT__onexit_table_t;
+static MSVCRT__onexit_table_t MSVCRT_atexit_table;
+
typedef void (__stdcall *_tls_callback_type)(void*,ULONG,void*);
static _tls_callback_type tls_atexit_callback;
@@ -61,21 +60,97 @@ static int MSVCRT_error_mode = MSVCRT__OUT_TO_DEFAULT;
void (*CDECL _aexit_rtn)(int) = MSVCRT__exit;
+static int __MSVCRT__initialize_onexit_table(MSVCRT__onexit_table_t *table)
+{
+ if (!table)
+ return -1;
+
+ if (table->_first == table->_end)
+ table->_last = table->_end = table->_first = NULL;
+ return 0;
+}
+
+
+/* INTERNAL: register onexit function */
+static int __MSVCRT__register_onexit_function(MSVCRT__onexit_table_t *table, MSVCRT__onexit_t func)
+{
+ if (!table)
+ return -1;
+
+ EnterCriticalSection(&MSVCRT_onexit_cs);
+ if (!table->_first)
+ {
+ table->_first = MSVCRT_calloc(32, sizeof(void *));
+ if (!table->_first)
+ {
+ WARN("failed to allocate initial table.\n");
+ LeaveCriticalSection(&MSVCRT_onexit_cs);
+ return -1;
+ }
+ table->_last = table->_first;
+ table->_end = table->_first + 32;
+ }
+
+ /* grow if full */
+ if (table->_last == table->_end)
+ {
+ int len = table->_end - table->_first;
+ MSVCRT__onexit_t *tmp = MSVCRT_realloc(table->_first, 2 * len * sizeof(void *));
+ if (!tmp)
+ {
+ WARN("failed to grow table.\n");
+ LeaveCriticalSection(&MSVCRT_onexit_cs);
+ return -1;
+ }
+ table->_first = tmp;
+ table->_end = table->_first + 2 * len;
+ table->_last = table->_first + len;
+ }
+
+ *table->_last = func;
+ table->_last++;
+ LeaveCriticalSection(&MSVCRT_onexit_cs);
+ return 0;
+}
+
+/* INTERNAL: call onexit functions */
+static int __MSVCRT__execute_onexit_table(MSVCRT__onexit_table_t *table)
+{
+ MSVCRT__onexit_t *func;
+ MSVCRT__onexit_table_t copy;
+
+ if (!table)
+ return -1;
+
+ EnterCriticalSection(&MSVCRT_onexit_cs);
+ if (!table->_first || table->_first >= table->_last)
+ {
+ LeaveCriticalSection(&MSVCRT_onexit_cs);
+ return 0;
+ }
+ copy._first = table->_first;
+ copy._last = table->_last;
+ copy._end = table->_end;
+ memset(table, 0, sizeof(*table));
+ __MSVCRT__initialize_onexit_table(table);
+ LeaveCriticalSection(&MSVCRT_onexit_cs);
+
+ for (func = copy._last - 1; func >= copy._first; func--)
+ {
+ if (*func)
+ (*func)();
+ }
+
+ MSVCRT_free(copy._first);
+ return 0;
+}
+
/* INTERNAL: call atexit functions */
static void __MSVCRT__call_atexit(void)
{
/* Note: should only be called with the exit lock held */
- TRACE("%d atext functions to call\n", MSVCRT_atexit_registered);
if (tls_atexit_callback) tls_atexit_callback(NULL, DLL_PROCESS_DETACH, NULL);
- /* Last registered gets executed first */
- while (MSVCRT_atexit_registered > 0)
- {
- MSVCRT_atexit_registered--;
- TRACE("next is %p\n",MSVCRT_atexit_table[MSVCRT_atexit_registered]);
- if (MSVCRT_atexit_table[MSVCRT_atexit_registered])
- (*MSVCRT_atexit_table[MSVCRT_atexit_registered])();
- TRACE("returned\n");
- }
+ __MSVCRT__execute_onexit_table(&MSVCRT_atexit_table);
}
/*********************************************************************
@@ -292,25 +367,9 @@ MSVCRT__onexit_t CDECL MSVCRT__onexit(MSVCRT__onexit_t func)
return NULL;
LOCK_EXIT;
- if (MSVCRT_atexit_registered > MSVCRT_atexit_table_size - 1)
- {
- MSVCRT__onexit_t *newtable;
- TRACE("expanding table\n");
- newtable = MSVCRT_calloc(MSVCRT_atexit_table_size + 32, sizeof(void *));
- if (!newtable)
- {
- TRACE("failed!\n");
- UNLOCK_EXIT;
- return NULL;
- }
- memcpy (newtable, MSVCRT_atexit_table, MSVCRT_atexit_table_size*sizeof(void *));
- MSVCRT_atexit_table_size += 32;
- MSVCRT_free (MSVCRT_atexit_table);
- MSVCRT_atexit_table = newtable;
- }
- MSVCRT_atexit_table[MSVCRT_atexit_registered] = func;
- MSVCRT_atexit_registered++;
+ __MSVCRT__register_onexit_function(&MSVCRT_atexit_table, func);
UNLOCK_EXIT;
+
return func;
}
@@ -359,7 +418,6 @@ int CDECL MSVCRT__crt_atexit(void (*func)(void))
return MSVCRT__onexit((MSVCRT__onexit_t)func) == (MSVCRT__onexit_t)func ? 0 : -1;
}
-
/*********************************************************************
* _initialize_onexit_table (UCRTBASE.@)
*/
@@ -367,12 +425,7 @@ int CDECL MSVCRT__initialize_onexit_table(MSVCRT__onexit_table_t *table)
{
TRACE("(%p)\n", table);
- if (!table)
- return -1;
-
- if (table->_first == table->_end)
- table->_last = table->_end = table->_first = NULL;
- return 0;
+ return __MSVCRT__initialize_onexit_table(table);
}
/*********************************************************************
@@ -382,43 +435,7 @@ int CDECL MSVCRT__register_onexit_function(MSVCRT__onexit_table_t *table, MSVCRT
{
TRACE("(%p %p)\n", table, func);
- if (!table)
- return -1;
-
- EnterCriticalSection(&MSVCRT_onexit_cs);
- if (!table->_first)
- {
- table->_first = MSVCRT_calloc(32, sizeof(void *));
- if (!table->_first)
- {
- WARN("failed to allocate initial table.\n");
- LeaveCriticalSection(&MSVCRT_onexit_cs);
- return -1;
- }
- table->_last = table->_first;
- table->_end = table->_first + 32;
- }
-
- /* grow if full */
- if (table->_last == table->_end)
- {
- int len = table->_end - table->_first;
- MSVCRT__onexit_t *tmp = MSVCRT_realloc(table->_first, 2 * len * sizeof(void *));
- if (!tmp)
- {
- WARN("failed to grow table.\n");
- LeaveCriticalSection(&MSVCRT_onexit_cs);
- return -1;
- }
- table->_first = tmp;
- table->_end = table->_first + 2 * len;
- table->_last = table->_first + len;
- }
-
- *table->_last = func;
- table->_last++;
- LeaveCriticalSection(&MSVCRT_onexit_cs);
- return 0;
+ return __MSVCRT__register_onexit_function(table, func);
}
/*********************************************************************
@@ -426,35 +443,9 @@ int CDECL MSVCRT__register_onexit_function(MSVCRT__onexit_table_t *table, MSVCRT
*/
int CDECL MSVCRT__execute_onexit_table(MSVCRT__onexit_table_t *table)
{
- MSVCRT__onexit_t *func;
- MSVCRT__onexit_table_t copy;
-
TRACE("(%p)\n", table);
- if (!table)
- return -1;
-
- EnterCriticalSection(&MSVCRT_onexit_cs);
- if (!table->_first || table->_first >= table->_last)
- {
- LeaveCriticalSection(&MSVCRT_onexit_cs);
- return 0;
- }
- copy._first = table->_first;
- copy._last = table->_last;
- copy._end = table->_end;
- memset(table, 0, sizeof(*table));
- MSVCRT__initialize_onexit_table(table);
- LeaveCriticalSection(&MSVCRT_onexit_cs);
-
- for (func = copy._last - 1; func >= copy._first; func--)
- {
- if (*func)
- (*func)();
- }
-
- MSVCRT_free(copy._first);
- return 0;
+ return __MSVCRT__execute_onexit_table(table);
}
/*********************************************************************
diff --git a/dlls/ucrtbase/tests/misc.c b/dlls/ucrtbase/tests/misc.c
index 354fab1e940..ed5bb0589c8 100644
--- a/dlls/ucrtbase/tests/misc.c
+++ b/dlls/ucrtbase/tests/misc.c
@@ -125,6 +125,8 @@ static int (CDECL *p_fesetround)(int);
static void (CDECL *p___setusermatherr)(MSVCRT_matherr_func);
static int* (CDECL *p_errno)(void);
static char* (CDECL *p_asctime)(const struct tm *);
+static void (CDECL *p_exit)(int);
+static int (CDECL *p__crt_atexit)(void (CDECL*)(void));
static void test__initialize_onexit_table(void)
{
@@ -429,6 +431,8 @@ static BOOL init(void)
p___setusermatherr = (void*)GetProcAddress(module, "__setusermatherr");
p_errno = (void*)GetProcAddress(module, "_errno");
p_asctime = (void*)GetProcAddress(module, "asctime");
+ p__crt_atexit = (void*)GetProcAddress(module, "_crt_atexit");
+ p_exit = (void*)GetProcAddress(module, "exit");
return TRUE;
}
@@ -765,6 +769,70 @@ static void test_asctime(void)
ok(!strcmp(ret, "Thu Jan 1 00:00:00 1970\n"), "asctime returned %s\n", ret);
}
+static void test_exit(const char *argv0)
+{
+ HANDLE exit_event1, exit_event2;
+ PROCESS_INFORMATION proc;
+ STARTUPINFOA startup = {0};
+ char path[MAX_PATH];
+ DWORD ret;
+
+ exit_event1 = CreateEventA(NULL, FALSE, FALSE, "exit_event1");
+ exit_event2 = CreateEventA(NULL, FALSE, FALSE, "exit_event2");
+
+ sprintf(path, "%s misc exit", argv0);
+ startup.cb = sizeof(startup);
+ CreateProcessA(NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &proc);
+ winetest_wait_child_process(proc.hProcess);
+
+ ret = WaitForSingleObject(exit_event1, 0);
+ ok(ret == WAIT_OBJECT_0, "exit_event1 was not set (%x)\n", ret);
+
+ CloseHandle(exit_event1);
+ CloseHandle(exit_event2);
+}
+
+static void CDECL at_exit_func1(void)
+{
+ HANDLE exit_event1 = CreateEventA(NULL, FALSE, FALSE, "exit_event1");
+ HANDLE exit_event2 = CreateEventA(NULL, FALSE, FALSE, "exit_event2");
+ DWORD ret;
+
+ ok(exit_event1 != NULL, "CreateEvent failed: %d\n", GetLastError());
+ ok(exit_event2 != NULL, "CreateEvent failed: %d\n", GetLastError());
+
+ ret = WaitForSingleObject(exit_event2, 0);
+ ok(ret == WAIT_OBJECT_0, "exit_event2 was not set (%x)\n", ret);
+
+ SetEvent(exit_event1);
+ CloseHandle(exit_event1);
+ CloseHandle(exit_event2);
+}
+
+static void CDECL at_exit_func2(void)
+{
+ HANDLE exit_event1 = CreateEventA(NULL, FALSE, FALSE, "exit_event1");
+ HANDLE exit_event2 = CreateEventA(NULL, FALSE, FALSE, "exit_event2");
+ DWORD ret;
+
+ ok(exit_event1 != NULL, "CreateEvent failed: %d\n", GetLastError());
+ ok(exit_event2 != NULL, "CreateEvent failed: %d\n", GetLastError());
+
+ ret = WaitForSingleObject(exit_event1, 0);
+ ok(ret == WAIT_TIMEOUT, "exit_event1 should not be set (%x)\n", ret);
+
+ SetEvent(exit_event2);
+ CloseHandle(exit_event1);
+ CloseHandle(exit_event2);
+}
+
+static void test_call_exit(void)
+{
+ ok(!p__crt_atexit(at_exit_func1), "_crt_atexit failed\n");
+ ok(!p__crt_atexit(at_exit_func2), "_crt_atexit failed\n");
+ p_exit(0);
+}
+
START_TEST(misc)
{
int arg_c;
@@ -775,7 +843,10 @@ START_TEST(misc)
arg_c = winetest_get_mainargs(&arg_v);
if(arg_c == 3) {
- test__get_narrow_winmain_command_line(NULL);
+ if(!strcmp(arg_v[2], "cmd"))
+ test__get_narrow_winmain_command_line(NULL);
+ else if(!strcmp(arg_v[2], "exit"))
+ test_call_exit();
return;
}
@@ -791,4 +862,5 @@ START_TEST(misc)
test_isblank();
test_math_errors();
test_asctime();
+ test_exit(arg_v[0]);
}
--
2.18.0
June 22, 2018
Re: [PATCH v2] msvcrt: Use already existent oneexit_table functions for _onexit and _c_exit
by Fabian Maurer
> It's still needed to hold the exit lock. Older versions of msvcrt
were
> doing it (I didn't test if newer versions are still using this lock).
Thanks, I'll have an updated version soon. Though I don't see a
good way to write a test for this lock.
Regards,
Fabian Maurer
June 22, 2018
Re: [PATCH] mp3dmod: Support COM aggregation.
by Zebediah Figura
On 06/22/2018 01:22 PM, Jacek Caban wrote:
> Hi Zebediah,
>
> On 06/22/2018 08:06 PM, Zebediah Figura wrote:
>> -static HRESULT create_mp3_decoder(REFIID iid, void **obj)
>> +static HRESULT create_mp3_decoder(IUnknown *outer, REFIID iid, void **obj)
>> {
>> struct mp3_decoder *This;
>> int err;
>> @@ -424,15 +457,17 @@ static HRESULT create_mp3_decoder(REFIID iid, void **obj)
>> if (!(This = heap_alloc_zero(sizeof(*This))))
>> return E_OUTOFMEMORY;
>>
>> - This->IMediaObject_iface.lpVtbl = &IMediaObject_vtbl;
>> + This->IUnknown_inner.lpVtbl = &Unknown_vtbl;
>> + This->IMediaObject_iface.lpVtbl = &MediaObject_vtbl;
>> This->ref = 0;
>> + This->outer = outer ? outer : &This->IUnknown_inner;
>>
>> mpg123_init();
>> This->mh = mpg123_new(NULL, &err);
>> mpg123_open_feed(This->mh);
>> mpg123_format_none(This->mh);
>>
>> - return IMediaObject_QueryInterface(&This->IMediaObject_iface, iid, obj);
>> + return IUnknown_QueryInterface(&This->IUnknown_inner, iid, obj);
>
>
> This leaks in non-aggregated case if QueryInterface fails.
>
>
> Jacek
>
Thanks; I've sent an updated patch.
June 22, 2018
[PATCH v2] mp3dmod: Support COM aggregation.
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/mp3dmod/mp3dmod.c | 80 ++++++++++++++++++++++++++++++++------------
dlls/mp3dmod/tests/mp3dmod.c | 57 +++++++++++++++++++++++++++++++
2 files changed, 116 insertions(+), 21 deletions(-)
diff --git a/dlls/mp3dmod/mp3dmod.c b/dlls/mp3dmod/mp3dmod.c
index 4949780..90bcf66 100644
--- a/dlls/mp3dmod/mp3dmod.c
+++ b/dlls/mp3dmod/mp3dmod.c
@@ -43,7 +43,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(mp3dmod);
static HINSTANCE mp3dmod_instance;
struct mp3_decoder {
+ IUnknown IUnknown_inner;
IMediaObject IMediaObject_iface;
+ IUnknown *outer;
LONG ref;
mpg123_handle *mh;
DMO_MEDIA_TYPE outtype;
@@ -51,33 +53,35 @@ struct mp3_decoder {
REFERENCE_TIME timestamp;
};
-static inline struct mp3_decoder *impl_from_IMediaObject(IMediaObject *iface)
+static inline struct mp3_decoder *impl_from_IUnknown(IUnknown *iface)
{
- return CONTAINING_RECORD(iface, struct mp3_decoder, IMediaObject_iface);
+ return CONTAINING_RECORD(iface, struct mp3_decoder, IUnknown_inner);
}
-static HRESULT WINAPI MediaObject_QueryInterface(IMediaObject *iface, REFIID iid, void **ppv)
+static HRESULT WINAPI Unknown_QueryInterface(IUnknown *iface, REFIID iid, void **obj)
{
- struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ struct mp3_decoder *This = impl_from_IUnknown(iface);
- TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), ppv);
+ TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
- if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IMediaObject))
- *ppv = &This->IMediaObject_iface;
+ if (IsEqualGUID(iid, &IID_IUnknown))
+ *obj = &This->IUnknown_inner;
+ else if (IsEqualGUID(iid, &IID_IMediaObject))
+ *obj = &This->IMediaObject_iface;
else
{
FIXME("no interface for %s\n", debugstr_guid(iid));
- *ppv = NULL;
+ *obj = NULL;
return E_NOINTERFACE;
}
- IMediaObject_AddRef(iface);
+ IUnknown_AddRef((IUnknown *)*obj);
return S_OK;
}
-static ULONG WINAPI MediaObject_AddRef(IMediaObject *iface)
+static ULONG WINAPI Unknown_AddRef(IUnknown *iface)
{
- struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ struct mp3_decoder *This = impl_from_IUnknown(iface);
ULONG refcount = InterlockedIncrement(&This->ref);
TRACE("(%p) AddRef from %d\n", This, refcount - 1);
@@ -85,9 +89,9 @@ static ULONG WINAPI MediaObject_AddRef(IMediaObject *iface)
return refcount;
}
-static ULONG WINAPI MediaObject_Release(IMediaObject *iface)
+static ULONG WINAPI Unknown_Release(IUnknown *iface)
{
- struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ struct mp3_decoder *This = impl_from_IUnknown(iface);
ULONG refcount = InterlockedDecrement(&This->ref);
TRACE("(%p) Release from %d\n", This, refcount + 1);
@@ -100,6 +104,35 @@ static ULONG WINAPI MediaObject_Release(IMediaObject *iface)
return refcount;
}
+static const IUnknownVtbl Unknown_vtbl = {
+ Unknown_QueryInterface,
+ Unknown_AddRef,
+ Unknown_Release,
+};
+
+static inline struct mp3_decoder *impl_from_IMediaObject(IMediaObject *iface)
+{
+ return CONTAINING_RECORD(iface, struct mp3_decoder, IMediaObject_iface);
+}
+
+static HRESULT WINAPI MediaObject_QueryInterface(IMediaObject *iface, REFIID iid, void **obj)
+{
+ struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ return IUnknown_QueryInterface(This->outer, iid, obj);
+}
+
+static ULONG WINAPI MediaObject_AddRef(IMediaObject *iface)
+{
+ struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ return IUnknown_AddRef(This->outer);
+}
+
+static ULONG WINAPI MediaObject_Release(IMediaObject *iface)
+{
+ struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ return IUnknown_Release(This->outer);
+}
+
static HRESULT WINAPI MediaObject_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output)
{
FIXME("(%p)->(%p, %p) stub!\n", iface, input, output);
@@ -389,7 +422,7 @@ static HRESULT WINAPI MediaObject_Lock(IMediaObject *iface, LONG lock)
return E_NOTIMPL;
}
-static const IMediaObjectVtbl IMediaObject_vtbl = {
+static const IMediaObjectVtbl MediaObject_vtbl = {
MediaObject_QueryInterface,
MediaObject_AddRef,
MediaObject_Release,
@@ -416,23 +449,28 @@ static const IMediaObjectVtbl IMediaObject_vtbl = {
MediaObject_Lock,
};
-static HRESULT create_mp3_decoder(REFIID iid, void **obj)
+static HRESULT create_mp3_decoder(IUnknown *outer, REFIID iid, void **obj)
{
struct mp3_decoder *This;
+ HRESULT hr;
int err;
if (!(This = heap_alloc_zero(sizeof(*This))))
return E_OUTOFMEMORY;
- This->IMediaObject_iface.lpVtbl = &IMediaObject_vtbl;
- This->ref = 0;
+ This->IUnknown_inner.lpVtbl = &Unknown_vtbl;
+ This->IMediaObject_iface.lpVtbl = &MediaObject_vtbl;
+ This->ref = 1;
+ This->outer = outer ? outer : &This->IUnknown_inner;
mpg123_init();
This->mh = mpg123_new(NULL, &err);
mpg123_open_feed(This->mh);
mpg123_format_none(This->mh);
- return IMediaObject_QueryInterface(&This->IMediaObject_iface, iid, obj);
+ hr = IUnknown_QueryInterface(&This->IUnknown_inner, iid, obj);
+ IUnknown_Release(&This->IUnknown_inner);
+ return hr;
}
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID iid, void **obj)
@@ -466,13 +504,13 @@ static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown
{
TRACE("(%p, %s, %p)\n", outer, debugstr_guid(iid), obj);
- if (outer)
+ if (outer && !IsEqualGUID(iid, &IID_IUnknown))
{
*obj = NULL;
- return CLASS_E_NOAGGREGATION;
+ return E_NOINTERFACE;
}
- return create_mp3_decoder(iid, obj);
+ return create_mp3_decoder(outer, iid, obj);
}
static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL lock)
diff --git a/dlls/mp3dmod/tests/mp3dmod.c b/dlls/mp3dmod/tests/mp3dmod.c
index 68c6b4d..75fd0e2 100644
--- a/dlls/mp3dmod/tests/mp3dmod.c
+++ b/dlls/mp3dmod/tests/mp3dmod.c
@@ -230,6 +230,62 @@ static void test_convert(void)
IMediaObject_Release(dmo);
}
+static const GUID IID_test_outer = {0xdeadbeef,0,0,{0,0,0,0,0,0,0,0x66}};
+
+static HRESULT WINAPI Outer_QueryInterface(IUnknown *iface, REFIID iid, void **obj)
+{
+ if (IsEqualGUID(iid, &IID_test_outer))
+ {
+ *obj = (IUnknown *)0xdeadbeef;
+ return S_OK;
+ }
+ ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI Outer_AddRef(IUnknown *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI Outer_Release(IUnknown *iface)
+{
+ return 1;
+}
+
+static IUnknownVtbl Outer_vtbl = {
+ Outer_QueryInterface,
+ Outer_AddRef,
+ Outer_Release,
+};
+
+static IUnknown Outer = { &Outer_vtbl };
+
+static void test_aggregation(void)
+{
+ IUnknown *unk, *unk2;
+ IMediaObject *dmo;
+ HRESULT hr;
+
+ hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, &Outer, CLSCTX_INPROC_SERVER,
+ &IID_IUnknown, (void **)&unk);
+ ok(hr == S_OK, "got %#x\n", hr);
+
+ hr = IUnknown_QueryInterface(unk, &IID_IMediaObject, (void **)&dmo);
+ ok(hr == S_OK, "got %#x\n", hr);
+
+ hr = IMediaObject_QueryInterface(dmo, &IID_test_outer, (void **)&unk2);
+ ok(hr == S_OK, "got %#x\n", hr);
+ ok(unk2 == (IUnknown *)0xdeadbeef, "got unk %p\n", unk2);
+
+ IUnknown_Release(dmo);
+ IUnknown_Release(unk);
+
+ hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, &Outer, CLSCTX_INPROC_SERVER,
+ &IID_IMediaObject, (void **)&unk);
+ ok(hr == E_NOINTERFACE, "got %#x\n", hr);
+}
+
START_TEST(mp3dmod)
{
IMediaObject *dmo;
@@ -247,6 +303,7 @@ START_TEST(mp3dmod)
IMediaObject_Release(dmo);
test_convert();
+ test_aggregation();
CoUninitialize();
}
--
2.7.4
June 22, 2018
[PATCH v3] user32: Always release menu item in EnableMenuItem
by Fabian Maurer
The menu must be release on all code-paths,
else the underlying lock will never be released.
Fixes bug 45355.
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
---
dlls/user32/menu.c | 33 +++++++++++++++------------------
1 file changed, 15 insertions(+), 18 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 8c541cc4f91..ab1ae9bc1bd 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -3741,28 +3741,25 @@ BOOL WINAPI EnableMenuItem( HMENU hMenu, UINT id, UINT wFlags )
item->fState ^= (oldflags ^ wFlags) & (MF_GRAYED | MF_DISABLED);
/* If the close item in the system menu change update the close button */
- if ((item->wID == SC_CLOSE) && (oldflags != wFlags))
+ if ((item->wID == SC_CLOSE) && (oldflags != wFlags) && menu->hSysMenuOwner)
{
- if (menu->hSysMenuOwner)
- {
- RECT rc;
- POPUPMENU* parentMenu;
- HWND hwnd;
+ RECT rc;
+ POPUPMENU* parentMenu;
+ HWND hwnd;
- /* Get the parent menu to access*/
- parentMenu = grab_menu_ptr(menu->hSysMenuOwner);
- release_menu_ptr(menu);
- if (!parentMenu)
- return (UINT)-1;
+ /* Get the parent menu to access */
+ parentMenu = grab_menu_ptr(menu->hSysMenuOwner);
+ release_menu_ptr(menu);
+ if (!parentMenu)
+ return (UINT)-1;
- hwnd = parentMenu->hWnd;
- release_menu_ptr(parentMenu);
+ hwnd = parentMenu->hWnd;
+ release_menu_ptr(parentMenu);
- /* Refresh the frame to reflect the change */
- WIN_GetRectangles( hwnd, COORDS_CLIENT, &rc, NULL );
- rc.bottom = 0;
- RedrawWindow(hwnd, &rc, 0, RDW_FRAME | RDW_INVALIDATE | RDW_NOCHILDREN);
- }
+ /* Refresh the frame to reflect the change */
+ WIN_GetRectangles(hwnd, COORDS_CLIENT, &rc, NULL);
+ rc.bottom = 0;
+ RedrawWindow(hwnd, &rc, 0, RDW_FRAME | RDW_INVALIDATE | RDW_NOCHILDREN);
}
else
release_menu_ptr(menu);
--
2.18.0
June 22, 2018
Re: [PATCH] mp3dmod: Support COM aggregation.
by Jacek Caban
Hi Zebediah,
On 06/22/2018 08:06 PM, Zebediah Figura wrote:
> -static HRESULT create_mp3_decoder(REFIID iid, void **obj)
> +static HRESULT create_mp3_decoder(IUnknown *outer, REFIID iid, void **obj)
> {
> struct mp3_decoder *This;
> int err;
> @@ -424,15 +457,17 @@ static HRESULT create_mp3_decoder(REFIID iid, void **obj)
> if (!(This = heap_alloc_zero(sizeof(*This))))
> return E_OUTOFMEMORY;
>
> - This->IMediaObject_iface.lpVtbl = &IMediaObject_vtbl;
> + This->IUnknown_inner.lpVtbl = &Unknown_vtbl;
> + This->IMediaObject_iface.lpVtbl = &MediaObject_vtbl;
> This->ref = 0;
> + This->outer = outer ? outer : &This->IUnknown_inner;
>
> mpg123_init();
> This->mh = mpg123_new(NULL, &err);
> mpg123_open_feed(This->mh);
> mpg123_format_none(This->mh);
>
> - return IMediaObject_QueryInterface(&This->IMediaObject_iface, iid, obj);
> + return IUnknown_QueryInterface(&This->IUnknown_inner, iid, obj);
This leaks in non-aggregated case if QueryInterface fails.
Jacek
June 22, 2018
[PATCH] mp3dmod: Support COM aggregation.
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/mp3dmod/mp3dmod.c | 75 ++++++++++++++++++++++++++++++++------------
dlls/mp3dmod/tests/mp3dmod.c | 57 +++++++++++++++++++++++++++++++++
2 files changed, 112 insertions(+), 20 deletions(-)
diff --git a/dlls/mp3dmod/mp3dmod.c b/dlls/mp3dmod/mp3dmod.c
index 4949780..4820c51 100644
--- a/dlls/mp3dmod/mp3dmod.c
+++ b/dlls/mp3dmod/mp3dmod.c
@@ -43,7 +43,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(mp3dmod);
static HINSTANCE mp3dmod_instance;
struct mp3_decoder {
+ IUnknown IUnknown_inner;
IMediaObject IMediaObject_iface;
+ IUnknown *outer;
LONG ref;
mpg123_handle *mh;
DMO_MEDIA_TYPE outtype;
@@ -51,33 +53,35 @@ struct mp3_decoder {
REFERENCE_TIME timestamp;
};
-static inline struct mp3_decoder *impl_from_IMediaObject(IMediaObject *iface)
+static inline struct mp3_decoder *impl_from_IUnknown(IUnknown *iface)
{
- return CONTAINING_RECORD(iface, struct mp3_decoder, IMediaObject_iface);
+ return CONTAINING_RECORD(iface, struct mp3_decoder, IUnknown_inner);
}
-static HRESULT WINAPI MediaObject_QueryInterface(IMediaObject *iface, REFIID iid, void **ppv)
+static HRESULT WINAPI Unknown_QueryInterface(IUnknown *iface, REFIID iid, void **obj)
{
- struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ struct mp3_decoder *This = impl_from_IUnknown(iface);
- TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), ppv);
+ TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
- if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IMediaObject))
- *ppv = &This->IMediaObject_iface;
+ if (IsEqualGUID(iid, &IID_IUnknown))
+ *obj = &This->IUnknown_inner;
+ else if (IsEqualGUID(iid, &IID_IMediaObject))
+ *obj = &This->IMediaObject_iface;
else
{
FIXME("no interface for %s\n", debugstr_guid(iid));
- *ppv = NULL;
+ *obj = NULL;
return E_NOINTERFACE;
}
- IMediaObject_AddRef(iface);
+ IUnknown_AddRef((IUnknown *)*obj);
return S_OK;
}
-static ULONG WINAPI MediaObject_AddRef(IMediaObject *iface)
+static ULONG WINAPI Unknown_AddRef(IUnknown *iface)
{
- struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ struct mp3_decoder *This = impl_from_IUnknown(iface);
ULONG refcount = InterlockedIncrement(&This->ref);
TRACE("(%p) AddRef from %d\n", This, refcount - 1);
@@ -85,9 +89,9 @@ static ULONG WINAPI MediaObject_AddRef(IMediaObject *iface)
return refcount;
}
-static ULONG WINAPI MediaObject_Release(IMediaObject *iface)
+static ULONG WINAPI Unknown_Release(IUnknown *iface)
{
- struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ struct mp3_decoder *This = impl_from_IUnknown(iface);
ULONG refcount = InterlockedDecrement(&This->ref);
TRACE("(%p) Release from %d\n", This, refcount + 1);
@@ -100,6 +104,35 @@ static ULONG WINAPI MediaObject_Release(IMediaObject *iface)
return refcount;
}
+static const IUnknownVtbl Unknown_vtbl = {
+ Unknown_QueryInterface,
+ Unknown_AddRef,
+ Unknown_Release,
+};
+
+static inline struct mp3_decoder *impl_from_IMediaObject(IMediaObject *iface)
+{
+ return CONTAINING_RECORD(iface, struct mp3_decoder, IMediaObject_iface);
+}
+
+static HRESULT WINAPI MediaObject_QueryInterface(IMediaObject *iface, REFIID iid, void **obj)
+{
+ struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ return IUnknown_QueryInterface(This->outer, iid, obj);
+}
+
+static ULONG WINAPI MediaObject_AddRef(IMediaObject *iface)
+{
+ struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ return IUnknown_AddRef(This->outer);
+}
+
+static ULONG WINAPI MediaObject_Release(IMediaObject *iface)
+{
+ struct mp3_decoder *This = impl_from_IMediaObject(iface);
+ return IUnknown_Release(This->outer);
+}
+
static HRESULT WINAPI MediaObject_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output)
{
FIXME("(%p)->(%p, %p) stub!\n", iface, input, output);
@@ -389,7 +422,7 @@ static HRESULT WINAPI MediaObject_Lock(IMediaObject *iface, LONG lock)
return E_NOTIMPL;
}
-static const IMediaObjectVtbl IMediaObject_vtbl = {
+static const IMediaObjectVtbl MediaObject_vtbl = {
MediaObject_QueryInterface,
MediaObject_AddRef,
MediaObject_Release,
@@ -416,7 +449,7 @@ static const IMediaObjectVtbl IMediaObject_vtbl = {
MediaObject_Lock,
};
-static HRESULT create_mp3_decoder(REFIID iid, void **obj)
+static HRESULT create_mp3_decoder(IUnknown *outer, REFIID iid, void **obj)
{
struct mp3_decoder *This;
int err;
@@ -424,15 +457,17 @@ static HRESULT create_mp3_decoder(REFIID iid, void **obj)
if (!(This = heap_alloc_zero(sizeof(*This))))
return E_OUTOFMEMORY;
- This->IMediaObject_iface.lpVtbl = &IMediaObject_vtbl;
+ This->IUnknown_inner.lpVtbl = &Unknown_vtbl;
+ This->IMediaObject_iface.lpVtbl = &MediaObject_vtbl;
This->ref = 0;
+ This->outer = outer ? outer : &This->IUnknown_inner;
mpg123_init();
This->mh = mpg123_new(NULL, &err);
mpg123_open_feed(This->mh);
mpg123_format_none(This->mh);
- return IMediaObject_QueryInterface(&This->IMediaObject_iface, iid, obj);
+ return IUnknown_QueryInterface(&This->IUnknown_inner, iid, obj);
}
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID iid, void **obj)
@@ -466,13 +501,13 @@ static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown
{
TRACE("(%p, %s, %p)\n", outer, debugstr_guid(iid), obj);
- if (outer)
+ if (outer && !IsEqualGUID(iid, &IID_IUnknown))
{
*obj = NULL;
- return CLASS_E_NOAGGREGATION;
+ return E_NOINTERFACE;
}
- return create_mp3_decoder(iid, obj);
+ return create_mp3_decoder(outer, iid, obj);
}
static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL lock)
diff --git a/dlls/mp3dmod/tests/mp3dmod.c b/dlls/mp3dmod/tests/mp3dmod.c
index 68c6b4d..75fd0e2 100644
--- a/dlls/mp3dmod/tests/mp3dmod.c
+++ b/dlls/mp3dmod/tests/mp3dmod.c
@@ -230,6 +230,62 @@ static void test_convert(void)
IMediaObject_Release(dmo);
}
+static const GUID IID_test_outer = {0xdeadbeef,0,0,{0,0,0,0,0,0,0,0x66}};
+
+static HRESULT WINAPI Outer_QueryInterface(IUnknown *iface, REFIID iid, void **obj)
+{
+ if (IsEqualGUID(iid, &IID_test_outer))
+ {
+ *obj = (IUnknown *)0xdeadbeef;
+ return S_OK;
+ }
+ ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI Outer_AddRef(IUnknown *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI Outer_Release(IUnknown *iface)
+{
+ return 1;
+}
+
+static IUnknownVtbl Outer_vtbl = {
+ Outer_QueryInterface,
+ Outer_AddRef,
+ Outer_Release,
+};
+
+static IUnknown Outer = { &Outer_vtbl };
+
+static void test_aggregation(void)
+{
+ IUnknown *unk, *unk2;
+ IMediaObject *dmo;
+ HRESULT hr;
+
+ hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, &Outer, CLSCTX_INPROC_SERVER,
+ &IID_IUnknown, (void **)&unk);
+ ok(hr == S_OK, "got %#x\n", hr);
+
+ hr = IUnknown_QueryInterface(unk, &IID_IMediaObject, (void **)&dmo);
+ ok(hr == S_OK, "got %#x\n", hr);
+
+ hr = IMediaObject_QueryInterface(dmo, &IID_test_outer, (void **)&unk2);
+ ok(hr == S_OK, "got %#x\n", hr);
+ ok(unk2 == (IUnknown *)0xdeadbeef, "got unk %p\n", unk2);
+
+ IUnknown_Release(dmo);
+ IUnknown_Release(unk);
+
+ hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, &Outer, CLSCTX_INPROC_SERVER,
+ &IID_IMediaObject, (void **)&unk);
+ ok(hr == E_NOINTERFACE, "got %#x\n", hr);
+}
+
START_TEST(mp3dmod)
{
IMediaObject *dmo;
@@ -247,6 +303,7 @@ START_TEST(mp3dmod)
IMediaObject_Release(dmo);
test_convert();
+ test_aggregation();
CoUninitialize();
}
--
2.7.4
June 22, 2018
[PATCH] crypt32/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/crypt32/tests/base64.c | 10 ++--
dlls/crypt32/tests/cert.c | 2 +-
dlls/crypt32/tests/encode.c | 108 +++++++++++++++++++++-----------------------
dlls/crypt32/tests/main.c | 8 ++--
dlls/crypt32/tests/msg.c | 6 +--
dlls/crypt32/tests/oid.c | 6 +--
dlls/crypt32/tests/sip.c | 9 ++--
dlls/crypt32/tests/store.c | 6 +--
dlls/crypt32/tests/str.c | 17 +++----
9 files changed, 80 insertions(+), 92 deletions(-)
diff --git a/dlls/crypt32/tests/base64.c b/dlls/crypt32/tests/base64.c
index e127fc3891..633e6d1775 100644
--- a/dlls/crypt32/tests/base64.c
+++ b/dlls/crypt32/tests/base64.c
@@ -128,7 +128,7 @@ static void testBinaryToStringA(void)
ret = CryptBinaryToStringA(NULL, 0, 0, NULL, &strLen);
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
- for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(tests); i++)
{
DWORD strLen = 0;
LPSTR str = NULL;
@@ -163,7 +163,7 @@ static void testBinaryToStringA(void)
CRYPT_STRING_BASE64X509CRLHEADER, tests[i].base64, X509_HEADER,
X509_TRAILER);
}
- for (i = 0; i < sizeof(testsNoCR) / sizeof(testsNoCR[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(testsNoCR); i++)
{
DWORD strLen = 0;
LPSTR str = NULL;
@@ -380,7 +380,7 @@ static void testStringToBinaryA(void)
ok(!ret && GetLastError() == ERROR_INVALID_DATA,
"Expected ERROR_INVALID_DATA, got ret=%d le=%u\n", ret, GetLastError());
/* Bad strings */
- for (i = 0; i < sizeof(badStrings) / sizeof(badStrings[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(badStrings); i++)
{
bufLen = 0;
ret = CryptStringToBinaryA(badStrings[i].str, 0, badStrings[i].format,
@@ -447,7 +447,7 @@ static void testStringToBinaryA(void)
ret, bufLen, buf[0]);
/* Good strings */
- for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(tests); i++)
{
bufLen = 0;
/* Bogus length--oddly enough, that succeeds, even though it's not
@@ -504,7 +504,7 @@ static void testStringToBinaryA(void)
*/
}
/* And again, with no CR--decoding handles this automatically */
- for (i = 0; i < sizeof(testsNoCR) / sizeof(testsNoCR[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(testsNoCR); i++)
{
bufLen = 0;
/* Bogus length--oddly enough, that succeeds, even though it's not
diff --git a/dlls/crypt32/tests/cert.c b/dlls/crypt32/tests/cert.c
index e49b2a9798..bb0cc525e7 100644
--- a/dlls/crypt32/tests/cert.c
+++ b/dlls/crypt32/tests/cert.c
@@ -3177,7 +3177,7 @@ static void testCompareIntegerBlob(void)
DWORD i;
BOOL ret;
- for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(intBlobs); i++)
{
ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
ok(ret == intBlobs[i].areEqual,
diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c
index a4daec09c9..4a6626ab00 100644
--- a/dlls/crypt32/tests/encode.c
+++ b/dlls/crypt32/tests/encode.c
@@ -113,7 +113,7 @@ static void test_encodeInt(DWORD dwEncoding)
ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
"Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
}
- for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(ints); i++)
{
/* encode as normal integer */
ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
@@ -155,7 +155,7 @@ static void test_encodeInt(DWORD dwEncoding)
/* encode a couple bigger ints, just to show it's little-endian and leading
* sign bytes are dropped
*/
- for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(bigInts); i++)
{
blob.cbData = strlen((const char*)bigInts[i].val);
blob.pbData = (BYTE *)bigInts[i].val;
@@ -178,7 +178,7 @@ static void test_encodeInt(DWORD dwEncoding)
}
}
/* and, encode some uints */
- for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(bigUInts); i++)
{
blob.cbData = strlen((const char*)bigUInts[i].val);
blob.pbData = (BYTE*)bigUInts[i].val;
@@ -242,7 +242,7 @@ static void test_decodeInt(DWORD dwEncoding)
GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
"Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
GetLastError());
- for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(ints); i++)
{
/* When the output buffer is NULL, this always succeeds */
SetLastError(0xdeadbeef);
@@ -264,7 +264,7 @@ static void test_decodeInt(DWORD dwEncoding)
LocalFree(buf);
}
}
- for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(bigInts); i++)
{
ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
@@ -289,7 +289,7 @@ static void test_decodeInt(DWORD dwEncoding)
LocalFree(buf);
}
}
- for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(bigUInts); i++)
{
ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
@@ -377,9 +377,9 @@ static void test_encodeEnumerated(DWORD dwEncoding)
{
DWORD i, j;
- for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(enumeratedTypes); i++)
{
- for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
+ for (j = 0; j < ARRAY_SIZE(enums); j++)
{
BOOL ret;
BYTE *buf = NULL;
@@ -410,9 +410,9 @@ static void test_decodeEnumerated(DWORD dwEncoding)
{
DWORD i, j;
- for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(enumeratedTypes); i++)
{
- for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
+ for (j = 0; j < ARRAY_SIZE(enums); j++)
{
BOOL ret;
DWORD bufSize = sizeof(int);
@@ -563,7 +563,7 @@ static void test_encodeFiletime(DWORD dwEncoding)
{
DWORD i;
- for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(times); i++)
{
testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, ×[i]);
testTimeEncoding(dwEncoding, PKCS_UTC_TIME, ×[i]);
@@ -645,19 +645,19 @@ static void test_decodeFiletime(DWORD dwEncoding)
ok(!ret && GetLastError() == ERROR_MORE_DATA,
"Expected ERROR_MORE_DATA, got %d\n", GetLastError());
/* Normal tests */
- for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(times); i++)
{
testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, ×[i]);
testTimeDecoding(dwEncoding, PKCS_UTC_TIME, ×[i]);
testTimeDecoding(dwEncoding, szOID_RSA_signingTime, ×[i]);
}
- for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(otherTimes); i++)
{
testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
}
- for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(bogusTimes); i++)
{
size = sizeof(ft1);
ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
@@ -861,7 +861,7 @@ static void test_encodeName(DWORD dwEncoding)
ok(!ret && GetLastError() == E_INVALIDARG,
"Expected E_INVALIDARG, got %08x\n", GetLastError());
/* Test a more complex name */
- rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
+ rdn.cRDNAttr = ARRAY_SIZE(rdnAttrs);
rdn.rgRDNAttr = rdnAttrs;
info.cRDN = 1;
info.rgRDN = &rdn;
@@ -1139,7 +1139,7 @@ static void test_decodeName(DWORD dwEncoding)
(BYTE *)commonName } },
};
- rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
+ rdn.cRDNAttr = ARRAY_SIZE(attrs);
rdn.rgRDNAttr = attrs;
compareNames(&info, (CERT_NAME_INFO *)buf);
LocalFree(buf);
@@ -1157,7 +1157,7 @@ static void test_decodeName(DWORD dwEncoding)
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
if (ret)
{
- rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
+ rdn.cRDNAttr = ARRAY_SIZE(decodedRdnAttrs);
rdn.rgRDNAttr = decodedRdnAttrs;
compareNames(&info, (CERT_NAME_INFO *)buf);
LocalFree(buf);
@@ -1223,7 +1223,7 @@ static void test_decodeUnicodeName(DWORD dwEncoding)
{ lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
};
- rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
+ rdn.cRDNAttr = ARRAY_SIZE(attrs);
rdn.rgRDNAttr = attrs;
compareNames(&info, (CERT_NAME_INFO *)buf);
LocalFree(buf);
@@ -1332,7 +1332,7 @@ static void test_encodeNameValue(DWORD dwEncoding)
"Unexpected encoding\n");
LocalFree(buf);
}
- for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(nameValues); i++)
{
ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
&nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
@@ -1370,7 +1370,7 @@ static void test_decodeNameValue(DWORD dwEncoding)
DWORD bufSize = 0;
BOOL ret;
- for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(nameValues); i++)
{
ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
nameValues[i].encoded, nameValues[i].encoded[1] + 2,
@@ -1866,7 +1866,7 @@ static void test_encodeUnicodeNameValue(DWORD dwEncoding)
"Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
/* More failure checking */
value.Value.cbData = 0;
- for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(unicodeErrors); i++)
{
value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
value.dwValueType = unicodeErrors[i].valueType;
@@ -1881,7 +1881,7 @@ static void test_encodeUnicodeNameValue(DWORD dwEncoding)
}
/* cbData can be zero if the string is NULL-terminated */
value.Value.cbData = 0;
- for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(unicodeResults); i++)
{
value.Value.pbData = (LPBYTE)unicodeResults[i].str;
value.dwValueType = unicodeResults[i].valueType;
@@ -1903,7 +1903,7 @@ static void test_encodeUnicodeNameValue(DWORD dwEncoding)
* rather than properly encoding it. Kept separate from the proper results,
* because the encoded forms won't decode to their original strings.
*/
- for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(unicodeWeirdness); i++)
{
value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
value.dwValueType = unicodeWeirdness[i].valueType;
@@ -1933,7 +1933,7 @@ static void test_decodeUnicodeNameValue(DWORD dwEncoding)
{
DWORD i;
- for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(unicodeResults); i++)
{
BYTE *buf = NULL;
BOOL ret;
@@ -1991,7 +1991,7 @@ static void test_encodeOctets(DWORD dwEncoding)
}
};
- for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(tests); i++)
{
BYTE *buf = NULL;
BOOL ret;
@@ -2065,7 +2065,7 @@ static void test_decodeOctets(DWORD dwEncoding)
}
};
- for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(tests); i++)
{
BYTE *buf = NULL;
BOOL ret;
@@ -2127,7 +2127,7 @@ static void test_encodeBits(DWORD dwEncoding)
{
DWORD i;
- for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(bits); i++)
{
CRYPT_BIT_BLOB blob;
BOOL ret;
@@ -2162,7 +2162,7 @@ static void test_decodeBits(DWORD dwEncoding)
DWORD bufSize = 0;
/* normal cases */
- for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(bits); i++)
{
ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
@@ -2249,7 +2249,7 @@ static void test_encodeBasicConstraints(DWORD dwEncoding)
BYTE *buf = NULL;
/* First test with the simpler info2 */
- for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(constraints2); i++)
{
ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
&constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
@@ -2312,7 +2312,7 @@ static void test_decodeBasicConstraints(DWORD dwEncoding)
DWORD bufSize = 0;
/* First test with simpler info2 */
- for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(constraints2); i++)
{
ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
constraints2[i].encoded, constraints2[i].encoded[1] + 2,
@@ -2494,7 +2494,7 @@ static void test_encodeRsaPublicKey(DWORD dwEncoding)
"Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
/* Finally, all valid */
hdr->aiKeyAlg = CALG_RSA_KEYX;
- for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(rsaPubKeys); i++)
{
memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
@@ -2540,7 +2540,7 @@ static void test_decodeRsaPublicKey(DWORD dwEncoding)
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
"Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
/* Now try success cases */
- for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(rsaPubKeys); i++)
{
bufSize = 0;
ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
@@ -2590,7 +2590,7 @@ static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
static void test_encodeSequenceOfAny(DWORD dwEncoding)
{
- CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
+ CRYPT_DER_BLOB blobs[ARRAY_SIZE(ints)];
CRYPT_SEQUENCE_OF_ANY seq;
DWORD i;
BOOL ret;
@@ -2598,12 +2598,12 @@ static void test_encodeSequenceOfAny(DWORD dwEncoding)
DWORD bufSize = 0;
/* Encode a homogeneous sequence */
- for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(ints); i++)
{
blobs[i].cbData = ints[i].encoded[1] + 2;
blobs[i].pbData = (BYTE *)ints[i].encoded;
}
- seq.cValue = sizeof(ints) / sizeof(ints[0]);
+ seq.cValue = ARRAY_SIZE(ints);
seq.rgValue = blobs;
ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
@@ -2646,9 +2646,8 @@ static void test_decodeSequenceOfAny(DWORD dwEncoding)
CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
DWORD i;
- ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
- "Wrong elements %d\n", seq->cValue);
- for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
+ ok(seq->cValue == ARRAY_SIZE(ints), "Wrong elements %d\n", seq->cValue);
+ for (i = 0; i < min(seq->cValue, ARRAY_SIZE(ints)); i++)
{
ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
"Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
@@ -2666,8 +2665,7 @@ static void test_decodeSequenceOfAny(DWORD dwEncoding)
{
CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
- ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
- "Wrong elements %d\n", seq->cValue);
+ ok(seq->cValue == ARRAY_SIZE(ints), "Wrong elements %d\n", seq->cValue);
/* Just check the first element since it's all that changed */
ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
"Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
@@ -2713,7 +2711,7 @@ static void test_encodeExtensions(DWORD dwEncoding)
{
DWORD i;
- for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
+ for (i = 0; i < ARRAY_SIZE(exts); i++)
{
BOOL ret;
BYTE *buf = NULL;
@@ -2737,7 +2735,7 @@ static void test_decodeExtensions(DWORD dwEncoding)
{
DWORD i;
- for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
+ for (i = 0; i < ARRAY_SIZE(exts); i++)
{
BOOL ret;
BYTE *buf = NULL;
@@ -2851,7 +2849,7 @@ static void test_encodePublicKeyInfo(DWORD dwEncoding)
{
DWORD i;
- for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(pubKeys); i++)
{
BOOL ret;
BYTE *buf = NULL;
@@ -2907,7 +2905,7 @@ static void test_decodePublicKeyInfo(DWORD dwEncoding)
BYTE *buf = NULL;
DWORD bufSize = 0;
- for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(pubKeys); i++)
{
/* The NULL form decodes to the decoded member */
ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
@@ -3260,7 +3258,7 @@ static void test_decodeCertToBeSigned(DWORD dwEncoding)
* CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
* serial number, an issuer, a subject, and a public key.
*/
- for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(corruptCerts); i++)
{
ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
@@ -4688,7 +4686,7 @@ static void test_decodeCRLToBeSigned(DWORD dwEncoding)
BYTE *buf = NULL;
DWORD size = 0, i;
- for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(corruptCRLs); i++)
{
ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
@@ -4854,7 +4852,7 @@ static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
LocalFree(buf);
}
/* Test with a few usages */
- usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
+ usage.cUsageIdentifier = ARRAY_SIZE(keyUsages);
usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
@@ -4898,8 +4896,8 @@ static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
ok(size >= sizeof(CERT_ENHKEY_USAGE),
"Wrong size %d\n", size);
- ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
- "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
+ ok(usage->cUsageIdentifier == ARRAY_SIZE(keyUsages),
+ "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
for (i = 0; i < usage->cUsageIdentifier; i++)
ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
"Expected OID %s, got %s\n", keyUsages[i],
@@ -6109,7 +6107,7 @@ static void test_decodePKCSContentInfo(DWORD dwEncoding)
"1.2.3", content_constructed_abcd + 8, 10 }
};
- for (i = 0; i < sizeof(tests)/sizeof(*tests); i++)
+ for (i = 0; i < ARRAY_SIZE(tests); i++)
{
ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, tests[i].encoded,
tests[i].encoded_size, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
@@ -7397,9 +7395,7 @@ static void test_decodeNameConstraints(DWORD dwEncoding)
U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
- for (i = 0;
- i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
- i++)
+ for (i = 0; i < ARRAY_SIZE(encodedNameConstraints); i++)
{
DWORD size;
@@ -7749,7 +7745,7 @@ static void test_encodeCertPolicyMappings(DWORD dwEncoding)
DWORD size, i;
/* Each of the mapping OIDs is equivalent, so check with all of them */
- for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(mappingOids); i++)
{
memset(&info, 0, sizeof(info));
ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
@@ -7814,7 +7810,7 @@ static void test_decodeCertPolicyMappings(DWORD dwEncoding)
BOOL ret;
/* Each of the mapping OIDs is equivalent, so check with all of them */
- for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(mappingOids); i++)
{
ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
@@ -8525,7 +8521,7 @@ START_TEST(encode)
return;
}
- for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(encodings); i++)
{
test_encodeInt(encodings[i]);
test_decodeInt(encodings[i]);
diff --git a/dlls/crypt32/tests/main.c b/dlls/crypt32/tests/main.c
index a0019b5869..11beff11c4 100644
--- a/dlls/crypt32/tests/main.c
+++ b/dlls/crypt32/tests/main.c
@@ -36,7 +36,7 @@ static void test_findAttribute(void)
BYTE blobbin[] = {0x02,0x01,0x01};
static CHAR oid[] = "1.2.3";
CRYPT_ATTR_BLOB blobs[] = { { sizeof blobbin, blobbin }, };
- CRYPT_ATTRIBUTE attr = { oid, sizeof(blobs) / sizeof(blobs[0]), blobs };
+ CRYPT_ATTRIBUTE attr = { oid, ARRAY_SIZE(blobs), blobs };
/* returns NULL, last error not set */
SetLastError(0xdeadbeef);
@@ -128,10 +128,8 @@ static void test_findRDNAttr(void)
CERT_RDN_ATTR attrs[] = {
{ oid, CERT_RDN_IA5_STRING, { sizeof bin, bin } },
};
- CERT_RDN rdns[] = {
- { sizeof(attrs) / sizeof(attrs[0]), attrs },
- };
- CERT_NAME_INFO nameInfo = { sizeof(rdns) / sizeof(rdns[0]), rdns };
+ CERT_RDN rdns[] = { { ARRAY_SIZE(attrs), attrs } };
+ CERT_NAME_INFO nameInfo = { ARRAY_SIZE(rdns), rdns };
if (0)
{
diff --git a/dlls/crypt32/tests/msg.c b/dlls/crypt32/tests/msg.c
index c2405335b9..b6921273ee 100644
--- a/dlls/crypt32/tests/msg.c
+++ b/dlls/crypt32/tests/msg.c
@@ -575,7 +575,7 @@ static CRYPT_DATA_BLOB b1[] = {
{ sizeof(u2), u2 },
{ sizeof(u2), u2 },
};
-static const struct update_accum a1 = { sizeof(b1) / sizeof(b1[0]), b1 };
+static const struct update_accum a1 = { ARRAY_SIZE(b1), b1 };
/* The updates of a definite-length encoded message */
static BYTE u3[] = { 0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
0x07,0x01,0xa0,0x06,0x04,0x04 };
@@ -583,7 +583,7 @@ static CRYPT_DATA_BLOB b2[] = {
{ sizeof(u3), u3 },
{ sizeof(u2), u2 },
};
-static const struct update_accum a2 = { sizeof(b2) / sizeof(b2[0]), b2 };
+static const struct update_accum a2 = { ARRAY_SIZE(b2), b2 };
/* The updates of an indefinite-length encoded message */
static BYTE u4[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
0x07,0x01,0xa0,0x80,0x24,0x80 };
@@ -597,7 +597,7 @@ static CRYPT_DATA_BLOB b3[] = {
{ sizeof(u2), u2 },
{ sizeof(u6), u6 },
};
-static const struct update_accum a3 = { sizeof(b3) / sizeof(b3[0]), b3 };
+static const struct update_accum a3 = { ARRAY_SIZE(b3), b3 };
static void check_updates(LPCSTR header, const struct update_accum *expected,
const struct update_accum *got)
diff --git a/dlls/crypt32/tests/oid.c b/dlls/crypt32/tests/oid.c
index 8fc67b3353..9485764ed7 100644
--- a/dlls/crypt32/tests/oid.c
+++ b/dlls/crypt32/tests/oid.c
@@ -105,7 +105,7 @@ static void testOIDToAlgID(void)
alg = CertOIDToAlgId("1.2.3");
ok(!alg, "Expected failure, got %d\n", alg);
- for (i = 0; i < sizeof(oidToAlgID) / sizeof(oidToAlgID[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(oidToAlgID); i++)
{
alg = CertOIDToAlgId(oidToAlgID[i].oid);
ok(alg == oidToAlgID[i].algID || (oidToAlgID[i].altAlgID && alg == oidToAlgID[i].altAlgID),
@@ -123,7 +123,7 @@ static void testAlgIDToOID(void)
oid = CertAlgIdToOID(ALG_CLASS_SIGNATURE | ALG_TYPE_ANY | 80);
ok(!oid && GetLastError() == 0xdeadbeef,
"Didn't expect last error (%08x) to be set\n", GetLastError());
- for (i = 0; i < sizeof(algIDToOID) / sizeof(algIDToOID[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(algIDToOID); i++)
{
oid = CertAlgIdToOID(algIDToOID[i].algID);
/* Allow failure, not every version of Windows supports every algo */
@@ -423,7 +423,7 @@ static void test_registerDefaultOIDFunction(void)
DWORD type, size;
LPSTR ptr;
- size = sizeof(dllBuf) / sizeof(dllBuf[0]);
+ size = ARRAY_SIZE(dllBuf);
rc = RegQueryValueExA(key, dllA, NULL, &type, (LPBYTE)dllBuf, &size);
ok(rc == 0,
"Expected Dll value to exist, RegQueryValueExA failed: %d\n", rc);
diff --git a/dlls/crypt32/tests/sip.c b/dlls/crypt32/tests/sip.c
index e2ec2f411d..d8d6a87445 100644
--- a/dlls/crypt32/tests/sip.c
+++ b/dlls/crypt32/tests/sip.c
@@ -187,9 +187,8 @@ static void test_SIPRetrieveSubjectGUID(void)
ok (ret > 0, "expected GEVA(windir) to succeed, last error %d\n", GetLastError());
strcat(regeditPath, "\\");
strcat(regeditPath, regeditExe);
- MultiByteToWideChar( CP_ACP, 0, regeditPath,
- strlen(regeditPath)+1, regeditPathW,
- sizeof(regeditPathW)/sizeof(regeditPathW[0]) );
+ MultiByteToWideChar(CP_ACP, 0, regeditPath, strlen(regeditPath)+1, regeditPathW,
+ ARRAY_SIZE(regeditPathW));
SetLastError(0xdeadbeef);
memset(&subject, 1, sizeof(GUID));
@@ -221,9 +220,7 @@ static void test_SIPRetrieveSubjectGUID(void)
/* Now with an empty file */
GetTempPathA(sizeof(path), path);
GetTempFileNameA(path, "sip", 0 , tempfile);
- MultiByteToWideChar( CP_ACP, 0, tempfile,
- strlen(tempfile)+1, tempfileW,
- sizeof(tempfileW)/sizeof(tempfileW[0]) );
+ MultiByteToWideChar(CP_ACP, 0, tempfile, strlen(tempfile)+1, tempfileW, ARRAY_SIZE(tempfileW));
SetLastError(0xdeadbeef);
memset(&subject, 1, sizeof(GUID));
diff --git a/dlls/crypt32/tests/store.c b/dlls/crypt32/tests/store.c
index 47cd0b38cd..9915482277 100644
--- a/dlls/crypt32/tests/store.c
+++ b/dlls/crypt32/tests/store.c
@@ -385,7 +385,7 @@ static void testRegStoreSavedCerts(void)
BOOL ret;
DWORD res,i;
- for (i = 0; i < sizeof(reg_store_saved_certs) / sizeof(reg_store_saved_certs[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(reg_store_saved_certs); i++)
{
DWORD err;
@@ -2081,7 +2081,7 @@ static void testCertRegisterSystemStore(void)
const CERT_CONTEXT *cert, *cert2;
unsigned int i;
- for (i = 0; i < sizeof(reg_system_store_test_data) / sizeof(reg_system_store_test_data[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(reg_system_store_test_data); i++) {
cur_flag = reg_system_store_test_data[i].cert_store;
ret = CertRegisterSystemStore(WineTestW, cur_flag, NULL, NULL);
if (!ret)
@@ -2469,7 +2469,7 @@ static void delete_test_key(void)
RegQueryInfoKeyW(test_key, NULL, NULL, NULL, &num_subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
for (idx = num_subkeys; idx-- > 0;)
{
- subkey_name_len = sizeof(subkey_name)/sizeof(WCHAR);
+ subkey_name_len = ARRAY_SIZE(subkey_name);
RegEnumKeyExW(test_key, idx, subkey_name, &subkey_name_len, NULL, NULL, NULL, NULL);
RegDeleteKeyW(test_key, subkey_name);
}
diff --git a/dlls/crypt32/tests/str.c b/dlls/crypt32/tests/str.c
index 5245885503..d382c0e6b0 100644
--- a/dlls/crypt32/tests/str.c
+++ b/dlls/crypt32/tests/str.c
@@ -250,7 +250,7 @@ static void test_CertRDNValueToStrA(void)
ok(ret == 1 && GetLastError() == 0xdeadbeef, "Expected empty string\n");
ok(!buffer[0], "Expected empty string\n");
- for (i = 0; i < sizeof(attrs) / sizeof(attrs[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(attrs); i++)
{
ret = pCertRDNValueToStrA(attrs[i].dwValueType, &attrs[i].Value,
buffer, sizeof(buffer));
@@ -341,15 +341,13 @@ static void test_CertRDNValueToStrW(void)
SetLastError(0xdeadbeef);
ret = pCertRDNValueToStrW(0, &blob, NULL, 0);
ok(ret == 1 && GetLastError() == 0xdeadbeef, "Expected empty string\n");
- ret = pCertRDNValueToStrW(0, &blob, buffer,
- sizeof(buffer) / sizeof(buffer[0]));
+ ret = pCertRDNValueToStrW(0, &blob, buffer, ARRAY_SIZE(buffer));
ok(ret == 1 && GetLastError() == 0xdeadbeef, "Expected empty string\n");
ok(!buffer[0], "Expected empty string\n");
- for (i = 0; i < sizeof(attrs) / sizeof(attrs[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(attrs); i++)
{
- ret = pCertRDNValueToStrW(attrs[i].dwValueType, &attrs[i].Value,
- buffer, sizeof(buffer) / sizeof(buffer[0]));
+ ret = pCertRDNValueToStrW(attrs[i].dwValueType, &attrs[i].Value, buffer, ARRAY_SIZE(buffer));
todo_wine_if (attrs[i].todo)
{
ok(ret == lstrlenW(attrs[i].str) + 1,
@@ -550,8 +548,7 @@ static void test_NameToStrConversionW(PCERT_NAME_BLOB pName, DWORD dwStrType,
todo_wine_if (todo)
ok(i == lstrlenW(expected) + 1, "Expected %d chars, got %d\n",
lstrlenW(expected) + 1, i);
- i = pCertNameToStrW(X509_ASN_ENCODING,pName, dwStrType, buffer,
- sizeof(buffer) / sizeof(buffer[0]));
+ i = pCertNameToStrW(X509_ASN_ENCODING,pName, dwStrType, buffer, ARRAY_SIZE(buffer));
todo_wine_if (todo)
ok(i == lstrlenW(expected) + 1, "Expected %d chars, got %d\n",
lstrlenW(expected) + 1, i);
@@ -795,7 +792,7 @@ static void test_CertStrToNameA(void)
&size, NULL);
ok(!ret && GetLastError() == ERROR_MORE_DATA,
"Expected ERROR_MORE_DATA, got %08x\n", GetLastError());
- for (i = 0; i < sizeof(namesA) / sizeof(namesA[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(namesA); i++)
{
size = sizeof(buf);
ret = pCertStrToNameA(X509_ASN_ENCODING, namesA[i].x500, 0, NULL, buf,
@@ -889,7 +886,7 @@ static void test_CertStrToNameW(void)
ok(!ret && GetLastError() == CRYPT_E_INVALID_X500_STRING,
"Expected CRYPT_E_INVALID_X500_STRING, got %08x\n", GetLastError());
ok(errorPtr && *errorPtr == '1', "Expected first error character was 1\n");
- for (i = 0; i < sizeof(namesW) / sizeof(namesW[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(namesW); i++)
{
size = sizeof(buf);
ret = pCertStrToNameW(X509_ASN_ENCODING, namesW[i].x500, 0, NULL, buf,
--
2.14.4
June 22, 2018
[PATCH] crypt32: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/crypt32/chain.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/crypt32/chain.c b/dlls/crypt32/chain.c
index dd3fc33db6..6e8076c66c 100644
--- a/dlls/crypt32/chain.c
+++ b/dlls/crypt32/chain.c
@@ -738,8 +738,7 @@ static BOOL url_matches(LPCWSTR constraint, LPCWSTR name,
/* Ignore any path or query portion of the URL. */
if (*authority_end)
{
- if (authority_end - name < sizeof(hostname_buf) /
- sizeof(hostname_buf[0]))
+ if (authority_end - name < ARRAY_SIZE(hostname_buf))
{
memcpy(hostname_buf, name,
(authority_end - name) * sizeof(WCHAR));
--
2.14.4
June 22, 2018
[PATCH] kernel32/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Only locale.c for now due to its size.
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/kernel32/tests/locale.c | 598 +++++++++++++++++++++----------------------
1 file changed, 287 insertions(+), 311 deletions(-)
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index 791f015766..06a7aa75e7 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -154,15 +154,14 @@ static void InitFunctionPointers(void)
(label), (received), (expected))
#define BUFFER_SIZE 128
-#define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
#define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0xdeadbeef); buffer[0] = '\0'
#define EXPECT_LENA ok(ret == lstrlenA(Expected)+1, "Expected len %d, got %d\n", lstrlenA(Expected)+1, ret)
#define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
"Expected '%s', got '%s'\n", Expected, buffer)
-#define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
- MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
+#define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,ARRAY_SIZE(input)); \
+ MultiByteToWideChar(CP_ACP,0,y,-1,Expected,ARRAY_SIZE(Expected)); \
SetLastError(0xdeadbeef); buffer[0] = '\0'
#define EXPECT_LENW ok(ret == lstrlenW(Expected)+1, "Expected Len %d, got %d\n", lstrlenW(Expected)+1, ret)
#define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
@@ -187,21 +186,21 @@ static void test_GetLocaleInfoA(void)
/* en and ar use SUBLANG_NEUTRAL, but GetLocaleInfo assume SUBLANG_DEFAULT
Same is true for zh on pre-Vista, but on Vista and higher GetLocaleInfo
assumes SUBLANG_NEUTRAL for zh */
- memset(expected, 0, COUNTOF(expected));
- len = GetLocaleInfoA(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
+ memset(expected, 0, ARRAY_SIZE(expected));
+ len = GetLocaleInfoA(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, ARRAY_SIZE(expected));
SetLastError(0xdeadbeef);
- memset(buffer, 0, COUNTOF(buffer));
- ret = GetLocaleInfoA(LANG_ENGLISH, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
+ memset(buffer, 0, ARRAY_SIZE(buffer));
+ ret = GetLocaleInfoA(LANG_ENGLISH, LOCALE_SLANGUAGE, buffer, ARRAY_SIZE(buffer));
ok((ret == len) && !lstrcmpA(buffer, expected),
"got %d with '%s' (expected %d with '%s')\n",
ret, buffer, len, expected);
- memset(expected, 0, COUNTOF(expected));
- len = GetLocaleInfoA(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
+ memset(expected, 0, ARRAY_SIZE(expected));
+ len = GetLocaleInfoA(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, ARRAY_SIZE(expected));
if (len) {
SetLastError(0xdeadbeef);
- memset(buffer, 0, COUNTOF(buffer));
- ret = GetLocaleInfoA(LANG_ARABIC, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
+ memset(buffer, 0, ARRAY_SIZE(buffer));
+ ret = GetLocaleInfoA(LANG_ARABIC, LOCALE_SLANGUAGE, buffer, ARRAY_SIZE(buffer));
ok((ret == len) && !lstrcmpA(buffer, expected),
"got %d with '%s' (expected %d with '%s')\n",
ret, buffer, len, expected);
@@ -210,11 +209,11 @@ static void test_GetLocaleInfoA(void)
win_skip("LANG_ARABIC not installed\n");
/* SUBLANG_DEFAULT is required for mlang.dll, but optional for GetLocaleInfo */
- memset(expected, 0, COUNTOF(expected));
- len = GetLocaleInfoA(MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
+ memset(expected, 0, ARRAY_SIZE(expected));
+ len = GetLocaleInfoA(MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, ARRAY_SIZE(expected));
SetLastError(0xdeadbeef);
- memset(buffer, 0, COUNTOF(buffer));
- ret = GetLocaleInfoA(LANG_GERMAN, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
+ memset(buffer, 0, ARRAY_SIZE(buffer));
+ ret = GetLocaleInfoA(LANG_GERMAN, LOCALE_SLANGUAGE, buffer, ARRAY_SIZE(buffer));
ok((ret == len) && !lstrcmpA(buffer, expected),
"got %d with '%s' (expected %d with '%s')\n",
ret, buffer, len, expected);
@@ -224,19 +223,19 @@ static void test_GetLocaleInfoA(void)
* partially fill the buffer even if it is too short. See bug 637.
*/
SetLastError(0xdeadbeef);
- memset(buffer, 0, COUNTOF(buffer));
+ memset(buffer, 0, ARRAY_SIZE(buffer));
ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
SetLastError(0xdeadbeef);
- memset(buffer, 0, COUNTOF(buffer));
+ memset(buffer, 0, ARRAY_SIZE(buffer));
ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
"Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
SetLastError(0xdeadbeef);
- memset(buffer, 0, COUNTOF(buffer));
+ memset(buffer, 0, ARRAY_SIZE(buffer));
ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
ok(ret == 7, "Expected ret == 7, got %d, error %d\n", ret, GetLastError());
ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
@@ -296,7 +295,7 @@ static void test_GetLocaleInfoW(void)
DWORD ret;
INT i;
- ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
+ ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1, bufferW, ARRAY_SIZE(bufferW));
if (!ret) {
win_skip("GetLocaleInfoW() isn't implemented\n");
return;
@@ -306,7 +305,7 @@ static void test_GetLocaleInfoW(void)
ok(ret, "got %d\n", ret);
ok(val == lcid_en, "got 0x%08x\n", val);
- ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SNAME, bufferW, COUNTOF(bufferW));
+ ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SNAME, bufferW, ARRAY_SIZE(bufferW));
if (ret)
{
static const WCHAR slangW[] = {'E','n','g','l','i','s','h',' ','(','U','n','i','t','e','d',' ',
@@ -317,7 +316,7 @@ static void test_GetLocaleInfoW(void)
ok(!lstrcmpW(bufferW, enW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
- ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SCOUNTRY, bufferW, COUNTOF(bufferW));
+ ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SCOUNTRY, bufferW, ARRAY_SIZE(bufferW));
ok(ret, "got %d\n", ret);
if ((PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) != LANG_ENGLISH) ||
(PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH))
@@ -327,7 +326,7 @@ static void test_GetLocaleInfoW(void)
else
ok(!lstrcmpW(statesW, bufferW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
- ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SLANGUAGE, bufferW, COUNTOF(bufferW));
+ ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SLANGUAGE, bufferW, ARRAY_SIZE(bufferW));
ok(ret, "got %d\n", ret);
if ((PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) != LANG_ENGLISH) ||
(PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH))
@@ -353,7 +352,7 @@ static void test_GetLocaleInfoW(void)
wine_dbgstr_w(ptr->name), val, ptr->lcid);
/* now check LOCALE_SNAME */
- GetLocaleInfoW(lcid, LOCALE_SNAME, bufferW, COUNTOF(bufferW));
+ GetLocaleInfoW(lcid, LOCALE_SNAME, bufferW, ARRAY_SIZE(bufferW));
todo_wine_if (ptr->todo & 0x2)
ok(!lstrcmpW(bufferW, ptr->sname) ||
(*ptr->sname_broken && broken(!lstrcmpW(bufferW, ptr->sname_broken))),
@@ -364,13 +363,13 @@ static void test_GetLocaleInfoW(void)
else
win_skip("English neutral locale not supported\n");
- ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
+ ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1, bufferW, ARRAY_SIZE(bufferW));
if (!ret) {
win_skip("LANG_RUSSIAN locale data unavailable\n");
return;
}
ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
- bufferW, COUNTOF(bufferW));
+ bufferW, ARRAY_SIZE(bufferW));
if (!ret) {
win_skip("LOCALE_RETURN_GENITIVE_NAMES isn't supported\n");
return;
@@ -380,7 +379,7 @@ static void test_GetLocaleInfoW(void)
bufferA[0] = 'a';
SetLastError(0xdeadbeef);
ret = GetLocaleInfoA(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
- bufferA, COUNTOF(bufferA));
+ bufferA, ARRAY_SIZE(bufferA));
ok(ret == 0, "LOCALE_RETURN_GENITIVE_NAMES should fail with GetLocaleInfoA\n");
ok(bufferA[0] == 'a', "Expected buffer to be untouched\n");
ok(GetLastError() == ERROR_INVALID_FLAGS,
@@ -388,8 +387,7 @@ static void test_GetLocaleInfoW(void)
bufferW[0] = 'a';
SetLastError(0xdeadbeef);
- ret = GetLocaleInfoW(lcid_ru, LOCALE_RETURN_GENITIVE_NAMES,
- bufferW, COUNTOF(bufferW));
+ ret = GetLocaleInfoW(lcid_ru, LOCALE_RETURN_GENITIVE_NAMES, bufferW, ARRAY_SIZE(bufferW));
ok(ret == 0,
"LOCALE_RETURN_GENITIVE_NAMES itself doesn't return anything, got %d\n", ret);
ok(bufferW[0] == 'a', "Expected buffer to be untouched\n");
@@ -400,13 +398,12 @@ static void test_GetLocaleInfoW(void)
for (i = 0; i < 12; i++) {
bufferW[0] = 0;
ret = GetLocaleInfoW(lcid_ru, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
- bufferW, COUNTOF(bufferW));
+ bufferW, ARRAY_SIZE(bufferW));
ok(ret, "Expected non zero result\n");
ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
ret, lstrlenW(bufferW));
buffer2W[0] = 0;
- ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1+i,
- buffer2W, COUNTOF(buffer2W));
+ ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1+i, buffer2W, ARRAY_SIZE(buffer2W));
ok(ret, "Expected non zero result\n");
ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
ret, lstrlenW(buffer2W));
@@ -417,13 +414,12 @@ static void test_GetLocaleInfoW(void)
/* for locale without genitive names nominative returned in both cases */
bufferW[0] = 0;
ret = GetLocaleInfoW(lcid_en, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
- bufferW, COUNTOF(bufferW));
+ bufferW, ARRAY_SIZE(bufferW));
ok(ret, "Expected non zero result\n");
ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
ret, lstrlenW(bufferW));
buffer2W[0] = 0;
- ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1+i,
- buffer2W, COUNTOF(buffer2W));
+ ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1+i, buffer2W, ARRAY_SIZE(buffer2W));
ok(ret, "Expected non zero result\n");
ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
ret, lstrlenW(buffer2W));
@@ -443,7 +439,7 @@ static void test_GetTimeFormatA(void)
memset(&curtime, 2, sizeof(SYSTEMTIME));
STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
SetLastError(0xdeadbeef);
- ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
@@ -453,13 +449,13 @@ static void test_GetTimeFormatA(void)
curtime.wMilliseconds = 22;
STRINGSA("tt HH':'mm'@'ss", "AM 08:56(a)13"); /* Valid time */
SetLastError(0xdeadbeef);
- ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
/* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
SetLastError(0xdeadbeef);
- ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
"Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
@@ -475,62 +471,62 @@ static void test_GetTimeFormatA(void)
EXPECT_LENA;
STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
- ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
- ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "4" )), /* win9x */
"Expected '', got '%s'\n", buffer );
STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
- ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
strcpy(Expected, "8:56 AM");
- ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
- ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
ok( !strcmp( buffer, "8.@:56AM" ) || broken( !strcmp( buffer, "8.@:56.@:AM" )) /* win9x */,
"Expected '8.@:56AM', got '%s'\n", buffer );
STRINGSA("s1s2s3", ""); /* Duplicate tokens */
- ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "3" )), /* win9x */
"Expected '', got '%s'\n", buffer );
STRINGSA("t/tt", "A/AM"); /* AM time marker */
- ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
curtime.wHour = 13;
STRINGSA("t/tt", "P/PM"); /* PM time marker */
- ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
- ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
- ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
- ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
@@ -538,18 +534,18 @@ static void test_GetTimeFormatA(void)
curtime.wMinute = 5;
curtime.wSecond = 3;
STRINGSA("h hh H HH m mm s ss t tt", "2 02 14 14 5 05 3 03 P PM"); /* 24 hrs, leading 0 */
- ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
curtime.wHour = 0;
STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
- ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
- ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
@@ -565,7 +561,7 @@ static void test_GetTimeFormatA(void)
curtime.wMilliseconds = 22;
STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
"8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
- ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
@@ -577,53 +573,53 @@ static void test_GetTimeFormatA(void)
STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
"8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
- ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("'''", "'"); /* invalid quoted string */
- ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
/* test that msdn suggested single quotation usage works as expected */
STRINGSA("''''", "'"); /* single quote mark */
- ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("''HHHHHH", "08"); /* Normal use */
- ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
/* and test for normal use of the single quotation mark */
STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
- ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
- ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
- ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
curtime.wHour = 25;
STRINGSA("'123'tt", ""); /* Invalid time */
SetLastError(0xdeadbeef);
- ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
curtime.wHour = 12;
curtime.wMonth = 60; /* Invalid */
STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
- ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
}
@@ -643,7 +639,7 @@ static void test_GetTimeFormatEx(void)
memset(&curtime, 2, sizeof(SYSTEMTIME));
STRINGSW("tt HH':'mm'@'ss", ""); /* Invalid time */
SetLastError(0xdeadbeef);
- ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
@@ -653,13 +649,13 @@ static void test_GetTimeFormatEx(void)
curtime.wMilliseconds = 22;
STRINGSW("tt HH':'mm'@'ss", "AM 08:56(a)13"); /* Valid time */
SetLastError(0xdeadbeef);
- ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
/* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
SetLastError(0xdeadbeef);
- ret = pGetTimeFormatEx(localeW, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
"Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
@@ -675,58 +671,58 @@ static void test_GetTimeFormatEx(void)
EXPECT_LENW;
STRINGSW("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
- ret = pGetTimeFormatEx(localeW, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
- ret = pGetTimeFormatEx(localeW, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret == strlenW(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
- ret = pGetTimeFormatEx(localeW, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
- ret = pGetTimeFormatEx(localeW, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, TIME_NOSECONDS, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
- ret = pGetTimeFormatEx(localeW, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, TIME_NOSECONDS, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("s1s2s3", ""); /* Duplicate tokens */
- ret = pGetTimeFormatEx(localeW, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, TIME_NOSECONDS, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret == strlenW(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("t/tt", "A/AM"); /* AM time marker */
- ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
curtime.wHour = 13;
STRINGSW("t/tt", "P/PM"); /* PM time marker */
- ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
- ret = pGetTimeFormatEx(localeW, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, TIME_NOTIMEMARKER, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
- ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
- ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
@@ -734,18 +730,18 @@ static void test_GetTimeFormatEx(void)
curtime.wMinute = 5;
curtime.wSecond = 3;
STRINGSW("h hh H HH m mm s ss t tt", "2 02 14 14 5 05 3 03 P PM"); /* 24 hrs, leading 0 */
- ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
curtime.wHour = 0;
STRINGSW("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
- ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
- ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
@@ -761,7 +757,7 @@ static void test_GetTimeFormatEx(void)
curtime.wMilliseconds = 22;
STRINGSW("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
"8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
- ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
@@ -773,53 +769,53 @@ static void test_GetTimeFormatEx(void)
STRINGSW("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
"8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
- ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("'''", "'"); /* invalid quoted string */
- ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
/* test that msdn suggested single quotation usage works as expected */
STRINGSW("''''", "'"); /* single quote mark */
- ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("''HHHHHH", "08"); /* Normal use */
- ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
/* and test for normal use of the single quotation mark */
STRINGSW("'''HHHHHH'", "'HHHHHH"); /* Normal use */
- ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("'''HHHHHH", "'HHHHHH"); /* Odd use */
- ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
- ret = pGetTimeFormatEx(localeW, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, TIME_NOTIMEMARKER, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
curtime.wHour = 25;
STRINGSW("'123'tt", ""); /* Invalid time */
SetLastError(0xdeadbeef);
- ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
curtime.wHour = 12;
curtime.wMonth = 60; /* Invalid */
STRINGSW("h:m:s", "12:56:13"); /* Invalid date */
- ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
}
@@ -837,7 +833,7 @@ static void test_GetDateFormatA(void)
memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
STRINGSA("ddd',' MMM dd yy","");
SetLastError(0xdeadbeef);
- ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
@@ -846,26 +842,26 @@ static void test_GetDateFormatA(void)
curtime.wDay = 4;
curtime.wDayOfWeek = 3;
STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
- ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
/* Same as above but with LOCALE_NOUSEROVERRIDE */
STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
SetLastError(0xdeadbeef);
- ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
"Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
EXPECT_EQA;
STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
- ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
curtime.wHour = 36; /* Invalid */
STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
- ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
@@ -881,13 +877,13 @@ static void test_GetDateFormatA(void)
"Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
- ret = GetDateFormatA(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid, NUO, &curtime, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
SetLastError(0xdeadbeef); buffer[0] = '\0'; /* DATE_LONGDATE */
- ret = GetDateFormatA(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
ok(strcmp(buffer, "Saturday, May 04, 2002") == 0 ||
strcmp(buffer, "Saturday, May 4, 2002") == 0 /* Win 8 */,
@@ -897,7 +893,7 @@ static void test_GetDateFormatA(void)
/* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
SetLastError(0xdeadbeef);
- ret = GetDateFormatA(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
"Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
EXPECT_EQA;
@@ -906,12 +902,12 @@ static void test_GetDateFormatA(void)
/* and return values */
STRINGSA("m/d/y", ""); /* Invalid flags */
SetLastError(0xdeadbeef);
- ret = GetDateFormatA(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
- &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE, &curtime, input,
+ buffer, ARRAY_SIZE(buffer));
ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
"Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
- ret = GetDateFormatA(lcid_ru, 0, &curtime, "ddMMMM", buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid_ru, 0, &curtime, "ddMMMM", buffer, ARRAY_SIZE(buffer));
if (!ret)
{
win_skip("LANG_RUSSIAN locale data unavailable\n");
@@ -920,37 +916,37 @@ static void test_GetDateFormatA(void)
/* month part should be in genitive form */
strcpy(genitive_month, buffer + 2);
- ret = GetDateFormatA(lcid_ru, 0, &curtime, "MMMM", buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid_ru, 0, &curtime, "MMMM", buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
strcpy(month, buffer);
ok(strcmp(genitive_month, month) != 0, "Expected different month forms\n");
- ret = GetDateFormatA(lcid_ru, 0, &curtime, "ddd", buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid_ru, 0, &curtime, "ddd", buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
strcpy(short_day, buffer);
STRINGSA("dd MMMMddd dd", "");
sprintf(Expected, "04 %s%s 04", genitive_month, short_day);
- ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_EQA;
STRINGSA("MMMMddd dd", "");
sprintf(Expected, "%s%s 04", month, short_day);
- ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_EQA;
STRINGSA("MMMMddd", "");
sprintf(Expected, "%s%s", month, short_day);
- ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_EQA;
STRINGSA("MMMMdd", "");
sprintf(Expected, "%s04", genitive_month);
sprintf(Broken, "%s04", month);
- ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
@@ -959,7 +955,7 @@ static void test_GetDateFormatA(void)
STRINGSA("MMMMdd ddd", "");
sprintf(Expected, "%s04 %s", genitive_month, short_day);
sprintf(Broken, "%s04 %s", month, short_day);
- ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
@@ -967,14 +963,14 @@ static void test_GetDateFormatA(void)
STRINGSA("dd dddMMMM", "");
sprintf(Expected, "04 %s%s", short_day, month);
- ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_EQA;
STRINGSA("dd dddMMMM ddd MMMMdd", "");
sprintf(Expected, "04 %s%s %s %s04", short_day, month, short_day, genitive_month);
sprintf(Broken, "04 %s%s %s %s04", short_day, month, short_day, month);
- ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
@@ -984,7 +980,7 @@ static void test_GetDateFormatA(void)
STRINGSA("ddd',' MMMM dd", "");
sprintf(Expected, "%s, %s 04", short_day, genitive_month);
sprintf(Broken, "%s, %s 04", short_day, month);
- ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
@@ -1005,15 +1001,14 @@ static void test_GetDateFormatEx(void)
STRINGSW("",""); /* If flags are set, then format must be NULL */
SetLastError(0xdeadbeef);
- ret = pGetDateFormatEx(localeW, DATE_LONGDATE, NULL,
- input, buffer, COUNTOF(buffer), NULL);
+ ret = pGetDateFormatEx(localeW, DATE_LONGDATE, NULL, input, buffer, ARRAY_SIZE(buffer), NULL);
ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
"Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
EXPECT_EQW;
STRINGSW("",""); /* NULL buffer, len > 0 */
SetLastError(0xdeadbeef);
- ret = pGetDateFormatEx(localeW, 0, NULL, input, NULL, COUNTOF(buffer), NULL);
+ ret = pGetDateFormatEx(localeW, 0, NULL, input, NULL, ARRAY_SIZE(buffer), NULL);
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
@@ -1039,7 +1034,7 @@ static void test_GetDateFormatEx(void)
curtime.wSecond = 65535; /* Invalid */
curtime.wMilliseconds = 12345;
STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
- ret = pGetDateFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer), NULL);
+ ret = pGetDateFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer), NULL);
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
@@ -1052,7 +1047,7 @@ static void test_GetDateFormatEx(void)
curtime.wSecond = 65535; /* Invalid */
curtime.wMilliseconds = 12345;
STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002");
- ret = pGetDateFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer), emptyW); /* Use reserved arg */
+ ret = pGetDateFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer), emptyW); /* Use reserved arg */
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
@@ -1068,7 +1063,7 @@ static void test_GetDateFormatEx(void)
curtime.wMilliseconds = 0;
STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
SetLastError(0xdeadbeef);
- ret = pGetDateFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer), NULL);
+ ret = pGetDateFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer), NULL);
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
@@ -1082,7 +1077,7 @@ static void test_GetDateFormatEx(void)
curtime.wMilliseconds = 999;
STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
SetLastError(0xdeadbeef);
- ret = pGetDateFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer), NULL);
+ ret = pGetDateFormatEx(localeW, 0, &curtime, input, buffer, ARRAY_SIZE(buffer), NULL);
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
}
@@ -1095,8 +1090,7 @@ static void test_GetDateFormatW(void)
LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
STRINGSW("",""); /* If flags is not zero then format must be NULL */
- ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
- input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL, input, buffer, ARRAY_SIZE(buffer));
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
win_skip("GetDateFormatW is not implemented\n");
@@ -1108,7 +1102,7 @@ static void test_GetDateFormatW(void)
STRINGSW("",""); /* NULL buffer, len > 0 */
SetLastError(0xdeadbeef);
- ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
+ ret = GetDateFormatW (lcid, 0, NULL, input, NULL, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
@@ -1126,7 +1120,7 @@ static void test_GetDateFormatW(void)
curtime.wSecond = 65535; /* Invalid */
curtime.wMilliseconds = 12345;
STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
- ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
@@ -1142,7 +1136,7 @@ static void test_GetDateFormatW(void)
curtime.wMilliseconds = 0;
STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
SetLastError(0xdeadbeef);
- ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
@@ -1156,7 +1150,7 @@ static void test_GetDateFormatW(void)
curtime.wMilliseconds = 999;
STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
SetLastError(0xdeadbeef);
- ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
}
@@ -1181,37 +1175,37 @@ static void test_GetCurrencyFormatA(void)
STRINGSA("23",""); /* NULL output, length > 0 --> Error */
SetLastError(0xdeadbeef);
- ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSA("23,53",""); /* Invalid character --> Error */
SetLastError(0xdeadbeef);
- ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSA("--",""); /* Double '-' --> Error */
SetLastError(0xdeadbeef);
- ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSA("0-",""); /* Trailing '-' --> Error */
SetLastError(0xdeadbeef);
- ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSA("0..",""); /* Double '.' --> Error */
SetLastError(0xdeadbeef);
- ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSA(" 0.1",""); /* Leading space --> Error */
SetLastError(0xdeadbeef);
- ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
@@ -1223,39 +1217,39 @@ static void test_GetCurrencyFormatA(void)
STRINGSA("2353",""); /* Format and flags given --> Error */
SetLastError(0xdeadbeef);
- ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, ARRAY_SIZE(buffer));
ok( !ret, "Expected ret == 0, got %d\n", ret);
ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
STRINGSA("2353",""); /* Invalid format --> Error */
SetLastError(0xdeadbeef);
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSA("2353","$2,353.00"); /* Valid number */
- ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
- ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("2353.1","$2,353.10"); /* Valid real number */
- ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
- ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
- ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
@@ -1269,151 +1263,151 @@ static void test_GetCurrencyFormatA(void)
format.lpCurrencySymbol = szDollar;
STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
STRINGSA("2353","$2353.0");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.Grouping = 2; /* Group by 100's */
STRINGSA("2353","$23,53.0");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("235","$235.0"); /* Grouping of a positive number */
format.Grouping = 3;
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("-235","$-235.0"); /* Grouping of a negative number */
format.NegativeOrder = 2;
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.LeadingZero = 1; /* Always provide leading zero */
STRINGSA(".5","$0.5");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.PositiveOrder = CY_POS_RIGHT;
STRINGSA("1","1.0$");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.PositiveOrder = CY_POS_LEFT_SPACE;
STRINGSA("1","$ 1.0");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.PositiveOrder = CY_POS_RIGHT_SPACE;
STRINGSA("1","1.0 $");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = 0;
STRINGSA("-1","($1.0)");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = 1;
STRINGSA("-1","-$1.0");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = 2;
STRINGSA("-1","$-1.0");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = 3;
STRINGSA("-1","$1.0-");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = 4;
STRINGSA("-1","(1.0$)");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = 5;
STRINGSA("-1","-1.0$");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = 6;
STRINGSA("-1","1.0-$");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = 7;
STRINGSA("-1","1.0$-");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = 8;
STRINGSA("-1","-1.0 $");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = 9;
STRINGSA("-1","-$ 1.0");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = 10;
STRINGSA("-1","1.0 $-");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = 11;
STRINGSA("-1","$ 1.0-");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = 12;
STRINGSA("-1","$ -1.0");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = 13;
STRINGSA("-1","1.0- $");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = 14;
STRINGSA("-1","($ 1.0)");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = 15;
STRINGSA("-1","(1.0 $)");
- ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
}
@@ -1437,37 +1431,37 @@ static void test_GetNumberFormatA(void)
STRINGSA("23",""); /* NULL output, length > 0 --> Error */
SetLastError(0xdeadbeef);
- ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSA("23,53",""); /* Invalid character --> Error */
SetLastError(0xdeadbeef);
- ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSA("--",""); /* Double '-' --> Error */
SetLastError(0xdeadbeef);
- ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSA("0-",""); /* Trailing '-' --> Error */
SetLastError(0xdeadbeef);
- ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSA("0..",""); /* Double '.' --> Error */
SetLastError(0xdeadbeef);
- ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSA(" 0.1",""); /* Leading space --> Error */
SetLastError(0xdeadbeef);
- ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
@@ -1479,44 +1473,44 @@ static void test_GetNumberFormatA(void)
STRINGSA("2353",""); /* Format and flags given --> Error */
SetLastError(0xdeadbeef);
- ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, ARRAY_SIZE(buffer));
ok( !ret, "Expected ret == 0, got %d\n", ret);
ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
STRINGSA("2353",""); /* Invalid format --> Error */
SetLastError(0xdeadbeef);
- ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSA("2353","2,353.00"); /* Valid number */
- ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("-2353","-2,353.00"); /* Valid negative number */
- ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
- ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("2353.1","2,353.10"); /* Valid real number */
- ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
- ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
- ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
@@ -1528,67 +1522,67 @@ static void test_GetNumberFormatA(void)
format.lpThousandSep = szComma;
STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
- ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
STRINGSA("2353","2353.0");
- ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.Grouping = 2; /* Group by 100's */
STRINGSA("2353","23,53.0");
- ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("235","235.0"); /* Grouping of a positive number */
format.Grouping = 3;
- ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
STRINGSA("-235","-235.0"); /* Grouping of a negative number */
format.NegativeOrder = NEG_LEFT;
- ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.LeadingZero = 1; /* Always provide leading zero */
STRINGSA(".5","0.5");
- ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = NEG_PARENS;
STRINGSA("-1","(1.0)");
- ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = NEG_LEFT;
STRINGSA("-1","-1.0");
- ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = NEG_LEFT_SPACE;
STRINGSA("-1","- 1.0");
- ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = NEG_RIGHT;
STRINGSA("-1","1.0-");
- ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
format.NegativeOrder = NEG_RIGHT_SPACE;
STRINGSA("-1","1.0 -");
- ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
@@ -1598,7 +1592,7 @@ static void test_GetNumberFormatA(void)
{
STRINGSA("-12345","-12 345,00"); /* Try French formatting */
Expected[3] = 160; /* Non breaking space */
- ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENA; EXPECT_EQA;
}
@@ -1622,32 +1616,32 @@ static void test_GetNumberFormatEx(void)
}
STRINGSW("23",""); /* NULL output, length > 0 --> Error */
- ret = pGetNumberFormatEx(enW, 0, input, NULL, NULL, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, NULL, NULL, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSW("23,53",""); /* Invalid character --> Error */
- ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSW("--",""); /* Double '-' --> Error */
- ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSW("0-",""); /* Trailing '-' --> Error */
- ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSW("0..",""); /* Double '.' --> Error */
- ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSW(" 0.1",""); /* Leading space --> Error */
- ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
@@ -1657,50 +1651,50 @@ static void test_GetNumberFormatEx(void)
"Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
STRINGSW("23",""); /* Bogus locale --> Error */
- ret = pGetNumberFormatEx(bogusW, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(bogusW, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
memset(&format, 0, sizeof(format));
STRINGSW("2353",""); /* Format and flags given --> Error */
- ret = pGetNumberFormatEx(enW, NUO, input, &format, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, NUO, input, &format, buffer, ARRAY_SIZE(buffer));
ok( !ret, "Expected ret == 0, got %d\n", ret);
ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
STRINGSW("2353",""); /* Invalid format --> Error */
- ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSW("2353","2,353.00"); /* Valid number */
- ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("-2353","-2,353.00"); /* Valid negative number */
- ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("-353","-353.00"); /* test for off by one error in grouping */
- ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("2353.1","2,353.10"); /* Valid real number */
- ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("2353.111","2,353.11"); /* Too many DP --> Truncated */
- ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("2353.119","2,353.12"); /* Too many DP --> Rounded */
- ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
@@ -1712,67 +1706,67 @@ static void test_GetNumberFormatEx(void)
format.lpThousandSep = commaW;
STRINGSW("2353","2353"); /* No decimal or grouping chars expected */
- ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
STRINGSW("2353","2353.0");
- ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
format.Grouping = 2; /* Group by 100's */
STRINGSW("2353","23,53.0");
- ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("235","235.0"); /* Grouping of a positive number */
format.Grouping = 3;
- ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("-235","-235.0"); /* Grouping of a negative number */
format.NegativeOrder = NEG_LEFT;
- ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
format.LeadingZero = 1; /* Always provide leading zero */
STRINGSW(".5","0.5");
- ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
format.NegativeOrder = NEG_PARENS;
STRINGSW("-1","(1.0)");
- ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
format.NegativeOrder = NEG_LEFT;
STRINGSW("-1","-1.0");
- ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
format.NegativeOrder = NEG_LEFT_SPACE;
STRINGSW("-1","- 1.0");
- ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
format.NegativeOrder = NEG_RIGHT;
STRINGSW("-1","1.0-");
- ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
format.NegativeOrder = NEG_RIGHT_SPACE;
STRINGSW("-1","1.0 -");
- ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
@@ -1780,7 +1774,7 @@ static void test_GetNumberFormatEx(void)
{
STRINGSW("-12345","-12 345,00"); /* Try French formatting */
Expected[3] = 160; /* Non breaking space */
- ret = pGetNumberFormatEx(frW, NUO, input, NULL, buffer, COUNTOF(buffer));
+ ret = pGetNumberFormatEx(frW, NUO, input, NULL, buffer, ARRAY_SIZE(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
}
@@ -1849,7 +1843,7 @@ static void test_CompareStringA(void)
char a[256];
LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
- for (i = 0; i < sizeof(comparestringa_data)/sizeof(struct comparestringa_entry); i++)
+ for (i = 0; i < ARRAY_SIZE(comparestringa_data); i++)
{
const struct comparestringa_entry *entry = &comparestringa_data[i];
@@ -2194,11 +2188,11 @@ static void test_CompareStringEx(void)
return;
}
- for (i = 0; i < sizeof(comparestringex_tests)/sizeof(comparestringex_tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(comparestringex_tests); i++)
{
const struct comparestringex_test *e = &comparestringex_tests[i];
- MultiByteToWideChar(CP_ACP, 0, e->locale, -1, locale, sizeof(locale)/sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, e->locale, -1, locale, ARRAY_SIZE(locale));
ret = pCompareStringEx(locale, e->flags, e->first, -1, e->second, -1, NULL, NULL, 0);
todo_wine_if (e->todo)
ok(ret == e->ret || broken(ret == e->broken),
@@ -2258,7 +2252,7 @@ static void test_LCMapStringA(void)
"unexpected error code %d\n", GetLastError());
/* test invalid flag combinations */
- for (i = 0; i < sizeof(lcmap_invalid_flags)/sizeof(lcmap_invalid_flags[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(lcmap_invalid_flags); i++) {
lstrcpyA(buf, "foo");
SetLastError(0xdeadbeef);
ret = LCMapStringA(LOCALE_USER_DEFAULT, lcmap_invalid_flags[i],
@@ -2420,8 +2414,7 @@ static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *f
char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
/* LCMAP_LOWERCASE | LCMAP_UPPERCASE makes LCMAP_TITLECASE, so it's valid now. */
- ret = func_ptr(LCMAP_LOWERCASE | LCMAP_UPPERCASE,
- lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ret = func_ptr(LCMAP_LOWERCASE | LCMAP_UPPERCASE, lower_case, -1, buf, ARRAY_SIZE(buf));
todo_wine ok(ret == lstrlenW(title_case) + 1 || broken(!ret),
"%s ret %d, error %d, expected value %d\n", func_name,
ret, GetLastError(), lstrlenW(title_case) + 1);
@@ -2429,7 +2422,7 @@ static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *f
"Expected title case string\n");
/* test invalid flag combinations */
- for (i = 0; i < sizeof(lcmap_invalid_flags)/sizeof(lcmap_invalid_flags[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(lcmap_invalid_flags); i++) {
lstrcpyW(buf, fooW);
SetLastError(0xdeadbeef);
ret = func_ptr(lcmap_invalid_flags[i],
@@ -2442,22 +2435,19 @@ static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *f
}
/* test LCMAP_LOWERCASE */
- ret = func_ptr(LCMAP_LOWERCASE,
- upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ret = func_ptr(LCMAP_LOWERCASE, upper_case, -1, buf, ARRAY_SIZE(buf));
ok(ret == lstrlenW(upper_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
ret, GetLastError(), lstrlenW(upper_case) + 1);
ok(!lstrcmpW(buf, lower_case), "%s string compare mismatch\n", func_name);
/* test LCMAP_UPPERCASE */
- ret = func_ptr(LCMAP_UPPERCASE,
- lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ret = func_ptr(LCMAP_UPPERCASE, lower_case, -1, buf, ARRAY_SIZE(buf));
ok(ret == lstrlenW(lower_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
ret, GetLastError(), lstrlenW(lower_case) + 1);
ok(!lstrcmpW(buf, upper_case), "%s string compare mismatch\n", func_name);
/* test LCMAP_HIRAGANA */
- ret = func_ptr(LCMAP_HIRAGANA,
- japanese_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ret = func_ptr(LCMAP_HIRAGANA, japanese_text, -1, buf, ARRAY_SIZE(buf));
ok(ret == lstrlenW(hiragana_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
ret, GetLastError(), lstrlenW(hiragana_text) + 1);
ok(!lstrcmpW(buf, hiragana_text), "%s string compare mismatch\n", func_name);
@@ -2471,15 +2461,13 @@ static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *f
"%s expected %04x, got %04x\n", func_name, 0x3095, buf2[0]);
/* test LCMAP_KATAKANA | LCMAP_LOWERCASE */
- ret = func_ptr(LCMAP_KATAKANA | LCMAP_LOWERCASE,
- japanese_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ret = func_ptr(LCMAP_KATAKANA | LCMAP_LOWERCASE, japanese_text, -1, buf, ARRAY_SIZE(buf));
ok(ret == lstrlenW(katakana_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
ret, GetLastError(), lstrlenW(katakana_text) + 1);
ok(!lstrcmpW(buf, katakana_text), "%s string compare mismatch\n", func_name);
/* test LCMAP_FULLWIDTH */
- ret = func_ptr(LCMAP_FULLWIDTH,
- halfwidth_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ret = func_ptr(LCMAP_FULLWIDTH, halfwidth_text, -1, buf, ARRAY_SIZE(buf));
ok(ret == lstrlenW(japanese_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
ret, GetLastError(), lstrlenW(japanese_text) + 1);
ok(!lstrcmpW(buf, japanese_text), "%s string compare mismatch\n", func_name);
@@ -2489,8 +2477,7 @@ static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *f
/* test LCMAP_FULLWIDTH | LCMAP_HIRAGANA
(half-width katakana is converted into full-width hiragana) */
- ret = func_ptr(LCMAP_FULLWIDTH | LCMAP_HIRAGANA,
- halfwidth_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ret = func_ptr(LCMAP_FULLWIDTH | LCMAP_HIRAGANA, halfwidth_text, -1, buf, ARRAY_SIZE(buf));
ok(ret == lstrlenW(hiragana_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
ret, GetLastError(), lstrlenW(hiragana_text) + 1);
ok(!lstrcmpW(buf, hiragana_text), "%s string compare mismatch\n", func_name);
@@ -2499,8 +2486,7 @@ static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *f
ok(ret == ret2, "%s ret %d, expected value %d\n", func_name, ret, ret2);
/* test LCMAP_HALFWIDTH */
- ret = func_ptr(LCMAP_HALFWIDTH,
- japanese_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ret = func_ptr(LCMAP_HALFWIDTH, japanese_text, -1, buf, ARRAY_SIZE(buf));
ok(ret == lstrlenW(halfwidth_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
ret, GetLastError(), lstrlenW(halfwidth_text) + 1);
ok(!lstrcmpW(buf, halfwidth_text), "%s string compare mismatch\n", func_name);
@@ -2525,15 +2511,13 @@ static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *f
/* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
lstrcpyW(buf, lower_case);
- ret = func_ptr(LCMAP_UPPERCASE,
- buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ret = func_ptr(LCMAP_UPPERCASE, buf, -1, buf, ARRAY_SIZE(buf));
ok(ret == lstrlenW(lower_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
ret, GetLastError(), lstrlenW(lower_case) + 1);
ok(!lstrcmpW(buf, upper_case), "%s string compare mismatch\n", func_name);
lstrcpyW(buf, upper_case);
- ret = func_ptr(LCMAP_LOWERCASE,
- buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ret = func_ptr(LCMAP_LOWERCASE, buf, -1, buf, ARRAY_SIZE(buf));
ok(ret == lstrlenW(upper_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
ret, GetLastError(), lstrlenW(lower_case) + 1);
ok(!lstrcmpW(buf, lower_case), "%s string compare mismatch\n", func_name);
@@ -2582,31 +2566,28 @@ static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *f
/* test NORM_IGNORENONSPACE */
lstrcpyW(buf, fooW);
- ret = func_ptr(NORM_IGNORENONSPACE,
- lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ret = func_ptr(NORM_IGNORENONSPACE, lower_case, -1, buf, ARRAY_SIZE(buf));
ok(ret == lstrlenW(lower_case) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
lstrlenW(lower_case) + 1, ret);
ok(!lstrcmpW(buf, lower_case), "%s string comparison mismatch\n", func_name);
/* test NORM_IGNORESYMBOLS */
lstrcpyW(buf, fooW);
- ret = func_ptr(NORM_IGNORESYMBOLS,
- lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ret = func_ptr(NORM_IGNORESYMBOLS, lower_case, -1, buf, ARRAY_SIZE(buf));
ok(ret == lstrlenW(symbols_stripped) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
lstrlenW(symbols_stripped) + 1, ret);
ok(!lstrcmpW(buf, symbols_stripped), "%s string comparison mismatch\n", func_name);
/* test NORM_IGNORESYMBOLS | NORM_IGNORENONSPACE */
lstrcpyW(buf, fooW);
- ret = func_ptr(NORM_IGNORESYMBOLS | NORM_IGNORENONSPACE,
- lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ret = func_ptr(NORM_IGNORESYMBOLS | NORM_IGNORENONSPACE, lower_case, -1, buf, ARRAY_SIZE(buf));
ok(ret == lstrlenW(symbols_stripped) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
lstrlenW(symbols_stripped) + 1, ret);
ok(!lstrcmpW(buf, symbols_stripped), "%s string comparison mismatch\n", func_name);
/* test srclen = 0 */
SetLastError(0xdeadbeef);
- ret = func_ptr(0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
+ ret = func_ptr(0, upper_case, 0, buf, ARRAY_SIZE(buf));
ok(!ret, "%s func_ptr should fail with srclen = 0\n", func_name);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"%s unexpected error code %d\n", func_name, GetLastError());
@@ -2625,7 +2606,7 @@ static void test_LCMapStringW(void)
trace("testing LCMapStringW\n");
SetLastError(0xdeadbeef);
- ret = LCMapStringW((LCID)-1, LCMAP_LOWERCASE, upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ret = LCMapStringW((LCID)-1, LCMAP_LOWERCASE, upper_case, -1, buf, ARRAY_SIZE(buf));
todo_wine {
ok(!ret, "LCMapStringW should fail with bad lcid\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "unexpected error code %d\n", GetLastError());
@@ -2654,7 +2635,7 @@ static void test_LCMapStringEx(void)
SetLastError(0xdeadbeef);
ret = pLCMapStringEx(invalidW, LCMAP_LOWERCASE,
- upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, NULL, 0);
+ upper_case, -1, buf, ARRAY_SIZE(buf), NULL, NULL, 0);
todo_wine {
ok(!ret, "LCMapStringEx should fail with bad locale name\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "unexpected error code %d\n", GetLastError());
@@ -2662,13 +2643,13 @@ static void test_LCMapStringEx(void)
/* test reserved parameters */
ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
- upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, NULL, 1);
+ upper_case, -1, buf, ARRAY_SIZE(buf), NULL, NULL, 1);
ok(ret == lstrlenW(upper_case) + 1, "ret %d, error %d, expected value %d\n",
ret, GetLastError(), lstrlenW(upper_case) + 1);
ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
- upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, (void*)1, 0);
+ upper_case, -1, buf, ARRAY_SIZE(buf), NULL, (void*)1, 0);
ok(ret == lstrlenW(upper_case) + 1, "ret %d, error %d, expected value %d\n",
ret, GetLastError(), lstrlenW(upper_case) + 1);
ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
@@ -2676,7 +2657,7 @@ static void test_LCMapStringEx(void)
/* crashes on native */
if(0)
ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
- upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), (void*)1, NULL, 0);
+ upper_case, -1, buf, ARRAY_SIZE(buf), (void*)1, NULL, 0);
test_lcmapstring_unicode(LCMapStringEx_wrapper, "LCMapStringEx:");
}
@@ -2779,7 +2760,7 @@ static void test_LocaleNameToLCID(void)
wine_dbgstr_w(ptr->name), lcid, ptr->lcid);
*buffer = 0;
- ret = pLCIDToLocaleName(lcid, buffer, sizeof(buffer)/sizeof(WCHAR), 0);
+ ret = pLCIDToLocaleName(lcid, buffer, ARRAY_SIZE(buffer), 0);
ok(ret > 0, "%s: got %d\n", wine_dbgstr_w(ptr->name), ret);
ok(!lstrcmpW(ptr->sname, buffer), "%s: got wrong locale name %s\n",
wine_dbgstr_w(ptr->name), wine_dbgstr_w(buffer));
@@ -2791,12 +2772,13 @@ static void test_LocaleNameToLCID(void)
lcid = pLocaleNameToLCID(zhHantW, 0);
ok(lcid == MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_HONGKONG), SORT_DEFAULT),
"%s: got wrong lcid 0x%04x\n", wine_dbgstr_w(zhHantW), lcid);
- ret = pLCIDToLocaleName(lcid, buffer, sizeof(buffer)/sizeof(WCHAR), 0);
+ ret = pLCIDToLocaleName(lcid, buffer, ARRAY_SIZE(buffer), 0);
ok(ret > 0, "%s: got %d\n", wine_dbgstr_w(zhHantW), ret);
ok(!lstrcmpW(zhhkW, buffer), "%s: got wrong locale name %s\n",
wine_dbgstr_w(zhHantW), wine_dbgstr_w(buffer));
/* check that 0x7c04 also works and is mapped to zh-HK */
- ret = pLCIDToLocaleName(MAKELANGID(LANG_CHINESE_TRADITIONAL, SUBLANG_CHINESE_TRADITIONAL), buffer, sizeof(buffer)/sizeof(WCHAR), 0);
+ ret = pLCIDToLocaleName(MAKELANGID(LANG_CHINESE_TRADITIONAL, SUBLANG_CHINESE_TRADITIONAL),
+ buffer, ARRAY_SIZE(buffer), 0);
todo_wine ok(ret > 0, "%s: got %d\n", wine_dbgstr_w(zhHantW), ret);
ok(!lstrcmpW(zhhkW, buffer), "%s: got wrong locale name %s\n",
wine_dbgstr_w(zhHantW), wine_dbgstr_w(buffer));
@@ -2805,7 +2787,7 @@ static void test_LocaleNameToLCID(void)
lcid = pLocaleNameToLCID(zhhantW, 0);
ok(lcid == MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_HONGKONG), SORT_DEFAULT),
"%s: got wrong lcid 0x%04x\n", wine_dbgstr_w(zhhantW), lcid);
- ret = pLCIDToLocaleName(lcid, buffer, sizeof(buffer)/sizeof(WCHAR), 0);
+ ret = pLCIDToLocaleName(lcid, buffer, ARRAY_SIZE(buffer), 0);
ok(ret > 0, "%s: got %d\n", wine_dbgstr_w(zhhantW), ret);
ok(!lstrcmpW(zhhkW, buffer), "%s: got wrong locale name %s\n",
wine_dbgstr_w(zhhantW), wine_dbgstr_w(buffer));
@@ -2815,12 +2797,12 @@ static void test_LocaleNameToLCID(void)
/* check that LocaleNameToLCID actually returns 0x0804 */
ok(lcid == MAKELCID(MAKELANGID(LANG_CHINESE_SIMPLIFIED, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT),
"%s: got wrong lcid 0x%04x\n", wine_dbgstr_w(zhHansW), lcid);
- ret = pLCIDToLocaleName(lcid, buffer, sizeof(buffer)/sizeof(WCHAR), 0);
+ ret = pLCIDToLocaleName(lcid, buffer, ARRAY_SIZE(buffer), 0);
ok(ret > 0, "%s: got %d\n", wine_dbgstr_w(zhHansW), ret);
ok(!lstrcmpW(zhcnW, buffer), "%s: got wrong locale name %s\n",
wine_dbgstr_w(zhHansW), wine_dbgstr_w(buffer));
/* check that 0x0004 also works and is mapped to zh-CN */
- ret = pLCIDToLocaleName(MAKELANGID(LANG_CHINESE, SUBLANG_NEUTRAL), buffer, sizeof(buffer)/sizeof(WCHAR), 0);
+ ret = pLCIDToLocaleName(MAKELANGID(LANG_CHINESE, SUBLANG_NEUTRAL), buffer, ARRAY_SIZE(buffer), 0);
ok(ret > 0, "%s: got %d\n", wine_dbgstr_w(zhHansW), ret);
ok(!lstrcmpW(zhcnW, buffer), "%s: got wrong locale name %s\n",
wine_dbgstr_w(zhHansW), wine_dbgstr_w(buffer));
@@ -2829,7 +2811,7 @@ static void test_LocaleNameToLCID(void)
lcid = pLocaleNameToLCID(zhhansW, 0);
ok(lcid == MAKELCID(MAKELANGID(LANG_CHINESE_SIMPLIFIED, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT),
"%s: got wrong lcid 0x%04x\n", wine_dbgstr_w(zhhansW), lcid);
- ret = pLCIDToLocaleName(lcid, buffer, sizeof(buffer)/sizeof(WCHAR), 0);
+ ret = pLCIDToLocaleName(lcid, buffer, ARRAY_SIZE(buffer), 0);
ok(ret > 0, "%s: got %d\n", wine_dbgstr_w(zhhansW), ret);
ok(!lstrcmpW(zhcnW, buffer), "%s: got wrong locale name %s\n",
wine_dbgstr_w(zhhansW), wine_dbgstr_w(buffer));
@@ -2938,24 +2920,24 @@ static void test_sorting(void)
/* 1. sort using lstrcmpA */
memcpy(buf, strings, sizeof(strings));
- qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
- for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
+ qsort(buf, ARRAY_SIZE(strings), sizeof(strings[0]), compare_string1);
+ for (i = 0; i < ARRAY_SIZE(strings); i++)
{
ok(!strcmp(strings_sorted[i], str_buf[i]),
"qsort using lstrcmpA failed for element %d\n", i);
}
/* 2. sort using CompareStringA */
memcpy(buf, strings, sizeof(strings));
- qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
- for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
+ qsort(buf, ARRAY_SIZE(strings), sizeof(strings[0]), compare_string2);
+ for (i = 0; i < ARRAY_SIZE(strings); i++)
{
ok(!strcmp(strings_sorted[i], str_buf[i]),
"qsort using CompareStringA failed for element %d\n", i);
}
/* 3. sort using sort keys */
memcpy(buf, strings, sizeof(strings));
- qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
- for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
+ qsort(buf, ARRAY_SIZE(strings), sizeof(strings[0]), compare_string3);
+ for (i = 0; i < ARRAY_SIZE(strings); i++)
{
ok(!strcmp(strings_sorted[i], str_buf[i]),
"qsort using sort keys failed for element %d\n", i);
@@ -3333,7 +3315,7 @@ static void test_FoldStringW(void)
}
/* Invalid flag combinations */
- for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(badFlags); i++)
{
src[0] = dst[0] = '\0';
SetLastError(0);
@@ -3395,7 +3377,7 @@ static void test_FoldStringW(void)
'A','X', ret, dst[0], dst[1], GetLastError());
/* MAP_FOLDDIGITS */
- for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
+ for (j = 0; j < ARRAY_SIZE(digitRanges); j++)
{
/* Check everything before this range */
for (ch = prev_ch; ch < digitRanges[j]; ch++)
@@ -3447,14 +3429,12 @@ static void test_FoldStringW(void)
/* MAP_FOLDCZONE */
SetLastError(0);
ret = pFoldStringW(MAP_FOLDCZONE, foldczone_src, -1, dst, 256);
- ok(ret == sizeof(foldczone_dst)/sizeof(foldczone_dst[0]),
- "Got %d, error %d\n", ret, GetLastError());
+ ok(ret == ARRAY_SIZE(foldczone_dst), "Got %d, error %d\n", ret, GetLastError());
ok(!memcmp(dst, foldczone_dst, sizeof(foldczone_dst)),
"MAP_FOLDCZONE: Expanded incorrectly\n");
ret = pFoldStringW(MAP_FOLDCZONE|MAP_PRECOMPOSED, foldczone_todo_src, -1, dst, 256);
- todo_wine ok(ret == sizeof(foldczone_todo_dst)/sizeof(foldczone_todo_dst[0]),
- "Got %d, error %d\n", ret, GetLastError());
+ todo_wine ok(ret == ARRAY_SIZE(foldczone_todo_dst), "Got %d, error %d\n", ret, GetLastError());
todo_wine ok(!memcmp(dst, foldczone_todo_dst, sizeof(foldczone_todo_dst))
|| broken(!memcmp(dst, foldczone_todo_broken_dst, sizeof(foldczone_todo_broken_dst))),
"MAP_FOLDCZONE: Expanded incorrectly (%s)\n", wine_dbgstr_w(dst));
@@ -3464,8 +3444,7 @@ static void test_FoldStringW(void)
ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
/* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
- ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
- "Got %d, error %d\n", ret, GetLastError());
+ ok(ret == ARRAY_SIZE(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
"MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
}
@@ -3866,7 +3845,7 @@ static void test_EnumTimeFormatsW(void)
date_fmt_bufW[0] = 0;
ret = EnumTimeFormatsW(enum_datetime_procW, lcid, 0);
ok(ret, "EnumTimeFormatsW(0) error %d\n", GetLastError());
- ret = GetLocaleInfoW(lcid, LOCALE_STIMEFORMAT, bufW, sizeof(bufW)/sizeof(bufW[0]));
+ ret = GetLocaleInfoW(lcid, LOCALE_STIMEFORMAT, bufW, ARRAY_SIZE(bufW));
ok(ret, "GetLocaleInfoW(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
ok(!lstrcmpW(date_fmt_bufW, bufW), "expected \"%s\" got \"%s\"\n", wine_dbgstr_w(date_fmt_bufW),
wine_dbgstr_w(bufW));
@@ -3874,7 +3853,7 @@ static void test_EnumTimeFormatsW(void)
date_fmt_bufW[0] = 0;
ret = EnumTimeFormatsW(enum_datetime_procW, lcid, LOCALE_USE_CP_ACP);
ok(ret, "EnumTimeFormatsW(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
- ret = GetLocaleInfoW(lcid, LOCALE_STIMEFORMAT, bufW, sizeof(bufW)/sizeof(bufW[0]));
+ ret = GetLocaleInfoW(lcid, LOCALE_STIMEFORMAT, bufW, ARRAY_SIZE(bufW));
ok(ret, "GetLocaleInfoW(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
ok(!lstrcmpW(date_fmt_bufW, bufW), "expected \"%s\" got \"%s\"\n", wine_dbgstr_w(date_fmt_bufW),
wine_dbgstr_w(bufW));
@@ -3888,7 +3867,7 @@ static void test_EnumTimeFormatsW(void)
char buf[256];
ok(ret, "EnumTimeFormatsW(TIME_NOSECONDS) error %d\n", GetLastError());
- ret = GetLocaleInfoW(lcid, LOCALE_SSHORTTIME, bufW, sizeof(bufW)/sizeof(bufW[0]));
+ ret = GetLocaleInfoW(lcid, LOCALE_SSHORTTIME, bufW, ARRAY_SIZE(bufW));
ok(ret, "GetLocaleInfoW(LOCALE_SSHORTTIME) error %d\n", GetLastError());
ok(!lstrcmpW(date_fmt_bufW, bufW), "expected \"%s\" got \"%s\"\n", wine_dbgstr_w(date_fmt_bufW),
wine_dbgstr_w(bufW));
@@ -3903,7 +3882,7 @@ static void test_EnumTimeFormatsW(void)
GetLastError());
/* And it's not supported by GetLocaleInfoA either */
- ret = GetLocaleInfoA(lcid, LOCALE_SSHORTTIME, buf, sizeof(buf)/sizeof(buf[0]));
+ ret = GetLocaleInfoA(lcid, LOCALE_SSHORTTIME, buf, ARRAY_SIZE(buf));
ok(!ret && GetLastError() == ERROR_INVALID_FLAGS, "GetLocaleInfoA(LOCALE_SSHORTTIME) ret %d, error %d\n", ret,
GetLastError());
}
@@ -4241,28 +4220,25 @@ static void test_IdnToNameprepUnicode(void)
ok(err == test_data[1].err, "err = %d\n", err);
SetLastError(0xdeadbeef);
- ret = pIdnToNameprepUnicode(0, test_data[0].in, -1,
- buf, sizeof(buf)/sizeof(WCHAR));
+ ret = pIdnToNameprepUnicode(0, test_data[0].in, -1, buf, ARRAY_SIZE(buf));
err = GetLastError();
ok(ret == test_data[0].ret, "ret = %d\n", ret);
ok(err == 0xdeadbeef, "err = %d\n", err);
SetLastError(0xdeadbeef);
- ret = pIdnToNameprepUnicode(0, test_data[0].in, -2,
- buf, sizeof(buf)/sizeof(WCHAR));
+ ret = pIdnToNameprepUnicode(0, test_data[0].in, -2, buf, ARRAY_SIZE(buf));
err = GetLastError();
ok(ret == 0, "ret = %d\n", ret);
ok(err == ERROR_INVALID_PARAMETER, "err = %d\n", err);
SetLastError(0xdeadbeef);
- ret = pIdnToNameprepUnicode(0, test_data[0].in, 0,
- buf, sizeof(buf)/sizeof(WCHAR));
+ ret = pIdnToNameprepUnicode(0, test_data[0].in, 0, buf, ARRAY_SIZE(buf));
err = GetLastError();
ok(ret == 0, "ret = %d\n", ret);
ok(err == ERROR_INVALID_NAME, "err = %d\n", err);
ret = pIdnToNameprepUnicode(IDN_ALLOW_UNASSIGNED|IDN_USE_STD3_ASCII_RULES,
- test_data[0].in, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ test_data[0].in, -1, buf, ARRAY_SIZE(buf));
ok(ret == test_data[0].ret, "ret = %d\n", ret);
SetLastError(0xdeadbeef);
@@ -4278,11 +4254,11 @@ static void test_IdnToNameprepUnicode(void)
ok(err == ERROR_INVALID_FLAGS || err == ERROR_INVALID_PARAMETER /* Win8 */,
"err = %d\n", err);
- for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
+ for (i=0; i<ARRAY_SIZE(test_data); i++)
{
SetLastError(0xdeadbeef);
- ret = pIdnToNameprepUnicode(test_data[i].flags, test_data[i].in,
- test_data[i].in_len, buf, sizeof(buf)/sizeof(WCHAR));
+ ret = pIdnToNameprepUnicode(test_data[i].flags, test_data[i].in, test_data[i].in_len,
+ buf, ARRAY_SIZE(buf));
err = GetLastError();
todo_wine_if (test_data[i].todo)
@@ -4355,7 +4331,7 @@ static void test_IdnToAscii(void)
return;
}
- for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
+ for (i=0; i<ARRAY_SIZE(test_data); i++)
{
SetLastError(0xdeadbeef);
ret = pIdnToAscii(test_data[i].flags, test_data[i].in,
@@ -4427,7 +4403,7 @@ static void test_IdnToUnicode(void)
return;
}
- for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
+ for (i=0; i<ARRAY_SIZE(test_data); i++)
{
ret = pIdnToUnicode(test_data[i].flags, test_data[i].in,
test_data[i].in_len, NULL, 0);
@@ -4456,7 +4432,7 @@ static void test_GetLocaleInfoEx(void)
return;
}
- ret = pGetLocaleInfoEx(enW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
+ ret = pGetLocaleInfoEx(enW, LOCALE_SNAME, bufferW, ARRAY_SIZE(bufferW));
ok(ret || broken(ret == 0) /* Vista */, "got %d\n", ret);
if (ret)
{
@@ -4479,31 +4455,31 @@ static void test_GetLocaleInfoEx(void)
ret = pGetLocaleInfoEx(enW, LOCALE_SNAME, NULL, 0);
ok(ret == 3 && GetLastError() == 0xdeadbeef, "got %d, %d\n", ret, GetLastError());
- ret = pGetLocaleInfoEx(enusW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
+ ret = pGetLocaleInfoEx(enusW, LOCALE_SNAME, bufferW, ARRAY_SIZE(bufferW));
ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
ok(!lstrcmpW(bufferW, enusW), "got %s\n", wine_dbgstr_w(bufferW));
- ret = pGetLocaleInfoEx(enW, LOCALE_SABBREVCTRYNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
+ ret = pGetLocaleInfoEx(enW, LOCALE_SABBREVCTRYNAME, bufferW, ARRAY_SIZE(bufferW));
ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
ok(!lstrcmpW(bufferW, usaW), "got %s\n", wine_dbgstr_w(bufferW));
- ret = pGetLocaleInfoEx(enW, LOCALE_SABBREVLANGNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
+ ret = pGetLocaleInfoEx(enW, LOCALE_SABBREVLANGNAME, bufferW, ARRAY_SIZE(bufferW));
ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
ok(!lstrcmpW(bufferW, enuW), "got %s\n", wine_dbgstr_w(bufferW));
- ret = pGetLocaleInfoEx(enusW, LOCALE_SPARENT, bufferW, sizeof(bufferW)/sizeof(WCHAR));
+ ret = pGetLocaleInfoEx(enusW, LOCALE_SPARENT, bufferW, ARRAY_SIZE(bufferW));
ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
ok(!lstrcmpW(bufferW, enW), "got %s\n", wine_dbgstr_w(bufferW));
- ret = pGetLocaleInfoEx(enW, LOCALE_SPARENT, bufferW, sizeof(bufferW)/sizeof(WCHAR));
+ ret = pGetLocaleInfoEx(enW, LOCALE_SPARENT, bufferW, ARRAY_SIZE(bufferW));
ok(ret == 1, "got %d\n", ret);
ok(!bufferW[0], "got %s\n", wine_dbgstr_w(bufferW));
- ret = pGetLocaleInfoEx(enW, LOCALE_SPARENT | LOCALE_NOUSEROVERRIDE, bufferW, sizeof(bufferW)/sizeof(WCHAR));
+ ret = pGetLocaleInfoEx(enW, LOCALE_SPARENT | LOCALE_NOUSEROVERRIDE, bufferW, ARRAY_SIZE(bufferW));
ok(ret == 1, "got %d\n", ret);
ok(!bufferW[0], "got %s\n", wine_dbgstr_w(bufferW));
- ret = pGetLocaleInfoEx(enW, LOCALE_SCOUNTRY, bufferW, sizeof(bufferW)/sizeof(WCHAR));
+ ret = pGetLocaleInfoEx(enW, LOCALE_SCOUNTRY, bufferW, ARRAY_SIZE(bufferW));
ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
if ((PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) != LANG_ENGLISH) ||
(PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH))
@@ -4515,7 +4491,7 @@ static void test_GetLocaleInfoEx(void)
bufferW[0] = 0;
SetLastError(0xdeadbeef);
- ret = pGetLocaleInfoEx(dummyW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
+ ret = pGetLocaleInfoEx(dummyW, LOCALE_SNAME, bufferW, ARRAY_SIZE(bufferW));
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
while (*ptr->name)
@@ -4525,15 +4501,15 @@ static void test_GetLocaleInfoEx(void)
todo_wine_if (ptr->todo)
ok(val == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n", wine_dbgstr_w(ptr->name), val, ptr->lcid);
bufferW[0] = 0;
- ret = pGetLocaleInfoEx(ptr->name, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
+ ret = pGetLocaleInfoEx(ptr->name, LOCALE_SNAME, bufferW, ARRAY_SIZE(bufferW));
ok(ret == lstrlenW(bufferW)+1, "%s: got ret value %d\n", wine_dbgstr_w(ptr->name), ret);
ok(!lstrcmpW(bufferW, ptr->name), "%s: got wrong LOCALE_SNAME %s\n", wine_dbgstr_w(ptr->name), wine_dbgstr_w(bufferW));
ptr++;
}
- ret = pGetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
+ ret = pGetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, bufferW, ARRAY_SIZE(bufferW));
ok(ret && ret == lstrlenW(bufferW)+1, "got ret value %d\n", ret);
- ret = GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_SNAME, buffer2, sizeof(buffer2)/sizeof(WCHAR));
+ ret = GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_SNAME, buffer2, ARRAY_SIZE(buffer2));
ok(ret && ret == lstrlenW(buffer2)+1, "got ret value %d\n", ret);
ok(!lstrcmpW(bufferW, buffer2), "LOCALE_SNAMEs don't match %s %s\n", wine_dbgstr_w(bufferW), wine_dbgstr_w(buffer2));
}
@@ -5367,18 +5343,18 @@ static void test_FindNLSStringEx(void)
static struct test_data test_arr[] =
{
- { localeW, FIND_FROMSTART, en_simpsimpW, sizeof(en_simpsimpW)/sizeof(WCHAR)-1,
- en_simpW, sizeof(en_simpW)/sizeof(WCHAR)-1, 0, 0, 6, 0, FALSE},
- { localeW, FIND_FROMEND, en_simpsimpW, sizeof(en_simpsimpW)/sizeof(WCHAR)-1,
- en_simpW, sizeof(en_simpW)/sizeof(WCHAR)-1, 0, 6, 6, 0, FALSE},
- { localeW, FIND_STARTSWITH, en_simpsimpW, sizeof(en_simpsimpW)/sizeof(WCHAR)-1,
- en_simpW, sizeof(en_simpW)/sizeof(WCHAR)-1, 0, 0, 6, 0, FALSE},
- { localeW, FIND_ENDSWITH, en_simpsimpW, sizeof(en_simpsimpW)/sizeof(WCHAR)-1,
- en_simpW, sizeof(en_simpW)/sizeof(WCHAR)-1, 0, 6, 6, 0, FALSE},
- { localeW, FIND_FROMSTART, comb_s_accent1W, sizeof(comb_s_accent1W)/sizeof(WCHAR)-1,
- comb_s_accent2W, sizeof(comb_s_accent2W)/sizeof(WCHAR)-1, 0, 0, 6, 1, TRUE },
- { localeW, FIND_FROMSTART, comb_q_accent1W, sizeof(comb_q_accent1W)/sizeof(WCHAR)-1,
- comb_q_accent2W, sizeof(comb_q_accent2W)/sizeof(WCHAR)-1, 0, 0, 7, 1, FALSE },
+ { localeW, FIND_FROMSTART, en_simpsimpW, ARRAY_SIZE(en_simpsimpW)-1,
+ en_simpW, ARRAY_SIZE(en_simpW)-1, 0, 0, 6, 0, FALSE},
+ { localeW, FIND_FROMEND, en_simpsimpW, ARRAY_SIZE(en_simpsimpW)-1,
+ en_simpW, ARRAY_SIZE(en_simpW)-1, 0, 6, 6, 0, FALSE},
+ { localeW, FIND_STARTSWITH, en_simpsimpW, ARRAY_SIZE(en_simpsimpW)-1,
+ en_simpW, ARRAY_SIZE(en_simpW)-1, 0, 0, 6, 0, FALSE},
+ { localeW, FIND_ENDSWITH, en_simpsimpW, ARRAY_SIZE(en_simpsimpW)-1,
+ en_simpW, ARRAY_SIZE(en_simpW)-1, 0, 6, 6, 0, FALSE},
+ { localeW, FIND_FROMSTART, comb_s_accent1W, ARRAY_SIZE(comb_s_accent1W)-1,
+ comb_s_accent2W, ARRAY_SIZE(comb_s_accent2W)-1, 0, 0, 6, 1, TRUE },
+ { localeW, FIND_FROMSTART, comb_q_accent1W, ARRAY_SIZE(comb_q_accent1W)-1,
+ comb_q_accent2W, ARRAY_SIZE(comb_q_accent2W)-1, 0, 0, 7, 1, FALSE },
{ 0 }
};
struct test_data *ptest;
--
2.14.4
June 22, 2018
Re: [PATCH] wininet/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Sorry about this one, sent the wrong (old) patch out.
bye
michael
On 06/22/2018 07:02 PM, Michael Stefaniuc wrote:
> Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
> ---
> dlls/wininet/tests/ftp.c | 2 +-
> dlls/wininet/tests/http.c | 10 ++++-----
> dlls/wininet/tests/internet.c | 16 ++++++-------
> dlls/wininet/tests/url.c | 52 +++++++++++++++++++++----------------------
> dlls/wininet/tests/urlcache.c | 4 ++--
> 5 files changed, 42 insertions(+), 42 deletions(-)
>
> diff --git a/dlls/wininet/tests/ftp.c b/dlls/wininet/tests/ftp.c
> index d2118faded..6f50104f3b 100644
> --- a/dlls/wininet/tests/ftp.c
> +++ b/dlls/wininet/tests/ftp.c
> @@ -735,7 +735,7 @@ static void test_command(HINTERNET hFtp, HINTERNET hConnect)
> return;
> }
>
> - for (i = 0; i < sizeof(command_test) / sizeof(command_test[0]); i++)
> + for (i = 0; i < ARRAY_SIZE(command_test); i++)
> {
> SetLastError(0xdeadbeef);
> ret = pFtpCommandA(hFtp, FALSE, FTP_TRANSFER_TYPE_ASCII, command_test[i].cmd, 0, NULL);
> diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c
> index 0524ddf3fd..ace8512399 100644
> --- a/dlls/wininet/tests/http.c
> +++ b/dlls/wininet/tests/http.c
> @@ -172,7 +172,7 @@ static BOOL (WINAPI *pInternetGetSecurityInfoByURLA)(LPSTR,PCCERT_CHAIN_CONTEXT*
> static int strcmp_wa(LPCWSTR strw, const char *stra)
> {
> WCHAR buf[512];
> - MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(WCHAR));
> + MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, ARRAY_SIZE(buf));
> return lstrcmpW(strw, buf);
> }
>
> @@ -4204,7 +4204,7 @@ static void test_http_status(int port)
> DWORD i, size;
> BOOL res;
>
> - for(i=0; i < sizeof(http_status_tests)/sizeof(*http_status_tests); i++) {
> + for(i = 0; i < ARRAY_SIZE(http_status_tests); i++) {
> send_buffer = http_status_tests[i].response_text;
>
> open_simple_request(&req, "localhost", port, NULL, "/send_from_buffer");
> @@ -6543,14 +6543,14 @@ static const struct notification async_send_request_ex_chunked_test[] =
> static const struct notification_data notification_data[] = {
> {
> async_send_request_ex_chunked_test,
> - sizeof(async_send_request_ex_chunked_test)/sizeof(async_send_request_ex_chunked_test[0]),
> + ARRAY_SIZE(async_send_request_ex_chunked_test),
> "GET",
> "test.winehq.org",
> "tests/data.php"
> },
> {
> async_send_request_ex_test,
> - sizeof(async_send_request_ex_test)/sizeof(async_send_request_ex_test[0]),
> + ARRAY_SIZE(async_send_request_ex_test),
> "POST",
> "test.winehq.org",
> "tests/post.php",
> @@ -6565,7 +6565,7 @@ static const struct notification_data notification_data[] = {
> },
> {
> async_send_request_ex_resolve_failure_test,
> - sizeof(async_send_request_ex_resolve_failure_test)/sizeof(async_send_request_ex_resolve_failure_test[0]),
> + ARRAY_SIZE(async_send_request_ex_resolve_failure_test),
> "GET",
> "brokenhost",
> "index.html",
> diff --git a/dlls/wininet/tests/internet.c b/dlls/wininet/tests/internet.c
> index 39c698f5db..7889e40ea8 100644
> --- a/dlls/wininet/tests/internet.c
> +++ b/dlls/wininet/tests/internet.c
> @@ -629,7 +629,7 @@ static void test_cookie_url(void)
> ok(!res && GetLastError() == ERROR_INVALID_PARAMETER,
> "InternetGetCookeA failed: %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
>
> - len = sizeof(bufw)/sizeof(*bufw);
> + len = ARRAY_SIZE(bufw);
> res = InternetGetCookieW(about_blankW, NULL, bufw, &len);
> ok(!res && GetLastError() == ERROR_INVALID_PARAMETER,
> "InternetGetCookeW failed: %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
> @@ -639,7 +639,7 @@ static void test_cookie_url(void)
> ok(!res && GetLastError() == ERROR_INVALID_PARAMETER,
> "InternetGetCookeExA failed: %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
>
> - len = sizeof(bufw)/sizeof(*bufw);
> + len = ARRAY_SIZE(bufw);
> res = pInternetGetCookieExW(about_blankW, NULL, bufw, &len, 0, NULL);
> ok(!res && GetLastError() == ERROR_INVALID_PARAMETER,
> "InternetGetCookeExW failed: %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
> @@ -887,7 +887,7 @@ static void InternetTimeFromSystemTimeW_test(void)
>
> /* test too small buffer size */
> SetLastError(0xdeadbeef);
> - ret = pInternetTimeFromSystemTimeW( &time, INTERNET_RFC1123_FORMAT, string, sizeof(string)/sizeof(string[0]) );
> + ret = pInternetTimeFromSystemTimeW( &time, INTERNET_RFC1123_FORMAT, string, ARRAY_SIZE(string));
> error = GetLastError();
> ok( !ret, "InternetTimeFromSystemTimeW should have returned FALSE\n" );
> ok( error == ERROR_INSUFFICIENT_BUFFER,
> @@ -1084,7 +1084,7 @@ static void test_PrivacyGetSetZonePreferenceW(void)
> trace("template %u\n", old_template);
>
> if(old_template == PRIVACY_TEMPLATE_ADVANCED) {
> - pref_size = sizeof(pref)/sizeof(WCHAR);
> + pref_size = ARRAY_SIZE(pref);
> ret = pPrivacyGetZonePreferenceW(zone, type, &old_template, pref, &pref_size);
> ok(ret == 0, "expected ret == 0, got %u\n", ret);
> }
> @@ -1721,7 +1721,7 @@ static void test_InternetGetConnectedStateExW(void)
>
> flags = 0;
> buffer[0] = 0;
> - res = pInternetGetConnectedStateExW(&flags, buffer, sizeof(buffer) / sizeof(buffer[0]), 0);
> + res = pInternetGetConnectedStateExW(&flags, buffer, ARRAY_SIZE(buffer), 0);
> trace("Internet Connection: Flags 0x%02x - Name '%s'\n", flags, wine_dbgstr_w(buffer));
> todo_wine
> ok (flags & INTERNET_RAS_INSTALLED, "Missing RAS flag\n");
> @@ -1755,21 +1755,21 @@ todo_wine
> ok(!buffer[0], "Buffer must not change, got %02X\n", buffer[0]);
>
> buffer[0] = 0;
> - res = pInternetGetConnectedStateExW(NULL, buffer, sizeof(buffer) / sizeof(buffer[0]), 0);
> + res = pInternetGetConnectedStateExW(NULL, buffer, ARRAY_SIZE(buffer), 0);
> ok(res == TRUE, "Expected TRUE, got %d\n", res);
> sz = lstrlenW(buffer);
> ok(sz > 0, "Expected a connection name\n");
>
> buffer[0] = 0;
> flags = 0;
> - res = pInternetGetConnectedStateExW(&flags, buffer, sizeof(buffer) / sizeof(buffer[0]), 0);
> + res = pInternetGetConnectedStateExW(&flags, buffer, ARRAY_SIZE(buffer), 0);
> ok(res == TRUE, "Expected TRUE, got %d\n", res);
> ok(flags, "Expected at least one flag set\n");
> sz = lstrlenW(buffer);
> ok(sz > 0, "Expected a connection name\n");
>
> flags = 0;
> - res = pInternetGetConnectedStateExW(&flags, NULL, sizeof(buffer) / sizeof(buffer[0]), 0);
> + res = pInternetGetConnectedStateExW(&flags, NULL, ARRAY_SIZE(buffer), 0);
> ok(res == TRUE, "Expected TRUE, got %d\n", res);
> ok(flags, "Expected at least one flag set\n");
>
> diff --git a/dlls/wininet/tests/url.c b/dlls/wininet/tests/url.c
> index 0af58358eb..18c77b6647 100644
> --- a/dlls/wininet/tests/url.c
> +++ b/dlls/wininet/tests/url.c
> @@ -672,17 +672,17 @@ static void InternetCrackUrlW_test(void)
> memset(&comp, 0, sizeof comp);
> comp.dwStructSize = sizeof(comp);
> comp.lpszScheme = scheme;
> - comp.dwSchemeLength = sizeof(scheme)/sizeof(scheme[0]);
> + comp.dwSchemeLength = ARRAY_SIZE(scheme);
> comp.lpszHostName = host;
> - comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
> + comp.dwHostNameLength = ARRAY_SIZE(host);
> comp.lpszUserName = user;
> - comp.dwUserNameLength = sizeof(user)/sizeof(user[0]);
> + comp.dwUserNameLength = ARRAY_SIZE(user);
> comp.lpszPassword = pwd;
> - comp.dwPasswordLength = sizeof(pwd)/sizeof(pwd[0]);
> + comp.dwPasswordLength = ARRAY_SIZE(pwd);
> comp.lpszUrlPath = urlpart;
> - comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
> + comp.dwUrlPathLength = ARRAY_SIZE(urlpart);
> comp.lpszExtraInfo = extra;
> - comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
> + comp.dwExtraInfoLength = ARRAY_SIZE(extra);
>
> SetLastError(0xdeadbeef);
> r = InternetCrackUrlW(NULL, 0, 0, &comp );
> @@ -721,9 +721,9 @@ static void InternetCrackUrlW_test(void)
> memset(&comp, 0, sizeof comp);
> comp.dwStructSize = sizeof comp;
> comp.lpszHostName = host;
> - comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
> + comp.dwHostNameLength = ARRAY_SIZE(host);
> comp.lpszUrlPath = urlpart;
> - comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
> + comp.dwUrlPathLength = ARRAY_SIZE(urlpart);
>
> r = InternetCrackUrlW(url, 0, 0, &comp );
> ok( r, "failed to crack url\n");
> @@ -739,11 +739,11 @@ static void InternetCrackUrlW_test(void)
> memset(&comp, 0, sizeof comp);
> comp.dwStructSize = sizeof comp;
> comp.lpszHostName = host;
> - comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
> + comp.dwHostNameLength = ARRAY_SIZE(host);
> comp.lpszUrlPath = urlpart;
> - comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
> + comp.dwUrlPathLength = ARRAY_SIZE(urlpart);
> comp.lpszExtraInfo = NULL;
> - comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
> + comp.dwExtraInfoLength = ARRAY_SIZE(extra);
>
> r = InternetCrackUrlW(url, 0, 0, &comp );
> ok( r, "failed to crack url\n");
> @@ -763,17 +763,17 @@ static void InternetCrackUrlW_test(void)
> memset(&comp, 0, sizeof(comp));
> comp.dwStructSize = sizeof(comp);
> comp.lpszScheme = scheme;
> - comp.dwSchemeLength = sizeof(scheme)/sizeof(scheme[0]);
> + comp.dwSchemeLength = ARRAY_SIZE(scheme);
> comp.lpszHostName = host;
> - comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
> + comp.dwHostNameLength = ARRAY_SIZE(host);
> comp.lpszUserName = user;
> - comp.dwUserNameLength = sizeof(user)/sizeof(user[0]);
> + comp.dwUserNameLength = ARRAY_SIZE(user);
> comp.lpszPassword = pwd;
> - comp.dwPasswordLength = sizeof(pwd)/sizeof(pwd[0]);
> + comp.dwPasswordLength = ARRAY_SIZE(pwd);
> comp.lpszUrlPath = urlpart;
> - comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
> + comp.dwUrlPathLength = ARRAY_SIZE(urlpart);
> comp.lpszExtraInfo = extra;
> - comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
> + comp.dwExtraInfoLength = ARRAY_SIZE(extra);
>
> r = InternetCrackUrlW(url2, 0, 0, &comp);
> ok(!r, "InternetCrackUrl should have failed\n");
> @@ -791,17 +791,17 @@ static void InternetCrackUrlW_test(void)
> memset(&comp, 0, sizeof comp);
> comp.dwStructSize = sizeof comp;
> comp.lpszScheme = scheme;
> - comp.dwSchemeLength = sizeof(scheme)/sizeof(scheme[0]);
> + comp.dwSchemeLength = ARRAY_SIZE(scheme);
> comp.lpszHostName = host;
> - comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
> + comp.dwHostNameLength = ARRAY_SIZE(host);
> comp.lpszUserName = user;
> - comp.dwUserNameLength = sizeof(user)/sizeof(user[0]);
> + comp.dwUserNameLength = ARRAY_SIZE(user);
> comp.lpszPassword = pwd;
> - comp.dwPasswordLength = sizeof(pwd)/sizeof(pwd[0]);
> + comp.dwPasswordLength = ARRAY_SIZE(pwd);
> comp.lpszUrlPath = urlpart;
> - comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
> + comp.dwUrlPathLength = ARRAY_SIZE(urlpart);
> comp.lpszExtraInfo = extra;
> - comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
> + comp.dwExtraInfoLength = ARRAY_SIZE(extra);
> r = InternetCrackUrlW(url3, 0, 0, &comp );
> ok( r, "InternetCrackUrlW failed unexpectedly\n");
> ok( host[0] == 'x', "host should be x.org\n");
> @@ -812,9 +812,9 @@ static void InternetCrackUrlW_test(void)
> memset(&comp, 0, sizeof(comp));
> comp.dwStructSize = sizeof(comp);
> comp.lpszHostName = host;
> - comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
> + comp.dwHostNameLength = ARRAY_SIZE(host);
> comp.lpszUrlPath = urlpart;
> - comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
> + comp.dwUrlPathLength = ARRAY_SIZE(urlpart);
> r = InternetCrackUrlW(url3, 0, ICU_DECODE, &comp);
> todo_wine ok(r, "InternetCrackUrlW failed unexpectedly\n");
> todo_wine ok(!strcmp_wa(host, "x.org"), "host is %s, should be x.org\n", wine_dbgstr_w(host));
> @@ -1224,7 +1224,7 @@ START_TEST(url)
> return;
> }
>
> - for(i=0; i < sizeof(crack_url_tests)/sizeof(*crack_url_tests); i++)
> + for(i = 0; i < ARRAY_SIZE(crack_url_tests); i++)
> test_crack_url(crack_url_tests+i);
>
> test_long_url();
> diff --git a/dlls/wininet/tests/urlcache.c b/dlls/wininet/tests/urlcache.c
> index 310054b6a7..3799500489 100644
> --- a/dlls/wininet/tests/urlcache.c
> +++ b/dlls/wininet/tests/urlcache.c
> @@ -891,13 +891,13 @@ static void test_urlcacheW(void)
>
> if(ie10_cache) {
> if(!MultiByteToWideChar(CP_ACP, 0, urls[6].encoded_url, -1,
> - urls[6].url, sizeof(urls[6].url)/sizeof(WCHAR)))
> + urls[6].url, ARRAY_SIZE(urls[6].url)))
> urls[6].url[0] = 0;
>
> trace("converted url in test 6: %s\n", wine_dbgstr_w(urls[6].url));
> }
>
> - for(i=0; i<sizeof(urls)/sizeof(*urls); i++) {
> + for(i=0; i<ARRAY_SIZE(urls); i++) {
> INTERNET_CACHE_ENTRY_INFOA *entry_infoA;
> INTERNET_CACHE_ENTRY_INFOW *entry_infoW;
> DWORD size;
>
June 22, 2018
[PATCH] wininet/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/wininet/tests/ftp.c | 2 +-
dlls/wininet/tests/http.c | 10 ++++-----
dlls/wininet/tests/internet.c | 16 ++++++-------
dlls/wininet/tests/url.c | 52 +++++++++++++++++++++----------------------
dlls/wininet/tests/urlcache.c | 4 ++--
5 files changed, 42 insertions(+), 42 deletions(-)
diff --git a/dlls/wininet/tests/ftp.c b/dlls/wininet/tests/ftp.c
index d2118faded..6f50104f3b 100644
--- a/dlls/wininet/tests/ftp.c
+++ b/dlls/wininet/tests/ftp.c
@@ -735,7 +735,7 @@ static void test_command(HINTERNET hFtp, HINTERNET hConnect)
return;
}
- for (i = 0; i < sizeof(command_test) / sizeof(command_test[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(command_test); i++)
{
SetLastError(0xdeadbeef);
ret = pFtpCommandA(hFtp, FALSE, FTP_TRANSFER_TYPE_ASCII, command_test[i].cmd, 0, NULL);
diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c
index 0524ddf3fd..ace8512399 100644
--- a/dlls/wininet/tests/http.c
+++ b/dlls/wininet/tests/http.c
@@ -172,7 +172,7 @@ static BOOL (WINAPI *pInternetGetSecurityInfoByURLA)(LPSTR,PCCERT_CHAIN_CONTEXT*
static int strcmp_wa(LPCWSTR strw, const char *stra)
{
WCHAR buf[512];
- MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, ARRAY_SIZE(buf));
return lstrcmpW(strw, buf);
}
@@ -4204,7 +4204,7 @@ static void test_http_status(int port)
DWORD i, size;
BOOL res;
- for(i=0; i < sizeof(http_status_tests)/sizeof(*http_status_tests); i++) {
+ for(i = 0; i < ARRAY_SIZE(http_status_tests); i++) {
send_buffer = http_status_tests[i].response_text;
open_simple_request(&req, "localhost", port, NULL, "/send_from_buffer");
@@ -6543,14 +6543,14 @@ static const struct notification async_send_request_ex_chunked_test[] =
static const struct notification_data notification_data[] = {
{
async_send_request_ex_chunked_test,
- sizeof(async_send_request_ex_chunked_test)/sizeof(async_send_request_ex_chunked_test[0]),
+ ARRAY_SIZE(async_send_request_ex_chunked_test),
"GET",
"test.winehq.org",
"tests/data.php"
},
{
async_send_request_ex_test,
- sizeof(async_send_request_ex_test)/sizeof(async_send_request_ex_test[0]),
+ ARRAY_SIZE(async_send_request_ex_test),
"POST",
"test.winehq.org",
"tests/post.php",
@@ -6565,7 +6565,7 @@ static const struct notification_data notification_data[] = {
},
{
async_send_request_ex_resolve_failure_test,
- sizeof(async_send_request_ex_resolve_failure_test)/sizeof(async_send_request_ex_resolve_failure_test[0]),
+ ARRAY_SIZE(async_send_request_ex_resolve_failure_test),
"GET",
"brokenhost",
"index.html",
diff --git a/dlls/wininet/tests/internet.c b/dlls/wininet/tests/internet.c
index 39c698f5db..7889e40ea8 100644
--- a/dlls/wininet/tests/internet.c
+++ b/dlls/wininet/tests/internet.c
@@ -629,7 +629,7 @@ static void test_cookie_url(void)
ok(!res && GetLastError() == ERROR_INVALID_PARAMETER,
"InternetGetCookeA failed: %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
- len = sizeof(bufw)/sizeof(*bufw);
+ len = ARRAY_SIZE(bufw);
res = InternetGetCookieW(about_blankW, NULL, bufw, &len);
ok(!res && GetLastError() == ERROR_INVALID_PARAMETER,
"InternetGetCookeW failed: %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
@@ -639,7 +639,7 @@ static void test_cookie_url(void)
ok(!res && GetLastError() == ERROR_INVALID_PARAMETER,
"InternetGetCookeExA failed: %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
- len = sizeof(bufw)/sizeof(*bufw);
+ len = ARRAY_SIZE(bufw);
res = pInternetGetCookieExW(about_blankW, NULL, bufw, &len, 0, NULL);
ok(!res && GetLastError() == ERROR_INVALID_PARAMETER,
"InternetGetCookeExW failed: %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
@@ -887,7 +887,7 @@ static void InternetTimeFromSystemTimeW_test(void)
/* test too small buffer size */
SetLastError(0xdeadbeef);
- ret = pInternetTimeFromSystemTimeW( &time, INTERNET_RFC1123_FORMAT, string, sizeof(string)/sizeof(string[0]) );
+ ret = pInternetTimeFromSystemTimeW( &time, INTERNET_RFC1123_FORMAT, string, ARRAY_SIZE(string));
error = GetLastError();
ok( !ret, "InternetTimeFromSystemTimeW should have returned FALSE\n" );
ok( error == ERROR_INSUFFICIENT_BUFFER,
@@ -1084,7 +1084,7 @@ static void test_PrivacyGetSetZonePreferenceW(void)
trace("template %u\n", old_template);
if(old_template == PRIVACY_TEMPLATE_ADVANCED) {
- pref_size = sizeof(pref)/sizeof(WCHAR);
+ pref_size = ARRAY_SIZE(pref);
ret = pPrivacyGetZonePreferenceW(zone, type, &old_template, pref, &pref_size);
ok(ret == 0, "expected ret == 0, got %u\n", ret);
}
@@ -1721,7 +1721,7 @@ static void test_InternetGetConnectedStateExW(void)
flags = 0;
buffer[0] = 0;
- res = pInternetGetConnectedStateExW(&flags, buffer, sizeof(buffer) / sizeof(buffer[0]), 0);
+ res = pInternetGetConnectedStateExW(&flags, buffer, ARRAY_SIZE(buffer), 0);
trace("Internet Connection: Flags 0x%02x - Name '%s'\n", flags, wine_dbgstr_w(buffer));
todo_wine
ok (flags & INTERNET_RAS_INSTALLED, "Missing RAS flag\n");
@@ -1755,21 +1755,21 @@ todo_wine
ok(!buffer[0], "Buffer must not change, got %02X\n", buffer[0]);
buffer[0] = 0;
- res = pInternetGetConnectedStateExW(NULL, buffer, sizeof(buffer) / sizeof(buffer[0]), 0);
+ res = pInternetGetConnectedStateExW(NULL, buffer, ARRAY_SIZE(buffer), 0);
ok(res == TRUE, "Expected TRUE, got %d\n", res);
sz = lstrlenW(buffer);
ok(sz > 0, "Expected a connection name\n");
buffer[0] = 0;
flags = 0;
- res = pInternetGetConnectedStateExW(&flags, buffer, sizeof(buffer) / sizeof(buffer[0]), 0);
+ res = pInternetGetConnectedStateExW(&flags, buffer, ARRAY_SIZE(buffer), 0);
ok(res == TRUE, "Expected TRUE, got %d\n", res);
ok(flags, "Expected at least one flag set\n");
sz = lstrlenW(buffer);
ok(sz > 0, "Expected a connection name\n");
flags = 0;
- res = pInternetGetConnectedStateExW(&flags, NULL, sizeof(buffer) / sizeof(buffer[0]), 0);
+ res = pInternetGetConnectedStateExW(&flags, NULL, ARRAY_SIZE(buffer), 0);
ok(res == TRUE, "Expected TRUE, got %d\n", res);
ok(flags, "Expected at least one flag set\n");
diff --git a/dlls/wininet/tests/url.c b/dlls/wininet/tests/url.c
index 0af58358eb..18c77b6647 100644
--- a/dlls/wininet/tests/url.c
+++ b/dlls/wininet/tests/url.c
@@ -672,17 +672,17 @@ static void InternetCrackUrlW_test(void)
memset(&comp, 0, sizeof comp);
comp.dwStructSize = sizeof(comp);
comp.lpszScheme = scheme;
- comp.dwSchemeLength = sizeof(scheme)/sizeof(scheme[0]);
+ comp.dwSchemeLength = ARRAY_SIZE(scheme);
comp.lpszHostName = host;
- comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
+ comp.dwHostNameLength = ARRAY_SIZE(host);
comp.lpszUserName = user;
- comp.dwUserNameLength = sizeof(user)/sizeof(user[0]);
+ comp.dwUserNameLength = ARRAY_SIZE(user);
comp.lpszPassword = pwd;
- comp.dwPasswordLength = sizeof(pwd)/sizeof(pwd[0]);
+ comp.dwPasswordLength = ARRAY_SIZE(pwd);
comp.lpszUrlPath = urlpart;
- comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
+ comp.dwUrlPathLength = ARRAY_SIZE(urlpart);
comp.lpszExtraInfo = extra;
- comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
+ comp.dwExtraInfoLength = ARRAY_SIZE(extra);
SetLastError(0xdeadbeef);
r = InternetCrackUrlW(NULL, 0, 0, &comp );
@@ -721,9 +721,9 @@ static void InternetCrackUrlW_test(void)
memset(&comp, 0, sizeof comp);
comp.dwStructSize = sizeof comp;
comp.lpszHostName = host;
- comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
+ comp.dwHostNameLength = ARRAY_SIZE(host);
comp.lpszUrlPath = urlpart;
- comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
+ comp.dwUrlPathLength = ARRAY_SIZE(urlpart);
r = InternetCrackUrlW(url, 0, 0, &comp );
ok( r, "failed to crack url\n");
@@ -739,11 +739,11 @@ static void InternetCrackUrlW_test(void)
memset(&comp, 0, sizeof comp);
comp.dwStructSize = sizeof comp;
comp.lpszHostName = host;
- comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
+ comp.dwHostNameLength = ARRAY_SIZE(host);
comp.lpszUrlPath = urlpart;
- comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
+ comp.dwUrlPathLength = ARRAY_SIZE(urlpart);
comp.lpszExtraInfo = NULL;
- comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
+ comp.dwExtraInfoLength = ARRAY_SIZE(extra);
r = InternetCrackUrlW(url, 0, 0, &comp );
ok( r, "failed to crack url\n");
@@ -763,17 +763,17 @@ static void InternetCrackUrlW_test(void)
memset(&comp, 0, sizeof(comp));
comp.dwStructSize = sizeof(comp);
comp.lpszScheme = scheme;
- comp.dwSchemeLength = sizeof(scheme)/sizeof(scheme[0]);
+ comp.dwSchemeLength = ARRAY_SIZE(scheme);
comp.lpszHostName = host;
- comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
+ comp.dwHostNameLength = ARRAY_SIZE(host);
comp.lpszUserName = user;
- comp.dwUserNameLength = sizeof(user)/sizeof(user[0]);
+ comp.dwUserNameLength = ARRAY_SIZE(user);
comp.lpszPassword = pwd;
- comp.dwPasswordLength = sizeof(pwd)/sizeof(pwd[0]);
+ comp.dwPasswordLength = ARRAY_SIZE(pwd);
comp.lpszUrlPath = urlpart;
- comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
+ comp.dwUrlPathLength = ARRAY_SIZE(urlpart);
comp.lpszExtraInfo = extra;
- comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
+ comp.dwExtraInfoLength = ARRAY_SIZE(extra);
r = InternetCrackUrlW(url2, 0, 0, &comp);
ok(!r, "InternetCrackUrl should have failed\n");
@@ -791,17 +791,17 @@ static void InternetCrackUrlW_test(void)
memset(&comp, 0, sizeof comp);
comp.dwStructSize = sizeof comp;
comp.lpszScheme = scheme;
- comp.dwSchemeLength = sizeof(scheme)/sizeof(scheme[0]);
+ comp.dwSchemeLength = ARRAY_SIZE(scheme);
comp.lpszHostName = host;
- comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
+ comp.dwHostNameLength = ARRAY_SIZE(host);
comp.lpszUserName = user;
- comp.dwUserNameLength = sizeof(user)/sizeof(user[0]);
+ comp.dwUserNameLength = ARRAY_SIZE(user);
comp.lpszPassword = pwd;
- comp.dwPasswordLength = sizeof(pwd)/sizeof(pwd[0]);
+ comp.dwPasswordLength = ARRAY_SIZE(pwd);
comp.lpszUrlPath = urlpart;
- comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
+ comp.dwUrlPathLength = ARRAY_SIZE(urlpart);
comp.lpszExtraInfo = extra;
- comp.dwExtraInfoLength = sizeof(extra)/sizeof(extra[0]);
+ comp.dwExtraInfoLength = ARRAY_SIZE(extra);
r = InternetCrackUrlW(url3, 0, 0, &comp );
ok( r, "InternetCrackUrlW failed unexpectedly\n");
ok( host[0] == 'x', "host should be x.org\n");
@@ -812,9 +812,9 @@ static void InternetCrackUrlW_test(void)
memset(&comp, 0, sizeof(comp));
comp.dwStructSize = sizeof(comp);
comp.lpszHostName = host;
- comp.dwHostNameLength = sizeof(host)/sizeof(host[0]);
+ comp.dwHostNameLength = ARRAY_SIZE(host);
comp.lpszUrlPath = urlpart;
- comp.dwUrlPathLength = sizeof(urlpart)/sizeof(urlpart[0]);
+ comp.dwUrlPathLength = ARRAY_SIZE(urlpart);
r = InternetCrackUrlW(url3, 0, ICU_DECODE, &comp);
todo_wine ok(r, "InternetCrackUrlW failed unexpectedly\n");
todo_wine ok(!strcmp_wa(host, "x.org"), "host is %s, should be x.org\n", wine_dbgstr_w(host));
@@ -1224,7 +1224,7 @@ START_TEST(url)
return;
}
- for(i=0; i < sizeof(crack_url_tests)/sizeof(*crack_url_tests); i++)
+ for(i = 0; i < ARRAY_SIZE(crack_url_tests); i++)
test_crack_url(crack_url_tests+i);
test_long_url();
diff --git a/dlls/wininet/tests/urlcache.c b/dlls/wininet/tests/urlcache.c
index 310054b6a7..3799500489 100644
--- a/dlls/wininet/tests/urlcache.c
+++ b/dlls/wininet/tests/urlcache.c
@@ -891,13 +891,13 @@ static void test_urlcacheW(void)
if(ie10_cache) {
if(!MultiByteToWideChar(CP_ACP, 0, urls[6].encoded_url, -1,
- urls[6].url, sizeof(urls[6].url)/sizeof(WCHAR)))
+ urls[6].url, ARRAY_SIZE(urls[6].url)))
urls[6].url[0] = 0;
trace("converted url in test 6: %s\n", wine_dbgstr_w(urls[6].url));
}
- for(i=0; i<sizeof(urls)/sizeof(*urls); i++) {
+ for(i=0; i<ARRAY_SIZE(urls); i++) {
INTERNET_CACHE_ENTRY_INFOA *entry_infoA;
INTERNET_CACHE_ENTRY_INFOW *entry_infoW;
DWORD size;
--
2.14.4
June 22, 2018
Re: [PATCH] fonts: Add clock images to Wingdings font.
by Alexandre Julliard
Dmitry Timoshkov <dmitry(a)baikal.ru> writes:
> Alexandre Julliard <julliard(a)winehq.org> wrote:
>
>> > Glyphs were copied from the Android Emoji font.
>>
>> As far as I can tell, this Android font is under the SIL Open Font
>> License, which is not LGPL-compatible.
>
> I had an impression that this font is part of the Android codebase
> which is under a BSD-like license.
>
> Perhaps you have a suggestion for the font with a compatible license?
I haven't looked if there are compatible fonts that include the needed
glyphs. The free font license situation is sadly almost as bad as the
free software one...
--
Alexandre Julliard
julliard(a)winehq.org
June 22, 2018
[PATCH] psapi/tests: Add todo_wine to a failing test.
by Zebediah Figura
This test was based on an implementation of K32EnumProcessModules() which was later rewritten.
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/psapi/tests/psapi_main.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c
index 0ff212c..ec74716 100644
--- a/dlls/psapi/tests/psapi_main.c
+++ b/dlls/psapi/tests/psapi_main.c
@@ -229,6 +229,7 @@ todo_wine
SetLastError(0xdeadbeef);
ret = pEnumProcessModules(pi.hProcess, &hMod, sizeof(HMODULE), &cbNeeded);
ok(!ret, "got %d\n", ret);
+todo_wine
ok(GetLastError() == ERROR_PARTIAL_COPY, "got error %u\n", GetLastError());
TerminateProcess(pi.hProcess, 0);
--
2.7.4
June 22, 2018
[PATCH] testbot: Avoid scalar(%hash) for compatibility with Perl 5.20.
by Francois Gouget
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
This is probably needed on the official TestBot!
I'm surprised we did not have the Engine or a script die already.
testbot/lib/WineTestBot/PatchUtils.pm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/testbot/lib/WineTestBot/PatchUtils.pm b/testbot/lib/WineTestBot/PatchUtils.pm
index f83df6087..b6ea54bcb 100644
--- a/testbot/lib/WineTestBot/PatchUtils.pm
+++ b/testbot/lib/WineTestBot/PatchUtils.pm
@@ -298,7 +298,7 @@ sub GetPatchImpact($;$$)
}
}
- $TestInfo->{UnitCount} = scalar(%{$TestInfo->{Units}});
+ $TestInfo->{UnitCount} = scalar(keys %{$TestInfo->{Units}});
if ($TestInfo->{UnitCount})
{
$Impacts->{ModuleCount}++;
--
2.17.1
June 22, 2018
[PATCH] testbot/WineRunTask: Show the Wine report filename in error messages.
by Francois Gouget
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/bin/WineRunTask.pl | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/testbot/bin/WineRunTask.pl b/testbot/bin/WineRunTask.pl
index 3f5a3ee8d..37c63b4b5 100755
--- a/testbot/bin/WineRunTask.pl
+++ b/testbot/bin/WineRunTask.pl
@@ -789,12 +789,12 @@ if ($TA->GetFile($RptFileName, "$TaskDir/$RptFileName"))
{
$NewStatus = 'boterror';
Error "Unable to open '$RptFileName' for reading: $!\n";
- LogTaskError("Unable to open the log file for reading: $!\n");
+ LogTaskError("Unable to open '$RptFileName' for reading: $!\n");
}
}
elsif (!defined $TAError)
{
- $TAError = "An error occurred while retrieving the test report: ". $TA->GetLastError();
+ $TAError = "An error occurred while retrieving $RptFileName: ". $TA->GetLastError();
}
$TA->Disconnect();
--
2.17.1
June 22, 2018
[PATCH 3/3] crypt32: Add oids for sha256ECDSA and sha384ECDSA.
by Nikolay Sivov
From: Michael Müller <michael(a)fds-team.de>
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/crypt32/oid.c | 15 +++++++++++++++
dlls/crypt32/tests/oid.c | 2 +-
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/dlls/crypt32/oid.c b/dlls/crypt32/oid.c
index 61b2cbc88e..c9b0b412cf 100644
--- a/dlls/crypt32/oid.c
+++ b/dlls/crypt32/oid.c
@@ -25,6 +25,7 @@
#define NONAMELESSUNION
#include "windef.h"
#include "winbase.h"
+#define CRYPT_OID_INFO_HAS_EXTRA_FIELDS
#include "wincrypt.h"
#include "winreg.h"
#include "winuser.h"
@@ -1080,6 +1081,8 @@ static const WCHAR sha384RSA[] = { 's','h','a','3','8','4','R','S','A',0 };
static const WCHAR sha512RSA[] = { 's','h','a','5','1','2','R','S','A',0 };
static const WCHAR mosaicUpdatedSig[] =
{ 'm','o','s','a','i','c','U','p','d','a','t','e','d','S','i','g',0 };
+static const WCHAR sha256ECDSA[] = { 's','h','a','2','5','6','E','C','D','S','A',0 };
+static const WCHAR sha384ECDSA[] = { 's','h','a','3','8','4','E','C','D','S','A',0 };
static const WCHAR CN[] = { 'C','N',0 };
static const WCHAR L[] = { 'L',0 };
static const WCHAR O[] = { 'O',0 };
@@ -1126,12 +1129,14 @@ static const DWORD dssSign[2] = { CALG_DSS_SIGN,
static const DWORD mosaicSign[2] = { CALG_DSS_SIGN,
CRYPT_OID_INHIBIT_SIGNATURE_FORMAT_FLAG |
CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG };
+static const DWORD ecdsaSign[2] = { CALG_OID_INFO_PARAMETERS, CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG };
static const CRYPT_DATA_BLOB rsaSignBlob = { sizeof(rsaSign),
(LPBYTE)&rsaSign };
static const CRYPT_DATA_BLOB dssSignBlob = { sizeof(dssSign),
(LPBYTE)dssSign };
static const CRYPT_DATA_BLOB mosaicSignBlob = { sizeof(mosaicSign),
(LPBYTE)mosaicSign };
+static const CRYPT_DATA_BLOB ecdsaSignBlob = { sizeof(ecdsaSign), (BYTE *)ecdsaSign };
static const DWORD ia5String[] = { CERT_RDN_IA5_STRING, 0 };
static const DWORD numericString[] = { CERT_RDN_NUMERIC_STRING, 0 };
@@ -1153,6 +1158,8 @@ static const struct OIDInfoConstructor {
UINT Algid;
LPCWSTR pwszName;
const CRYPT_DATA_BLOB *blob;
+ const WCHAR *pwszCNGAlgid;
+ const WCHAR *pwszCNGExtraAlgid;
} oidInfoConstructors[] = {
{ 1, szOID_OIWSEC_sha1, CALG_SHA1, sha1, NULL },
{ 1, szOID_OIWSEC_sha1, CALG_SHA1, sha, NULL },
@@ -1208,6 +1215,10 @@ static const struct OIDInfoConstructor {
{ 4, szOID_OIWSEC_dsaSHA1, CALG_SHA1, dsaSHA1, &dssSignBlob },
{ 4, szOID_INFOSEC_mosaicUpdatedSig, CALG_SHA1, mosaicUpdatedSig,
&mosaicSignBlob },
+ { 4, szOID_ECDSA_SHA256, CALG_OID_INFO_CNG_ONLY, sha256ECDSA, &ecdsaSignBlob,
+ BCRYPT_SHA256_ALGORITHM, CRYPT_OID_INFO_ECC_PARAMETERS_ALGORITHM },
+ { 4, szOID_ECDSA_SHA384, CALG_OID_INFO_CNG_ONLY, sha384ECDSA, &ecdsaSignBlob,
+ BCRYPT_SHA384_ALGORITHM, CRYPT_OID_INFO_ECC_PARAMETERS_ALGORITHM },
{ 5, szOID_COMMON_NAME, 0, CN, NULL },
{ 5, szOID_LOCALITY_NAME, 0, L, NULL },
@@ -1422,6 +1433,8 @@ static void init_oid_info(void)
info->info.ExtraInfo.pbData =
oidInfoConstructors[i].blob->pbData;
}
+ info->info.pwszCNGAlgid = oidInfoConstructors[i].pwszCNGAlgid;
+ info->info.pwszCNGExtraAlgid = oidInfoConstructors[i].pwszCNGExtraAlgid;
list_add_tail(&oidInfo, &info->entry);
}
}
@@ -1454,6 +1467,8 @@ static void init_oid_info(void)
info->info.ExtraInfo.pbData =
oidInfoConstructors[i].blob->pbData;
}
+ info->info.pwszCNGAlgid = oidInfoConstructors[i].pwszCNGAlgid;
+ info->info.pwszCNGExtraAlgid = oidInfoConstructors[i].pwszCNGExtraAlgid;
list_add_tail(&oidInfo, &info->entry);
}
}
diff --git a/dlls/crypt32/tests/oid.c b/dlls/crypt32/tests/oid.c
index 00a6d5461e..05822478cb 100644
--- a/dlls/crypt32/tests/oid.c
+++ b/dlls/crypt32/tests/oid.c
@@ -611,7 +611,7 @@ static void test_findOIDInfo(void)
wine_dbgstr_w(CRYPT_OID_INFO_ECC_PARAMETERS_ALGORITHM), wine_dbgstr_w(info->pwszCNGExtraAlgid));
}
else
- todo_wine win_skip("Host does not support ECDSA_SHA256, skipping test\n");
+ win_skip("Host does not support ECDSA_SHA256, skipping test\n");
}
START_TEST(oid)
--
2.17.1
June 22, 2018
[PATCH 2/3] crypt32/tests: Add a basic test for ecdsa oid.
by Nikolay Sivov
From: Michael Müller <michael(a)fds-team.de>
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/crypt32/tests/oid.c | 31 +++++++++++++++++++++++++++++++
include/wincrypt.h | 15 +++++++++++++++
2 files changed, 46 insertions(+)
diff --git a/dlls/crypt32/tests/oid.c b/dlls/crypt32/tests/oid.c
index 0e1442334f..00a6d5461e 100644
--- a/dlls/crypt32/tests/oid.c
+++ b/dlls/crypt32/tests/oid.c
@@ -22,6 +22,7 @@
#include <windef.h>
#include <winbase.h>
#include <winerror.h>
+#define CRYPT_OID_INFO_HAS_EXTRA_FIELDS
#include <wincrypt.h>
#include <winreg.h>
@@ -543,8 +544,10 @@ static void test_enumOIDInfo(void)
static void test_findOIDInfo(void)
{
+ static WCHAR sha256ECDSA[] = { 's','h','a','2','5','6','E','C','D','S','A',0 };
static WCHAR sha1[] = { 's','h','a','1',0 };
static CHAR oid_rsa_md5[] = szOID_RSA_MD5, oid_sha256[] = szOID_NIST_sha256;
+ static CHAR oid_ecdsa_sha256[] = szOID_ECDSA_SHA256;
ALG_ID alg = CALG_SHA1;
ALG_ID algs[2] = { CALG_MD5, CALG_RSA_SIGN };
const struct oid_info
@@ -581,6 +584,34 @@ static void test_findOIDInfo(void)
"Unexpected Algid %d, expected %d\n", U(*info).Algid, test->algid);
}
}
+
+ info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, oid_ecdsa_sha256, 0);
+ if (info)
+ {
+ DWORD *data;
+
+ ok(info->cbSize == sizeof(*info), "Unexpected structure size %d.\n", info->cbSize);
+ ok(!strcmp(info->pszOID, oid_ecdsa_sha256), "Expected %s, got %s\n", oid_ecdsa_sha256, info->pszOID);
+ ok(!lstrcmpW(info->pwszName, sha256ECDSA), "Expected %s, got %s\n",
+ wine_dbgstr_w(sha256ECDSA), wine_dbgstr_w(info->pwszName));
+ ok(info->dwGroupId == CRYPT_SIGN_ALG_OID_GROUP_ID,
+ "Expected CRYPT_SIGN_ALG_OID_GROUP_ID, got %u\n", info->dwGroupId);
+ ok(U(*info).Algid == CALG_OID_INFO_CNG_ONLY,
+ "Expected CALG_OID_INFO_CNG_ONLY, got %d\n", U(*info).Algid);
+
+ data = (DWORD *)info->ExtraInfo.pbData;
+ ok(info->ExtraInfo.cbData == 8, "Expected 8, got %d\n", info->ExtraInfo.cbData);
+ ok(data[0] == CALG_OID_INFO_PARAMETERS, "Expected CALG_OID_INFO_PARAMETERS, got %x\n", data[0]);
+ ok(data[1] == CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG,
+ "Expected CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG, got %x\n", data[1]);
+
+ ok(!lstrcmpW(info->pwszCNGAlgid, BCRYPT_SHA256_ALGORITHM), "Expected %s, got %s\n",
+ wine_dbgstr_w(BCRYPT_SHA256_ALGORITHM), wine_dbgstr_w(info->pwszCNGAlgid));
+ ok(!lstrcmpW(info->pwszCNGExtraAlgid, CRYPT_OID_INFO_ECC_PARAMETERS_ALGORITHM), "Expected %s, got %s\n",
+ wine_dbgstr_w(CRYPT_OID_INFO_ECC_PARAMETERS_ALGORITHM), wine_dbgstr_w(info->pwszCNGExtraAlgid));
+ }
+ else
+ todo_wine win_skip("Host does not support ECDSA_SHA256, skipping test\n");
}
START_TEST(oid)
diff --git a/include/wincrypt.h b/include/wincrypt.h
index a7c24e7831..373acacd26 100644
--- a/include/wincrypt.h
+++ b/include/wincrypt.h
@@ -1244,6 +1244,17 @@ typedef BOOL (WINAPI *PFN_CRYPT_ENUM_OID_FUNC)(DWORD dwEncodingType,
#define CRYPT_MATCH_ANY_ENCODING_TYPE 0xffffffff
+#define CALG_OID_INFO_CNG_ONLY 0xffffffff
+#define CALG_OID_INFO_PARAMETERS 0xfffffffe
+
+#define CRYPT_OID_INFO_HASH_PARAMETERS_ALGORITHM (const WCHAR []){'C','r','y','p','t','O','I','D','I','n','f','o','H','a','s','h','P','a','r','a','m','e','t','e','r','s',0}
+#define CRYPT_OID_INFO_ECC_PARAMETERS_ALGORITHM (const WCHAR []){'C','r','y','p','t','O','I','D','I','n','f','o','E','C','C','P','a','r','a','m','e','t','e','r','s',0}
+#define CRYPT_OID_INFO_MGF1_PARAMETERS_ALGORITHM (const WCHAR []){'C','r','y','p','t','O','I','D','I','n','f','o','M','g','f','1','P','a','r','a','m','e','t','e','r','s',0}
+#define CRYPT_OID_INFO_NO_SIGN_ALGORITHM (const WCHAR []){'C','r','y','p','t','O','I','D','I','n','f','o','N','o','S','i','g','n',0}
+#define CRYPT_OID_INFO_OAEP_PARAMETERS_ALGORITHM (const WCHAR []){'C','r','y','p','t','O','I','D','I','n','f','o','O','A','E','P','P','a','r','a','m','e','t','e','r','s',0}
+#define CRYPT_OID_INFO_ECC_WRAP_PARAMETERS_ALGORITHM (const WCHAR []){'C','r','y','p','t','O','I','D','I','n','f','o','E','C','C','W','r','a','p','P','a','r','a','m','e','t','e','r','s',0}
+#define CRYPT_OID_INFO_NO_PARAMETERS_ALGORITHM (const WCHAR []){'C','r','y','p','t','O','I','D','I','n','f','o','N','o','P','a','r','a','m','e','t','e','r','s',0}
+
typedef struct _CRYPT_OID_INFO {
DWORD cbSize;
LPCSTR pszOID;
@@ -1255,6 +1266,10 @@ typedef struct _CRYPT_OID_INFO {
DWORD dwLength;
} DUMMYUNIONNAME;
CRYPT_DATA_BLOB ExtraInfo;
+#ifdef CRYPT_OID_INFO_HAS_EXTRA_FIELDS
+ LPCWSTR pwszCNGAlgid;
+ LPCWSTR pwszCNGExtraAlgid;
+#endif
} CRYPT_OID_INFO, *PCRYPT_OID_INFO;
typedef const CRYPT_OID_INFO CCRYPT_OID_INFO, *PCCRYPT_OID_INFO;
--
2.17.1
June 22, 2018
[PATCH 1/3] crypt32/tests: Compact existing OID tests
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/crypt32/tests/oid.c | 73 +++++++++++++++-------------------------
1 file changed, 27 insertions(+), 46 deletions(-)
diff --git a/dlls/crypt32/tests/oid.c b/dlls/crypt32/tests/oid.c
index 8fc67b3353..0e1442334f 100644
--- a/dlls/crypt32/tests/oid.c
+++ b/dlls/crypt32/tests/oid.c
@@ -547,58 +547,39 @@ static void test_findOIDInfo(void)
static CHAR oid_rsa_md5[] = szOID_RSA_MD5, oid_sha256[] = szOID_NIST_sha256;
ALG_ID alg = CALG_SHA1;
ALG_ID algs[2] = { CALG_MD5, CALG_RSA_SIGN };
+ const struct oid_info
+ {
+ DWORD key_type;
+ void *key;
+ const char *oid;
+ ALG_ID algid;
+ ALG_ID broken_algid;
+ } oid_test_info [] =
+ {
+ { CRYPT_OID_INFO_OID_KEY, oid_rsa_md5, szOID_RSA_MD5, CALG_MD5 },
+ { CRYPT_OID_INFO_NAME_KEY, sha1, szOID_OIWSEC_sha1, CALG_SHA1 },
+ { CRYPT_OID_INFO_ALGID_KEY, &alg, szOID_OIWSEC_sha1, CALG_SHA1 },
+ { CRYPT_OID_INFO_SIGN_KEY, algs, szOID_RSA_MD5RSA, CALG_MD5 },
+ { CRYPT_OID_INFO_OID_KEY, oid_sha256, szOID_NIST_sha256, CALG_SHA_256, -1 },
+ };
PCCRYPT_OID_INFO info;
-
- static const WCHAR sha256W[] = {'s','h','a','2','5','6',0};
+ int i;
info = CryptFindOIDInfo(0, NULL, 0);
ok(info == NULL, "Expected NULL\n");
- info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, oid_rsa_md5, 0);
- ok(info != NULL, "Expected to find szOID_RSA_MD5\n");
- if (info)
- {
- ok(!strcmp(info->pszOID, szOID_RSA_MD5), "Expected %s, got %s\n",
- szOID_RSA_MD5, info->pszOID);
- ok(U(*info).Algid == CALG_MD5, "Expected CALG_MD5, got %d\n",
- U(*info).Algid);
- }
- info = CryptFindOIDInfo(CRYPT_OID_INFO_NAME_KEY, sha1, 0);
- ok(info != NULL, "Expected to find sha1\n");
- if (info)
- {
- ok(!strcmp(info->pszOID, szOID_OIWSEC_sha1), "Expected %s, got %s\n",
- szOID_OIWSEC_sha1, info->pszOID);
- ok(U(*info).Algid == CALG_SHA1, "Expected CALG_SHA1, got %d\n",
- U(*info).Algid);
- }
- info = CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY, &alg, 0);
- ok(info != NULL, "Expected to find sha1\n");
- if (info)
- {
- ok(!strcmp(info->pszOID, szOID_OIWSEC_sha1), "Expected %s, got %s\n",
- szOID_OIWSEC_sha1, info->pszOID);
- ok(U(*info).Algid == CALG_SHA1, "Expected CALG_SHA1, got %d\n",
- U(*info).Algid);
- }
- info = CryptFindOIDInfo(CRYPT_OID_INFO_SIGN_KEY, algs, 0);
- ok(info != NULL, "Expected to find md5RSA\n");
- if (info)
- {
- ok(!strcmp(info->pszOID, szOID_RSA_MD5RSA), "Expected %s, got %s\n",
- szOID_RSA_MD5RSA, info->pszOID);
- ok(U(*info).Algid == CALG_MD5, "Expected CALG_MD5, got %d\n",
- U(*info).Algid);
- }
- info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, oid_sha256, 0);
- ok(info != NULL, "Expected to find szOID_RSA_MD5\n");
- if (info)
+ for (i = 0; i < ARRAY_SIZE(oid_test_info); i++)
{
- ok(!strcmp(info->pszOID, szOID_NIST_sha256), "Expected %s, got %s\n",
- szOID_NIST_sha256, info->pszOID);
- ok(!lstrcmpW(info->pwszName, sha256W), "pwszName = %s\n", wine_dbgstr_w(info->pwszName));
- ok(U(*info).Algid == CALG_SHA_256 || U(*info).Algid == -1,
- "Expected CALG_MD5 or -1, got %d\n", U(*info).Algid);
+ const struct oid_info *test = &oid_test_info[i];
+
+ info = CryptFindOIDInfo(test->key_type, test->key, 0);
+ ok(info != NULL, "Failed to find %s.\n", test->oid);
+ if (info)
+ {
+ ok(!strcmp(info->pszOID, test->oid), "Unexpected OID %s, expected %s\n", info->pszOID, test->oid);
+ ok(U(*info).Algid == test->algid || broken(U(*info).Algid == test->broken_algid),
+ "Unexpected Algid %d, expected %d\n", U(*info).Algid, test->algid);
+ }
}
}
--
2.17.1
June 22, 2018
[PATCH 4/4] shell32/tests: Remove empty element from known_folders[].
by Józef Kucia
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
dlls/shell32/tests/shellpath.c | 17 ++++++-----------
1 file changed, 6 insertions(+), 11 deletions(-)
diff --git a/dlls/shell32/tests/shellpath.c b/dlls/shell32/tests/shellpath.c
index a5784237b162..bac64e57a7b9 100644
--- a/dlls/shell32/tests/shellpath.c
+++ b/dlls/shell32/tests/shellpath.c
@@ -1306,10 +1306,9 @@ static const struct knownFolderDef known_folders[] = {
NULL,
0,
0),
- { 0 }
};
#undef KNOWN_FOLDER
-BOOL known_folder_found[ARRAY_SIZE(known_folders)-1];
+BOOL known_folder_found[ARRAY_SIZE(known_folders)];
static void test_parameters(void)
{
@@ -1873,9 +1872,6 @@ if (0) { /* crashes */
{
const KNOWNFOLDERID *folder_id = known_folders[i].folderId;
- if (!folder_id)
- continue;
-
path = NULL;
hr = pSHGetKnownFolderPath(folder_id, KF_FLAG_DEFAULT, NULL, &path);
if (FAILED(hr))
@@ -1968,19 +1964,20 @@ static BOOL is_in_strarray(const WCHAR *needle, const char *hay)
static void check_known_folder(IKnownFolderManager *mgr, KNOWNFOLDERID *folderId)
{
HRESULT hr;
- const struct knownFolderDef *known_folder = &known_folders[0];
int csidl, expectedCsidl, ret;
KNOWNFOLDER_DEFINITION kfd;
IKnownFolder *folder;
WCHAR sName[1024];
- BOOL *current_known_folder_found = &known_folder_found[0];
BOOL found = FALSE;
+ unsigned int i;
- while(known_folder->folderId != NULL)
+ for (i = 0; i < ARRAY_SIZE(known_folders); ++i)
{
+ const struct knownFolderDef *known_folder = &known_folders[i];
+
if(IsEqualGUID(known_folder->folderId, folderId))
{
- *current_known_folder_found = TRUE;
+ known_folder_found[i] = TRUE;
found = TRUE;
/* verify CSIDL */
if(!(known_folder->csidl & NO_CSIDL))
@@ -2032,8 +2029,6 @@ static void check_known_folder(IKnownFolderManager *mgr, KNOWNFOLDERID *folderId
break;
}
- known_folder++;
- current_known_folder_found++;
}
if(!found)
--
2.16.4
June 22, 2018
[PATCH 3/4] shell32/tests: Add tests for SHGetKnownFolderPath() flags.
by Józef Kucia
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
dlls/shell32/tests/shellpath.c | 41 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/dlls/shell32/tests/shellpath.c b/dlls/shell32/tests/shellpath.c
index 736cd3b8caa3..a5784237b162 100644
--- a/dlls/shell32/tests/shellpath.c
+++ b/dlls/shell32/tests/shellpath.c
@@ -1842,8 +1842,9 @@ static void test_NonExistentPath(void)
static void test_SHGetFolderPathEx(void)
{
+ WCHAR buffer[MAX_PATH], *path, *path2;
+ unsigned int i;
HRESULT hr;
- WCHAR buffer[MAX_PATH], *path;
DWORD len;
if (!pSHGetKnownFolderPath || !pSHGetFolderPathEx)
@@ -1868,6 +1869,44 @@ if (0) { /* crashes */
ok(path != NULL, "expected path != NULL\n");
CoTaskMemFree(path);
+ for (i = 0; i < ARRAY_SIZE(known_folders); ++i)
+ {
+ const KNOWNFOLDERID *folder_id = known_folders[i].folderId;
+
+ if (!folder_id)
+ continue;
+
+ path = NULL;
+ hr = pSHGetKnownFolderPath(folder_id, KF_FLAG_DEFAULT, NULL, &path);
+ if (FAILED(hr))
+ continue;
+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+ ok(path != NULL, "expected path != NULL\n");
+
+ path2 = NULL;
+ hr = pSHGetKnownFolderPath(folder_id, KF_FLAG_SIMPLE_IDLIST, NULL, &path2);
+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+ ok(path != NULL, "expected path != NULL\n");
+ ok(!lstrcmpiW(path, path2), "expected equal paths: %s, %s\n", wine_dbgstr_w(path), wine_dbgstr_w(path2));
+ CoTaskMemFree(path2);
+
+ path2 = NULL;
+ hr = pSHGetKnownFolderPath(folder_id, KF_FLAG_DONT_UNEXPAND, NULL, &path2);
+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+ ok(path2 != NULL, "expected path != NULL\n");
+ ok(!lstrcmpiW(path, path2), "expected equal paths: %s, %s\n", wine_dbgstr_w(path), wine_dbgstr_w(path2));
+ CoTaskMemFree(path2);
+
+ path2 = NULL;
+ hr = pSHGetKnownFolderPath(folder_id, KF_FLAG_SIMPLE_IDLIST | KF_FLAG_DONT_UNEXPAND, NULL, &path2);
+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+ ok(path2 != NULL, "expected path != NULL\n");
+ ok(!lstrcmpiW(path, path2), "expected equal paths: %s, %s\n", wine_dbgstr_w(path), wine_dbgstr_w(path2));
+ CoTaskMemFree(path2);
+
+ CoTaskMemFree(path);
+ }
+
path = NULL;
hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &path);
ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
--
2.16.4
June 22, 2018
[PATCH 2/4] shell32/tests: Reorder known_folders table definition.
by Józef Kucia
To use it in other tests.
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
dlls/shell32/tests/shellpath.c | 1170 ++++++++++++++++++++--------------------
1 file changed, 585 insertions(+), 585 deletions(-)
diff --git a/dlls/shell32/tests/shellpath.c b/dlls/shell32/tests/shellpath.c
index 505da2778e26..736cd3b8caa3 100644
--- a/dlls/shell32/tests/shellpath.c
+++ b/dlls/shell32/tests/shellpath.c
@@ -304,591 +304,6 @@ static const char *getFolderName(int folder)
}
}
-static void test_parameters(void)
-{
- LPITEMIDLIST pidl = NULL;
- char path[MAX_PATH];
- HRESULT hr;
-
- if (pSHGetFolderLocation)
- {
- /* check a bogus CSIDL: */
- pidl = NULL;
- hr = pSHGetFolderLocation(NULL, 0xeeee, NULL, 0, &pidl);
- ok(hr == E_INVALIDARG, "got 0x%08x, expected E_INVALIDARG\n", hr);
- if (hr == S_OK) IMalloc_Free(pMalloc, pidl);
-
- /* check a bogus user token: */
- pidl = NULL;
- hr = pSHGetFolderLocation(NULL, CSIDL_FAVORITES, (HANDLE)2, 0, &pidl);
- ok(hr == E_FAIL || hr == E_HANDLE, "got 0x%08x, expected E_FAIL or E_HANDLE\n", hr);
- if (hr == S_OK) IMalloc_Free(pMalloc, pidl);
-
- /* a NULL pidl pointer crashes, so don't test it */
- }
-
- if (pSHGetSpecialFolderLocation)
- {
- if (0)
- /* crashes */
- SHGetSpecialFolderLocation(NULL, 0, NULL);
-
- hr = pSHGetSpecialFolderLocation(NULL, 0xeeee, &pidl);
- ok(hr == E_INVALIDARG, "got returned 0x%08x\n", hr);
- }
-
- if (pSHGetFolderPathA)
- {
- /* expect 2's a bogus handle, especially since we didn't open it */
- hr = pSHGetFolderPathA(NULL, CSIDL_DESKTOP, (HANDLE)2, SHGFP_TYPE_DEFAULT, path);
- ok(hr == E_FAIL || hr == E_HANDLE || /* Vista and 2k8 */
- broken(hr == S_OK), /* W2k and Me */ "got 0x%08x, expected E_FAIL\n", hr);
-
- hr = pSHGetFolderPathA(NULL, 0xeeee, NULL, SHGFP_TYPE_DEFAULT, path);
- ok(hr == E_INVALIDARG, "got 0x%08x, expected E_INVALIDARG\n", hr);
- }
-
- if (pSHGetSpecialFolderPathA)
- {
- BOOL ret;
-
- if (0)
- pSHGetSpecialFolderPathA(NULL, NULL, CSIDL_BITBUCKET, FALSE);
-
- /* odd but true: calling with a NULL path still succeeds if it's a real
- * dir (on some windows platform). on winME it generates exception.
- */
- ret = pSHGetSpecialFolderPathA(NULL, path, CSIDL_PROGRAMS, FALSE);
- ok(ret, "got %d\n", ret);
-
- ret = pSHGetSpecialFolderPathA(NULL, path, 0xeeee, FALSE);
- ok(!ret, "got %d\n", ret);
- }
-}
-
-/* Returns the folder's PIDL type, or 0xff if one can't be found. */
-static BYTE testSHGetFolderLocation(int folder)
-{
- LPITEMIDLIST pidl;
- HRESULT hr;
- BYTE ret = 0xff;
-
- /* treat absence of function as success */
- if (!pSHGetFolderLocation) return TRUE;
-
- pidl = NULL;
- hr = pSHGetFolderLocation(NULL, folder, NULL, 0, &pidl);
- if (hr == S_OK)
- {
- if (pidl)
- {
- LPITEMIDLIST pidlLast = pILFindLastID(pidl);
-
- ok(pidlLast != NULL, "%s: ILFindLastID failed\n",
- getFolderName(folder));
- if (pidlLast)
- ret = pidlLast->mkid.abID[0];
- IMalloc_Free(pMalloc, pidl);
- }
- }
- return ret;
-}
-
-/* Returns the folder's PIDL type, or 0xff if one can't be found. */
-static BYTE testSHGetSpecialFolderLocation(int folder)
-{
- LPITEMIDLIST pidl;
- HRESULT hr;
- BYTE ret = 0xff;
-
- /* treat absence of function as success */
- if (!pSHGetSpecialFolderLocation) return TRUE;
-
- pidl = NULL;
- hr = pSHGetSpecialFolderLocation(NULL, folder, &pidl);
- if (hr == S_OK)
- {
- if (pidl)
- {
- LPITEMIDLIST pidlLast = pILFindLastID(pidl);
-
- ok(pidlLast != NULL,
- "%s: ILFindLastID failed\n", getFolderName(folder));
- if (pidlLast)
- ret = pidlLast->mkid.abID[0];
- IMalloc_Free(pMalloc, pidl);
- }
- }
- return ret;
-}
-
-static void test_SHGetFolderPath(BOOL optional, int folder)
-{
- char path[MAX_PATH];
- HRESULT hr;
-
- if (!pSHGetFolderPathA) return;
-
- hr = pSHGetFolderPathA(NULL, folder, NULL, SHGFP_TYPE_CURRENT, path);
- ok(hr == S_OK || optional,
- "SHGetFolderPathA(NULL, %s, NULL, SHGFP_TYPE_CURRENT, path) failed: 0x%08x\n", getFolderName(folder), hr);
-}
-
-static void test_SHGetSpecialFolderPath(BOOL optional, int folder)
-{
- char path[MAX_PATH];
- BOOL ret;
-
- if (!pSHGetSpecialFolderPathA) return;
-
- ret = pSHGetSpecialFolderPathA(NULL, path, folder, FALSE);
- if (ret && winetest_interactive)
- printf("%s: %s\n", getFolderName(folder), path);
- ok(ret || optional,
- "SHGetSpecialFolderPathA(NULL, path, %s, FALSE) failed\n",
- getFolderName(folder));
-}
-
-static void test_ShellValues(const struct shellExpectedValues testEntries[],
- int numEntries, BOOL optional)
-{
- int i;
-
- for (i = 0; i < numEntries; i++)
- {
- BYTE type;
- int j;
- BOOL foundTypeMatch = FALSE;
-
- if (pSHGetFolderLocation)
- {
- type = testSHGetFolderLocation(testEntries[i].folder);
- for (j = 0; !foundTypeMatch && j < testEntries[i].numTypes; j++)
- if (testEntries[i].types[j] == type)
- foundTypeMatch = TRUE;
- ok(foundTypeMatch || optional || broken(type == 0xff) /* Win9x */,
- "%s has unexpected type %d (0x%02x)\n",
- getFolderName(testEntries[i].folder), type, type);
- }
- type = testSHGetSpecialFolderLocation(testEntries[i].folder);
- for (j = 0, foundTypeMatch = FALSE; !foundTypeMatch &&
- j < testEntries[i].numTypes; j++)
- if (testEntries[i].types[j] == type)
- foundTypeMatch = TRUE;
- ok(foundTypeMatch || optional || broken(type == 0xff) /* Win9x */,
- "%s has unexpected type %d (0x%02x)\n",
- getFolderName(testEntries[i].folder), type, type);
- switch (type)
- {
- case PT_FOLDER:
- case PT_DRIVE:
- case PT_DRIVE2:
- case PT_IESPECIAL2:
- test_SHGetFolderPath(optional, testEntries[i].folder);
- test_SHGetSpecialFolderPath(optional, testEntries[i].folder);
- break;
- }
- }
-}
-
-/* Attempts to verify that the folder path corresponding to the folder CSIDL
- * value has the same value as the environment variable with name envVar.
- * Doesn't mind if SHGetSpecialFolderPath fails for folder or if envVar isn't
- * set in this environment; different OS and shell version behave differently.
- * However, if both are present, fails if envVar's value is not the same
- * (byte-for-byte) as what SHGetSpecialFolderPath returns.
- */
-static void matchSpecialFolderPathToEnv(int folder, const char *envVar)
-{
- char path[MAX_PATH];
-
- if (!pSHGetSpecialFolderPathA) return;
-
- if (pSHGetSpecialFolderPathA(NULL, path, folder, FALSE))
- {
- char *envVal = getenv(envVar);
-
- ok(!envVal || !lstrcmpiA(envVal, path),
- "%%%s%% does not match SHGetSpecialFolderPath:\n"
- "%%%s%% is %s\nSHGetSpecialFolderPath returns %s\n",
- envVar, envVar, envVal, path);
- }
-}
-
-/* Attempts to match the GUID returned by SHGetFolderLocation for folder with
- * GUID. Assumes the type of the returned PIDL is in fact a GUID, but doesn't
- * fail if it isn't--that check should already have been done.
- * Fails if the returned PIDL is a GUID whose value does not match guid.
- */
-static void matchGUID(int folder, const GUID *guid, const GUID *guid_alt)
-{
- LPITEMIDLIST pidl;
- HRESULT hr;
-
- if (!pSHGetFolderLocation) return;
- if (!guid) return;
-
- pidl = NULL;
- hr = pSHGetFolderLocation(NULL, folder, NULL, 0, &pidl);
- if (hr == S_OK)
- {
- LPITEMIDLIST pidlLast = pILFindLastID(pidl);
-
- if (pidlLast && (pidlLast->mkid.abID[0] == PT_SHELLEXT ||
- pidlLast->mkid.abID[0] == PT_GUID))
- {
- GUID *shellGuid = (GUID *)(pidlLast->mkid.abID + 2);
-
- if (!guid_alt)
- ok(IsEqualIID(shellGuid, guid),
- "%s: got GUID %s, expected %s\n", getFolderName(folder),
- wine_dbgstr_guid(shellGuid), wine_dbgstr_guid(guid));
- else
- ok(IsEqualIID(shellGuid, guid) ||
- IsEqualIID(shellGuid, guid_alt),
- "%s: got GUID %s, expected %s or %s\n", getFolderName(folder),
- wine_dbgstr_guid(shellGuid), wine_dbgstr_guid(guid), wine_dbgstr_guid(guid_alt));
- }
- IMalloc_Free(pMalloc, pidl);
- }
-}
-
-/* Checks the PIDL type of all the known values. */
-static void test_PidlTypes(void)
-{
- /* Desktop */
- test_SHGetFolderPath(FALSE, CSIDL_DESKTOP);
- test_SHGetSpecialFolderPath(FALSE, CSIDL_DESKTOP);
-
- test_ShellValues(requiredShellValues, ARRAY_SIZE(requiredShellValues), FALSE);
- test_ShellValues(optionalShellValues, ARRAY_SIZE(optionalShellValues), TRUE);
-}
-
-/* FIXME: Should be in shobjidl.idl */
-DEFINE_GUID(CLSID_NetworkExplorerFolder, 0xF02C1A0D, 0xBE21, 0x4350, 0x88, 0xB0, 0x73, 0x67, 0xFC, 0x96, 0xEF, 0x3C);
-DEFINE_GUID(_CLSID_Documents, 0xA8CDFF1C, 0x4878, 0x43be, 0xB5, 0xFD, 0xF8, 0x09, 0x1C, 0x1C, 0x60, 0xD0);
-
-/* Verifies various shell virtual folders have the correct well-known GUIDs. */
-static void test_GUIDs(void)
-{
- matchGUID(CSIDL_BITBUCKET, &CLSID_RecycleBin, NULL);
- matchGUID(CSIDL_CONTROLS, &CLSID_ControlPanel, NULL);
- matchGUID(CSIDL_DRIVES, &CLSID_MyComputer, NULL);
- matchGUID(CSIDL_INTERNET, &CLSID_Internet, NULL);
- matchGUID(CSIDL_NETWORK, &CLSID_NetworkPlaces, &CLSID_NetworkExplorerFolder); /* Vista and higher */
- matchGUID(CSIDL_PERSONAL, &CLSID_MyDocuments, &_CLSID_Documents /* win8 */);
- matchGUID(CSIDL_COMMON_DOCUMENTS, &CLSID_CommonDocuments, NULL);
- matchGUID(CSIDL_PRINTERS, &CLSID_Printers, NULL);
-}
-
-/* Verifies various shell paths match the environment variables to which they
- * correspond.
- */
-static void test_EnvVars(void)
-{
- matchSpecialFolderPathToEnv(CSIDL_PROGRAM_FILES, "ProgramFiles");
- matchSpecialFolderPathToEnv(CSIDL_APPDATA, "APPDATA");
- matchSpecialFolderPathToEnv(CSIDL_PROFILE, "USERPROFILE");
- matchSpecialFolderPathToEnv(CSIDL_WINDOWS, "SystemRoot");
- matchSpecialFolderPathToEnv(CSIDL_WINDOWS, "windir");
- matchSpecialFolderPathToEnv(CSIDL_PROGRAM_FILES_COMMON, "CommonProgramFiles");
- /* this is only set on Wine, but can't hurt to verify it: */
- matchSpecialFolderPathToEnv(CSIDL_SYSTEM, "winsysdir");
-}
-
-/* Loosely based on PathRemoveBackslashA from dlls/shlwapi/path.c */
-static BOOL myPathIsRootA(LPCSTR lpszPath)
-{
- if (lpszPath && *lpszPath &&
- lpszPath[1] == ':' && lpszPath[2] == '\\' && lpszPath[3] == '\0')
- return TRUE; /* X:\ */
- return FALSE;
-}
-static LPSTR myPathRemoveBackslashA( LPSTR lpszPath )
-{
- LPSTR szTemp = NULL;
-
- if(lpszPath)
- {
- szTemp = CharPrevA(lpszPath, lpszPath + strlen(lpszPath));
- if (!myPathIsRootA(lpszPath) && *szTemp == '\\')
- *szTemp = '\0';
- }
- return szTemp;
-}
-
-/* Verifies the shell path for CSIDL_WINDOWS matches the return from
- * GetWindowsDirectory. If SHGetSpecialFolderPath fails, no harm, no foul--not
- * every shell32 version supports CSIDL_WINDOWS.
- */
-static void testWinDir(void)
-{
- char windowsShellPath[MAX_PATH], windowsDir[MAX_PATH] = { 0 };
-
- if (!pSHGetSpecialFolderPathA) return;
-
- if (pSHGetSpecialFolderPathA(NULL, windowsShellPath, CSIDL_WINDOWS, FALSE))
- {
- myPathRemoveBackslashA(windowsShellPath);
- GetWindowsDirectoryA(windowsDir, sizeof(windowsDir));
- myPathRemoveBackslashA(windowsDir);
- ok(!lstrcmpiA(windowsDir, windowsShellPath),
- "GetWindowsDirectory returns %s SHGetSpecialFolderPath returns %s\n",
- windowsDir, windowsShellPath);
- }
-}
-
-/* Verifies the shell path for CSIDL_SYSTEM matches the return from
- * GetSystemDirectory. If SHGetSpecialFolderPath fails, no harm,
- * no foul--not every shell32 version supports CSIDL_SYSTEM.
- */
-static void testSystemDir(void)
-{
- char systemShellPath[MAX_PATH], systemDir[MAX_PATH], systemDirx86[MAX_PATH];
-
- if (!pSHGetSpecialFolderPathA) return;
-
- GetSystemDirectoryA(systemDir, sizeof(systemDir));
- myPathRemoveBackslashA(systemDir);
- if (pSHGetSpecialFolderPathA(NULL, systemShellPath, CSIDL_SYSTEM, FALSE))
- {
- myPathRemoveBackslashA(systemShellPath);
- ok(!lstrcmpiA(systemDir, systemShellPath),
- "GetSystemDirectory returns %s SHGetSpecialFolderPath returns %s\n",
- systemDir, systemShellPath);
- }
-
- if (!pGetSystemWow64DirectoryA || !pGetSystemWow64DirectoryA(systemDirx86, sizeof(systemDirx86)))
- GetSystemDirectoryA(systemDirx86, sizeof(systemDirx86));
- myPathRemoveBackslashA(systemDirx86);
- if (pSHGetSpecialFolderPathA(NULL, systemShellPath, CSIDL_SYSTEMX86, FALSE))
- {
- myPathRemoveBackslashA(systemShellPath);
- ok(!lstrcmpiA(systemDirx86, systemShellPath) || broken(!lstrcmpiA(systemDir, systemShellPath)),
- "GetSystemDirectory returns %s SHGetSpecialFolderPath returns %s\n",
- systemDir, systemShellPath);
- }
-}
-
-/* Globals used by subprocesses */
-static int myARGC;
-static char **myARGV;
-static char base[MAX_PATH];
-static char selfname[MAX_PATH];
-
-static BOOL init(void)
-{
- myARGC = winetest_get_mainargs(&myARGV);
- if (!GetCurrentDirectoryA(sizeof(base), base)) return FALSE;
- strcpy(selfname, myARGV[0]);
- return TRUE;
-}
-
-static void doChild(const char *arg)
-{
- char path[MAX_PATH];
- HRESULT hr;
-
- if (arg[0] == '1')
- {
- LPITEMIDLIST pidl;
- char *p;
-
- /* test what happens when CSIDL_FAVORITES is set to a nonexistent directory */
-
- /* test some failure cases first: */
- hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES, NULL, SHGFP_TYPE_CURRENT, path);
- ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
- "SHGetFolderPath returned 0x%08x, expected 0x80070002\n", hr);
-
- pidl = NULL;
- hr = pSHGetFolderLocation(NULL, CSIDL_FAVORITES, NULL, 0, &pidl);
- ok(hr == E_FAIL || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
- "SHGetFolderLocation returned 0x%08x\n", hr);
- if (hr == S_OK && pidl) IMalloc_Free(pMalloc, pidl);
-
- ok(!pSHGetSpecialFolderPathA(NULL, path, CSIDL_FAVORITES, FALSE),
- "SHGetSpecialFolderPath succeeded, expected failure\n");
-
- pidl = NULL;
- hr = pSHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidl);
- ok(hr == E_FAIL || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
- "SHGetFolderLocation returned 0x%08x\n", hr);
-
- if (hr == S_OK && pidl) IMalloc_Free(pMalloc, pidl);
-
- /* now test success: */
- hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES | CSIDL_FLAG_CREATE, NULL,
- SHGFP_TYPE_CURRENT, path);
- ok (hr == S_OK, "got 0x%08x\n", hr);
- if (hr == S_OK)
- {
- BOOL ret;
-
- trace("CSIDL_FAVORITES was changed to %s\n", path);
- ret = CreateDirectoryA(path, NULL);
- ok(!ret, "expected failure with ERROR_ALREADY_EXISTS\n");
- if (!ret)
- ok(GetLastError() == ERROR_ALREADY_EXISTS,
- "got %d, expected ERROR_ALREADY_EXISTS\n", GetLastError());
-
- p = path + strlen(path);
- strcpy(p, "\\desktop.ini");
- DeleteFileA(path);
- *p = 0;
- SetFileAttributesA( path, FILE_ATTRIBUTE_NORMAL );
- ret = RemoveDirectoryA(path);
- ok( ret, "failed to remove %s error %u\n", path, GetLastError() );
- }
- }
- else if (arg[0] == '2')
- {
- /* make sure SHGetFolderPath still succeeds when the
- original value of CSIDL_FAVORITES is restored. */
- hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES | CSIDL_FLAG_CREATE, NULL,
- SHGFP_TYPE_CURRENT, path);
- ok(hr == S_OK, "SHGetFolderPath failed: 0x%08x\n", hr);
- }
-}
-
-/* Tests the return values from the various shell functions both with and
- * without the use of the CSIDL_FLAG_CREATE flag. This flag only appeared in
- * version 5 of the shell, so don't test unless it's at least version 5.
- * The test reads a value from the registry, modifies it, calls
- * SHGetFolderPath once with the CSIDL_FLAG_CREATE flag, and immediately
- * afterward without it. Then it restores the registry and deletes the folder
- * that was created.
- * One oddity with respect to restoration: shell32 caches somehow, so it needs
- * to be reloaded in order to see the correct (restored) value.
- * Some APIs unrelated to the ones under test may fail, but I expect they're
- * covered by other unit tests; I just print out something about failure to
- * help trace what's going on.
- */
-static void test_NonExistentPath(void)
-{
- static const char userShellFolders[] =
- "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders";
- char originalPath[MAX_PATH], modifiedPath[MAX_PATH];
- HKEY key;
-
- if (!pSHGetFolderPathA) return;
- if (!pSHGetFolderLocation) return;
- if (!pSHGetSpecialFolderPathA) return;
- if (!pSHGetSpecialFolderLocation) return;
- if (!pSHFileOperationA) return;
- if (shellVersion.dwMajorVersion < 5) return;
-
- if (!RegOpenKeyExA(HKEY_CURRENT_USER, userShellFolders, 0, KEY_ALL_ACCESS,
- &key))
- {
- DWORD len, type;
-
- len = sizeof(originalPath);
- if (!RegQueryValueExA(key, "Favorites", NULL, &type,
- (LPBYTE)&originalPath, &len))
- {
- size_t len = strlen(originalPath);
-
- memcpy(modifiedPath, originalPath, len);
- modifiedPath[len++] = '2';
- modifiedPath[len++] = '\0';
- trace("Changing CSIDL_FAVORITES to %s\n", modifiedPath);
- if (!RegSetValueExA(key, "Favorites", 0, type,
- (LPBYTE)modifiedPath, len))
- {
- char buffer[MAX_PATH+20];
- STARTUPINFOA startup;
- PROCESS_INFORMATION info;
-
- sprintf(buffer, "%s tests/shellpath.c 1", selfname);
- memset(&startup, 0, sizeof(startup));
- startup.cb = sizeof(startup);
- startup.dwFlags = STARTF_USESHOWWINDOW;
- startup.wShowWindow = SW_SHOWNORMAL;
- CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL,
- &startup, &info);
- winetest_wait_child_process( info.hProcess );
-
- /* restore original values: */
- trace("Restoring CSIDL_FAVORITES to %s\n", originalPath);
- RegSetValueExA(key, "Favorites", 0, type, (LPBYTE) originalPath,
- strlen(originalPath) + 1);
- RegFlushKey(key);
-
- sprintf(buffer, "%s tests/shellpath.c 2", selfname);
- memset(&startup, 0, sizeof(startup));
- startup.cb = sizeof(startup);
- startup.dwFlags = STARTF_USESHOWWINDOW;
- startup.wShowWindow = SW_SHOWNORMAL;
- CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL,
- &startup, &info);
- ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0,
- "child process termination\n");
- }
- }
- else skip("RegQueryValueExA(key, Favorites, ...) failed\n");
- if (key)
- RegCloseKey(key);
- }
- else skip("RegOpenKeyExA(HKEY_CURRENT_USER, %s, ...) failed\n", userShellFolders);
-}
-
-static void test_SHGetFolderPathEx(void)
-{
- HRESULT hr;
- WCHAR buffer[MAX_PATH], *path;
- DWORD len;
-
- if (!pSHGetKnownFolderPath || !pSHGetFolderPathEx)
- {
- win_skip("SHGetKnownFolderPath or SHGetFolderPathEx not available\n");
- return;
- }
-
-if (0) { /* crashes */
- hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, NULL);
- ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
-}
- /* non-existent folder id */
- path = (void *)0xdeadbeef;
- hr = pSHGetKnownFolderPath(&IID_IOleObject, 0, NULL, &path);
- ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr);
- ok(path == NULL, "got %p\n", path);
-
- path = NULL;
- hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, KF_FLAG_DEFAULT_PATH, NULL, &path);
- ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
- ok(path != NULL, "expected path != NULL\n");
- CoTaskMemFree(path);
-
- path = NULL;
- hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &path);
- ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
- ok(path != NULL, "expected path != NULL\n");
-
- hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, MAX_PATH);
- ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
- ok(!lstrcmpiW(path, buffer), "expected equal paths\n");
- len = lstrlenW(buffer);
- CoTaskMemFree(path);
-
- hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, 0);
- ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
-
-if (0) { /* crashes */
- hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, NULL, len + 1);
- ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
-
- hr = pSHGetFolderPathEx(NULL, 0, NULL, buffer, MAX_PATH);
- ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
-}
- hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, len);
- ok(hr == E_NOT_SUFFICIENT_BUFFER, "expected E_NOT_SUFFICIENT_BUFFER, got 0x%08x\n", hr);
-
- hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, len + 1);
- ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
-}
-
/* Standard CSIDL values (and their flags) uses only two less-significant bytes */
#define NO_CSIDL 0x10000
#define WINE_ATTRIBUTES_OPTIONAL 0x20000
@@ -1896,6 +1311,591 @@ static const struct knownFolderDef known_folders[] = {
#undef KNOWN_FOLDER
BOOL known_folder_found[ARRAY_SIZE(known_folders)-1];
+static void test_parameters(void)
+{
+ LPITEMIDLIST pidl = NULL;
+ char path[MAX_PATH];
+ HRESULT hr;
+
+ if (pSHGetFolderLocation)
+ {
+ /* check a bogus CSIDL: */
+ pidl = NULL;
+ hr = pSHGetFolderLocation(NULL, 0xeeee, NULL, 0, &pidl);
+ ok(hr == E_INVALIDARG, "got 0x%08x, expected E_INVALIDARG\n", hr);
+ if (hr == S_OK) IMalloc_Free(pMalloc, pidl);
+
+ /* check a bogus user token: */
+ pidl = NULL;
+ hr = pSHGetFolderLocation(NULL, CSIDL_FAVORITES, (HANDLE)2, 0, &pidl);
+ ok(hr == E_FAIL || hr == E_HANDLE, "got 0x%08x, expected E_FAIL or E_HANDLE\n", hr);
+ if (hr == S_OK) IMalloc_Free(pMalloc, pidl);
+
+ /* a NULL pidl pointer crashes, so don't test it */
+ }
+
+ if (pSHGetSpecialFolderLocation)
+ {
+ if (0)
+ /* crashes */
+ SHGetSpecialFolderLocation(NULL, 0, NULL);
+
+ hr = pSHGetSpecialFolderLocation(NULL, 0xeeee, &pidl);
+ ok(hr == E_INVALIDARG, "got returned 0x%08x\n", hr);
+ }
+
+ if (pSHGetFolderPathA)
+ {
+ /* expect 2's a bogus handle, especially since we didn't open it */
+ hr = pSHGetFolderPathA(NULL, CSIDL_DESKTOP, (HANDLE)2, SHGFP_TYPE_DEFAULT, path);
+ ok(hr == E_FAIL || hr == E_HANDLE || /* Vista and 2k8 */
+ broken(hr == S_OK), /* W2k and Me */ "got 0x%08x, expected E_FAIL\n", hr);
+
+ hr = pSHGetFolderPathA(NULL, 0xeeee, NULL, SHGFP_TYPE_DEFAULT, path);
+ ok(hr == E_INVALIDARG, "got 0x%08x, expected E_INVALIDARG\n", hr);
+ }
+
+ if (pSHGetSpecialFolderPathA)
+ {
+ BOOL ret;
+
+ if (0)
+ pSHGetSpecialFolderPathA(NULL, NULL, CSIDL_BITBUCKET, FALSE);
+
+ /* odd but true: calling with a NULL path still succeeds if it's a real
+ * dir (on some windows platform). on winME it generates exception.
+ */
+ ret = pSHGetSpecialFolderPathA(NULL, path, CSIDL_PROGRAMS, FALSE);
+ ok(ret, "got %d\n", ret);
+
+ ret = pSHGetSpecialFolderPathA(NULL, path, 0xeeee, FALSE);
+ ok(!ret, "got %d\n", ret);
+ }
+}
+
+/* Returns the folder's PIDL type, or 0xff if one can't be found. */
+static BYTE testSHGetFolderLocation(int folder)
+{
+ LPITEMIDLIST pidl;
+ HRESULT hr;
+ BYTE ret = 0xff;
+
+ /* treat absence of function as success */
+ if (!pSHGetFolderLocation) return TRUE;
+
+ pidl = NULL;
+ hr = pSHGetFolderLocation(NULL, folder, NULL, 0, &pidl);
+ if (hr == S_OK)
+ {
+ if (pidl)
+ {
+ LPITEMIDLIST pidlLast = pILFindLastID(pidl);
+
+ ok(pidlLast != NULL, "%s: ILFindLastID failed\n",
+ getFolderName(folder));
+ if (pidlLast)
+ ret = pidlLast->mkid.abID[0];
+ IMalloc_Free(pMalloc, pidl);
+ }
+ }
+ return ret;
+}
+
+/* Returns the folder's PIDL type, or 0xff if one can't be found. */
+static BYTE testSHGetSpecialFolderLocation(int folder)
+{
+ LPITEMIDLIST pidl;
+ HRESULT hr;
+ BYTE ret = 0xff;
+
+ /* treat absence of function as success */
+ if (!pSHGetSpecialFolderLocation) return TRUE;
+
+ pidl = NULL;
+ hr = pSHGetSpecialFolderLocation(NULL, folder, &pidl);
+ if (hr == S_OK)
+ {
+ if (pidl)
+ {
+ LPITEMIDLIST pidlLast = pILFindLastID(pidl);
+
+ ok(pidlLast != NULL,
+ "%s: ILFindLastID failed\n", getFolderName(folder));
+ if (pidlLast)
+ ret = pidlLast->mkid.abID[0];
+ IMalloc_Free(pMalloc, pidl);
+ }
+ }
+ return ret;
+}
+
+static void test_SHGetFolderPath(BOOL optional, int folder)
+{
+ char path[MAX_PATH];
+ HRESULT hr;
+
+ if (!pSHGetFolderPathA) return;
+
+ hr = pSHGetFolderPathA(NULL, folder, NULL, SHGFP_TYPE_CURRENT, path);
+ ok(hr == S_OK || optional,
+ "SHGetFolderPathA(NULL, %s, NULL, SHGFP_TYPE_CURRENT, path) failed: 0x%08x\n", getFolderName(folder), hr);
+}
+
+static void test_SHGetSpecialFolderPath(BOOL optional, int folder)
+{
+ char path[MAX_PATH];
+ BOOL ret;
+
+ if (!pSHGetSpecialFolderPathA) return;
+
+ ret = pSHGetSpecialFolderPathA(NULL, path, folder, FALSE);
+ if (ret && winetest_interactive)
+ printf("%s: %s\n", getFolderName(folder), path);
+ ok(ret || optional,
+ "SHGetSpecialFolderPathA(NULL, path, %s, FALSE) failed\n",
+ getFolderName(folder));
+}
+
+static void test_ShellValues(const struct shellExpectedValues testEntries[],
+ int numEntries, BOOL optional)
+{
+ int i;
+
+ for (i = 0; i < numEntries; i++)
+ {
+ BYTE type;
+ int j;
+ BOOL foundTypeMatch = FALSE;
+
+ if (pSHGetFolderLocation)
+ {
+ type = testSHGetFolderLocation(testEntries[i].folder);
+ for (j = 0; !foundTypeMatch && j < testEntries[i].numTypes; j++)
+ if (testEntries[i].types[j] == type)
+ foundTypeMatch = TRUE;
+ ok(foundTypeMatch || optional || broken(type == 0xff) /* Win9x */,
+ "%s has unexpected type %d (0x%02x)\n",
+ getFolderName(testEntries[i].folder), type, type);
+ }
+ type = testSHGetSpecialFolderLocation(testEntries[i].folder);
+ for (j = 0, foundTypeMatch = FALSE; !foundTypeMatch &&
+ j < testEntries[i].numTypes; j++)
+ if (testEntries[i].types[j] == type)
+ foundTypeMatch = TRUE;
+ ok(foundTypeMatch || optional || broken(type == 0xff) /* Win9x */,
+ "%s has unexpected type %d (0x%02x)\n",
+ getFolderName(testEntries[i].folder), type, type);
+ switch (type)
+ {
+ case PT_FOLDER:
+ case PT_DRIVE:
+ case PT_DRIVE2:
+ case PT_IESPECIAL2:
+ test_SHGetFolderPath(optional, testEntries[i].folder);
+ test_SHGetSpecialFolderPath(optional, testEntries[i].folder);
+ break;
+ }
+ }
+}
+
+/* Attempts to verify that the folder path corresponding to the folder CSIDL
+ * value has the same value as the environment variable with name envVar.
+ * Doesn't mind if SHGetSpecialFolderPath fails for folder or if envVar isn't
+ * set in this environment; different OS and shell version behave differently.
+ * However, if both are present, fails if envVar's value is not the same
+ * (byte-for-byte) as what SHGetSpecialFolderPath returns.
+ */
+static void matchSpecialFolderPathToEnv(int folder, const char *envVar)
+{
+ char path[MAX_PATH];
+
+ if (!pSHGetSpecialFolderPathA) return;
+
+ if (pSHGetSpecialFolderPathA(NULL, path, folder, FALSE))
+ {
+ char *envVal = getenv(envVar);
+
+ ok(!envVal || !lstrcmpiA(envVal, path),
+ "%%%s%% does not match SHGetSpecialFolderPath:\n"
+ "%%%s%% is %s\nSHGetSpecialFolderPath returns %s\n",
+ envVar, envVar, envVal, path);
+ }
+}
+
+/* Attempts to match the GUID returned by SHGetFolderLocation for folder with
+ * GUID. Assumes the type of the returned PIDL is in fact a GUID, but doesn't
+ * fail if it isn't--that check should already have been done.
+ * Fails if the returned PIDL is a GUID whose value does not match guid.
+ */
+static void matchGUID(int folder, const GUID *guid, const GUID *guid_alt)
+{
+ LPITEMIDLIST pidl;
+ HRESULT hr;
+
+ if (!pSHGetFolderLocation) return;
+ if (!guid) return;
+
+ pidl = NULL;
+ hr = pSHGetFolderLocation(NULL, folder, NULL, 0, &pidl);
+ if (hr == S_OK)
+ {
+ LPITEMIDLIST pidlLast = pILFindLastID(pidl);
+
+ if (pidlLast && (pidlLast->mkid.abID[0] == PT_SHELLEXT ||
+ pidlLast->mkid.abID[0] == PT_GUID))
+ {
+ GUID *shellGuid = (GUID *)(pidlLast->mkid.abID + 2);
+
+ if (!guid_alt)
+ ok(IsEqualIID(shellGuid, guid),
+ "%s: got GUID %s, expected %s\n", getFolderName(folder),
+ wine_dbgstr_guid(shellGuid), wine_dbgstr_guid(guid));
+ else
+ ok(IsEqualIID(shellGuid, guid) ||
+ IsEqualIID(shellGuid, guid_alt),
+ "%s: got GUID %s, expected %s or %s\n", getFolderName(folder),
+ wine_dbgstr_guid(shellGuid), wine_dbgstr_guid(guid), wine_dbgstr_guid(guid_alt));
+ }
+ IMalloc_Free(pMalloc, pidl);
+ }
+}
+
+/* Checks the PIDL type of all the known values. */
+static void test_PidlTypes(void)
+{
+ /* Desktop */
+ test_SHGetFolderPath(FALSE, CSIDL_DESKTOP);
+ test_SHGetSpecialFolderPath(FALSE, CSIDL_DESKTOP);
+
+ test_ShellValues(requiredShellValues, ARRAY_SIZE(requiredShellValues), FALSE);
+ test_ShellValues(optionalShellValues, ARRAY_SIZE(optionalShellValues), TRUE);
+}
+
+/* FIXME: Should be in shobjidl.idl */
+DEFINE_GUID(CLSID_NetworkExplorerFolder, 0xF02C1A0D, 0xBE21, 0x4350, 0x88, 0xB0, 0x73, 0x67, 0xFC, 0x96, 0xEF, 0x3C);
+DEFINE_GUID(_CLSID_Documents, 0xA8CDFF1C, 0x4878, 0x43be, 0xB5, 0xFD, 0xF8, 0x09, 0x1C, 0x1C, 0x60, 0xD0);
+
+/* Verifies various shell virtual folders have the correct well-known GUIDs. */
+static void test_GUIDs(void)
+{
+ matchGUID(CSIDL_BITBUCKET, &CLSID_RecycleBin, NULL);
+ matchGUID(CSIDL_CONTROLS, &CLSID_ControlPanel, NULL);
+ matchGUID(CSIDL_DRIVES, &CLSID_MyComputer, NULL);
+ matchGUID(CSIDL_INTERNET, &CLSID_Internet, NULL);
+ matchGUID(CSIDL_NETWORK, &CLSID_NetworkPlaces, &CLSID_NetworkExplorerFolder); /* Vista and higher */
+ matchGUID(CSIDL_PERSONAL, &CLSID_MyDocuments, &_CLSID_Documents /* win8 */);
+ matchGUID(CSIDL_COMMON_DOCUMENTS, &CLSID_CommonDocuments, NULL);
+ matchGUID(CSIDL_PRINTERS, &CLSID_Printers, NULL);
+}
+
+/* Verifies various shell paths match the environment variables to which they
+ * correspond.
+ */
+static void test_EnvVars(void)
+{
+ matchSpecialFolderPathToEnv(CSIDL_PROGRAM_FILES, "ProgramFiles");
+ matchSpecialFolderPathToEnv(CSIDL_APPDATA, "APPDATA");
+ matchSpecialFolderPathToEnv(CSIDL_PROFILE, "USERPROFILE");
+ matchSpecialFolderPathToEnv(CSIDL_WINDOWS, "SystemRoot");
+ matchSpecialFolderPathToEnv(CSIDL_WINDOWS, "windir");
+ matchSpecialFolderPathToEnv(CSIDL_PROGRAM_FILES_COMMON, "CommonProgramFiles");
+ /* this is only set on Wine, but can't hurt to verify it: */
+ matchSpecialFolderPathToEnv(CSIDL_SYSTEM, "winsysdir");
+}
+
+/* Loosely based on PathRemoveBackslashA from dlls/shlwapi/path.c */
+static BOOL myPathIsRootA(LPCSTR lpszPath)
+{
+ if (lpszPath && *lpszPath &&
+ lpszPath[1] == ':' && lpszPath[2] == '\\' && lpszPath[3] == '\0')
+ return TRUE; /* X:\ */
+ return FALSE;
+}
+static LPSTR myPathRemoveBackslashA( LPSTR lpszPath )
+{
+ LPSTR szTemp = NULL;
+
+ if(lpszPath)
+ {
+ szTemp = CharPrevA(lpszPath, lpszPath + strlen(lpszPath));
+ if (!myPathIsRootA(lpszPath) && *szTemp == '\\')
+ *szTemp = '\0';
+ }
+ return szTemp;
+}
+
+/* Verifies the shell path for CSIDL_WINDOWS matches the return from
+ * GetWindowsDirectory. If SHGetSpecialFolderPath fails, no harm, no foul--not
+ * every shell32 version supports CSIDL_WINDOWS.
+ */
+static void testWinDir(void)
+{
+ char windowsShellPath[MAX_PATH], windowsDir[MAX_PATH] = { 0 };
+
+ if (!pSHGetSpecialFolderPathA) return;
+
+ if (pSHGetSpecialFolderPathA(NULL, windowsShellPath, CSIDL_WINDOWS, FALSE))
+ {
+ myPathRemoveBackslashA(windowsShellPath);
+ GetWindowsDirectoryA(windowsDir, sizeof(windowsDir));
+ myPathRemoveBackslashA(windowsDir);
+ ok(!lstrcmpiA(windowsDir, windowsShellPath),
+ "GetWindowsDirectory returns %s SHGetSpecialFolderPath returns %s\n",
+ windowsDir, windowsShellPath);
+ }
+}
+
+/* Verifies the shell path for CSIDL_SYSTEM matches the return from
+ * GetSystemDirectory. If SHGetSpecialFolderPath fails, no harm,
+ * no foul--not every shell32 version supports CSIDL_SYSTEM.
+ */
+static void testSystemDir(void)
+{
+ char systemShellPath[MAX_PATH], systemDir[MAX_PATH], systemDirx86[MAX_PATH];
+
+ if (!pSHGetSpecialFolderPathA) return;
+
+ GetSystemDirectoryA(systemDir, sizeof(systemDir));
+ myPathRemoveBackslashA(systemDir);
+ if (pSHGetSpecialFolderPathA(NULL, systemShellPath, CSIDL_SYSTEM, FALSE))
+ {
+ myPathRemoveBackslashA(systemShellPath);
+ ok(!lstrcmpiA(systemDir, systemShellPath),
+ "GetSystemDirectory returns %s SHGetSpecialFolderPath returns %s\n",
+ systemDir, systemShellPath);
+ }
+
+ if (!pGetSystemWow64DirectoryA || !pGetSystemWow64DirectoryA(systemDirx86, sizeof(systemDirx86)))
+ GetSystemDirectoryA(systemDirx86, sizeof(systemDirx86));
+ myPathRemoveBackslashA(systemDirx86);
+ if (pSHGetSpecialFolderPathA(NULL, systemShellPath, CSIDL_SYSTEMX86, FALSE))
+ {
+ myPathRemoveBackslashA(systemShellPath);
+ ok(!lstrcmpiA(systemDirx86, systemShellPath) || broken(!lstrcmpiA(systemDir, systemShellPath)),
+ "GetSystemDirectory returns %s SHGetSpecialFolderPath returns %s\n",
+ systemDir, systemShellPath);
+ }
+}
+
+/* Globals used by subprocesses */
+static int myARGC;
+static char **myARGV;
+static char base[MAX_PATH];
+static char selfname[MAX_PATH];
+
+static BOOL init(void)
+{
+ myARGC = winetest_get_mainargs(&myARGV);
+ if (!GetCurrentDirectoryA(sizeof(base), base)) return FALSE;
+ strcpy(selfname, myARGV[0]);
+ return TRUE;
+}
+
+static void doChild(const char *arg)
+{
+ char path[MAX_PATH];
+ HRESULT hr;
+
+ if (arg[0] == '1')
+ {
+ LPITEMIDLIST pidl;
+ char *p;
+
+ /* test what happens when CSIDL_FAVORITES is set to a nonexistent directory */
+
+ /* test some failure cases first: */
+ hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES, NULL, SHGFP_TYPE_CURRENT, path);
+ ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
+ "SHGetFolderPath returned 0x%08x, expected 0x80070002\n", hr);
+
+ pidl = NULL;
+ hr = pSHGetFolderLocation(NULL, CSIDL_FAVORITES, NULL, 0, &pidl);
+ ok(hr == E_FAIL || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
+ "SHGetFolderLocation returned 0x%08x\n", hr);
+ if (hr == S_OK && pidl) IMalloc_Free(pMalloc, pidl);
+
+ ok(!pSHGetSpecialFolderPathA(NULL, path, CSIDL_FAVORITES, FALSE),
+ "SHGetSpecialFolderPath succeeded, expected failure\n");
+
+ pidl = NULL;
+ hr = pSHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidl);
+ ok(hr == E_FAIL || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
+ "SHGetFolderLocation returned 0x%08x\n", hr);
+
+ if (hr == S_OK && pidl) IMalloc_Free(pMalloc, pidl);
+
+ /* now test success: */
+ hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES | CSIDL_FLAG_CREATE, NULL,
+ SHGFP_TYPE_CURRENT, path);
+ ok (hr == S_OK, "got 0x%08x\n", hr);
+ if (hr == S_OK)
+ {
+ BOOL ret;
+
+ trace("CSIDL_FAVORITES was changed to %s\n", path);
+ ret = CreateDirectoryA(path, NULL);
+ ok(!ret, "expected failure with ERROR_ALREADY_EXISTS\n");
+ if (!ret)
+ ok(GetLastError() == ERROR_ALREADY_EXISTS,
+ "got %d, expected ERROR_ALREADY_EXISTS\n", GetLastError());
+
+ p = path + strlen(path);
+ strcpy(p, "\\desktop.ini");
+ DeleteFileA(path);
+ *p = 0;
+ SetFileAttributesA( path, FILE_ATTRIBUTE_NORMAL );
+ ret = RemoveDirectoryA(path);
+ ok( ret, "failed to remove %s error %u\n", path, GetLastError() );
+ }
+ }
+ else if (arg[0] == '2')
+ {
+ /* make sure SHGetFolderPath still succeeds when the
+ original value of CSIDL_FAVORITES is restored. */
+ hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES | CSIDL_FLAG_CREATE, NULL,
+ SHGFP_TYPE_CURRENT, path);
+ ok(hr == S_OK, "SHGetFolderPath failed: 0x%08x\n", hr);
+ }
+}
+
+/* Tests the return values from the various shell functions both with and
+ * without the use of the CSIDL_FLAG_CREATE flag. This flag only appeared in
+ * version 5 of the shell, so don't test unless it's at least version 5.
+ * The test reads a value from the registry, modifies it, calls
+ * SHGetFolderPath once with the CSIDL_FLAG_CREATE flag, and immediately
+ * afterward without it. Then it restores the registry and deletes the folder
+ * that was created.
+ * One oddity with respect to restoration: shell32 caches somehow, so it needs
+ * to be reloaded in order to see the correct (restored) value.
+ * Some APIs unrelated to the ones under test may fail, but I expect they're
+ * covered by other unit tests; I just print out something about failure to
+ * help trace what's going on.
+ */
+static void test_NonExistentPath(void)
+{
+ static const char userShellFolders[] =
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders";
+ char originalPath[MAX_PATH], modifiedPath[MAX_PATH];
+ HKEY key;
+
+ if (!pSHGetFolderPathA) return;
+ if (!pSHGetFolderLocation) return;
+ if (!pSHGetSpecialFolderPathA) return;
+ if (!pSHGetSpecialFolderLocation) return;
+ if (!pSHFileOperationA) return;
+ if (shellVersion.dwMajorVersion < 5) return;
+
+ if (!RegOpenKeyExA(HKEY_CURRENT_USER, userShellFolders, 0, KEY_ALL_ACCESS,
+ &key))
+ {
+ DWORD len, type;
+
+ len = sizeof(originalPath);
+ if (!RegQueryValueExA(key, "Favorites", NULL, &type,
+ (LPBYTE)&originalPath, &len))
+ {
+ size_t len = strlen(originalPath);
+
+ memcpy(modifiedPath, originalPath, len);
+ modifiedPath[len++] = '2';
+ modifiedPath[len++] = '\0';
+ trace("Changing CSIDL_FAVORITES to %s\n", modifiedPath);
+ if (!RegSetValueExA(key, "Favorites", 0, type,
+ (LPBYTE)modifiedPath, len))
+ {
+ char buffer[MAX_PATH+20];
+ STARTUPINFOA startup;
+ PROCESS_INFORMATION info;
+
+ sprintf(buffer, "%s tests/shellpath.c 1", selfname);
+ memset(&startup, 0, sizeof(startup));
+ startup.cb = sizeof(startup);
+ startup.dwFlags = STARTF_USESHOWWINDOW;
+ startup.wShowWindow = SW_SHOWNORMAL;
+ CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL,
+ &startup, &info);
+ winetest_wait_child_process( info.hProcess );
+
+ /* restore original values: */
+ trace("Restoring CSIDL_FAVORITES to %s\n", originalPath);
+ RegSetValueExA(key, "Favorites", 0, type, (LPBYTE) originalPath,
+ strlen(originalPath) + 1);
+ RegFlushKey(key);
+
+ sprintf(buffer, "%s tests/shellpath.c 2", selfname);
+ memset(&startup, 0, sizeof(startup));
+ startup.cb = sizeof(startup);
+ startup.dwFlags = STARTF_USESHOWWINDOW;
+ startup.wShowWindow = SW_SHOWNORMAL;
+ CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL,
+ &startup, &info);
+ ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0,
+ "child process termination\n");
+ }
+ }
+ else skip("RegQueryValueExA(key, Favorites, ...) failed\n");
+ if (key)
+ RegCloseKey(key);
+ }
+ else skip("RegOpenKeyExA(HKEY_CURRENT_USER, %s, ...) failed\n", userShellFolders);
+}
+
+static void test_SHGetFolderPathEx(void)
+{
+ HRESULT hr;
+ WCHAR buffer[MAX_PATH], *path;
+ DWORD len;
+
+ if (!pSHGetKnownFolderPath || !pSHGetFolderPathEx)
+ {
+ win_skip("SHGetKnownFolderPath or SHGetFolderPathEx not available\n");
+ return;
+ }
+
+if (0) { /* crashes */
+ hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, NULL);
+ ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
+}
+ /* non-existent folder id */
+ path = (void *)0xdeadbeef;
+ hr = pSHGetKnownFolderPath(&IID_IOleObject, 0, NULL, &path);
+ ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr);
+ ok(path == NULL, "got %p\n", path);
+
+ path = NULL;
+ hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, KF_FLAG_DEFAULT_PATH, NULL, &path);
+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+ ok(path != NULL, "expected path != NULL\n");
+ CoTaskMemFree(path);
+
+ path = NULL;
+ hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &path);
+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+ ok(path != NULL, "expected path != NULL\n");
+
+ hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, MAX_PATH);
+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+ ok(!lstrcmpiW(path, buffer), "expected equal paths\n");
+ len = lstrlenW(buffer);
+ CoTaskMemFree(path);
+
+ hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, 0);
+ ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
+
+if (0) { /* crashes */
+ hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, NULL, len + 1);
+ ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
+
+ hr = pSHGetFolderPathEx(NULL, 0, NULL, buffer, MAX_PATH);
+ ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
+}
+ hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, len);
+ ok(hr == E_NOT_SUFFICIENT_BUFFER, "expected E_NOT_SUFFICIENT_BUFFER, got 0x%08x\n", hr);
+
+ hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, len + 1);
+ ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+}
+
static BOOL is_in_strarray(const WCHAR *needle, const char *hay)
{
WCHAR wstr[MAX_PATH];
--
2.16.4
June 22, 2018
[PATCH 1/4] shell32: Accept more flags in SHGetKnownFolderPath().
by Józef Kucia
KF_FLAG_SIMPLE_IDLIST | KF_FLAG_DONT_UNEXPAND doesn't seem to influence
results returned by SHGetKnownFolderPath().
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
dlls/shell32/shellpath.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/shell32/shellpath.c b/dlls/shell32/shellpath.c
index a551e93aa8c7..de4bf7d566c1 100644
--- a/dlls/shell32/shellpath.c
+++ b/dlls/shell32/shellpath.c
@@ -4885,8 +4885,8 @@ HRESULT WINAPI SHGetKnownFolderPath(REFKNOWNFOLDERID rfid, DWORD flags, HANDLE t
if (folder < 0)
return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
- if (flags & ~(KF_FLAG_CREATE|KF_FLAG_DONT_VERIFY|KF_FLAG_NO_ALIAS|
- KF_FLAG_INIT|KF_FLAG_DEFAULT_PATH))
+ if (flags & ~(KF_FLAG_CREATE|KF_FLAG_SIMPLE_IDLIST|KF_FLAG_DONT_UNEXPAND|
+ KF_FLAG_DONT_VERIFY|KF_FLAG_NO_ALIAS|KF_FLAG_INIT|KF_FLAG_DEFAULT_PATH))
{
FIXME("flags 0x%08x not supported\n", flags);
return E_INVALIDARG;
--
2.16.4
June 22, 2018
Re: [PATCH v2] user32: Always release menu item in EnableMenuItem
by Alexandre Julliard
Fabian Maurer <dark.shadow4(a)web.de> writes:
> @@ -3751,9 +3751,11 @@ BOOL WINAPI EnableMenuItem( HMENU hMenu, UINT id, UINT wFlags )
>
> /* Get the parent menu to access*/
> parentMenu = grab_menu_ptr(menu->hSysMenuOwner);
> - release_menu_ptr(menu);
> if (!parentMenu)
> + {
> + release_menu_ptr(menu);
> return (UINT)-1;
> + }
>
> hwnd = parentMenu->hWnd;
> release_menu_ptr(parentMenu);
> @@ -3764,8 +3766,7 @@ BOOL WINAPI EnableMenuItem( HMENU hMenu, UINT id, UINT wFlags )
> RedrawWindow(hwnd, &rc, 0, RDW_FRAME | RDW_INVALIDATE | RDW_NOCHILDREN);
> }
> }
> - else
> - release_menu_ptr(menu);
> + release_menu_ptr(menu);
You can't call RedrawWindow() while holding the lock.
--
Alexandre Julliard
julliard(a)winehq.org
June 22, 2018
Re: [PATCH] gdi32: Add a workaround for A->W text output with Symbol font encoding.
by Dmitry Timoshkov
Huw Davies <huw(a)codeweavers.com> wrote:
> Looks good. I've sent in a new version with a re-worded commit
> message that hopefully makes it clear that this isn't a work-around in
> Wine, but a work-around in Windows. I also fixed a grammar issue in
> an existing comment and took the opportunity to make the formatting
> more consistent.
Thanks Huw!
--
Dmitry.
June 22, 2018