From c18bbbf9a74b1abbbed6840d301147a6860041ba Mon Sep 17 00:00:00 2001 From: The Wine Synchronizer Date: Fri, 24 Aug 2007 09:42:29 +0000 Subject: [PATCH] Autosyncing with Wine HEAD svn path=/trunk/; revision=28513 --- rostests/winetests/directory.rbuild | 3 + rostests/winetests/mlang/mlang.c | 788 ++++++++++++++ rostests/winetests/mlang/mlang.rbuild | 15 + rostests/winetests/mlang/testlist.c | 15 + rostests/winetests/shlwapi/clist.c | 82 +- rostests/winetests/shlwapi/clsid.c | 48 +- rostests/winetests/shlwapi/generated.c | 6 - rostests/winetests/shlwapi/ordinal.c | 282 ++++- rostests/winetests/shlwapi/path.c | 1147 ++++++++++++++++++++- rostests/winetests/shlwapi/shlwapi.rbuild | 34 +- rostests/winetests/shlwapi/shreg.c | 129 +-- rostests/winetests/shlwapi/string.c | 160 ++- rostests/winetests/shlwapi/testlist.c | 6 +- 13 files changed, 2458 insertions(+), 257 deletions(-) create mode 100644 rostests/winetests/mlang/mlang.c create mode 100644 rostests/winetests/mlang/mlang.rbuild create mode 100644 rostests/winetests/mlang/testlist.c diff --git a/rostests/winetests/directory.rbuild b/rostests/winetests/directory.rbuild index 2f8e1c86939..d4cc460d946 100644 --- a/rostests/winetests/directory.rbuild +++ b/rostests/winetests/directory.rbuild @@ -23,6 +23,9 @@ + + + diff --git a/rostests/winetests/mlang/mlang.c b/rostests/winetests/mlang/mlang.c new file mode 100644 index 00000000000..fb50e2e050d --- /dev/null +++ b/rostests/winetests/mlang/mlang.c @@ -0,0 +1,788 @@ +/* + * Unit test suite for MLANG APIs. + * + * Copyright 2004 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "mlang.h" + +#include "wine/test.h" + +#ifndef CP_UNICODE +#define CP_UNICODE 1200 +#endif + +#if 0 +#define DUMP_CP_INFO +#define DUMP_SCRIPT_INFO + +#if defined DUMP_CP_INFO || defined DUMP_SCRIPT_INFO +#include "wine/debug.h" +#endif +#endif /* 0 */ + +#define TRACE_2 OutputDebugStringA + +static BOOL (WINAPI *pGetCPInfoExA)(UINT,DWORD,LPCPINFOEXA); + +static void test_multibyte_to_unicode_translations(IMultiLanguage2 *iML2) +{ + /* these APIs are broken regarding constness of the input buffer */ + char stringA[] = "Just a test string\0"; /* double 0 for CP_UNICODE tests */ + WCHAR stringW[] = {'J','u','s','t',' ','a',' ','t','e','s','t',' ','s','t','r','i','n','g',0}; + char bufA[256]; + WCHAR bufW[256]; + UINT lenA, lenW, expected_len; + HRESULT ret; + HMODULE hMlang; + FARPROC pConvertINetMultiByteToUnicode; + FARPROC pConvertINetUnicodeToMultiByte; + + hMlang = LoadLibraryA("mlang.dll"); + ok(hMlang != 0, "couldn't load mlang.dll\n"); + + pConvertINetMultiByteToUnicode = GetProcAddress(hMlang, "ConvertINetMultiByteToUnicode"); + ok(pConvertINetMultiByteToUnicode != NULL, "couldn't resolve ConvertINetMultiByteToUnicode\n"); + pConvertINetUnicodeToMultiByte = GetProcAddress(hMlang, "ConvertINetUnicodeToMultiByte"); + ok(pConvertINetUnicodeToMultiByte != NULL, "couldn't resolve ConvertINetUnicodeToMultiByte\n"); + + /* IMultiLanguage2_ConvertStringToUnicode tests */ + + memset(bufW, 'x', sizeof(bufW)); + lenA = 0; + lenW = sizeof(bufW)/sizeof(bufW[0]); + TRACE_2("Call IMultiLanguage2_ConvertStringToUnicode\n"); + ret = IMultiLanguage2_ConvertStringToUnicode(iML2, NULL, 1252, stringA, &lenA, bufW, &lenW); + ok(ret == S_OK, "IMultiLanguage2_ConvertStringToUnicode failed: %08x\n", ret); + ok(lenA == 0, "expected lenA 0, got %u\n", lenA); + ok(lenW == 0, "expected lenW 0, got %u\n", lenW); + + memset(bufW, 'x', sizeof(bufW)); + lenA = -1; + lenW = sizeof(bufW)/sizeof(bufW[0]); + TRACE_2("Call IMultiLanguage2_ConvertStringToUnicode\n"); + ret = IMultiLanguage2_ConvertStringToUnicode(iML2, NULL, 1252, stringA, &lenA, bufW, &lenW); + ok(ret == S_OK, "IMultiLanguage2_ConvertStringToUnicode failed: %08x\n", ret); + ok(lenA == lstrlenA(stringA), "expected lenA %u, got %u\n", lstrlenA(stringA), lenA); + ok(lenW == lstrlenW(stringW), "expected lenW %u, got %u\n", lstrlenW(stringW), lenW); + if (lenW < sizeof(bufW)/sizeof(bufW[0])) { + /* can only happen if the convert call fails */ + ok(bufW[lenW] != 0, "buf should not be 0 terminated\n"); + bufW[lenW] = 0; /* -1 doesn't include 0 terminator */ + } + ok(!lstrcmpW(bufW, stringW), "bufW/stringW mismatch\n"); + + memset(bufW, 'x', sizeof(bufW)); + lenA = -1; + lenW = 5; + TRACE_2("Call IMultiLanguage2_ConvertStringToUnicode\n"); + ret = IMultiLanguage2_ConvertStringToUnicode(iML2, NULL, 1252, stringA, &lenA, bufW, &lenW); + ok(ret == E_FAIL, "IMultiLanguage2_ConvertStringToUnicode should fail: %08x\n", ret); + ok(lenW == 0, "expected lenW 0, got %u\n", lenW); + /* still has to do partial conversion */ + ok(!memcmp(bufW, stringW, 5 * sizeof(WCHAR)), "bufW/stringW mismatch\n"); + + memset(bufW, 'x', sizeof(bufW)); + lenA = -1; + lenW = sizeof(bufW)/sizeof(bufW[0]); + TRACE_2("Call IMultiLanguage2_ConvertStringToUnicode\n"); + ret = IMultiLanguage2_ConvertStringToUnicode(iML2, NULL, CP_UNICODE, stringA, &lenA, bufW, &lenW); + ok(ret == S_OK, "IMultiLanguage2_ConvertStringToUnicode failed: %08x\n", ret); + ok(lenA == lstrlenA(stringA), "expected lenA %u, got %u\n", lstrlenA(stringA), lenA); + ok(lenW == lstrlenW(stringW)/(int)sizeof(WCHAR), "wrong lenW %u\n", lenW); + ok(bufW[lenW] != 0, "buf should not be 0 terminated\n"); + bufW[lenW] = 0; /* -1 doesn't include 0 terminator */ + ok(!lstrcmpA((LPCSTR)bufW, stringA), "bufW/stringA mismatch\n"); + + memset(bufW, 'x', sizeof(bufW)); + lenA = lstrlenA(stringA); + lenW = 0; + ret = IMultiLanguage2_ConvertStringToUnicode(iML2, NULL, 1252, stringA, &lenA, NULL, &lenW); + ok(ret == S_OK, "IMultiLanguage2_ConvertStringToUnicode failed: %08x\n", ret); + ok(lenA == lstrlenA(stringA), "expected lenA %u, got %u\n", lstrlenA(stringA), lenA); + expected_len = MultiByteToWideChar(1252, 0, stringA, lenA, NULL, 0); + ok(lenW == expected_len, "expected lenW %u, got %u\n", expected_len, lenW); + + memset(bufW, 'x', sizeof(bufW)); + lenA = lstrlenA(stringA); + lenW = sizeof(bufW)/sizeof(bufW[0]); + ret = pConvertINetMultiByteToUnicode(NULL, 1252, stringA, &lenA, NULL, &lenW); + ok(ret == S_OK, "ConvertINetMultiByteToUnicode failed: %08x\n", ret); + ok(lenA == lstrlenA(stringA), "expected lenA %u, got %u\n", lstrlenA(stringA), lenA); + expected_len = MultiByteToWideChar(1252, 0, stringA, lenA, NULL, 0); + ok(lenW == expected_len, "expected lenW %u, got %u\n", expected_len, lenW); + + memset(bufW, 'x', sizeof(bufW)); + lenA = lstrlenA(stringA); + lenW = 0; + ret = pConvertINetMultiByteToUnicode(NULL, 1252, stringA, &lenA, NULL, &lenW); + ok(ret == S_OK, "ConvertINetMultiByteToUnicode failed: %08x\n", ret); + ok(lenA == lstrlenA(stringA), "expected lenA %u, got %u\n", lstrlenA(stringA), lenA); + expected_len = MultiByteToWideChar(1252, 0, stringA, lenA, NULL, 0); + ok(lenW == expected_len, "expected lenW %u, got %u\n", expected_len, lenW); + + /* IMultiLanguage2_ConvertStringFromUnicode tests */ + + memset(bufA, 'x', sizeof(bufA)); + lenW = 0; + lenA = sizeof(bufA); + TRACE_2("Call IMultiLanguage2_ConvertStringFromUnicode\n"); + ret = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, stringW, &lenW, bufA, &lenA); + ok(ret == S_OK, "IMultiLanguage2_ConvertStringFromUnicode failed: %08x\n", ret); + ok(lenA == 0, "expected lenA 0, got %u\n", lenA); + ok(lenW == 0, "expected lenW 0, got %u\n", lenW); + + memset(bufA, 'x', sizeof(bufA)); + lenW = -1; + lenA = sizeof(bufA); + TRACE_2("Call IMultiLanguage2_ConvertStringFromUnicode\n"); + ret = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, stringW, &lenW, bufA, &lenA); + ok(ret == S_OK, "IMultiLanguage2_ConvertStringFromUnicode failed: %08x\n", ret); + ok(lenA == lstrlenA(stringA), "expected lenA %u, got %u\n", lstrlenA(stringA), lenA); + ok(lenW == lstrlenW(stringW), "expected lenW %u, got %u\n", lstrlenW(stringW), lenW); + ok(bufA[lenA] != 0, "buf should not be 0 terminated\n"); + bufA[lenA] = 0; /* -1 doesn't include 0 terminator */ + ok(!lstrcmpA(bufA, stringA), "bufA/stringA mismatch\n"); + + memset(bufA, 'x', sizeof(bufA)); + lenW = -1; + lenA = 5; + TRACE_2("Call IMultiLanguage2_ConvertStringFromUnicode\n"); + ret = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, stringW, &lenW, bufA, &lenA); + ok(ret == E_FAIL, "IMultiLanguage2_ConvertStringFromUnicode should fail: %08x\n", ret); + ok(lenA == 0, "expected lenA 0, got %u\n", lenA); + /* still has to do partial conversion */ + ok(!memcmp(bufA, stringA, 5), "bufW/stringW mismatch\n"); + + memset(bufA, 'x', sizeof(bufA)); + lenW = -1; + lenA = sizeof(bufA); + TRACE_2("Call IMultiLanguage2_ConvertStringFromUnicode\n"); + ret = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, CP_UNICODE, stringW, &lenW, bufA, &lenA); + ok(ret == S_OK, "IMultiLanguage2_ConvertStringFromUnicode failed: %08x\n", ret); + ok(lenA == lstrlenA(stringA) * (int)sizeof(WCHAR), "wrong lenA %u\n", lenA); + ok(lenW == lstrlenW(stringW), "expected lenW %u, got %u\n", lstrlenW(stringW), lenW); + ok(bufA[lenA] != 0 && bufA[lenA+1] != 0, "buf should not be 0 terminated\n"); + bufA[lenA] = 0; /* -1 doesn't include 0 terminator */ + bufA[lenA+1] = 0; /* sizeof(WCHAR) */ + ok(!lstrcmpW((LPCWSTR)bufA, stringW), "bufA/stringW mismatch\n"); + + memset(bufA, 'x', sizeof(bufA)); + lenW = lstrlenW(stringW); + lenA = 0; + ret = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, stringW, &lenW, NULL, &lenA); + ok(ret == S_OK, "IMultiLanguage2_ConvertStringFromUnicode failed: %08x\n", ret); + ok(lenW == lstrlenW(stringW), "expected lenW %u, got %u\n", lstrlenW(stringW), lenW); + expected_len = WideCharToMultiByte(1252, 0, stringW, lenW, NULL, 0, NULL, NULL); + ok(lenA == expected_len, "expected lenA %u, got %u\n", expected_len, lenA); + + memset(bufA, 'x', sizeof(bufA)); + lenW = lstrlenW(stringW); + lenA = sizeof(bufA); + ret = pConvertINetUnicodeToMultiByte(NULL, 1252, stringW, &lenW, NULL, &lenA); + ok(ret == S_OK, "ConvertINetUnicodeToMultiByte failed: %08x\n", ret); + ok(lenW == lstrlenW(stringW), "expected lenW %u, got %u\n", lstrlenW(stringW), lenW); + expected_len = WideCharToMultiByte(1252, 0, stringW, lenW, NULL, 0, NULL, NULL); + ok(lenA == expected_len, "expected lenA %u, got %u\n", expected_len, lenA); + + memset(bufA, 'x', sizeof(bufA)); + lenW = lstrlenW(stringW); + lenA = 0; + ret = pConvertINetUnicodeToMultiByte(NULL, 1252, stringW, &lenW, NULL, &lenA); + ok(ret == S_OK, "ConvertINetUnicodeToMultiByte failed: %08x\n", ret); + ok(lenW == lstrlenW(stringW), "expected lenW %u, got %u\n", lstrlenW(stringW), lenW); + expected_len = WideCharToMultiByte(1252, 0, stringW, lenW, NULL, 0, NULL, NULL); + ok(lenA == expected_len, "expected lenA %u, got %u\n", expected_len, lenA); +} + +static inline void cpinfo_cmp(MIMECPINFO *cpinfo1, MIMECPINFO *cpinfo2) +{ + ok(cpinfo1->dwFlags == cpinfo2->dwFlags, "dwFlags mismatch: %08x != %08x\n", cpinfo1->dwFlags, cpinfo2->dwFlags); + ok(cpinfo1->uiCodePage == cpinfo2->uiCodePage, "uiCodePage mismatch: %u != %u\n", cpinfo1->uiCodePage, cpinfo2->uiCodePage); + ok(cpinfo1->uiFamilyCodePage == cpinfo2->uiFamilyCodePage, "uiFamilyCodePage mismatch: %u != %u\n", cpinfo1->uiFamilyCodePage, cpinfo2->uiFamilyCodePage); + ok(!lstrcmpW(cpinfo1->wszDescription, cpinfo2->wszDescription), "wszDescription mismatch\n"); + ok(!lstrcmpW(cpinfo1->wszWebCharset, cpinfo2->wszWebCharset), "wszWebCharset mismatch\n"); + ok(!lstrcmpW(cpinfo1->wszHeaderCharset, cpinfo2->wszHeaderCharset), "wszHeaderCharset mismatch\n"); + ok(!lstrcmpW(cpinfo1->wszBodyCharset, cpinfo2->wszBodyCharset), "wszBodyCharset mismatch\n"); + ok(!lstrcmpW(cpinfo1->wszFixedWidthFont, cpinfo2->wszFixedWidthFont), "wszFixedWidthFont mismatch\n"); + ok(!lstrcmpW(cpinfo1->wszProportionalFont, cpinfo2->wszProportionalFont), "wszProportionalFont mismatch\n"); + ok(cpinfo1->bGDICharset == cpinfo2->bGDICharset, "bGDICharset mismatch: %d != %d\n", cpinfo1->bGDICharset, cpinfo2->bGDICharset); +} + +#ifdef DUMP_CP_INFO +static const char *dump_mime_flags(DWORD flags) +{ + static char buf[1024]; + + buf[0] = 0; + + if (flags & MIMECONTF_MAILNEWS) strcat(buf, " MIMECONTF_MAILNEWS"); + if (flags & MIMECONTF_BROWSER) strcat(buf, " MIMECONTF_BROWSER"); + if (flags & MIMECONTF_MINIMAL) strcat(buf, " MIMECONTF_MINIMAL"); + if (flags & MIMECONTF_IMPORT) strcat(buf, " MIMECONTF_IMPORT"); + if (flags & MIMECONTF_SAVABLE_MAILNEWS) strcat(buf, " MIMECONTF_SAVABLE_MAILNEWS"); + if (flags & MIMECONTF_SAVABLE_BROWSER) strcat(buf, " MIMECONTF_SAVABLE_BROWSER"); + if (flags & MIMECONTF_EXPORT) strcat(buf, " MIMECONTF_EXPORT"); + if (flags & MIMECONTF_PRIVCONVERTER) strcat(buf, " MIMECONTF_PRIVCONVERTER"); + if (flags & MIMECONTF_VALID) strcat(buf, " MIMECONTF_VALID"); + if (flags & MIMECONTF_VALID_NLS) strcat(buf, " MIMECONTF_VALID_NLS"); + if (flags & MIMECONTF_MIME_IE4) strcat(buf, " MIMECONTF_MIME_IE4"); + if (flags & MIMECONTF_MIME_LATEST) strcat(buf, " MIMECONTF_MIME_LATEST"); + if (flags & MIMECONTF_MIME_REGISTRY) strcat(buf, " MIMECONTF_MIME_REGISTRY"); + + return buf; +} +#endif + +static void test_EnumCodePages(IMultiLanguage2 *iML2, DWORD flags) +{ + IEnumCodePage *iEnumCP = NULL; + MIMECPINFO *cpinfo; + MIMECPINFO cpinfo2; + HRESULT ret; + ULONG i, n; + UINT total; + + total = 0; + TRACE_2("Call IMultiLanguage2_GetNumberOfCodePageInfo\n"); + ret = IMultiLanguage2_GetNumberOfCodePageInfo(iML2, &total); + ok(ret == S_OK && total != 0, "IMultiLanguage2_GetNumberOfCodePageInfo: expected S_OK/!0, got %08x/%u\n", ret, total); + + trace("total mlang supported codepages %u\n", total); + + TRACE_2("Call IMultiLanguage2_EnumCodePages\n"); + ret = IMultiLanguage2_EnumCodePages(iML2, flags, LANG_NEUTRAL, &iEnumCP); + trace("IMultiLanguage2_EnumCodePages = %08x, iEnumCP = %p\n", ret, iEnumCP); + ok(ret == S_OK && iEnumCP, "IMultiLanguage2_EnumCodePages: expected S_OK/!NULL, got %08x/%p\n", ret, iEnumCP); + + TRACE_2("Call IEnumCodePage_Reset\n"); + ret = IEnumCodePage_Reset(iEnumCP); + ok(ret == S_OK, "IEnumCodePage_Reset: expected S_OK, got %08x\n", ret); + n = 65536; + TRACE_2("Call IEnumCodePage_Next\n"); + ret = IEnumCodePage_Next(iEnumCP, 0, NULL, &n); + ok(n == 0 && ret == S_FALSE, "IEnumCodePage_Next: expected 0/S_FALSE, got %u/%08x\n", n, ret); + TRACE_2("Call IEnumCodePage_Next\n"); + ret = IEnumCodePage_Next(iEnumCP, 0, NULL, NULL); + ok(ret == S_FALSE, "IEnumCodePage_Next: expected S_FALSE, got %08x\n", ret); + + cpinfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*cpinfo) * total * 2); + + n = total * 2; + TRACE_2("Call IEnumCodePage_Next\n"); + ret = IEnumCodePage_Next(iEnumCP, 0, cpinfo, &n); + trace("IEnumCodePage_Next = %08x, n = %u\n", ret, n); + ok(ret == S_FALSE && n == 0, "IEnumCodePage_Next: expected S_FALSE/0, got %08x/%u\n", ret, n); + + n = total * 2; + TRACE_2("Call IEnumCodePage_Next\n"); + ret = IEnumCodePage_Next(iEnumCP, n, cpinfo, &n); + ok(ret == S_OK && n != 0, "IEnumCodePage_Next: expected S_OK/!0, got %08x/%u\n", ret, n); + + trace("flags %08x, enumerated codepages %u\n", flags, n); + + if (!flags) + { + ok(n == total, "IEnumCodePage_Next: expected %u, got %u\n", total, n); + + flags = MIMECONTF_MIME_LATEST; + } + + total = n; + + for (i = 0; i < n; i++) + { + CPINFOEXA cpinfoex; + CHARSETINFO csi; + MIMECSETINFO mcsi; + static const WCHAR autoW[] = {'_','a','u','t','o',0}; + +#ifdef DUMP_CP_INFO + trace("MIMECPINFO #%u:\n" + "dwFlags %08x %s\n" + "uiCodePage %u\n" + "uiFamilyCodePage %u\n" + "wszDescription %s\n" + "wszWebCharset %s\n" + "wszHeaderCharset %s\n" + "wszBodyCharset %s\n" + "wszFixedWidthFont %s\n" + "wszProportionalFont %s\n" + "bGDICharset %d\n\n", + i, + cpinfo[i].dwFlags, dump_mime_flags(cpinfo[i].dwFlags), + cpinfo[i].uiCodePage, + cpinfo[i].uiFamilyCodePage, + wine_dbgstr_w(cpinfo[i].wszDescription), + wine_dbgstr_w(cpinfo[i].wszWebCharset), + wine_dbgstr_w(cpinfo[i].wszHeaderCharset), + wine_dbgstr_w(cpinfo[i].wszBodyCharset), + wine_dbgstr_w(cpinfo[i].wszFixedWidthFont), + wine_dbgstr_w(cpinfo[i].wszProportionalFont), + cpinfo[i].bGDICharset); +#endif + ok(cpinfo[i].dwFlags & flags, "enumerated flags %08x do not include requested %08x\n", cpinfo[i].dwFlags, flags); + + if (TranslateCharsetInfo((DWORD *)cpinfo[i].uiFamilyCodePage, &csi, TCI_SRCCODEPAGE)) + ok(cpinfo[i].bGDICharset == csi.ciCharset, "%d != %d\n", cpinfo[i].bGDICharset, csi.ciCharset); + else + trace("TranslateCharsetInfo failed for cp %u\n", cpinfo[i].uiFamilyCodePage); + + if (pGetCPInfoExA) + { + if (pGetCPInfoExA(cpinfo[i].uiCodePage, 0, &cpinfoex)) + trace("CodePage %u name: %s\n", cpinfo[i].uiCodePage, cpinfoex.CodePageName); + else + trace("GetCPInfoExA failed for cp %u\n", cpinfo[i].uiCodePage); + if (pGetCPInfoExA(cpinfo[i].uiFamilyCodePage, 0, &cpinfoex)) + trace("CodePage %u name: %s\n", cpinfo[i].uiFamilyCodePage, cpinfoex.CodePageName); + else + trace("GetCPInfoExA failed for cp %u\n", cpinfo[i].uiFamilyCodePage); + } + + /* Win95 does not support UTF-7 */ + if (cpinfo[i].uiCodePage == CP_UTF7) continue; + + /* support files for some codepages might be not installed, or + * the codepage is just an alias. + */ + if (IsValidCodePage(cpinfo[i].uiCodePage)) + { + TRACE_2("Call IMultiLanguage2_IsConvertible\n"); + ret = IMultiLanguage2_IsConvertible(iML2, cpinfo[i].uiCodePage, CP_UNICODE); + ok(ret == S_OK, "IMultiLanguage2_IsConvertible(%u -> CP_UNICODE) = %08x\n", cpinfo[i].uiCodePage, ret); + TRACE_2("Call IMultiLanguage2_IsConvertible\n"); + ret = IMultiLanguage2_IsConvertible(iML2, CP_UNICODE, cpinfo[i].uiCodePage); + ok(ret == S_OK, "IMultiLanguage2_IsConvertible(CP_UNICODE -> %u) = %08x\n", cpinfo[i].uiCodePage, ret); + + TRACE_2("Call IMultiLanguage2_IsConvertible\n"); + ret = IMultiLanguage2_IsConvertible(iML2, cpinfo[i].uiCodePage, CP_UTF8); + ok(ret == S_OK, "IMultiLanguage2_IsConvertible(%u -> CP_UTF8) = %08x\n", cpinfo[i].uiCodePage, ret); + TRACE_2("Call IMultiLanguage2_IsConvertible\n"); + ret = IMultiLanguage2_IsConvertible(iML2, CP_UTF8, cpinfo[i].uiCodePage); + ok(ret == S_OK, "IMultiLanguage2_IsConvertible(CP_UTF8 -> %u) = %08x\n", cpinfo[i].uiCodePage, ret); + } + else + trace("IsValidCodePage failed for cp %u\n", cpinfo[i].uiCodePage); + + ret = IMultiLanguage2_GetCharsetInfo(iML2, cpinfo[i].wszWebCharset, &mcsi); + /* _autoxxx charsets are a fake and GetCharsetInfo fails for them */ + if (memcmp(cpinfo[i].wszWebCharset, autoW, 5 * sizeof(WCHAR))) + { + ok (ret == S_OK, "IMultiLanguage2_GetCharsetInfo failed: %08x\n", ret); +#ifdef DUMP_CP_INFO + trace("%s: %u %u %s\n", wine_dbgstr_w(cpinfo[i].wszWebCharset), mcsi.uiCodePage, mcsi.uiInternetEncoding, wine_dbgstr_w(mcsi.wszCharset)); +#endif + ok(!lstrcmpiW(cpinfo[i].wszWebCharset, mcsi.wszCharset), +#ifdef DUMP_CP_INFO + "%s != %s\n", + wine_dbgstr_w(cpinfo[i].wszWebCharset), wine_dbgstr_w(mcsi.wszCharset)); +#else + "wszWebCharset mismatch"); +#endif + + if (0) + { + /* native mlang returns completely messed up encodings in some cases */ + ok(mcsi.uiInternetEncoding == cpinfo[i].uiCodePage || mcsi.uiInternetEncoding == cpinfo[i].uiFamilyCodePage, + "%u != %u || %u\n", mcsi.uiInternetEncoding, cpinfo[i].uiCodePage, cpinfo[i].uiFamilyCodePage); + ok(mcsi.uiCodePage == cpinfo[i].uiCodePage || mcsi.uiCodePage == cpinfo[i].uiFamilyCodePage, + "%u != %u || %u\n", mcsi.uiCodePage, cpinfo[i].uiCodePage, cpinfo[i].uiFamilyCodePage); + } + } + + ret = IMultiLanguage2_GetCharsetInfo(iML2, cpinfo[i].wszHeaderCharset, &mcsi); + /* _autoxxx charsets are a fake and GetCharsetInfo fails for them */ + if (memcmp(cpinfo[i].wszHeaderCharset, autoW, 5 * sizeof(WCHAR))) + { + ok (ret == S_OK, "IMultiLanguage2_GetCharsetInfo failed: %08x\n", ret); +#ifdef DUMP_CP_INFO + trace("%s: %u %u %s\n", wine_dbgstr_w(cpinfo[i].wszHeaderCharset), mcsi.uiCodePage, mcsi.uiInternetEncoding, wine_dbgstr_w(mcsi.wszCharset)); +#endif + ok(!lstrcmpiW(cpinfo[i].wszHeaderCharset, mcsi.wszCharset), +#ifdef DUMP_CP_INFO + "%s != %s\n", + wine_dbgstr_w(cpinfo[i].wszHeaderCharset), wine_dbgstr_w(mcsi.wszCharset)); +#else + "wszHeaderCharset mismatch"); +#endif + + if (0) + { + /* native mlang returns completely messed up encodings in some cases */ + ok(mcsi.uiInternetEncoding == cpinfo[i].uiCodePage || mcsi.uiInternetEncoding == cpinfo[i].uiFamilyCodePage, + "%u != %u || %u\n", mcsi.uiInternetEncoding, cpinfo[i].uiCodePage, cpinfo[i].uiFamilyCodePage); + ok(mcsi.uiCodePage == cpinfo[i].uiCodePage || mcsi.uiCodePage == cpinfo[i].uiFamilyCodePage, + "%u != %u || %u\n", mcsi.uiCodePage, cpinfo[i].uiCodePage, cpinfo[i].uiFamilyCodePage); + } + } + + ret = IMultiLanguage2_GetCharsetInfo(iML2, cpinfo[i].wszBodyCharset, &mcsi); + /* _autoxxx charsets are a fake and GetCharsetInfo fails for them */ + if (memcmp(cpinfo[i].wszBodyCharset, autoW, 5 * sizeof(WCHAR))) + { + ok (ret == S_OK, "IMultiLanguage2_GetCharsetInfo failed: %08x\n", ret); +#ifdef DUMP_CP_INFO + trace("%s: %u %u %s\n", wine_dbgstr_w(cpinfo[i].wszBodyCharset), mcsi.uiCodePage, mcsi.uiInternetEncoding, wine_dbgstr_w(mcsi.wszCharset)); +#endif + ok(!lstrcmpiW(cpinfo[i].wszBodyCharset, mcsi.wszCharset), +#ifdef DUMP_CP_INFO + "%s != %s\n", + wine_dbgstr_w(cpinfo[i].wszBodyCharset), wine_dbgstr_w(mcsi.wszCharset)); +#else + "wszBodyCharset mismatch"); +#endif + + if (0) + { + /* native mlang returns completely messed up encodings in some cases */ + ok(mcsi.uiInternetEncoding == cpinfo[i].uiCodePage || mcsi.uiInternetEncoding == cpinfo[i].uiFamilyCodePage, + "%u != %u || %u\n", mcsi.uiInternetEncoding, cpinfo[i].uiCodePage, cpinfo[i].uiFamilyCodePage); + ok(mcsi.uiCodePage == cpinfo[i].uiCodePage || mcsi.uiCodePage == cpinfo[i].uiFamilyCodePage, + "%u != %u || %u\n", mcsi.uiCodePage, cpinfo[i].uiCodePage, cpinfo[i].uiFamilyCodePage); + } + } + + trace("---\n"); + } + + /* now IEnumCodePage_Next should fail, since pointer is at the end */ + n = 1; + ret = IEnumCodePage_Next(iEnumCP, 1, &cpinfo2, &n); + ok(ret == S_FALSE && n == 0, "IEnumCodePage_Next: expected S_FALSE/0, got %08x/%u\n", ret, n); + + ret = IEnumCodePage_Reset(iEnumCP); + ok(ret == S_OK, "IEnumCodePage_Reset: expected S_OK, got %08x\n", ret); + n = 0; + ret = IEnumCodePage_Next(iEnumCP, 1, &cpinfo2, &n); + ok(n == 1 && ret == S_OK, "IEnumCodePage_Next: expected 1/S_OK, got %u/%08x\n", n, ret); + cpinfo_cmp(&cpinfo[0], &cpinfo2); + + if (0) + { + /* Due to a bug in MS' implementation of IEnumCodePage_Skip + * it's not used here. + */ + ret = IEnumCodePage_Skip(iEnumCP, 1); + ok(ret == S_OK, "IEnumCodePage_Skip: expected S_OK, got %08x\n", ret); + } + for (i = 0; i < total - 1; i++) + { + n = 0; + ret = IEnumCodePage_Next(iEnumCP, 1, &cpinfo2, &n); + ok(n == 1 && ret == S_OK, "IEnumCodePage_Next: expected 1/S_OK, got %u/%08x\n", n, ret); + cpinfo_cmp(&cpinfo[i + 1], &cpinfo2); + } + + HeapFree(GetProcessHeap(), 0, cpinfo); + IEnumCodePage_Release(iEnumCP); +} + +static inline void scriptinfo_cmp(SCRIPTINFO *sinfo1, SCRIPTINFO *sinfo2) +{ + ok(sinfo1->ScriptId == sinfo2->ScriptId, "ScriptId mismatch: %d != %d\n", sinfo1->ScriptId, sinfo2->ScriptId); + ok(sinfo1->uiCodePage == sinfo2->uiCodePage, "uiCodePage mismatch: %u != %u\n", sinfo1->uiCodePage, sinfo2->uiCodePage); + ok(!lstrcmpW(sinfo1->wszDescription, sinfo2->wszDescription), "wszDescription mismatch\n"); + ok(!lstrcmpW(sinfo1->wszFixedWidthFont, sinfo2->wszFixedWidthFont), "wszFixedWidthFont mismatch\n"); + ok(!lstrcmpW(sinfo1->wszProportionalFont, sinfo2->wszProportionalFont), "wszProportionalFont mismatch\n"); +} + +static void test_EnumScripts(IMultiLanguage2 *iML2, DWORD flags) +{ + IEnumScript *iEnumScript = NULL; + SCRIPTINFO *sinfo; + SCRIPTINFO sinfo2; + HRESULT ret; + ULONG i, n; + UINT total; + + total = 0; + TRACE_2("Call IMultiLanguage2_GetNumberOfScripts\n"); + ret = IMultiLanguage2_GetNumberOfScripts(iML2, &total); + ok(ret == S_OK && total != 0, "IMultiLanguage2_GetNumberOfScripts: expected S_OK/!0, got %08x/%u\n", ret, total); + + trace("total mlang supported scripts %u\n", total); + + TRACE_2("Call IMultiLanguage2_EnumScripts\n"); + ret = IMultiLanguage2_EnumScripts(iML2, flags, LANG_NEUTRAL, &iEnumScript); + trace("IMultiLanguage2_EnumScripts = %08x, iEnumScript = %p\n", ret, iEnumScript); + ok(ret == S_OK && iEnumScript, "IMultiLanguage2_EnumScripts: expected S_OK/!NULL, got %08x/%p\n", ret, iEnumScript); + + TRACE_2("Call IEnumScript_Reset\n"); + ret = IEnumScript_Reset(iEnumScript); + ok(ret == S_OK, "IEnumScript_Reset: expected S_OK, got %08x\n", ret); + n = 65536; + TRACE_2("Call IEnumScript_Next\n"); + ret = IEnumScript_Next(iEnumScript, 0, NULL, &n); + ok(n == 65536 && ret == E_FAIL, "IEnumScript_Next: expected 65536/E_FAIL, got %u/%08x\n", n, ret); + TRACE_2("Call IEnumScript_Next\n"); + ret = IEnumScript_Next(iEnumScript, 0, NULL, NULL); + ok(ret == E_FAIL, "IEnumScript_Next: expected E_FAIL, got %08x\n", ret); + + sinfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*sinfo) * total * 2); + + n = total * 2; + TRACE_2("Call IEnumScript_Next\n"); + ret = IEnumScript_Next(iEnumScript, 0, sinfo, &n); + ok(ret == S_FALSE && n == 0, "IEnumScript_Next: expected S_FALSE/0, got %08x/%u\n", ret, n); + + n = total * 2; + TRACE_2("Call IEnumScript_Next\n"); + ret = IEnumScript_Next(iEnumScript, n, sinfo, &n); + ok(ret == S_OK && n != 0, "IEnumScript_Next: expected S_OK, got %08x/%u\n", ret, n); + + trace("flags %08x, enumerated scripts %u\n", flags, n); + + if (!flags) + { + ok(n == total, "IEnumScript_Next: expected %u, got %u\n", total, n); + flags = SCRIPTCONTF_SCRIPT_USER | SCRIPTCONTF_SCRIPT_HIDE | SCRIPTCONTF_SCRIPT_SYSTEM; + } + + total = n; + + for (i = 0; pGetCPInfoExA && i < n; i++) + { + CPINFOEXA cpinfoex; +#ifdef DUMP_SCRIPT_INFO + trace("SCRIPTINFO #%u:\n" + "ScriptId %08x\n" + "uiCodePage %u\n" + "wszDescription %s\n" + "wszFixedWidthFont %s\n" + "wszProportionalFont %s\n\n", + i, + sinfo[i].ScriptId, + sinfo[i].uiCodePage, + wine_dbgstr_w(sinfo[i].wszDescription), + wine_dbgstr_w(sinfo[i].wszFixedWidthFont), + wine_dbgstr_w(sinfo[i].wszProportionalFont)); +#endif + if (pGetCPInfoExA(sinfo[i].uiCodePage, 0, &cpinfoex)) + trace("CodePage %u name: %s\n", sinfo[i].uiCodePage, cpinfoex.CodePageName); + else + trace("GetCPInfoExA failed for cp %u\n", sinfo[i].uiCodePage); + + trace("---\n"); + } + + /* now IEnumScript_Next should fail, since pointer is at the end */ + n = 1; + ret = IEnumScript_Next(iEnumScript, 1, &sinfo2, &n); + ok(ret == S_FALSE && n == 0, "IEnumScript_Next: expected S_FALSE/0, got %08x/%u\n", ret, n); + + ret = IEnumScript_Reset(iEnumScript); + ok(ret == S_OK, "IEnumScript_Reset: expected S_OK, got %08x\n", ret); + n = 0; + ret = IEnumScript_Next(iEnumScript, 1, &sinfo2, &n); + ok(n == 1 && ret == S_OK, "IEnumScript_Next: expected 1/S_OK, got %u/%08x\n", n, ret); + scriptinfo_cmp(&sinfo[0], &sinfo2); + + if (0) + { + /* Due to a bug in MS' implementation of IEnumScript_Skip + * it's not used here. + */ + ret = IEnumScript_Skip(iEnumScript, 1); + ok(ret == S_OK, "IEnumScript_Skip: expected S_OK, got %08x\n", ret); + } + for (i = 0; i < total - 1; i++) + { + n = 0; + ret = IEnumScript_Next(iEnumScript, 1, &sinfo2, &n); + ok(n == 1 && ret == S_OK, "IEnumScript_Next: expected 1/S_OK, got %u/%08x\n", n, ret); + scriptinfo_cmp(&sinfo[i + 1], &sinfo2); + } + + HeapFree(GetProcessHeap(), 0, sinfo); + IEnumScript_Release(iEnumScript); +} + +static void IMLangFontLink_Test(IMLangFontLink* iMLFL) +{ + DWORD dwCodePages = 0; + DWORD dwManyCodePages = 0; + UINT CodePage = 0; + + ok(IMLangFontLink_CodePageToCodePages(iMLFL, 932, &dwCodePages)==S_OK, + "IMLangFontLink_CodePageToCodePages failed\n"); + ok (dwCodePages != 0, "No CodePages returned\n"); + ok(IMLangFontLink_CodePagesToCodePage(iMLFL, dwCodePages, 1035, + &CodePage)==S_OK, + "IMLangFontLink_CodePagesToCodePage failed\n"); + ok(CodePage == 932, "Incorrect CodePage Returned (%i)\n",CodePage); + + ok(IMLangFontLink_CodePageToCodePages(iMLFL, 1252, &dwCodePages)==S_OK, + "IMLangFontLink_CodePageToCodePages failed\n"); + dwManyCodePages = dwManyCodePages | dwCodePages; + ok(IMLangFontLink_CodePageToCodePages(iMLFL, 1256, &dwCodePages)==S_OK, + "IMLangFontLink_CodePageToCodePages failed\n"); + dwManyCodePages = dwManyCodePages | dwCodePages; + ok(IMLangFontLink_CodePageToCodePages(iMLFL, 874, &dwCodePages)==S_OK, + "IMLangFontLink_CodePageToCodePages failed\n"); + dwManyCodePages = dwManyCodePages | dwCodePages; + + ok(IMLangFontLink_CodePagesToCodePage(iMLFL, dwManyCodePages, 1256, + &CodePage)==S_OK, + "IMLangFontLink_CodePagesToCodePage failed\n"); + ok(CodePage == 1256, "Incorrect CodePage Returned (%i)\n",CodePage); + + ok(IMLangFontLink_CodePagesToCodePage(iMLFL, dwManyCodePages, 936, + &CodePage)==S_OK, + "IMLangFontLink_CodePagesToCodePage failed\n"); + ok(CodePage == 1252, "Incorrect CodePage Returned (%i)\n",CodePage); +} + +static void test_rfc1766(IMultiLanguage2 *iML2) +{ + IEnumRfc1766 *pEnumRfc1766; + RFC1766INFO info; + ULONG n; + HRESULT ret; + + ret = IMultiLanguage2_EnumRfc1766(iML2, LANG_NEUTRAL, &pEnumRfc1766); + ok(ret == S_OK, "IMultiLanguage2_EnumRfc1766 error %08x\n", ret); + + while (1) + { + ret = IEnumRfc1766_Next(pEnumRfc1766, 1, &info, &n); + if (ret != S_OK) break; + +#ifdef DUMP_CP_INFO + trace("lcid %04x rfc_name %s locale_name %s\n", + info.lcid, wine_dbgstr_w(info.wszRfc1766), wine_dbgstr_w(info.wszLocaleName)); +#endif + + ok(n == 1, "couldn't fetch 1 RFC1766INFO structure\n"); + ok(IsValidLocale(info.lcid, LCID_SUPPORTED), "invalid lcid %04x\n", info.lcid); + } +} + +static void test_GetLcidFromRfc1766(IMultiLanguage2 *iML2) +{ + LCID lcid; + HRESULT ret; + + static WCHAR e[] = { 'e',0 }; + static WCHAR en[] = { 'e','n',0 }; + static WCHAR empty[] = { 0 }; + static WCHAR dash[] = { '-',0 }; + static WCHAR e_dash[] = { 'e','-',0 }; + static WCHAR en_gb[] = { 'e','n','-','g','b',0 }; + static WCHAR en_us[] = { 'e','n','-','u','s',0 }; + static WCHAR en_them[] = { 'e','n','-','t','h','e','m',0 }; + static WCHAR english[] = { 'e','n','g','l','i','s','h',0 }; + + ret = IMultiLanguage2_GetLcidFromRfc1766(iML2, NULL, en); + ok(ret == E_INVALIDARG, "GetLcidFromRfc1766 returned: %08x\n", ret); + + ret = IMultiLanguage2_GetLcidFromRfc1766(iML2, &lcid, NULL); + ok(ret == E_INVALIDARG, "GetLcidFromRfc1766 returned: %08x\n", ret); + + ret = IMultiLanguage2_GetLcidFromRfc1766(iML2, &lcid, e); + ok(ret == E_FAIL, "GetLcidFromRfc1766 returned: %08x\n", ret); + + ret = IMultiLanguage2_GetLcidFromRfc1766(iML2, &lcid, empty); + ok(ret == E_FAIL, "GetLcidFromRfc1766 returned: %08x\n", ret); + + ret = IMultiLanguage2_GetLcidFromRfc1766(iML2, &lcid, dash); + ok(ret == E_FAIL, "GetLcidFromRfc1766 returned: %08x\n", ret); + + ret = IMultiLanguage2_GetLcidFromRfc1766(iML2, &lcid, e_dash); + ok(ret == E_FAIL, "GetLcidFromRfc1766 returned: %08x\n", ret); + + ret = IMultiLanguage2_GetLcidFromRfc1766(iML2, &lcid, en_them); + ok(ret == E_FAIL, "GetLcidFromRfc1766 returned: %08x\n", ret); + + ret = IMultiLanguage2_GetLcidFromRfc1766(iML2, &lcid, english); + ok(ret == E_FAIL, "GetLcidFromRfc1766 returned: %08x\n", ret); + + lcid = 0; + + ret = IMultiLanguage2_GetLcidFromRfc1766(iML2, &lcid, en); + ok(ret == S_OK, "GetLcidFromRfc1766 returned: %08x\n", ret); + ok(lcid == 9, "got wrong lcid: %04x\n", lcid); + + ret = IMultiLanguage2_GetLcidFromRfc1766(iML2, &lcid, en_gb); + ok(ret == S_OK, "GetLcidFromRfc1766 returned: %08x\n", ret); + ok(lcid == 0x809, "got wrong lcid: %04x\n", lcid); + + ret = IMultiLanguage2_GetLcidFromRfc1766(iML2, &lcid, en_us); + ok(ret == S_OK, "GetLcidFromRfc1766 returned: %08x\n", ret); + ok(lcid == 0x409, "got wrong lcid: %04x\n", lcid); +} + +START_TEST(mlang) +{ + IMultiLanguage2 *iML2 = NULL; + IMLangFontLink *iMLFL = NULL; + HRESULT ret; + + pGetCPInfoExA = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetCPInfoExA"); + + CoInitialize(NULL); + TRACE_2("Call CoCreateInstance\n"); + ret = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, + &IID_IMultiLanguage2, (void **)&iML2); + + trace("ret = %08x, MultiLanguage2 iML2 = %p\n", ret, iML2); + if (ret != S_OK || !iML2) return; + + test_rfc1766(iML2); + test_GetLcidFromRfc1766(iML2); + + test_EnumCodePages(iML2, 0); + test_EnumCodePages(iML2, MIMECONTF_MIME_LATEST); + test_EnumCodePages(iML2, MIMECONTF_BROWSER); + test_EnumCodePages(iML2, MIMECONTF_MINIMAL); + test_EnumCodePages(iML2, MIMECONTF_VALID); + /* FIXME: why MIMECONTF_MIME_REGISTRY returns 0 of supported codepages? */ + /*test_EnumCodePages(iML2, MIMECONTF_MIME_REGISTRY);*/ + + test_EnumScripts(iML2, 0); + test_EnumScripts(iML2, SCRIPTCONTF_SCRIPT_USER); + test_EnumScripts(iML2, SCRIPTCONTF_SCRIPT_USER | SCRIPTCONTF_SCRIPT_HIDE | SCRIPTCONTF_SCRIPT_SYSTEM); + + TRACE_2("Call IMultiLanguage2_IsConvertible\n"); + ret = IMultiLanguage2_IsConvertible(iML2, CP_UTF8, CP_UNICODE); + ok(ret == S_OK, "IMultiLanguage2_IsConvertible(CP_UTF8 -> CP_UNICODE) = %08x\n", ret); + TRACE_2("Call IMultiLanguage2_IsConvertible\n"); + ret = IMultiLanguage2_IsConvertible(iML2, CP_UNICODE, CP_UTF8); + ok(ret == S_OK, "IMultiLanguage2_IsConvertible(CP_UNICODE -> CP_UTF8) = %08x\n", ret); + + test_multibyte_to_unicode_translations(iML2); + + IMultiLanguage2_Release(iML2); + + ret = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, + &IID_IMLangFontLink, (void **)&iMLFL); + + trace("ret = %08x, IMLangFontLink iMLFL = %p\n", ret, iMLFL); + if (ret != S_OK || !iML2) return; + + IMLangFontLink_Test(iMLFL); + IMLangFontLink_Release(iMLFL); + + CoUninitialize(); +} diff --git a/rostests/winetests/mlang/mlang.rbuild b/rostests/winetests/mlang/mlang.rbuild new file mode 100644 index 00000000000..e3bf83cb867 --- /dev/null +++ b/rostests/winetests/mlang/mlang.rbuild @@ -0,0 +1,15 @@ + + . + + 0x600 + 0x501 + 0x501 + wine + ole32 + gdi32 + kernel32 + uuid + ntdll + mlang.c + testlist.c + diff --git a/rostests/winetests/mlang/testlist.c b/rostests/winetests/mlang/testlist.c new file mode 100644 index 00000000000..db8217cf963 --- /dev/null +++ b/rostests/winetests/mlang/testlist.c @@ -0,0 +1,15 @@ +/* Automatically generated file; DO NOT EDIT!! */ + +#define WIN32_LEAN_AND_MEAN +#include + +#define STANDALONE +#include "wine/test.h" + +extern void func_mlang(void); + +const struct test winetest_testlist[] = +{ + { "mlang", func_mlang }, + { 0, 0 } +}; diff --git a/rostests/winetests/shlwapi/clist.c b/rostests/winetests/shlwapi/clist.c index 6abe85a9efa..5f94b4ff6cc 100755 --- a/rostests/winetests/shlwapi/clist.c +++ b/rostests/winetests/shlwapi/clist.c @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include @@ -214,33 +214,30 @@ static HRESULT (WINAPI *pSHLWAPI_214)(_IDummyStream*,ULARGE_INTEGER*); static void InitFunctionPtrs(void) { - SHLWAPI_hshlwapi = LoadLibraryA("shlwapi.dll"); - ok(SHLWAPI_hshlwapi != 0, "LoadLibrary failed\n"); - if (SHLWAPI_hshlwapi) - { - pSHLWAPI_17 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)17); - ok(pSHLWAPI_17 != 0, "No Ordinal 17\n"); - pSHLWAPI_18 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)18); - ok(pSHLWAPI_18 != 0, "No Ordinal 18\n"); - pSHLWAPI_19 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)19); - ok(pSHLWAPI_19 != 0, "No Ordinal 19\n"); - pSHLWAPI_20 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)20); - ok(pSHLWAPI_20 != 0, "No Ordinal 20\n"); - pSHLWAPI_21 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)21); - ok(pSHLWAPI_21 != 0, "No Ordinal 21\n"); - pSHLWAPI_22 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)22); - ok(pSHLWAPI_22 != 0, "No Ordinal 22\n"); - pSHLWAPI_166 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)166); - ok(pSHLWAPI_166 != 0, "No Ordinal 166\n"); - pSHLWAPI_184 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)184); - ok(pSHLWAPI_184 != 0, "No Ordinal 184\n"); - pSHLWAPI_212 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)212); - ok(pSHLWAPI_212 != 0, "No Ordinal 212\n"); - pSHLWAPI_213 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)213); - ok(pSHLWAPI_213 != 0, "No Ordinal 213\n"); - pSHLWAPI_214 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)214); - ok(pSHLWAPI_214 != 0, "No Ordinal 214\n"); - } + SHLWAPI_hshlwapi = GetModuleHandleA("shlwapi.dll"); + + pSHLWAPI_17 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)17); + ok(pSHLWAPI_17 != 0, "No Ordinal 17\n"); + pSHLWAPI_18 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)18); + ok(pSHLWAPI_18 != 0, "No Ordinal 18\n"); + pSHLWAPI_19 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)19); + ok(pSHLWAPI_19 != 0, "No Ordinal 19\n"); + pSHLWAPI_20 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)20); + ok(pSHLWAPI_20 != 0, "No Ordinal 20\n"); + pSHLWAPI_21 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)21); + ok(pSHLWAPI_21 != 0, "No Ordinal 21\n"); + pSHLWAPI_22 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)22); + ok(pSHLWAPI_22 != 0, "No Ordinal 22\n"); + pSHLWAPI_166 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)166); + ok(pSHLWAPI_166 != 0, "No Ordinal 166\n"); + pSHLWAPI_184 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)184); + ok(pSHLWAPI_184 != 0, "No Ordinal 184\n"); + pSHLWAPI_212 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)212); + ok(pSHLWAPI_212 != 0, "No Ordinal 212\n"); + pSHLWAPI_213 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)213); + ok(pSHLWAPI_213 != 0, "No Ordinal 213\n"); + pSHLWAPI_214 = (void *)GetProcAddress( SHLWAPI_hshlwapi, (LPSTR)214); + ok(pSHLWAPI_214 != 0, "No Ordinal 214\n"); } static void InitDummyStream(_IDummyStream* iface) @@ -299,21 +296,20 @@ static void test_CList(void) inserted = pSHLWAPI_22(list, item->ulId); ok(inserted != NULL, "lost after adding\n"); - ok(!inserted || inserted->ulId != ~0UL, "find returned a container\n"); + ok(!inserted || inserted->ulId != ~0U, "find returned a container\n"); /* Check size */ if (inserted && inserted->ulSize & 0x3) { /* Contained */ - ok(inserted[-1].ulId == ~0UL, "invalid size is not countained\n"); + ok(inserted[-1].ulId == ~0U, "invalid size is not countained\n"); ok(inserted[-1].ulSize > inserted->ulSize+sizeof(SHLWAPI_CLIST), "container too small\n"); } else if (inserted) { ok(inserted->ulSize==item->ulSize+sizeof(SHLWAPI_CLIST), - "id %ld size wrong (%ld!=%ld)\n", inserted->ulId, inserted->ulSize, - item->ulSize+sizeof(SHLWAPI_CLIST)); + "id %d wrong size %d\n", inserted->ulId, inserted->ulSize); } if (inserted) { @@ -370,20 +366,22 @@ static void test_CList(void) /* The call succeeds but the item is not inserted, except on some early * versions which return failure. Wine behaves like later versions. */ -#if 0 + if (0) + { ok(hRet == S_OK, "failed bad element size\n"); -#endif + } inserted = pSHLWAPI_22(list, 33); ok(inserted == NULL, "inserted bad element size\n"); inserted = (LPSHLWAPI_CLIST)buff; inserted->ulSize = 44; - inserted->ulId = ~0UL; + inserted->ulId = ~0U; hRet = pSHLWAPI_20(&list, inserted); /* See comment above, some early versions fail this call */ -#if 0 + if (0) + { ok(hRet == S_OK, "failed adding a container\n"); -#endif + } item = SHLWAPI_CLIST_items; /* Look for nonexistent item in populated list */ @@ -424,21 +422,20 @@ static void test_CList(void) inserted = pSHLWAPI_22(list, item->ulId); ok(inserted != NULL, "lost after adding\n"); - ok(!inserted || inserted->ulId != ~0UL, "find returned a container\n"); + ok(!inserted || inserted->ulId != ~0U, "find returned a container\n"); /* Check size */ if (inserted && inserted->ulSize & 0x3) { /* Contained */ - ok(inserted[-1].ulId == ~0UL, "invalid size is not countained\n"); + ok(inserted[-1].ulId == ~0U, "invalid size is not countained\n"); ok(inserted[-1].ulSize > inserted->ulSize+sizeof(SHLWAPI_CLIST), "container too small\n"); } else if (inserted) { ok(inserted->ulSize==item->ulSize+sizeof(SHLWAPI_CLIST), - "id %ld size wrong (%ld!=%ld)\n", inserted->ulId, inserted->ulSize, - item->ulSize+sizeof(SHLWAPI_CLIST)); + "id %d wrong size %d\n", inserted->ulId, inserted->ulSize); } ok(!inserted || inserted->ulId==item->ulId, "find got wrong item\n"); if (inserted) @@ -637,7 +634,4 @@ START_TEST(clist) test_SHLWAPI_213(); test_SHLWAPI_214(); } - - if (SHLWAPI_hshlwapi) - FreeLibrary(SHLWAPI_hshlwapi); } diff --git a/rostests/winetests/shlwapi/clsid.c b/rostests/winetests/shlwapi/clsid.c index ce496531f3e..74ad6e50b87 100755 --- a/rostests/winetests/shlwapi/clsid.c +++ b/rostests/winetests/shlwapi/clsid.c @@ -14,19 +14,25 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include -#define INITGUID #include "wine/test.h" #include "winbase.h" #include "winerror.h" #include "winnls.h" #include "winuser.h" #include "shlguid.h" -#include "wine/shobjidl.h" +#include "shobjidl.h" +#include "olectl.h" + +#define INITGUID +#include "initguid.h" + +/* This GUID has been removed from the PSDK */ +DEFINE_OLEGUID(WINE_IID_IDelayedRelease, 0x000214EDL, 0, 0); /* Function ptrs for ordinal calls */ static HMODULE hShlwapi = 0; @@ -56,7 +62,7 @@ const GUID * TEST_guids[] = { &IID_IPersistFolder, &IID_IExtractIconA, &IID_IShellDetails, - &IID_IDelayedRelease, + &WINE_IID_IDelayedRelease, &IID_IShellLinkA, &IID_IShellCopyHookA, &IID_IFileViewerA, @@ -153,19 +159,33 @@ static void test_ClassIDs(void) ok(szBuff[0] == '{', "Didn't write to buffer with ok length\n"); } +static void test_CLSIDFromProgIDWrap(void) +{ + HRESULT (WINAPI *pCLSIDFromProgIDWrap)(LPCOLESTR,LPCLSID); + CLSID clsid = IID_NULL; + HRESULT hres; + + static const WCHAR wszStdPicture[] = {'S','t','d','P','i','c','t','u','r','e',0}; + + pCLSIDFromProgIDWrap = (void*)GetProcAddress(hShlwapi,(char*)435); + + hres = pCLSIDFromProgIDWrap(wszStdPicture, &clsid); + ok(hres == S_OK, "CLSIDFromProgIDWrap failed: %08x\n", hres); + ok(IsEqualGUID(&CLSID_StdPicture, &clsid), "wrong clsid\n"); + + hres = pCLSIDFromProgIDWrap(NULL, &clsid); + ok(hres == E_INVALIDARG, "CLSIDFromProgIDWrap failed: %08x, expected E_INVALIDARG\n", hres); + + hres = pCLSIDFromProgIDWrap(wszStdPicture, NULL); + ok(hres == E_INVALIDARG, "CLSIDFromProgIDWrap failed: %08x, expected E_INVALIDARG\n", hres); +} START_TEST(clsid) { - hShlwapi = LoadLibraryA("shlwapi.dll"); - ok(hShlwapi != 0, "LoadLibraryA failed\n"); - if (hShlwapi) - { - pSHLWAPI_269 = (void*)GetProcAddress(hShlwapi, (LPSTR)269); - pSHLWAPI_23 = (void*)GetProcAddress(hShlwapi, (LPSTR)23); - } + hShlwapi = GetModuleHandleA("shlwapi.dll"); + pSHLWAPI_269 = (void*)GetProcAddress(hShlwapi, (LPSTR)269); + pSHLWAPI_23 = (void*)GetProcAddress(hShlwapi, (LPSTR)23); test_ClassIDs(); - - if (hShlwapi) - FreeLibrary(hShlwapi); + test_CLSIDFromProgIDWrap(); } diff --git a/rostests/winetests/shlwapi/generated.c b/rostests/winetests/shlwapi/generated.c index b1f618b87b8..d1bfa4c8200 100755 --- a/rostests/winetests/shlwapi/generated.c +++ b/rostests/winetests/shlwapi/generated.c @@ -157,11 +157,6 @@ static void test_pack_HUSKEY(void) TEST_TYPE(HUSKEY, 4, 4); } -static void test_pack_IQueryAssociations(void) -{ - /* IQueryAssociations */ -} - static void test_pack_PHUSKEY(void) { /* PHUSKEY */ @@ -176,7 +171,6 @@ static void test_pack(void) test_pack_DLLVERSIONINFO(); test_pack_DLLVERSIONINFO2(); test_pack_HUSKEY(); - test_pack_IQueryAssociations(); test_pack_PHUSKEY(); } diff --git a/rostests/winetests/shlwapi/ordinal.c b/rostests/winetests/shlwapi/ordinal.c index 20798c72c9a..c9482747af8 100755 --- a/rostests/winetests/shlwapi/ordinal.c +++ b/rostests/winetests/shlwapi/ordinal.c @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include @@ -46,8 +46,8 @@ static void test_GetAcceptLanguagesA(void) memset(buffer, 0, sizeof(buffer)); SetLastError(ERROR_SUCCESS); retval = pGetAcceptLanguagesA( buffer, &buffersize); - trace("GetAcceptLanguagesA: retval %08lx, size %08lx, buffer (%s)," - " last error %ld\n", retval, buffersize, buffer, GetLastError()); + trace("GetAcceptLanguagesA: retval %08x, size %08x, buffer (%s)," + " last error %u\n", retval, buffersize, buffer, GetLastError()); if(retval != S_OK) { trace("GetAcceptLanguagesA: skipping tests\n"); return; @@ -56,39 +56,39 @@ static void test_GetAcceptLanguagesA(void) (ERROR_CLASS_DOES_NOT_EXIST == GetLastError()) || (ERROR_PROC_NOT_FOUND == GetLastError()) || (ERROR_CALL_NOT_IMPLEMENTED == GetLastError()) || - (ERROR_SUCCESS == GetLastError()), "last error set to %ld\n", GetLastError()); + (ERROR_SUCCESS == GetLastError()), "last error set to %u\n", GetLastError()); exactsize = strlen(buffer); SetLastError(ERROR_SUCCESS); retval = pGetAcceptLanguagesA( NULL, NULL); ok(retval == E_FAIL, - "function result wrong: got %08lx; expected E_FAIL\n", retval); - ok(ERROR_SUCCESS == GetLastError(), "last error set to %ld\n", GetLastError()); + "function result wrong: got %08x; expected E_FAIL\n", retval); + ok(ERROR_SUCCESS == GetLastError(), "last error set to %u\n", GetLastError()); buffersize = sizeof(buffer); SetLastError(ERROR_SUCCESS); retval = pGetAcceptLanguagesA( NULL, &buffersize); ok(retval == E_FAIL, - "function result wrong: got %08lx; expected E_FAIL\n", retval); + "function result wrong: got %08x; expected E_FAIL\n", retval); ok(buffersize == sizeof(buffer), "buffersize was changed (2nd parameter; not on Win2k)\n"); - ok(ERROR_SUCCESS == GetLastError(), "last error set to %ld\n", GetLastError()); + ok(ERROR_SUCCESS == GetLastError(), "last error set to %u\n", GetLastError()); SetLastError(ERROR_SUCCESS); retval = pGetAcceptLanguagesA( buffer, NULL); ok(retval == E_FAIL, - "function result wrong: got %08lx; expected E_FAIL\n", retval); - ok(ERROR_SUCCESS == GetLastError(), "last error set to %ld\n", GetLastError()); + "function result wrong: got %08x; expected E_FAIL\n", retval); + ok(ERROR_SUCCESS == GetLastError(), "last error set to %u\n", GetLastError()); buffersize = 0; memset(buffer, 0, sizeof(buffer)); SetLastError(ERROR_SUCCESS); retval = pGetAcceptLanguagesA( buffer, &buffersize); ok(retval == E_FAIL, - "function result wrong: got %08lx; expected E_FAIL\n", retval); + "function result wrong: got %08x; expected E_FAIL\n", retval); ok(buffersize == 0, - "buffersize wrong(changed) got %08lx; expected 0 (2nd parameter; not on Win2k)\n", buffersize); - ok(ERROR_SUCCESS == GetLastError(), "last error set to %ld\n", GetLastError()); + "buffersize wrong(changed) got %08x; expected 0 (2nd parameter; not on Win2k)\n", buffersize); + ok(ERROR_SUCCESS == GetLastError(), "last error set to %u\n", GetLastError()); buffersize = buffersize2 = 1; memset(buffer, 0, sizeof(buffer)); @@ -99,29 +99,29 @@ static void test_GetAcceptLanguagesA(void) if(buffersize == exactsize) { ok( (ERROR_SUCCESS == GetLastError()) || (ERROR_CALL_NOT_IMPLEMENTED == GetLastError()) || (ERROR_PROC_NOT_FOUND == GetLastError()) || (ERROR_NO_IMPERSONATION_TOKEN == GetLastError()), - "last error wrong: got %08lx; expected ERROR_SUCCESS(NT4)/ERROR_CALL_NOT_IMPLEMENTED(98/ME)/" + "last error wrong: got %u; expected ERROR_SUCCESS(NT4)/ERROR_CALL_NOT_IMPLEMENTED(98/ME)/" "ERROR_PROC_NOT_FOUND(NT4)/ERROR_NO_IMPERSONATION_TOKEN(XP)\n", GetLastError()); ok(exactsize == strlen(buffer), - "buffer content (length) wrong: got %08x, expected %08lx \n", strlen(buffer), exactsize); + "buffer content (length) wrong: got %08x, expected %08x\n", lstrlenA(buffer), exactsize); } else if((buffersize +1) == buffersize2) { ok(ERROR_SUCCESS == GetLastError(), - "last error wrong: got %08lx; expected ERROR_SUCCESS\n", GetLastError()); + "last error wrong: got %u; expected ERROR_SUCCESS\n", GetLastError()); ok(buffersize == strlen(buffer), - "buffer content (length) wrong: got %08x, expected %08lx \n", strlen(buffer), buffersize); + "buffer content (length) wrong: got %08x, expected %08x\n", lstrlenA(buffer), buffersize); } else - ok( 0, "retval %08lx, size %08lx, buffer (%s), last error %ld\n", + ok( 0, "retval %08x, size %08x, buffer (%s), last error %u\n", retval, buffersize, buffer, GetLastError()); break; case E_INVALIDARG: ok(buffersize == 0, - "buffersize wrong: got %08lx, expected 0 (2nd parameter;Win2k)\n", buffersize); + "buffersize wrong: got %08x, expected 0 (2nd parameter;Win2k)\n", buffersize); ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), - "last error wrong: got %08lx; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError()); + "last error wrong: got %u; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError()); ok(buffersize2 == strlen(buffer), - "buffer content (length) wrong: got %08x, expected %08lx \n", strlen(buffer), buffersize2); + "buffer content (length) wrong: got %08x, expected %08x\n", lstrlenA(buffer), buffersize2); break; default: - ok( 0, "retval %08lx, size %08lx, buffer (%s), last error %ld\n", + ok( 0, "retval %08x, size %08x, buffer (%s), last error %u\n", retval, buffersize, buffer, GetLastError()); break; } @@ -133,25 +133,25 @@ static void test_GetAcceptLanguagesA(void) switch(retval) { case 0L: ok(ERROR_SUCCESS == GetLastError(), - "last error wrong: got %08lx; expected ERROR_SUCCESS\n", GetLastError()); + "last error wrong: got %u; expected ERROR_SUCCESS\n", GetLastError()); if((buffersize == exactsize) /* XP */ || ((buffersize +1)== exactsize) /* 98 */) ok(buffersize == strlen(buffer), - "buffer content (length) wrong: got %08x, expected %08lx \n", strlen(buffer), buffersize); + "buffer content (length) wrong: got %08x, expected %08x\n", lstrlenA(buffer), buffersize); else - ok( 0, "retval %08lx, size %08lx, buffer (%s), last error %ld\n", + ok( 0, "retval %08x, size %08x, buffer (%s), last error %u\n", retval, buffersize, buffer, GetLastError()); break; case E_INVALIDARG: ok(buffersize == 0, - "buffersize wrong: got %08lx, expected 0 (2nd parameter;Win2k)\n", buffersize); + "buffersize wrong: got %08x, expected 0 (2nd parameter;Win2k)\n", buffersize); ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), - "last error wrong: got %08lx; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError()); + "last error wrong: got %u; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError()); ok(buffersize2 == strlen(buffer), - "buffer content (length) wrong: got %08x, expected %08lx \n", strlen(buffer), buffersize2); + "buffer content (length) wrong: got %08x, expected %08x\n", lstrlenA(buffer), buffersize2); break; default: - ok( 0, "retval %08lx, size %08lx, buffer (%s), last error %ld\n", + ok( 0, "retval %08x, size %08x, buffer (%s), last error %u\n", retval, buffersize, buffer, GetLastError()); break; } @@ -208,31 +208,232 @@ static void test_alloc_shared(void) procid=GetCurrentProcessId(); hmem=pSHAllocShared(NULL,10,procid); - ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %ld\n", GetLastError()); + ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError()); ret = pSHFreeShared(hmem, procid); - ok( ret, "SHFreeShared failed: %ld\n", GetLastError()); + ok( ret, "SHFreeShared failed: %u\n", GetLastError()); val=0x12345678; hmem=pSHAllocShared(&val,4,procid); - ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %ld\n", GetLastError()); + ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError()); p=(int*)pSHLockShared(hmem,procid); - ok(p!=NULL,"SHLockShared failed: %ld\n", GetLastError()); + ok(p!=NULL,"SHLockShared failed: %u\n", GetLastError()); if (p!=NULL) ok(*p==val,"Wrong value in shared memory: %d instead of %d\n",*p,val); ret = pSHUnlockShared(p); - ok( ret, "SHUnlockShared failed: %ld\n", GetLastError()); + ok( ret, "SHUnlockShared failed: %u\n", GetLastError()); ret = pSHFreeShared(hmem, procid); - ok( ret, "SHFreeShared failed: %ld\n", GetLastError()); + ok( ret, "SHFreeShared failed: %u\n", GetLastError()); +} + +static void test_fdsa(void) +{ + typedef struct + { + DWORD num_items; /* Number of elements inserted */ + void *mem; /* Ptr to array */ + DWORD blocks_alloced; /* Number of elements allocated */ + BYTE inc; /* Number of elements to grow by when we need to expand */ + BYTE block_size; /* Size in bytes of an element */ + BYTE flags; /* Flags */ + } FDSA_info; + + BOOL (WINAPI *pFDSA_Initialize)(DWORD block_size, DWORD inc, FDSA_info *info, void *mem, + DWORD init_blocks); + BOOL (WINAPI *pFDSA_Destroy)(FDSA_info *info); + DWORD (WINAPI *pFDSA_InsertItem)(FDSA_info *info, DWORD where, const void *block); + BOOL (WINAPI *pFDSA_DeleteItem)(FDSA_info *info, DWORD where); + + FDSA_info info; + int block_size = 10, init_blocks = 4, inc = 2; + DWORD ret; + char *mem; + + pFDSA_Initialize = (void *)GetProcAddress(hShlwapi, (LPSTR)208); + pFDSA_Destroy = (void *)GetProcAddress(hShlwapi, (LPSTR)209); + pFDSA_InsertItem = (void *)GetProcAddress(hShlwapi, (LPSTR)210); + pFDSA_DeleteItem = (void *)GetProcAddress(hShlwapi, (LPSTR)211); + + mem = HeapAlloc(GetProcessHeap(), 0, block_size * init_blocks); + memset(&info, 0, sizeof(info)); + + ok(pFDSA_Initialize(block_size, inc, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n"); + ok(info.num_items == 0, "num_items = %d\n", info.num_items); + ok(info.mem == mem, "mem = %p\n", info.mem); + ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced); + ok(info.inc == inc, "inc = %d\n", info.inc); + ok(info.block_size == block_size, "block_size = %d\n", info.block_size); + ok(info.flags == 0, "flags = %d\n", info.flags); + + ret = pFDSA_InsertItem(&info, 1234, "1234567890"); + ok(ret == 0, "ret = %d\n", ret); + ok(info.num_items == 1, "num_items = %d\n", info.num_items); + ok(info.mem == mem, "mem = %p\n", info.mem); + ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced); + ok(info.inc == inc, "inc = %d\n", info.inc); + ok(info.block_size == block_size, "block_size = %d\n", info.block_size); + ok(info.flags == 0, "flags = %d\n", info.flags); + + ret = pFDSA_InsertItem(&info, 1234, "abcdefghij"); + ok(ret == 1, "ret = %d\n", ret); + + ret = pFDSA_InsertItem(&info, 1, "klmnopqrst"); + ok(ret == 1, "ret = %d\n", ret); + + ret = pFDSA_InsertItem(&info, 0, "uvwxyzABCD"); + ok(ret == 0, "ret = %d\n", ret); + ok(info.mem == mem, "mem = %p\n", info.mem); + ok(info.flags == 0, "flags = %d\n", info.flags); + + /* This next InsertItem will cause shlwapi to allocate its own mem buffer */ + ret = pFDSA_InsertItem(&info, 0, "EFGHIJKLMN"); + ok(ret == 0, "ret = %d\n", ret); + ok(info.mem != mem, "mem = %p\n", info.mem); + ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced); + ok(info.flags == 0x1, "flags = %d\n", info.flags); + + ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info.mem); + + ok(pFDSA_DeleteItem(&info, 2), "rets FALSE\n"); + ok(info.mem != mem, "mem = %p\n", info.mem); + ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced); + ok(info.flags == 0x1, "flags = %d\n", info.flags); + + ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info.mem); + + ok(pFDSA_DeleteItem(&info, 3), "rets FALSE\n"); + ok(info.mem != mem, "mem = %p\n", info.mem); + ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced); + ok(info.flags == 0x1, "flags = %d\n", info.flags); + + ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info.mem); + + ok(!pFDSA_DeleteItem(&info, 4), "does not ret FALSE\n"); + + /* As shlwapi has allocated memory internally, Destroy will ret FALSE */ + ok(!pFDSA_Destroy(&info), "FDSA_Destroy does not ret FALSE\n"); + + + /* When Initialize is called with inc = 0, set it to 1 */ + ok(pFDSA_Initialize(block_size, 0, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n"); + ok(info.inc == 1, "inc = %d\n", info.inc); + + /* This time, because shlwapi hasn't had to allocate memory + internally, Destroy rets non-zero */ + ok(pFDSA_Destroy(&info), "FDSA_Destroy rets FALSE\n"); + + + HeapFree(GetProcessHeap(), 0, mem); +} + + +typedef struct SHELL_USER_SID { + SID_IDENTIFIER_AUTHORITY sidAuthority; + DWORD dwUserGroupID; + DWORD dwUserID; +} SHELL_USER_SID, *PSHELL_USER_SID; +typedef struct SHELL_USER_PERMISSION { + SHELL_USER_SID susID; + DWORD dwAccessType; + BOOL fInherit; + DWORD dwAccessMask; + DWORD dwInheritMask; + DWORD dwInheritAccessMask; +} SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION; +static void test_GetShellSecurityDescriptor(void) +{ + SHELL_USER_PERMISSION supCurrentUserFull = { + { {SECURITY_NULL_SID_AUTHORITY}, 0, 0 }, + ACCESS_ALLOWED_ACE_TYPE, FALSE, + GENERIC_ALL, 0, 0 }; +#define MY_INHERITANCE 0xBE /* invalid value to proof behavior */ + SHELL_USER_PERMISSION supEveryoneDenied = { + { {SECURITY_WORLD_SID_AUTHORITY}, SECURITY_WORLD_RID, 0 }, + ACCESS_DENIED_ACE_TYPE, TRUE, + GENERIC_WRITE, MY_INHERITANCE | 0xDEADBA00, GENERIC_READ }; + PSHELL_USER_PERMISSION rgsup[2] = { + &supCurrentUserFull, &supEveryoneDenied, + }; + SECURITY_DESCRIPTOR* psd; + SECURITY_DESCRIPTOR* (WINAPI*pGetShellSecurityDescriptor)(PSHELL_USER_PERMISSION*,int); + + pGetShellSecurityDescriptor=(void*)GetProcAddress(hShlwapi,(char*)475); + + psd = pGetShellSecurityDescriptor(NULL, 2); + ok(psd==NULL, "GetShellSecurityDescriptor should fail\n"); + psd = pGetShellSecurityDescriptor(rgsup, 0); + ok(psd==NULL, "GetShellSecurityDescriptor should fail\n"); + + psd = pGetShellSecurityDescriptor(rgsup, 2); + ok(psd!=NULL, "GetShellSecurityDescriptor failed\n"); + if (psd!=NULL) + { + BOOL bHasDacl = FALSE, bDefaulted; + PACL pAcl; + DWORD dwRev; + SECURITY_DESCRIPTOR_CONTROL control; + + ok(IsValidSecurityDescriptor(psd), "returned value is not valid SD\n"); + + ok(GetSecurityDescriptorControl(psd, &control, &dwRev), + "GetSecurityDescriptorControl failed with error %u\n", GetLastError()); + ok(0 == (control & SE_SELF_RELATIVE), "SD should be absolute\n"); + + ok(GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted), + "GetSecurityDescriptorDacl failed with error %u\n", GetLastError()); + + ok(bHasDacl, "SD has no DACL\n"); + if (bHasDacl) + { + ok(!bDefaulted, "DACL should not be defaulted\n"); + + ok(pAcl != NULL, "NULL DACL!\n"); + if (pAcl != NULL) + { + ACL_SIZE_INFORMATION asiSize; + + ok(IsValidAcl(pAcl), "DACL is not valid\n"); + + ok(GetAclInformation(pAcl, &asiSize, sizeof(asiSize), AclSizeInformation), + "GetAclInformation failed with error %u\n", GetLastError()); + + ok(asiSize.AceCount == 3, "Incorrect number of ACEs: %d entries\n", asiSize.AceCount); + if (asiSize.AceCount == 3) + { + ACCESS_ALLOWED_ACE *paaa; /* will use for DENIED too */ + + ok(GetAce(pAcl, 0, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError()); + ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE, + "Invalid ACE type %d\n", paaa->Header.AceType); + ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags); + ok(paaa->Mask == GENERIC_ALL, "Invalid ACE mask %x\n", paaa->Mask); + + ok(GetAce(pAcl, 1, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError()); + ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE, + "Invalid ACE type %d\n", paaa->Header.AceType); + /* first one of two ACEs generated from inheritable entry - without inheritance */ + ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags); + ok(paaa->Mask == GENERIC_WRITE, "Invalid ACE mask %x\n", paaa->Mask); + + ok(GetAce(pAcl, 2, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError()); + ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE, + "Invalid ACE type %d\n", paaa->Header.AceType); + /* second ACE - with inheritance */ + ok(paaa->Header.AceFlags == MY_INHERITANCE, + "Invalid ACE flags %x\n", paaa->Header.AceFlags); + ok(paaa->Mask == GENERIC_READ, "Invalid ACE mask %x\n", paaa->Mask); + } + } + } + + LocalFree(psd); + } } START_TEST(ordinal) { - hShlwapi = LoadLibraryA("shlwapi.dll"); - ok(hShlwapi != 0, "LoadLibraryA failed\n"); - if (!hShlwapi) - return; + hShlwapi = GetModuleHandleA("shlwapi.dll"); pGetAcceptLanguagesA = (void*)GetProcAddress(hShlwapi, (LPSTR)14); pSHSearchMapInt = (void*)GetProcAddress(hShlwapi, (LPSTR)198); @@ -244,5 +445,6 @@ START_TEST(ordinal) test_GetAcceptLanguagesA(); test_SHSearchMapInt(); test_alloc_shared(); - FreeLibrary(hShlwapi); + test_fdsa(); + test_GetShellSecurityDescriptor(); } diff --git a/rostests/winetests/shlwapi/path.c b/rostests/winetests/shlwapi/path.c index 9812e083098..d4ed84d896b 100755 --- a/rostests/winetests/shlwapi/path.c +++ b/rostests/winetests/shlwapi/path.c @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include @@ -24,7 +24,6 @@ #include "wine/test.h" #include "windef.h" #include "winbase.h" -#include "wine/unicode.h" #include "winreg.h" #include "shlwapi.h" #include "wininet.h" @@ -32,6 +31,7 @@ static HMODULE hShlwapi; static HRESULT (WINAPI *pPathIsValidCharA)(char,DWORD); static HRESULT (WINAPI *pPathIsValidCharW)(WCHAR,DWORD); +static LPWSTR (WINAPI *pPathCombineW)(LPWSTR, LPCWSTR, LPCWSTR); const char* TEST_URL_1 = "http://www.winehq.org/tests?date=10/10/1923"; const char* TEST_URL_2 = "http://localhost:8080/tests%2e.html?date=Mon%2010/10/1923"; @@ -60,10 +60,31 @@ const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = { {"http://www.winehq.org/tests/../?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y"}, {"http://www.winehq.org/tests/..#example", 0, S_OK, "http://www.winehq.org/#example"}, {"http://www.winehq.org/tests/../#example", 0, S_OK, "http://www.winehq.org/#example"}, + {"http://www.winehq.org/tests\\../#example", 0, S_OK, "http://www.winehq.org/#example"}, + {"http://www.winehq.org/tests/..\\#example", 0, S_OK, "http://www.winehq.org/#example"}, + {"http://www.winehq.org\\tests/../#example", 0, S_OK, "http://www.winehq.org/#example"}, {"http://www.winehq.org/tests/../#example", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../#example"}, {"http://www.winehq.org/tests/foo bar", URL_ESCAPE_SPACES_ONLY| URL_DONT_ESCAPE_EXTRA_INFO , S_OK, "http://www.winehq.org/tests/foo%20bar"}, {"http://www.winehq.org/tests/foo%20bar", URL_UNESCAPE , S_OK, "http://www.winehq.org/tests/foo bar"}, {"file:///c:/tests/foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar"}, + {"file:///c:/tests\\foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar"}, + {"file:///c:/tests/foo%20bar", 0, S_OK, "file:///c:/tests/foo%20bar"}, + {"file:///c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"}, + {"file://c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"}, + {"file://c:/tests\\../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"}, + {"file://c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"}, + {"file:///c://tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\\\tests\\foo bar"}, + {"file:///c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo bar"}, + {"file:///c:\\tests\\foo bar", URL_DONT_SIMPLIFY, S_OK, "file:///c:/tests/foo bar"}, + {"http://www.winehq.org/site/about", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org/site/about"}, + {"file_://www.winehq.org/site/about", URL_FILE_USE_PATHURL, S_OK, "file_://www.winehq.org/site/about"}, + {"c:\\dir\\file", 0, S_OK, "file:///c:/dir/file"}, + {"file:///c:\\dir\\file", 0, S_OK, "file:///c:/dir/file"}, + {"c:dir\\file", 0, S_OK, "file:///c:dir/file"}, + {"c:\\tests\\foo bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"}, + {"c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo%20bar"}, + {"A", 0, S_OK, "A"}, + {"", 0, S_OK, ""} }; typedef struct _TEST_URL_ESCAPE { @@ -165,8 +186,10 @@ typedef struct _TEST_URL_COMBINE { const TEST_URL_COMBINE TEST_COMBINE[] = { {"http://www.winehq.org/tests", "tests1", 0, S_OK, "http://www.winehq.org/tests1"}, + {"http://www.%77inehq.org/tests", "tests1", 0, S_OK, "http://www.%77inehq.org/tests1"}, /*FIXME {"http://www.winehq.org/tests", "../tests2", 0, S_OK, "http://www.winehq.org/tests2"},*/ {"http://www.winehq.org/tests/", "../tests3", 0, S_OK, "http://www.winehq.org/tests3"}, + {"http://www.winehq.org/tests/test1", "test2", 0, S_OK, "http://www.winehq.org/tests/test2"}, {"http://www.winehq.org/tests/../tests", "tests4", 0, S_OK, "http://www.winehq.org/tests4"}, {"http://www.winehq.org/tests/../tests/", "tests5", 0, S_OK, "http://www.winehq.org/tests/tests5"}, {"http://www.winehq.org/tests/../tests/", "/tests6/..", 0, S_OK, "http://www.winehq.org/"}, @@ -175,6 +198,13 @@ const TEST_URL_COMBINE TEST_COMBINE[] = { {"http://www.winehq.org/tests/#example", "tests9", 0, S_OK, "http://www.winehq.org/tests/tests9"}, {"http://www.winehq.org/tests/../tests/", "/tests10/..", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests10/.."}, {"http://www.winehq.org/tests/../", "tests11", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../tests11"}, + {"file:///C:\\dir\\file.txt", "test.txt", 0, S_OK, "file:///C:/dir/test.txt"}, + {"http://www.winehq.org/test/", "test%20file.txt", 0, S_OK, "http://www.winehq.org/test/test%20file.txt"}, + {"http://www.winehq.org/test/", "test%20file.txt", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org/test/test%20file.txt"}, + {"http://www.winehq.org%2ftest/", "test%20file.txt", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org%2ftest/test%20file.txt"}, + {"xxx:@MSITStore:file.chm/file.html", "dir/file", 0, S_OK, "xxx:dir/file"}, + {"mk:@MSITStore:file.chm::/file.html", "/dir/file", 0, S_OK, "mk:@MSITStore:file.chm::/dir/file"}, + {"mk:@MSITStore:file.chm::/file.html", "mk:@MSITStore:file.chm::/dir/file", 0, S_OK, "mk:@MSITStore:file.chm::/dir/file"}, }; struct { @@ -285,6 +315,22 @@ struct { { "file:partial", FALSE, TRUE } }; +struct { + const char *path; + const char *result; +} TEST_PATH_UNQUOTE_SPACES[] = { + { "abcdef", "abcdef" }, + { "\"abcdef\"", "abcdef" }, + { "\"abcdef", "\"abcdef" }, + { "abcdef\"", "abcdef\"" }, + { "\"\"abcdef\"\"", "\"abcdef\"" }, + { "abc\"def", "abc\"def" }, + { "\"abc\"def", "\"abc\"def" }, + { "\"abc\"def\"", "abc\"def" }, + { "\'abcdef\'", "\'abcdef\'" }, + { "\"\"", "" }, + { "\"", "" } +}; static LPWSTR GetWideString(const char* szString) { @@ -300,6 +346,15 @@ static void FreeWideString(LPWSTR wszString) HeapFree(GetProcessHeap(), 0, wszString); } +static LPSTR strdupA(LPCSTR p) +{ + LPSTR ret; + DWORD len = (strlen(p) + 1); + ret = HeapAlloc(GetProcessHeap(), 0, len); + memcpy(ret, p, len); + return ret; +} + static void hash_url(const char* szUrl) { LPCSTR szTestUrl = szUrl; @@ -332,13 +387,13 @@ static void test_url_part(const char* szUrl, DWORD dwPart, DWORD dwFlags, const DWORD dwSize; dwSize = INTERNET_MAX_URL_LENGTH; - ok( UrlGetPartA(szUrl, szPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartA for \"%s\" part 0x%08lx didn't return S_OK but \"%s\"\n", szUrl, dwPart, szPart); + ok( UrlGetPartA(szUrl, szPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartA for \"%s\" part 0x%08x didn't return S_OK but \"%s\"\n", szUrl, dwPart, szPart); dwSize = INTERNET_MAX_URL_LENGTH; ok( UrlGetPartW(wszUrl, wszPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartW didn't return S_OK\n" ); wszConvertedPart = GetWideString(szPart); - ok(strcmpW(wszPart,wszConvertedPart)==0, "Strings didn't match between ascii and unicode UrlGetPart!\n"); + ok(lstrcmpW(wszPart,wszConvertedPart)==0, "Strings didn't match between ascii and unicode UrlGetPart!\n"); FreeWideString(wszUrl); FreeWideString(wszConvertedPart); @@ -351,6 +406,25 @@ static void test_url_part(const char* szUrl, DWORD dwPart, DWORD dwFlags, const static void test_UrlGetPart(void) { + CHAR szPart[INTERNET_MAX_URL_LENGTH]; + DWORD dwSize; + HRESULT res; + + dwSize = sizeof szPart; + szPart[0]='x'; szPart[1]=0; + res = UrlGetPartA("hi", szPart, &dwSize, URL_PART_SCHEME, 0); + todo_wine { + ok (res==S_FALSE, "UrlGetPartA(\"hi\") returned %08X\n", res); + ok(szPart[0]==0, "UrlGetPartA(\"hi\") return \"%s\" instead of \"\"\n", szPart); + } + dwSize = sizeof szPart; + szPart[0]='x'; szPart[1]=0; + res = UrlGetPartA("hi", szPart, &dwSize, URL_PART_QUERY, 0); + todo_wine { + ok (res==S_FALSE, "UrlGetPartA(\"hi\") returned %08X\n", res); + ok(szPart[0]==0, "UrlGetPartA(\"hi\") return \"%s\" instead of \"\"\n", szPart); + } + test_url_part(TEST_URL_3, URL_PART_HOSTNAME, 0, "localhost"); test_url_part(TEST_URL_3, URL_PART_PORT, 0, "21"); test_url_part(TEST_URL_3, URL_PART_USERNAME, 0, "foo"); @@ -367,15 +441,15 @@ static void test_url_escape(const char *szUrl, DWORD dwFlags, HRESULT dwExpectRe WCHAR *urlW, *expected_urlW; dwEscaped=INTERNET_MAX_URL_LENGTH; - ok(UrlEscapeA(szUrl, szReturnUrl, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeA didn't return 0x%08lx from \"%s\"\n", dwExpectReturn, szUrl); + ok(UrlEscapeA(szUrl, szReturnUrl, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeA didn't return 0x%08x from \"%s\"\n", dwExpectReturn, szUrl); ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", szExpectUrl, szReturnUrl, szUrl); dwEscaped = INTERNET_MAX_URL_LENGTH; urlW = GetWideString(szUrl); expected_urlW = GetWideString(szExpectUrl); - ok(UrlEscapeW(urlW, ret_urlW, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeW didn't return 0x%08lx from \"%s\"\n", dwExpectReturn, szUrl); + ok(UrlEscapeW(urlW, ret_urlW, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeW didn't return 0x%08x from \"%s\"\n", dwExpectReturn, szUrl); WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0); - ok(strcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08lx\n", szExpectUrl, szReturnUrl, szUrl, dwFlags); + ok(lstrcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08x\n", szExpectUrl, szReturnUrl, szUrl, dwFlags); FreeWideString(urlW); FreeWideString(expected_urlW); @@ -393,14 +467,14 @@ static void test_url_canonicalize(const char *szUrl, DWORD dwFlags, HRESULT dwEx dwSize = INTERNET_MAX_URL_LENGTH; ok(UrlCanonicalizeA(szUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n"); - ok(UrlCanonicalizeA(szUrl, szReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeA didn't return 0x%08lx\n", dwExpectReturn); - ok(strcmp(szReturnUrl,szExpectUrl)==0, "UrlCanonicalizeA dwFlags 0x%08lx Expected %s, but got %s\n", dwFlags, szExpectUrl, szReturnUrl); + ok(UrlCanonicalizeA(szUrl, szReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeA didn't return 0x%08x\n", dwExpectReturn); + ok(strcmp(szReturnUrl,szExpectUrl)==0, "UrlCanonicalizeA dwFlags 0x%08x Expected \"%s\", but got \"%s\"\n", dwFlags, szExpectUrl, szReturnUrl); dwSize = INTERNET_MAX_URL_LENGTH; ok(UrlCanonicalizeW(wszUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n"); - ok(UrlCanonicalizeW(wszUrl, wszReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeW didn't return 0x%08lx\n", dwExpectReturn); + ok(UrlCanonicalizeW(wszUrl, wszReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeW didn't return 0x%08x\n", dwExpectReturn); wszConvertedUrl = GetWideString(szReturnUrl); - ok(strcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCanonicalize!\n"); + ok(lstrcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCanonicalize!\n"); FreeWideString(wszConvertedUrl); @@ -411,7 +485,13 @@ static void test_url_canonicalize(const char *szUrl, DWORD dwFlags, HRESULT dwEx static void test_UrlEscape(void) { + DWORD size; + HRESULT ret; unsigned int i; + + ret = UrlEscapeA("/woningplan/woonkamer basis.swf", NULL, &size, URL_ESCAPE_SPACES_ONLY); + ok(ret == E_INVALIDARG, "got %x, expected %x\n", ret, E_INVALIDARG); + for(i=0; i 100 ) { + trace("skipping rest of PathIsValidCharW tests " + "because of the current number of errors\n"); + break; + } + } } } @@ -799,10 +914,926 @@ static void test_PathMakePretty(void) ok (strcmp(buff, "Test") == 0, "PathMakePretty: 1st char lowercased %s\n", buff); } +static void test_PathMatchSpec(void) +{ + static const char file[] = "c:\\foo\\bar\\filename.ext"; + static const char spec1[] = ".ext"; + static const char spec2[] = "*.ext"; + static const char spec3[] = "*.ext "; + static const char spec4[] = " *.ext"; + static const char spec5[] = "* .ext"; + static const char spec6[] = "*. ext"; + static const char spec7[] = "* . ext"; + static const char spec8[] = "*.e?t"; + static const char spec9[] = "filename.ext"; + static const char spec10[] = "*bar\\filename.ext"; + static const char spec11[] = " foo; *.ext"; + static const char spec12[] = "*.ext;*.bar"; + static const char spec13[] = "*bar*"; + + ok (PathMatchSpecA(file, spec1) == FALSE, "PathMatchSpec: Spec1 failed\n"); + ok (PathMatchSpecA(file, spec2) == TRUE, "PathMatchSpec: Spec2 failed\n"); + ok (PathMatchSpecA(file, spec3) == FALSE, "PathMatchSpec: Spec3 failed\n"); + ok (PathMatchSpecA(file, spec4) == TRUE, "PathMatchSpec: Spec4 failed\n"); + todo_wine ok (PathMatchSpecA(file, spec5) == TRUE, "PathMatchSpec: Spec5 failed\n"); + todo_wine ok (PathMatchSpecA(file, spec6) == TRUE, "PathMatchSpec: Spec6 failed\n"); + ok (PathMatchSpecA(file, spec7) == FALSE, "PathMatchSpec: Spec7 failed\n"); + ok (PathMatchSpecA(file, spec8) == TRUE, "PathMatchSpec: Spec8 failed\n"); + ok (PathMatchSpecA(file, spec9) == FALSE, "PathMatchSpec: Spec9 failed\n"); + ok (PathMatchSpecA(file, spec10) == TRUE, "PathMatchSpec: Spec10 failed\n"); + ok (PathMatchSpecA(file, spec11) == TRUE, "PathMatchSpec: Spec11 failed\n"); + ok (PathMatchSpecA(file, spec12) == TRUE, "PathMatchSpec: Spec12 failed\n"); + ok (PathMatchSpecA(file, spec13) == TRUE, "PathMatchSpec: Spec13 failed\n"); +} + +static void test_PathCombineW(void) +{ + LPWSTR wszString, wszString2; + WCHAR wbuf[MAX_PATH+1], wstr1[MAX_PATH] = {'C',':','\\',0}, wstr2[MAX_PATH]; + static const WCHAR expout[] = {'C',':','\\','A','A',0}; + int i; + + wszString2 = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); + + /* NULL test */ + wszString = pPathCombineW(NULL, NULL, NULL); + ok (wszString == NULL, "Expected a NULL return\n"); + + /* Some NULL */ + wszString2[0] = 'a'; + wszString = pPathCombineW(wszString2, NULL, NULL); + ok (wszString == NULL, "Expected a NULL return\n"); + ok (wszString2[0] == 0, "Destination string not empty\n"); + + HeapFree(GetProcessHeap(), 0, wszString2); + + /* overflow test */ + wstr2[0] = wstr2[1] = wstr2[2] = 'A'; + for (i=3; i - . - - ntdll - shlwapi - ole32 - oleaut32 - kernel32 - advapi32 - clist.c - ordinal.c - shreg.c - string.c - testlist.c + . + + 0x600 + 0x501 + 0x501 + wine + shlwapi + advapi32 + ole32 + oleaut32 + kernel32 + uuid + ntdll + clist.c + clsid.c + generated.c + ordinal.c + path.c + shreg.c + string.c + testlist.c diff --git a/rostests/winetests/shlwapi/shreg.c b/rostests/winetests/shlwapi/shreg.c index d8d4d923200..77a47e2240c 100755 --- a/rostests/winetests/shlwapi/shreg.c +++ b/rostests/winetests/shlwapi/shreg.c @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include @@ -39,21 +39,21 @@ static SHCopyKeyA_func pSHCopyKeyA; typedef DWORD (WINAPI *SHRegGetPathA_func)(HKEY,LPCSTR,LPCSTR,LPSTR,DWORD); static SHRegGetPathA_func pSHRegGetPathA; -static const char * sTestpath1 = "%LONGSYSTEMVAR%\\subdir1"; -static const char * sTestpath2 = "%FOO%\\subdir1"; +static char sTestpath1[] = "%LONGSYSTEMVAR%\\subdir1"; +static char sTestpath2[] = "%FOO%\\subdir1"; static const char * sEnvvar1 = "bar"; static const char * sEnvvar2 = "ImARatherLongButIndeedNeededString"; static char sExpTestpath1[MAX_PATH]; static char sExpTestpath2[MAX_PATH]; -static unsigned sExpLen1; -static unsigned sExpLen2; +static DWORD nExpLen1; +static DWORD nExpLen2; static const char * sEmptyBuffer ="0123456789"; /* delete key and all its subkeys */ -static DWORD delete_key( HKEY hkey, LPSTR parent, LPSTR keyname ) +static DWORD delete_key( HKEY hkey, LPCSTR parent, LPCSTR keyname ) { HKEY parentKey; DWORD ret; @@ -75,12 +75,13 @@ static HKEY create_test_entries(void) { HKEY hKey; DWORD ret; + DWORD nExpectedLen1, nExpectedLen2; SetEnvironmentVariableA("LONGSYSTEMVAR", sEnvvar1); SetEnvironmentVariableA("FOO", sEnvvar2); ret = RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_KEY, &hKey); - ok( ERROR_SUCCESS == ret, "RegCreateKeyA failed, ret=%lu\n", ret); + ok( ERROR_SUCCESS == ret, "RegCreateKeyA failed, ret=%u\n", ret); if (hKey) { @@ -89,15 +90,24 @@ static HKEY create_test_entries(void) ok(!RegSetValueExA(hKey,"Test3",0,REG_EXPAND_SZ, (LPBYTE) sTestpath2, strlen(sTestpath2)+1), "RegSetValueExA failed\n"); } - sExpLen1 = ExpandEnvironmentStringsA(sTestpath1, sExpTestpath1, sizeof(sExpTestpath1)); - sExpLen2 = ExpandEnvironmentStringsA(sTestpath2, sExpTestpath2, sizeof(sExpTestpath2)); + nExpLen1 = ExpandEnvironmentStringsA(sTestpath1, sExpTestpath1, sizeof(sExpTestpath1)); + nExpLen2 = ExpandEnvironmentStringsA(sTestpath2, sExpTestpath2, sizeof(sExpTestpath2)); - ok(sExpLen1 > 0, "Couldn't expand %s\n", sTestpath1); - trace("sExplen1 = (%d)\n", sExpLen1); - ok(sExpLen2 > 0, "Couldn't expand %s\n", sTestpath2); - trace("sExplen2 = (%d)\n", sExpLen2); + nExpectedLen1 = strlen(sTestpath1) - strlen("%LONGSYSTEMVAR%") + strlen(sEnvvar1) + 1; + nExpectedLen2 = strlen(sTestpath2) - strlen("%FOO%") + strlen(sEnvvar2) + 1; + /* ExpandEnvironmentStringsA on NT4 returns 2x the correct result */ + trace("sExplen1 = (%d)\n", nExpLen1); + if (nExpectedLen1 != nExpLen1) + trace( "Expanding %s failed (expected %d) - known bug in NT4\n", sTestpath1, nExpectedLen1 ); - return hKey; + trace("sExplen2 = (%d)\n", nExpLen2); + if (nExpectedLen2 != nExpLen2) + trace( "Expanding %s failed (expected %d) - known bug in NT4\n", sTestpath2, nExpectedLen2 ); + + /* Make sure we carry on with correct values */ + nExpLen1 = nExpectedLen1; + nExpLen2 = nExpectedLen2; + return hKey; } static void test_SHGetValue(void) @@ -111,17 +121,17 @@ static void test_SHGetValue(void) dwSize = MAX_PATH; dwType = -1; dwRet = SHGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test1", &dwType, buf, &dwSize); - ok( ERROR_SUCCESS == dwRet, "SHGetValueA failed, ret=%lu\n", dwRet); + ok( ERROR_SUCCESS == dwRet, "SHGetValueA failed, ret=%u\n", dwRet); ok( 0 == strcmp(sExpTestpath1, buf), "Comparing of (%s) with (%s) failed\n", buf, sExpTestpath1); - ok( REG_SZ == dwType, "Expected REG_SZ, got (%lu)\n", dwType); + ok( REG_SZ == dwType, "Expected REG_SZ, got (%u)\n", dwType); strcpy(buf, sEmptyBuffer); dwSize = MAX_PATH; dwType = -1; dwRet = SHGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test2", &dwType, buf, &dwSize); - ok( ERROR_SUCCESS == dwRet, "SHGetValueA failed, ret=%lu\n", dwRet); + ok( ERROR_SUCCESS == dwRet, "SHGetValueA failed, ret=%u\n", dwRet); ok( 0 == strcmp(sTestpath1, buf) , "Comparing of (%s) with (%s) failed\n", buf, sTestpath1); - ok( REG_SZ == dwType , "Expected REG_SZ, got (%lu)\n", dwType); + ok( REG_SZ == dwType , "Expected REG_SZ, got (%u)\n", dwType); } static void test_SHGetRegPath(void) @@ -134,7 +144,7 @@ static void test_SHGetRegPath(void) strcpy(buf, sEmptyBuffer); dwRet = (*pSHRegGetPathA)(HKEY_CURRENT_USER, REG_TEST_KEY, "Test1", buf, 0); - ok( ERROR_SUCCESS == dwRet, "SHRegGetPathA failed, ret=%lu\n", dwRet); + ok( ERROR_SUCCESS == dwRet, "SHRegGetPathA failed, ret=%u\n", dwRet); ok( 0 == strcmp(sExpTestpath1, buf) , "Comparing (%s) with (%s) failed\n", buf, sExpTestpath1); } @@ -150,7 +160,7 @@ static void test_SHQUeryValueEx(void) sTestedFunction = "RegOpenKeyExA"; dwRet = RegOpenKeyExA(HKEY_CURRENT_USER, REG_TEST_KEY, 0, KEY_QUERY_VALUE, &hKey); - ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%lu\n", sTestedFunction, dwRet); + ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%u\n", sTestedFunction, dwRet); /****** SHQueryValueExA ******/ @@ -161,15 +171,15 @@ static void test_SHQUeryValueEx(void) * Case 1.1 All arguments are NULL */ dwRet = SHQueryValueExA( hKey, "Test1", NULL, NULL, NULL, NULL); - ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%lu\n", sTestedFunction, dwRet); + ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%u\n", sTestedFunction, dwRet); /* * Case 1.2 dwType is set */ dwType = -1; dwRet = SHQueryValueExA( hKey, "Test1", NULL, &dwType, NULL, NULL); - ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%lu\n", sTestedFunction, dwRet); - ok( REG_SZ == dwType , "Expected REG_SZ, got (%lu)\n", dwType); + ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%u\n", sTestedFunction, dwRet); + ok( REG_SZ == dwType , "Expected REG_SZ, got (%u)\n", dwType); /* * dwSize is set @@ -177,16 +187,16 @@ static void test_SHQUeryValueEx(void) */ dwSize = 6; dwRet = SHQueryValueExA( hKey, "Test1", NULL, NULL, NULL, &dwSize); - ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%lu\n", sTestedFunction, dwRet); - ok( dwSize == nUsedBuffer1, "Buffer sizes (%lu) and (%lu) are not equal\n", dwSize, nUsedBuffer1); + ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%u\n", sTestedFunction, dwRet); + ok( dwSize == nUsedBuffer1, "Buffer sizes (%u) and (%u) are not equal\n", dwSize, nUsedBuffer1); /* * dwExpanded > dwUnExpanded */ dwSize = 6; dwRet = SHQueryValueExA( hKey, "Test3", NULL, NULL, NULL, &dwSize); - ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%lu\n", sTestedFunction, dwRet); - ok( dwSize >= nUsedBuffer2, "Buffer size (%lu) should be >= (%lu)\n", dwSize, nUsedBuffer2); + ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%u\n", sTestedFunction, dwRet); + ok( dwSize >= nUsedBuffer2, "Buffer size (%u) should be >= (%u)\n", dwSize, nUsedBuffer2); /* * Case 1 string shrinks during expanding @@ -195,63 +205,65 @@ static void test_SHQUeryValueEx(void) dwSize = 6; dwType = -1; dwRet = SHQueryValueExA( hKey, "Test1", NULL, &dwType, buf, &dwSize); - ok( ERROR_MORE_DATA == dwRet, "Expected ERROR_MORE_DATA, got (%lu)\n", dwRet); + ok( ERROR_MORE_DATA == dwRet, "Expected ERROR_MORE_DATA, got (%u)\n", dwRet); ok( 0 == strcmp(sEmptyBuffer, buf) , "Comparing (%s) with (%s) failed\n", buf, sEmptyBuffer); - ok( dwSize == nUsedBuffer1, "Buffer sizes (%lu) and (%lu) are not equal\n", dwSize, nUsedBuffer1); - ok( REG_SZ == dwType , "Expected REG_SZ, got (%lu)\n", dwType); + ok( dwSize == nUsedBuffer1, "Buffer sizes (%u) and (%u) are not equal\n", dwSize, nUsedBuffer1); + ok( REG_SZ == dwType , "Expected REG_SZ, got (%u)\n", dwType); /* * string grows during expanding - * dwSize is smaller then the size of the unexpanded string + * dwSize is smaller than the size of the unexpanded string */ strcpy(buf, sEmptyBuffer); dwSize = 6; dwType = -1; dwRet = SHQueryValueExA( hKey, "Test3", NULL, &dwType, buf, &dwSize); - ok( ERROR_MORE_DATA == dwRet, "Expected ERROR_MORE_DATA, got (%lu)\n", dwRet); + ok( ERROR_MORE_DATA == dwRet, "Expected ERROR_MORE_DATA, got (%u)\n", dwRet); ok( 0 == strcmp(sEmptyBuffer, buf) , "Comparing (%s) with (%s) failed\n", buf, sEmptyBuffer); - ok( dwSize >= nUsedBuffer2, "Buffer size (%lu) should be >= (%lu)\n", dwSize, nUsedBuffer2); - ok( REG_SZ == dwType , "Expected REG_SZ, got (%lu)\n", dwType); + ok( dwSize >= nUsedBuffer2, "Buffer size (%u) should be >= (%u)\n", dwSize, nUsedBuffer2); + ok( REG_SZ == dwType , "Expected REG_SZ, got (%u)\n", dwType); /* * string grows during expanding - * dwSize is larger then the size of the unexpanded string but smaller than the part before the backslash - * if the unexpanded string fits into the buffer it can get cut when expanded + * dwSize is larger than the size of the unexpanded string, but + * smaller than the part before the backslash. If the unexpanded + * string fits into the buffer, it can get cut when expanded. */ strcpy(buf, sEmptyBuffer); dwSize = strlen(sEnvvar2) - 2; dwType = -1; dwRet = SHQueryValueExA( hKey, "Test3", NULL, &dwType, buf, &dwSize); - ok( ERROR_MORE_DATA == dwRet, "Expected ERROR_MORE_DATA, got (%lu)\n", dwRet); + ok( ERROR_MORE_DATA == dwRet, "Expected ERROR_MORE_DATA, got (%u)\n", dwRet); todo_wine { - ok( (0 == strcmp("", buf)) | (0 == strcmp(sTestpath2, buf)), + ok( (0 == strcmp("", buf)) || (0 == strcmp(sTestpath2, buf)), "Expected empty or unexpanded string (win98), got (%s)\n", buf); } - ok( dwSize >= nUsedBuffer2, "Buffer size (%lu) should be >= (%lu)\n", dwSize, nUsedBuffer2); - ok( REG_SZ == dwType , "Expected REG_SZ, got (%lu)\n", dwType); + ok( dwSize >= nUsedBuffer2, "Buffer size (%u) should be >= (%u)\n", dwSize, nUsedBuffer2); + ok( REG_SZ == dwType , "Expected REG_SZ, got (%u)\n", dwType); /* * string grows during expanding - * dwSize is larger then the size of the part before the backslash but smaller then the expanded string - * if the unexpanded string fits into the buffer it can get cut when expanded + * dwSize is larger than the size of the part before the backslash, + * but smaller than the expanded string. If the unexpanded string fits + * into the buffer, it can get cut when expanded. */ strcpy(buf, sEmptyBuffer); - dwSize = sExpLen2 - 4; + dwSize = nExpLen2 - 4; dwType = -1; dwRet = SHQueryValueExA( hKey, "Test3", NULL, &dwType, buf, &dwSize); - ok( ERROR_MORE_DATA == dwRet, "Expected ERROR_MORE_DATA, got (%lu)\n", dwRet); + ok( ERROR_MORE_DATA == dwRet, "Expected ERROR_MORE_DATA, got (%u)\n", dwRet); todo_wine { - ok( (0 == strcmp("", buf)) | (0 == strcmp(sEnvvar2, buf)), + ok( (0 == strcmp("", buf)) || (0 == strcmp(sEnvvar2, buf)), "Expected empty or first part of the string \"%s\", got \"%s\"\n", sEnvvar2, buf); } - ok( dwSize >= nUsedBuffer2, "Buffer size (%lu) should be >= (%lu)\n", dwSize, nUsedBuffer2); - ok( REG_SZ == dwType , "Expected REG_SZ, got (%lu)\n", dwType); + ok( dwSize >= nUsedBuffer2, "Buffer size (%u) should be >= (%u)\n", dwSize, nUsedBuffer2); + ok( REG_SZ == dwType , "Expected REG_SZ, got (%u)\n", dwType); /* * The buffer is NULL but the size is set @@ -260,9 +272,9 @@ static void test_SHQUeryValueEx(void) dwSize = 6; dwType = -1; dwRet = SHQueryValueExA( hKey, "Test3", NULL, &dwType, NULL, &dwSize); - ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%lu\n", sTestedFunction, dwRet); - ok( dwSize >= nUsedBuffer2, "Buffer size (%lu) should be >= (%lu)\n", dwSize, nUsedBuffer2); - ok( REG_SZ == dwType , "Expected REG_SZ, got (%lu)\n", dwType); + ok( ERROR_SUCCESS == dwRet, "%s failed, ret=%u\n", sTestedFunction, dwRet); + ok( dwSize >= nUsedBuffer2, "Buffer size (%u) should be >= (%u)\n", dwSize, nUsedBuffer2); + ok( REG_SZ == dwType , "Expected REG_SZ, got (%u)\n", dwType); RegCloseKey(hKey); } @@ -284,7 +296,7 @@ static void test_SHCopyKey(void) dwRet = RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\CopyDestination", &hKeyDst); if (dwRet || !hKeyDst) { - ok( 0, "Destination couldn't be created, RegCreateKeyA returned (%lu)\n", dwRet); + ok( 0, "Destination couldn't be created, RegCreateKeyA returned (%u)\n", dwRet); return; } @@ -292,7 +304,7 @@ static void test_SHCopyKey(void) dwRet = RegOpenKeyA(HKEY_LOCAL_MACHINE, REG_CURRENT_VERSION, &hKeySrc); if (dwRet || !hKeySrc) { - ok( 0, "Source couldn't be opened, RegOpenKeyA returned (%lu)\n", dwRet); + ok( 0, "Source couldn't be opened, RegOpenKeyA returned (%u)\n", dwRet); return; } @@ -300,7 +312,7 @@ static void test_SHCopyKey(void) if (pSHCopyKeyA) { dwRet = (*pSHCopyKeyA)(hKeySrc, NULL, hKeyDst, 0); - ok ( ERROR_SUCCESS == dwRet, "Copy failed, ret=(%lu)\n", dwRet); + ok ( ERROR_SUCCESS == dwRet, "Copy failed, ret=(%u)\n", dwRet); } RegCloseKey(hKeySrc); @@ -311,7 +323,7 @@ static void test_SHCopyKey(void) dwRet = RegOpenKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\CopyDestination\\Setup", &hKeyDst); if (dwRet || !hKeyDst) { - ok ( 0, "Copy couldn't be opened, RegOpenKeyA returned (%lu)\n", dwRet); + ok ( 0, "Copy couldn't be opened, RegOpenKeyA returned (%u)\n", dwRet); return; } @@ -352,7 +364,7 @@ static void test_SHDeleteKey(void) { dwRet = SHDeleteKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\ODBC"); - ok ( ERROR_SUCCESS == dwRet, "SHDeleteKey failed, ret=(%lu)\n", dwRet); + ok ( ERROR_SUCCESS == dwRet, "SHDeleteKey failed, ret=(%u)\n", dwRet); dwRet = RegOpenKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\ODBC", &hKeyS); ok ( ERROR_FILE_NOT_FOUND == dwRet, "SHDeleteKey did not delete\n"); @@ -371,11 +383,8 @@ START_TEST(shreg) if (!hkey) return; hshlwapi = GetModuleHandleA("shlwapi.dll"); - if (hshlwapi) - { - pSHCopyKeyA=(SHCopyKeyA_func)GetProcAddress(hshlwapi,"SHCopyKeyA"); - pSHRegGetPathA=(SHRegGetPathA_func)GetProcAddress(hshlwapi,"SHRegGetPathA"); - } + pSHCopyKeyA=(SHCopyKeyA_func)GetProcAddress(hshlwapi,"SHCopyKeyA"); + pSHRegGetPathA=(SHRegGetPathA_func)GetProcAddress(hshlwapi,"SHRegGetPathA"); test_SHGetValue(); test_SHQUeryValueEx(); test_SHGetRegPath(); diff --git a/rostests/winetests/shlwapi/string.c b/rostests/winetests/shlwapi/string.c index 47d9a6c9bef..895d767611c 100755 --- a/rostests/winetests/shlwapi/string.c +++ b/rostests/winetests/shlwapi/string.c @@ -14,13 +14,11 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include -#define NONAMELESSUNION -#define NONAMELESSSTRUCT #include "wine/test.h" #include "winbase.h" #include "winerror.h" @@ -32,6 +30,11 @@ #include "shlwapi.h" #include "shtypes.h" +#define expect_eq(expr, val, type, fmt) do { \ + type ret = expr; \ + ok(ret == val, "Unexpected value of '" #expr "': " #fmt " instead of " #val "\n", ret); \ +} while (0); + static HMODULE hShlwapi; static LPSTR (WINAPI *pStrCpyNXA)(LPSTR,LPCSTR,int); static LPWSTR (WINAPI *pStrCpyNXW)(LPWSTR,LPCWSTR,int); @@ -43,7 +46,7 @@ static BOOL (WINAPI *pIntlStrEqWorkerA)(BOOL,LPCSTR,LPCSTR,int); static BOOL (WINAPI *pStrIsIntlEqualW)(BOOL,LPCWSTR,LPCWSTR,int); static BOOL (WINAPI *pIntlStrEqWorkerW)(BOOL,LPCWSTR,LPCWSTR,int); -static inline int strcmpW(const WCHAR *str1, const WCHAR *str2) +static int strcmpW(const WCHAR *str1, const WCHAR *str2) { while (*str1 && (*str1 == *str2)) { str1++; str2++; } return *str1 - *str2; @@ -492,7 +495,7 @@ static void test_StrFormatByteSize64A(void) StrFormatByteSize64A(result->value, szBuff, 256); ok(!strcmp(result->byte_size_64, szBuff), - "Formatted %lx%08lx wrong: got %s, expected %s\n", + "Formatted %x%08x wrong: got %s, expected %s\n", (LONG)(result->value >> 32), (LONG)result->value, szBuff, result->byte_size_64); result++; @@ -510,7 +513,7 @@ static void test_StrFormatKBSizeW(void) StrFormatKBSizeW(result->value, szBuffW, 256); WideCharToMultiByte(0,0,szBuffW,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR),0,0); ok(!strcmp(result->kb_size, szBuff), - "Formatted %lx%08lx wrong: got %s, expected %s\n", + "Formatted %x%08x wrong: got %s, expected %s\n", (LONG)(result->value >> 32), (LONG)result->value, szBuff, result->kb_size); result++; } @@ -526,7 +529,7 @@ static void test_StrFormatKBSizeA(void) StrFormatKBSizeA(result->value, szBuff, 256); ok(!strcmp(result->kb_size, szBuff), - "Formatted %lx%08lx wrong: got %s, expected %s\n", + "Formatted %x%08x wrong: got %s, expected %s\n", (LONG)(result->value >> 32), (LONG)result->value, szBuff, result->kb_size); result++; } @@ -541,7 +544,7 @@ static void test_StrFromTimeIntervalA(void) { StrFromTimeIntervalA(szBuff, 256, result->ms, result->digits); - ok(!strcmp(result->time_interval, szBuff), "Formatted %ld %d wrong\n", + ok(!strcmp(result->time_interval, szBuff), "Formatted %d %d wrong\n", result->ms, result->digits); result++; } @@ -602,7 +605,7 @@ static void test_StrCmpW(void) static WCHAR *CoDupStrW(const char* src) { INT len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0); - WCHAR* szTemp = (WCHAR*)CoTaskMemAlloc(len * sizeof(WCHAR)); + WCHAR* szTemp = CoTaskMemAlloc(len * sizeof(WCHAR)); MultiByteToWideChar(CP_ACP, 0, src, -1, szTemp, len); return szTemp; } @@ -619,28 +622,28 @@ static void test_StrRetToBSTR(void) if (!pStrRetToBSTR) return; strret.uType = STRRET_WSTR; - strret.u.pOleStr = CoDupStrW("Test"); + U(strret).pOleStr = CoDupStrW("Test"); bstr = 0; ret = pStrRetToBSTR(&strret, NULL, &bstr); ok(ret == S_OK && bstr && !strcmpW(bstr, szTestW), - "STRRET_WSTR: dup failed, ret=0x%08lx, bstr %p\n", ret, bstr); + "STRRET_WSTR: dup failed, ret=0x%08x, bstr %p\n", ret, bstr); if (bstr) SysFreeString(bstr); strret.uType = STRRET_CSTR; - lstrcpyA(strret.u.cStr, "Test"); + lstrcpyA(U(strret).cStr, "Test"); ret = pStrRetToBSTR(&strret, NULL, &bstr); ok(ret == S_OK && bstr && !strcmpW(bstr, szTestW), - "STRRET_CSTR: dup failed, ret=0x%08lx, bstr %p\n", ret, bstr); + "STRRET_CSTR: dup failed, ret=0x%08x, bstr %p\n", ret, bstr); if (bstr) SysFreeString(bstr); strret.uType = STRRET_OFFSET; - strret.u.uOffset = 1; + U(strret).uOffset = 1; strcpy((char*)&iidl, " Test"); ret = pStrRetToBSTR(&strret, iidl, &bstr); ok(ret == S_OK && bstr && !strcmpW(bstr, szTestW), - "STRRET_OFFSET: dup failed, ret=0x%08lx, bstr %p\n", ret, bstr); + "STRRET_OFFSET: dup failed, ret=0x%08x, bstr %p\n", ret, bstr); if (bstr) SysFreeString(bstr); @@ -683,6 +686,45 @@ static void test_StrCpyNXW(void) dest + 5, lpszRes, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); } +#define check_strrstri(type, str, pos, needle, exp) \ + ret##type = StrRStrI##type(str, str+pos, needle); \ + ok(ret##type == (exp), "Type " #type ", expected %p but got %p (string base %p)\n", \ + (exp), ret##type, str); + +static void test_StrRStrI(void) +{ + static const CHAR szTest[] = "yAxxxxAy"; + static const CHAR szTest2[] = "ABABABAB"; + static const WCHAR wszTest[] = {'y','A','x','x','x','x','A','y',0}; + static const WCHAR wszTest2[] = {'A','B','A','B','A','B','A','B',0}; + + static const WCHAR wszPattern1[] = {'A',0}; + static const WCHAR wszPattern2[] = {'a','X',0}; + static const WCHAR wszPattern3[] = {'A','y',0}; + static const WCHAR wszPattern4[] = {'a','b',0}; + LPWSTR retW; + LPSTR retA; + + check_strrstri(A, szTest, 4, "A", szTest+1); + check_strrstri(A, szTest, 4, "aX", szTest+1); + check_strrstri(A, szTest, 4, "Ay", NULL); + check_strrstri(W, wszTest, 4, wszPattern1, wszTest+1); + check_strrstri(W, wszTest, 4, wszPattern2, wszTest+1); + check_strrstri(W, wszTest, 4, wszPattern3, NULL); + + check_strrstri(A, szTest2, 4, "ab", szTest2+2); + check_strrstri(A, szTest2, 3, "ab", szTest2+2); + check_strrstri(A, szTest2, 2, "ab", szTest2); + check_strrstri(A, szTest2, 1, "ab", szTest2); + check_strrstri(A, szTest2, 0, "ab", NULL); + check_strrstri(W, wszTest2, 4, wszPattern4, wszTest2+2); + check_strrstri(W, wszTest2, 3, wszPattern4, wszTest2+2); + check_strrstri(W, wszTest2, 2, wszPattern4, wszTest2); + check_strrstri(W, wszTest2, 1, wszPattern4, wszTest2); + check_strrstri(W, wszTest2, 0, wszPattern4, NULL); + +} + static void test_SHAnsiToAnsi(void) { char dest[8]; @@ -695,7 +737,7 @@ static void test_SHAnsiToAnsi(void) memset(dest, '\n', sizeof(dest)); dwRet = pSHAnsiToAnsi("hello", dest, sizeof(dest)/sizeof(dest[0])); ok(dwRet == 6 && !memcmp(dest, "hello\0\n\n", sizeof(dest)), - "SHAnsiToAnsi: expected 6, \"hello\\0\\n\\n\", got %ld, \"%d,%d,%d,%d,%d,%d,%d,%d\"\n", + "SHAnsiToAnsi: expected 6, \"hello\\0\\n\\n\", got %d, \"%d,%d,%d,%d,%d,%d,%d,%d\"\n", dwRet, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); } @@ -714,17 +756,79 @@ static void test_SHUnicodeToUnicode(void) memcpy(dest, lpInit, sizeof(lpInit)); dwRet = pSHUnicodeToUnicode(lpSrc, dest, sizeof(dest)/sizeof(dest[0])); ok(dwRet == 6 && !memcmp(dest, lpRes, sizeof(dest)), - "SHUnicodeToUnicode: expected 6, \"hello\\0\\n\\n\", got %ld, \"%d,%d,%d,%d,%d,%d,%d,%d\"\n", + "SHUnicodeToUnicode: expected 6, \"hello\\0\\n\\n\", got %d, \"%d,%d,%d,%d,%d,%d,%d,%d\"\n", dwRet, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); } +static void test_StrXXX_overflows(void) +{ + CHAR str1[2*MAX_PATH+1], buf[2*MAX_PATH]; + WCHAR wstr1[2*MAX_PATH+1], wbuf[2*MAX_PATH]; + const WCHAR fmt[] = {'%','s',0}; + STRRET strret; + int ret; + int i; + + for (i=0; i<2*MAX_PATH; i++) + { + str1[i] = '0'+(i%10); + wstr1[i] = '0'+(i%10); + } + str1[2*MAX_PATH] = 0; + wstr1[2*MAX_PATH] = 0; + + memset(buf, 0xbf, sizeof(buf)); + expect_eq(StrCpyNA(buf, str1, 10), buf, PCHAR, "%p"); + expect_eq(buf[9], 0, CHAR, "%x"); + expect_eq(buf[10], '\xbf', CHAR, "%x"); + expect_eq(StrCatBuffA(buf, str1, 100), buf, PCHAR, "%p"); + expect_eq(buf[99], 0, CHAR, "%x"); + expect_eq(buf[100], '\xbf', CHAR, "%x"); + + memset(wbuf, 0xbf, sizeof(wbuf)); + expect_eq(StrCpyNW(wbuf, wstr1, 10), wbuf, PWCHAR, "%p"); + expect_eq(wbuf[9], 0, WCHAR, "%x"); + expect_eq(wbuf[10], (WCHAR)0xbfbf, WCHAR, "%x"); + expect_eq(StrCatBuffW(wbuf, wstr1, 100), wbuf, PWCHAR, "%p"); + expect_eq(wbuf[99], 0, WCHAR, "%x"); + expect_eq(wbuf[100], (WCHAR)0xbfbf, WCHAR, "%x"); + + memset(wbuf, 0xbf, sizeof(wbuf)); + strret.uType = STRRET_WSTR; + U(strret).pOleStr = StrDupW(wstr1); + expect_eq(StrRetToBufW(&strret, NULL, wbuf, 10), S_OK, HRESULT, "%x"); + expect_eq(wbuf[9], 0, WCHAR, "%x"); + expect_eq(wbuf[10], (WCHAR)0xbfbf, WCHAR, "%x"); + + memset(buf, 0xbf, sizeof(buf)); + strret.uType = STRRET_CSTR; + StrCpyN(U(strret).cStr, str1, MAX_PATH); + expect_eq(StrRetToBufA(&strret, NULL, buf, 10), S_OK, HRESULT, "%x"); + expect_eq(buf[9], 0, CHAR, "%x"); + expect_eq(buf[10], (CHAR)0xbf, CHAR, "%x"); + + memset(buf, 0xbf, sizeof(buf)); + ret = wnsprintfA(buf, 10, "%s", str1); + todo_wine ok(ret == 9, "Unexpected wsnprintfA return %d, expected 9\n", ret); + expect_eq(buf[9], 0, CHAR, "%x"); + expect_eq(buf[10], (CHAR)0xbf, CHAR, "%x"); + memset(wbuf, 0xbf, sizeof(wbuf)); + ret = wnsprintfW(wbuf, 10, fmt, wstr1); + todo_wine ok(ret == 9, "Unexpected wsnprintfW return %d, expected 9\n", ret); + expect_eq(wbuf[9], 0, WCHAR, "%x"); + expect_eq(wbuf[10], (WCHAR)0xbfbf, WCHAR, "%x"); +} + START_TEST(string) { + TCHAR thousandDelim[8]; + TCHAR decimalDelim[8]; CoInitialize(0); + GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, thousandDelim, 8); + GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, decimalDelim, 8); + hShlwapi = GetModuleHandleA("shlwapi"); - if (!hShlwapi) - return; test_StrChrA(); test_StrChrW(); @@ -738,23 +842,27 @@ START_TEST(string) test_StrToIntExA(); test_StrToIntExW(); test_StrDupA(); - if (0) + if (lstrcmp(thousandDelim, ",")==0 && lstrcmp(decimalDelim, ".")==0) { - /* this test fails on locales which do not use '.' as a decimal separator */ + /* these tests are locale-dependent */ test_StrFormatByteSize64A(); - - /* this test fails on locales which do not use '.' as a decimal separator */ test_StrFormatKBSizeA(); - - /* FIXME: Awaiting NLS fixes in kernel before these succeed */ test_StrFormatKBSizeW(); } - test_StrFromTimeIntervalA(); + + /* language-dependent test */ + if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH) + trace("Skipping StrFromTimeInterval test for non English language\n"); + else + test_StrFromTimeIntervalA(); + test_StrCmpA(); test_StrCmpW(); test_StrRetToBSTR(); test_StrCpyNXA(); test_StrCpyNXW(); + test_StrRStrI(); test_SHAnsiToAnsi(); test_SHUnicodeToUnicode(); + test_StrXXX_overflows(); } diff --git a/rostests/winetests/shlwapi/testlist.c b/rostests/winetests/shlwapi/testlist.c index de16432e06b..ec8185df119 100755 --- a/rostests/winetests/shlwapi/testlist.c +++ b/rostests/winetests/shlwapi/testlist.c @@ -17,10 +17,10 @@ extern void func_string(void); const struct test winetest_testlist[] = { { "clist", func_clist }, -// { "clsid", func_clsid }, -// { "generated", func_generated }, + { "clsid", func_clsid }, + { "generated", func_generated }, { "ordinal", func_ordinal }, -// { "path", func_path }, + { "path", func_path }, { "shreg", func_shreg }, { "string", func_string }, { 0, 0 }