<directory name="lz32">
<xi:include href="lz32/lz32.rbuild" />
</directory>
+<directory name="mlang">
+ <xi:include href="mlang/mlang.rbuild" />
+</directory>
<directory name="msi">
<xi:include href="msi/msi.rbuild" />
</directory>
--- /dev/null
+/*
+ * 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 <stdarg.h>
+
+#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();
+}
--- /dev/null
+<module name="mlang_winetest" type="win32cui" installbase="bin" installname="mlang_winetest.exe" allowwarnings="true">
+ <include base="mlang_winetest">.</include>
+ <define name="__USE_W32API" />
+ <define name="_WIN32_IE">0x600</define>
+ <define name="_WIN32_WINNT">0x501</define>
+ <define name="WINVER">0x501</define>
+ <library>wine</library>
+ <library>ole32</library>
+ <library>gdi32</library>
+ <library>kernel32</library>
+ <library>uuid</library>
+ <library>ntdll</library>
+ <file>mlang.c</file>
+ <file>testlist.c</file>
+</module>
--- /dev/null
+/* Automatically generated file; DO NOT EDIT!! */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#define STANDALONE
+#include "wine/test.h"
+
+extern void func_mlang(void);
+
+const struct test winetest_testlist[] =
+{
+ { "mlang", func_mlang },
+ { 0, 0 }
+};
*
* 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 <stdarg.h>
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)
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)
{
/* 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 */
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)
test_SHLWAPI_213();
test_SHLWAPI_214();
}
-
- if (SHLWAPI_hshlwapi)
- FreeLibrary(SHLWAPI_hshlwapi);
}
*
* 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 <stdio.h>
-#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;
&IID_IPersistFolder,
&IID_IExtractIconA,
&IID_IShellDetails,
- &IID_IDelayedRelease,
+ &WINE_IID_IDelayedRelease,
&IID_IShellLinkA,
&IID_IShellCopyHookA,
&IID_IFileViewerA,
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();
}
TEST_TYPE(HUSKEY, 4, 4);
}
-static void test_pack_IQueryAssociations(void)
-{
- /* IQueryAssociations */
-}
-
static void test_pack_PHUSKEY(void)
{
/* PHUSKEY */
test_pack_DLLVERSIONINFO();
test_pack_DLLVERSIONINFO2();
test_pack_HUSKEY();
- test_pack_IQueryAssociations();
test_pack_PHUSKEY();
}
*
* 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 <stdio.h>
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;
(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));
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;
}
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;
}
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);
test_GetAcceptLanguagesA();
test_SHSearchMapInt();
test_alloc_shared();
- FreeLibrary(hShlwapi);
+ test_fdsa();
+ test_GetShellSecurityDescriptor();
}
*
* 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 <assert.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
-#include "wine/unicode.h"
#include "winreg.h"
#include "shlwapi.h"
#include "wininet.h"
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";
{"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 {
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/"},
{"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 {
{ "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)
{
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;
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);
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");
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);
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);
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<sizeof(TEST_ESCAPE)/sizeof(TEST_ESCAPE[0]); i++) {
test_url_escape(TEST_ESCAPE[i].url, TEST_ESCAPE[i].flags,
TEST_ESCAPE[i].expectret, TEST_ESCAPE[i].expecturl);
static void test_UrlCanonicalize(void)
{
unsigned int i;
+ CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
+ DWORD dwSize;
+ HRESULT hr;
+
for(i=0; i<sizeof(TEST_CANONICALIZE)/sizeof(TEST_CANONICALIZE[0]); i++) {
test_url_canonicalize(TEST_CANONICALIZE[i].url, TEST_CANONICALIZE[i].flags,
TEST_CANONICALIZE[i].expectret, TEST_CANONICALIZE[i].expecturl);
}
+
+ /* move to TEST_CANONICALIZE when fixed */
+ dwSize = sizeof szReturnUrl;
+ /*LimeWire online installer calls this*/
+ hr = UrlCanonicalizeA("/uri-res/N2R?urn:sha1:B3K", szReturnUrl, &dwSize,URL_DONT_ESCAPE_EXTRA_INFO | URL_WININET_COMPATIBILITY /*0x82000000*/);
+ ok(hr==S_OK,"UrlCanonicalizeA returned 0x%08x instead of S_OK\n", hr);
+ todo_wine {
+ ok(strcmp(szReturnUrl,"/uri-res/N2R?urn:sha1:B3K")==0, "UrlCanonicalizeA got \"%s\" instead of \"/uri-res/N2R?urn:sha1:B3K\"\n", szReturnUrl);
+ }
}
static void test_url_combine(const char *szUrl1, const char *szUrl2, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
DWORD dwExpectLen = lstrlen(szExpectUrl);
hr = UrlCombineA(szUrl1, szUrl2, NULL, NULL, dwFlags);
- ok(hr == E_INVALIDARG, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_INVALIDARG);
+ ok(hr == E_INVALIDARG, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
dwSize = 0;
hr = UrlCombineA(szUrl1, szUrl2, NULL, &dwSize, dwFlags);
- ok(hr == E_POINTER, "Checking length of string, return was 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
- ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
+ ok(hr == E_POINTER, "Checking length of string, return was 0x%08x, expected 0x%08x\n", hr, E_POINTER);
+ ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
dwSize--;
hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
- ok(hr == E_POINTER, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
- ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
+ ok(hr == E_POINTER, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, E_POINTER);
+ ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
- ok(hr == dwExpectReturn, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, dwExpectReturn);
- ok(dwSize == dwExpectLen, "Got length %ld, expected %ld\n", dwSize, dwExpectLen);
+ ok(hr == dwExpectReturn, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, dwExpectReturn);
+ ok(dwSize == dwExpectLen, "Got length %d, expected %d\n", dwSize, dwExpectLen);
if(SUCCEEDED(hr)) {
ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected %s, but got %s\n", szExpectUrl, szReturnUrl);
}
dwSize = 0;
hr = UrlCombineW(wszUrl1, wszUrl2, NULL, &dwSize, dwFlags);
- ok(hr == E_POINTER, "Checking length of string, return was 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
- ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
+ ok(hr == E_POINTER, "Checking length of string, return was 0x%08x, expected 0x%08x\n", hr, E_POINTER);
+ ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
dwSize--;
hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
- ok(hr == E_POINTER, "UrlCombineA returned 0x%08lx, expected 0x%08lx\n", hr, E_POINTER);
- ok(dwSize == dwExpectLen+1, "Got length %ld, expected %ld\n", dwSize, dwExpectLen+1);
+ ok(hr == E_POINTER, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, E_POINTER);
+ ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
- ok(hr == dwExpectReturn, "UrlCombineW returned 0x%08lx, expected 0x%08lx\n", hr, dwExpectReturn);
- ok(dwSize == dwExpectLen, "Got length %ld, expected %ld\n", dwSize, dwExpectLen);
+ ok(hr == dwExpectReturn, "UrlCombineW returned 0x%08x, expected 0x%08x\n", hr, dwExpectReturn);
+ ok(dwSize == dwExpectLen, "Got length %d, expected %d\n", dwSize, dwExpectLen);
if(SUCCEEDED(hr)) {
wszConvertedUrl = GetWideString(szReturnUrl);
- ok(strcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCombine!\n");
+ ok(lstrcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCombine!\n");
FreeWideString(wszConvertedUrl);
}
for(i = 0; i < sizeof(TEST_URLFROMPATH) / sizeof(TEST_URLFROMPATH[0]); i++) {
len = INTERNET_MAX_URL_LENGTH;
ret = UrlCreateFromPathA(TEST_URLFROMPATH[i].path, ret_url, &len, 0);
- ok(ret == TEST_URLFROMPATH[i].ret, "ret %08lx from path %s\n", ret, TEST_URLFROMPATH[i].path);
+ ok(ret == TEST_URLFROMPATH[i].ret, "ret %08x from path %s\n", ret, TEST_URLFROMPATH[i].path);
ok(!lstrcmpi(ret_url, TEST_URLFROMPATH[i].url), "url %s from path %s\n", ret_url, TEST_URLFROMPATH[i].path);
- ok(len == strlen(ret_url), "ret len %ld from path %s\n", len, TEST_URLFROMPATH[i].path);
+ ok(len == strlen(ret_url), "ret len %d from path %s\n", len, TEST_URLFROMPATH[i].path);
len = INTERNET_MAX_URL_LENGTH;
pathW = GetWideString(TEST_URLFROMPATH[i].path);
urlW = GetWideString(TEST_URLFROMPATH[i].url);
ret = UrlCreateFromPathW(pathW, ret_urlW, &len, 0);
WideCharToMultiByte(CP_ACP, 0, ret_urlW, -1, ret_url, sizeof(ret_url),0,0);
- ok(ret == TEST_URLFROMPATH[i].ret, "ret %08lx from path L\"%s\", expected %08lx\n",
+ ok(ret == TEST_URLFROMPATH[i].ret, "ret %08x from path L\"%s\", expected %08x\n",
ret, TEST_URLFROMPATH[i].path, TEST_URLFROMPATH[i].ret);
ok(!lstrcmpiW(ret_urlW, urlW), "got %s expected %s from path L\"%s\"\n", ret_url, TEST_URLFROMPATH[i].url, TEST_URLFROMPATH[i].path);
- ok(len == strlenW(ret_urlW), "ret len %ld from path L\"%s\"\n", len, TEST_URLFROMPATH[i].path);
+ ok(len == lstrlenW(ret_urlW), "ret len %d from path L\"%s\"\n", len, TEST_URLFROMPATH[i].path);
FreeWideString(urlW);
FreeWideString(pathW);
}
WCHAR *urlW, *expected_urlW;
DWORD dwEscaped;
size_t i;
+ static char inplace[] = "file:///C:/Program%20Files";
+ static WCHAR inplaceW[] = {'f','i','l','e',':','/','/','/','C',':','/',
+ 'P','r','o','g','r','a','m','%','2','0','F','i','l','e','s',0};
for(i=0; i<sizeof(TEST_URL_UNESCAPE)/sizeof(TEST_URL_UNESCAPE[0]); i++) {
dwEscaped=INTERNET_MAX_URL_LENGTH;
- ok(UrlUnescapeA(TEST_URL_UNESCAPE[i].url, szReturnUrl, &dwEscaped, 0) == S_OK, "UrlEscapeA didn't return 0x%08lx from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url);
+ ok(UrlUnescapeA(TEST_URL_UNESCAPE[i].url, szReturnUrl, &dwEscaped, 0) == S_OK, "UrlUnescapeA didn't return 0x%08x from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url);
ok(strcmp(szReturnUrl,TEST_URL_UNESCAPE[i].expect)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", TEST_URL_UNESCAPE[i].expect, szReturnUrl, TEST_URL_UNESCAPE[i].url);
dwEscaped = INTERNET_MAX_URL_LENGTH;
urlW = GetWideString(TEST_URL_UNESCAPE[i].url);
expected_urlW = GetWideString(TEST_URL_UNESCAPE[i].expect);
- ok(UrlUnescapeW(urlW, ret_urlW, &dwEscaped, 0) == S_OK, "UrlEscapeW didn't return 0x%08lx from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url);
+ ok(UrlUnescapeW(urlW, ret_urlW, &dwEscaped, 0) == S_OK, "UrlUnescapeW didn't return 0x%08x from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url);
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", TEST_URL_UNESCAPE[i].expect, szReturnUrl, TEST_URL_UNESCAPE[i].url, 0L);
+ ok(lstrcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08lx\n", TEST_URL_UNESCAPE[i].expect, szReturnUrl, TEST_URL_UNESCAPE[i].url, 0L);
FreeWideString(urlW);
FreeWideString(expected_urlW);
}
+ dwEscaped = sizeof(inplace);
+ ok(UrlUnescapeA(inplace, NULL, &dwEscaped, URL_UNESCAPE_INPLACE) == S_OK, "UrlUnescapeA failed unexpectedly\n");
+
+ dwEscaped = sizeof(inplaceW);
+ ok(UrlUnescapeW(inplaceW, NULL, &dwEscaped, URL_UNESCAPE_INPLACE) == S_OK, "UrlUnescapeW failed unexpectedly\n");
}
static void test_PathSearchAndQualify(void)
"PathSearchAndQualify rets 0\n");
GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
PathAddBackslashW(cur_dir);
- strcatW(cur_dir, foo);
+ lstrcatW(cur_dir, foo);
ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
/* foo */
"PathSearchAndQualify rets 0\n");
GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
PathAddBackslashW(cur_dir);
- strcatW(cur_dir, foo);
+ lstrcatW(cur_dir, foo);
ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
/* \foo */
ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
"PathSearchAndQualify rets 0\n");
GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
- strcpyW(cur_dir + 2, path3);
+ lstrcpyW(cur_dir + 2, path3);
ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
/* win.ini */
DWORD len, ret;
WCHAR ret_pathW[INTERNET_MAX_URL_LENGTH];
WCHAR *pathW, *urlW;
+ static const char url[] = "http://www.winehq.org";
+
+ /* Check ret_path = NULL */
+ len = sizeof(url);
+ ret = PathCreateFromUrlA(url, NULL, &len, 0);
+ ok ( ret == E_INVALIDARG, "got 0x%08x expected E_INVALIDARG\n", ret);
for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
len = INTERNET_MAX_URL_LENGTH;
ret = PathCreateFromUrlA(TEST_PATHFROMURL[i].url, ret_path, &len, 0);
- ok(ret == TEST_PATHFROMURL[i].ret, "ret %08lx from url %s\n", ret, TEST_PATHFROMURL[i].url);
+ ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url %s\n", ret, TEST_PATHFROMURL[i].url);
if(TEST_PATHFROMURL[i].path) {
ok(!lstrcmpi(ret_path, TEST_PATHFROMURL[i].path), "got %s expected %s from url %s\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
- ok(len == strlen(ret_path), "ret len %ld from url %s\n", len, TEST_PATHFROMURL[i].url);
+ ok(len == strlen(ret_path), "ret len %d from url %s\n", len, TEST_PATHFROMURL[i].url);
}
len = INTERNET_MAX_URL_LENGTH;
pathW = GetWideString(TEST_PATHFROMURL[i].path);
urlW = GetWideString(TEST_PATHFROMURL[i].url);
ret = PathCreateFromUrlW(urlW, ret_pathW, &len, 0);
WideCharToMultiByte(CP_ACP, 0, ret_pathW, -1, ret_path, sizeof(ret_path),0,0);
- ok(ret == TEST_PATHFROMURL[i].ret, "ret %08lx from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
+ ok(ret == TEST_PATHFROMURL[i].ret, "ret %08x from url L\"%s\"\n", ret, TEST_PATHFROMURL[i].url);
if(TEST_PATHFROMURL[i].path) {
ok(!lstrcmpiW(ret_pathW, pathW), "got %s expected %s from url L\"%s\"\n", ret_path, TEST_PATHFROMURL[i].path, TEST_PATHFROMURL[i].url);
- ok(len == strlenW(ret_pathW), "ret len %ld from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url);
+ ok(len == lstrlenW(ret_pathW), "ret len %d from url L\"%s\"\n", len, TEST_PATHFROMURL[i].url);
}
FreeWideString(urlW);
FreeWideString(pathW);
unsigned int c;
ret = pPathIsValidCharA( 0x7f, 0 );
- ok ( !ret, "PathIsValidCharA succeeded: 0x%08lx\n", (DWORD)ret );
+ ok ( !ret, "PathIsValidCharA succeeded: 0x%08x\n", (DWORD)ret );
ret = pPathIsValidCharA( 0x7f, 1 );
- ok ( !ret, "PathIsValidCharA succeeded: 0x%08lx\n", (DWORD)ret );
+ ok ( !ret, "PathIsValidCharA succeeded: 0x%08x\n", (DWORD)ret );
for (c = 0; c < 0x7f; c++)
{
ret = pPathIsValidCharA( c, ~0U );
ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
- "PathIsValidCharA failed: 0x%02x got 0x%08lx expected 0x%08lx\n",
+ "PathIsValidCharA failed: 0x%02x got 0x%08x expected 0x%08x\n",
c, (DWORD)ret, SHELL_charclass[c] );
}
{
ret = pPathIsValidCharA( c, ~0U );
ok ( ret == 0x00000100,
- "PathIsValidCharA failed: 0x%02x got 0x%08lx expected 0x00000100\n",
+ "PathIsValidCharA failed: 0x%02x got 0x%08x expected 0x00000100\n",
c, (DWORD)ret );
}
}
static void test_PathIsValidCharW(void)
{
BOOL ret;
- unsigned int c;
+ unsigned int c, err_count = 0;
ret = pPathIsValidCharW( 0x7f, 0 );
- ok ( !ret, "PathIsValidCharW succeeded: 0x%08lx\n", (DWORD)ret );
+ ok ( !ret, "PathIsValidCharW succeeded: 0x%08x\n", (DWORD)ret );
ret = pPathIsValidCharW( 0x7f, 1 );
- ok ( !ret, "PathIsValidCharW succeeded: 0x%08lx\n", (DWORD)ret );
+ ok ( !ret, "PathIsValidCharW succeeded: 0x%08x\n", (DWORD)ret );
for (c = 0; c < 0x7f; c++)
{
ret = pPathIsValidCharW( c, ~0U );
ok ( ret == SHELL_charclass[c] || (ret == 1 && SHELL_charclass[c] == 0xffffffff),
- "PathIsValidCharW failed: 0x%02x got 0x%08lx expected 0x%08lx\n",
+ "PathIsValidCharW failed: 0x%02x got 0x%08x expected 0x%08x\n",
c, (DWORD)ret, SHELL_charclass[c] );
}
{
ret = pPathIsValidCharW( c, ~0U );
ok ( ret == 0x00000100,
- "PathIsValidCharW failed: 0x%02x got 0x%08lx expected 0x00000100\n",
+ "PathIsValidCharW failed: 0x%02x got 0x%08x expected 0x00000100\n",
c, (DWORD)ret );
+ if (ret != 0x00000100)
+ {
+ if(++err_count > 100 ) {
+ trace("skipping rest of PathIsValidCharW tests "
+ "because of the current number of errors\n");
+ break;
+ }
+ }
}
}
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<MAX_PATH/2; i++)
+ wstr1[i] = wstr2[i] = 'A';
+ wstr1[(MAX_PATH/2) - 1] = wstr2[MAX_PATH/2] = 0;
+ memset(wbuf, 0xbf, sizeof(wbuf));
+
+ wszString = pPathCombineW(wbuf, wstr1, wstr2);
+ ok(wszString == NULL, "Expected a NULL return\n");
+ ok(wbuf[0] == 0, "Buffer contains data\n");
+
+ /* PathCombineW can be used in place */
+ wstr1[3] = 0;
+ wstr2[2] = 0;
+ ok(PathCombineW(wstr1, wstr1, wstr2) == wstr1, "Expected a wstr1 return\n");
+ ok(StrCmpW(wstr1, expout) == 0, "Unexpected PathCombine output\n");
+}
+
+
+#define LONG_LEN (MAX_PATH * 2)
+#define HALF_LEN (MAX_PATH / 2 + 1)
+
+static void test_PathCombineA(void)
+{
+ LPSTR str;
+ char dest[MAX_PATH];
+ char too_long[LONG_LEN];
+ char one[HALF_LEN], two[HALF_LEN];
+
+ /* try NULL dest */
+ SetLastError(0xdeadbeef);
+ str = PathCombineA(NULL, "C:\\", "one\\two\\three");
+ ok(str == NULL, "Expected NULL, got %p\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try NULL dest and NULL directory */
+ SetLastError(0xdeadbeef);
+ str = PathCombineA(NULL, NULL, "one\\two\\three");
+ ok(str == NULL, "Expected NULL, got %p\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try all NULL*/
+ SetLastError(0xdeadbeef);
+ str = PathCombineA(NULL, NULL, NULL);
+ ok(str == NULL, "Expected NULL, got %p\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try NULL file part */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, "C:\\", NULL);
+ ok(str == dest, "Expected str == dest, got %p\n", str);
+ ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try empty file part */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, "C:\\", "");
+ ok(str == dest, "Expected str == dest, got %p\n", str);
+ ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try empty directory and file part */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, "", "");
+ ok(str == dest, "Expected str == dest, got %p\n", str);
+ ok(!lstrcmp(str, "\\"), "Expected \\, got %s\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try NULL directory */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, NULL, "one\\two\\three");
+ ok(str == dest, "Expected str == dest, got %p\n", str);
+ ok(!lstrcmp(str, "one\\two\\three"), "Expected one\\two\\three, got %s\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try NULL directory and empty file part */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, NULL, "");
+ ok(str == dest, "Expected str == dest, got %p\n", str);
+ ok(!lstrcmp(str, "\\"), "Expected \\, got %s\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try NULL directory and file part */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, NULL, NULL);
+ ok(str == NULL, "Expected str == NULL, got %p\n", str);
+ ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try directory without backslash */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, "C:", "one\\two\\three");
+ ok(str == dest, "Expected str == dest, got %p\n", str);
+ ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try directory with backslash */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, "C:\\", "one\\two\\three");
+ ok(str == dest, "Expected str == dest, got %p\n", str);
+ ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try directory with backslash and file with prepended backslash */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, "C:\\", "\\one\\two\\three");
+ ok(str == dest, "Expected str == dest, got %p\n", str);
+ ok(!lstrcmp(str, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try previous test, with backslash appended as well */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, "C:\\", "\\one\\two\\three\\");
+ ok(str == dest, "Expected str == dest, got %p\n", str);
+ ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try a relative directory */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, "relative\\dir", "\\one\\two\\three\\");
+ ok(str == dest, "Expected str == dest, got %p\n", str);
+ ok(!lstrcmp(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try forward slashes */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, "C:\\", "one/two/three\\");
+ ok(str == dest, "Expected str == dest, got %p\n", str);
+ ok(!lstrcmp(str, "C:\\one/two/three\\"), "Expected one/two/three\\, got %s\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try a really weird directory */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, "C:\\/\\/", "\\one\\two\\three\\");
+ ok(str == dest, "Expected str == dest, got %p\n", str);
+ ok(!lstrcmp(str, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try periods */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, "C:\\", "one\\..\\two\\.\\three");
+ ok(str == dest, "Expected str == dest, got %p\n", str);
+ ok(!lstrcmp(str, "C:\\two\\three"), "Expected C:\\two\\three, got %s\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try .. as file */
+ /* try forward slashes */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, "C:\\", "..");
+ ok(str == dest, "Expected str == dest, got %p\n", str);
+ ok(!lstrcmp(str, "C:\\"), "Expected C:\\, got %s\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ memset(too_long, 'a', LONG_LEN);
+ too_long[LONG_LEN - 1] = '\0';
+
+ /* try a file longer than MAX_PATH */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, "C:\\", too_long);
+ ok(str == NULL, "Expected str == NULL, got %p\n", str);
+ ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
+ todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try a directory longer than MAX_PATH */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, too_long, "one\\two\\three");
+ ok(str == NULL, "Expected str == NULL, got %p\n", str);
+ ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
+ todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ memset(one, 'b', HALF_LEN);
+ memset(two, 'c', HALF_LEN);
+ one[HALF_LEN - 1] = '\0';
+ two[HALF_LEN - 1] = '\0';
+
+ /* destination string is longer than MAX_PATH, but not the constituent parts */
+ SetLastError(0xdeadbeef);
+ lstrcpyA(dest, "control");
+ str = PathCombineA(dest, one, two);
+ ok(str == NULL, "Expected str == NULL, got %p\n", str);
+ ok(lstrlenA(dest) == 0, "Expected 0 length, got %i\n", lstrlenA(dest));
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+}
+
+static void test_PathAddBackslash(void)
+{
+ LPSTR str;
+ char path[MAX_PATH];
+ char too_long[LONG_LEN];
+
+ /* try a NULL path */
+ SetLastError(0xdeadbeef);
+ str = PathAddBackslashA(NULL);
+ ok(str == NULL, "Expected str == NULL, got %p\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try an empty path */
+ path[0] = '\0';
+ SetLastError(0xdeadbeef);
+ str = PathAddBackslashA(path);
+ ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
+ ok(lstrlenA(path) == 0, "Expected empty string, got %i\n", lstrlenA(path));
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try a relative path */
+ lstrcpyA(path, "one\\two");
+ SetLastError(0xdeadbeef);
+ str = PathAddBackslashA(path);
+ ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
+ ok(!lstrcmp(path, "one\\two\\"), "Expected one\\two\\, got %s\n", path);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try periods */
+ lstrcpyA(path, "one\\..\\two");
+ SetLastError(0xdeadbeef);
+ str = PathAddBackslashA(path);
+ ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
+ ok(!lstrcmp(path, "one\\..\\two\\"), "Expected one\\..\\two\\, got %s\n", path);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try just a space */
+ lstrcpyA(path, " ");
+ SetLastError(0xdeadbeef);
+ str = PathAddBackslashA(path);
+ ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
+ ok(!lstrcmp(path, " \\"), "Expected \\, got %s\n", path);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* path already has backslash */
+ lstrcpyA(path, "C:\\one\\");
+ SetLastError(0xdeadbeef);
+ str = PathAddBackslashA(path);
+ ok(str == (path + lstrlenA(path)), "Expected str to point to end of path, got %p\n", str);
+ ok(!lstrcmp(path, "C:\\one\\"), "Expected C:\\one\\, got %s\n", path);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ memset(too_long, 'a', LONG_LEN);
+ too_long[LONG_LEN - 1] = '\0';
+
+ /* path is longer than MAX_PATH */
+ SetLastError(0xdeadbeef);
+ str = PathAddBackslashA(too_long);
+ ok(str == NULL, "Expected str == NULL, got %p\n", str);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+}
+
+static void test_PathAppendA(void)
+{
+ char path[MAX_PATH];
+ char too_long[LONG_LEN];
+ char one[HALF_LEN], two[HALF_LEN];
+ BOOL res;
+
+ lstrcpy(path, "C:\\one");
+
+ /* try NULL pszMore */
+ SetLastError(0xdeadbeef);
+ res = PathAppendA(path, NULL);
+ ok(!res, "Expected failure\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
+
+ /* try empty pszMore */
+ SetLastError(0xdeadbeef);
+ res = PathAppendA(path, "");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(path, "C:\\one"), "Expected C:\\one, got %s\n", path);
+
+ /* try NULL pszPath */
+ SetLastError(0xdeadbeef);
+ res = PathAppendA(NULL, "two\\three");
+ ok(!res, "Expected failure\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try empty pszPath */
+ path[0] = '\0';
+ SetLastError(0xdeadbeef);
+ res = PathAppendA(path, "two\\three");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(path, "two\\three"), "Expected \\two\\three, got %s\n", path);
+
+ /* try empty pszPath and empty pszMore */
+ path[0] = '\0';
+ SetLastError(0xdeadbeef);
+ res = PathAppendA(path, "");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(path, "\\"), "Expected \\, got %s\n", path);
+
+ /* try legit params */
+ lstrcpy(path, "C:\\one");
+ SetLastError(0xdeadbeef);
+ res = PathAppendA(path, "two\\three");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
+
+ /* try pszPath with backslash after it */
+ lstrcpy(path, "C:\\one\\");
+ SetLastError(0xdeadbeef);
+ res = PathAppendA(path, "two\\three");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
+
+ /* try pszMore with backslash before it */
+ lstrcpy(path, "C:\\one");
+ SetLastError(0xdeadbeef);
+ res = PathAppendA(path, "\\two\\three");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(path, "C:\\one\\two\\three"), "Expected C:\\one\\two\\three, got %s\n", path);
+
+ /* try pszMore with backslash after it */
+ lstrcpy(path, "C:\\one");
+ SetLastError(0xdeadbeef);
+ res = PathAppendA(path, "two\\three\\");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(path, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", path);
+
+ /* try spaces in pszPath */
+ lstrcpy(path, "C: \\ one ");
+ SetLastError(0xdeadbeef);
+ res = PathAppendA(path, "two\\three");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(path, "C: \\ one \\two\\three"), "Expected C: \\ one \\two\\three, got %s\n", path);
+
+ /* try spaces in pszMore */
+ lstrcpy(path, "C:\\one");
+ SetLastError(0xdeadbeef);
+ res = PathAppendA(path, " two \\ three ");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(path, "C:\\one\\ two \\ three "), "Expected 'C:\\one\\ two \\ three ', got %s\n", path);
+
+ /* pszPath is too long */
+ memset(too_long, 'a', LONG_LEN);
+ too_long[LONG_LEN - 1] = '\0';
+ SetLastError(0xdeadbeef);
+ res = PathAppendA(too_long, "two\\three");
+ ok(!res, "Expected failure\n");
+ todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(lstrlen(too_long) == 0, "Expected length of too_long to be zero, got %i\n", lstrlen(too_long));
+
+ /* pszMore is too long */
+ lstrcpy(path, "C:\\one");
+ memset(too_long, 'a', LONG_LEN);
+ too_long[LONG_LEN - 1] = '\0';
+ SetLastError(0xdeadbeef);
+ res = PathAppendA(path, too_long);
+ ok(!res, "Expected failure\n");
+ todo_wine ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(lstrlen(path) == 0, "Expected length of path to be zero, got %i\n", lstrlen(path));
+
+ /* both params combined are too long */
+ memset(one, 'a', HALF_LEN);
+ one[HALF_LEN - 1] = '\0';
+ memset(two, 'b', HALF_LEN);
+ two[HALF_LEN - 1] = '\0';
+ SetLastError(0xdeadbeef);
+ res = PathAppendA(one, two);
+ ok(!res, "Expected failure\n");
+ ok(lstrlen(one) == 0, "Expected length of one to be zero, got %i\n", lstrlen(one));
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+}
+
+static void test_PathCanonicalizeA(void)
+{
+ char dest[MAX_PATH];
+ char too_long[LONG_LEN];
+ BOOL res;
+
+ /* try a NULL source */
+ lstrcpy(dest, "test");
+ SetLastError(0xdeadbeef);
+ res = PathCanonicalizeA(dest, NULL);
+ ok(!res, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+ todo_wine
+ {
+ ok(!lstrcmp(dest, "test"), "Expected test, got %s\n", dest);
+ }
+
+ /* try an empty source */
+ lstrcpy(dest, "test");
+ SetLastError(0xdeadbeef);
+ res = PathCanonicalizeA(dest, "");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(dest, "\\"), "Expected \\, got %s\n", dest);
+
+ /* try a NULL dest */
+ SetLastError(0xdeadbeef);
+ res = PathCanonicalizeA(NULL, "C:\\");
+ ok(!res, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ /* try empty dest */
+ dest[0] = '\0';
+ SetLastError(0xdeadbeef);
+ res = PathCanonicalizeA(dest, "C:\\");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
+
+ /* try non-empty dest */
+ lstrcpy(dest, "test");
+ SetLastError(0xdeadbeef);
+ res = PathCanonicalizeA(dest, "C:\\");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(dest, "C:\\"), "Expected C:\\, got %s\n", dest);
+
+ /* try a space for source */
+ lstrcpy(dest, "test");
+ SetLastError(0xdeadbeef);
+ res = PathCanonicalizeA(dest, " ");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(dest, " "), "Expected ' ', got %s\n", dest);
+
+ /* try a relative path */
+ lstrcpy(dest, "test");
+ SetLastError(0xdeadbeef);
+ res = PathCanonicalizeA(dest, "one\\two");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(dest, "one\\two"), "Expected one\\two, got %s\n", dest);
+
+ /* try current dir and previous dir */
+ lstrcpy(dest, "test");
+ SetLastError(0xdeadbeef);
+ res = PathCanonicalizeA(dest, "C:\\one\\.\\..\\two\\three\\..");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(dest, "C:\\two"), "Expected C:\\two, got %s\n", dest);
+
+ /* try simple forward slashes */
+ lstrcpy(dest, "test");
+ SetLastError(0xdeadbeef);
+ res = PathCanonicalizeA(dest, "C:\\one/two/three\\four/five\\six");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(dest, "C:\\one/two/three\\four/five\\six"),
+ "Expected C:\\one/two/three\\four/five\\six, got %s\n", dest);
+
+ /* try simple forward slashes with same dir */
+ lstrcpy(dest, "test");
+ SetLastError(0xdeadbeef);
+ res = PathCanonicalizeA(dest, "C:\\one/.\\two");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(dest, "C:\\one/.\\two"), "Expected C:\\one/.\\two, got %s\n", dest);
+
+ /* try simple forward slashes with change dir */
+ lstrcpy(dest, "test");
+ SetLastError(0xdeadbeef);
+ res = PathCanonicalizeA(dest, "C:\\one/.\\two\\..");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(dest, "C:\\one/."), "Expected C:\\one/., got %s\n", dest);
+
+ /* try forward slashes with change dirs
+ * NOTE: if there is a forward slash in between two backslashes,
+ * everything in between the two backslashes is considered on dir
+ */
+ lstrcpy(dest, "test");
+ SetLastError(0xdeadbeef);
+ res = PathCanonicalizeA(dest, "C:\\one/.\\..\\two/three\\..\\four/.five");
+ ok(res, "Expected success\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(!lstrcmp(dest, "C:\\four/.five"), "Expected C:\\four/.five, got %s\n", dest);
+
+ /* try src is too long */
+ memset(too_long, 'a', LONG_LEN);
+ too_long[LONG_LEN - 1] = '\0';
+ lstrcpy(dest, "test");
+ SetLastError(0xdeadbeef);
+ res = PathCanonicalizeA(dest, too_long);
+ todo_wine
+ {
+ ok(!res, "Expected failure\n");
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ }
+ ok(lstrlen(too_long) == LONG_LEN - 1, "Expected length LONG_LEN - 1, got %i\n", lstrlen(too_long));
+}
+
+static void test_PathFindExtensionA(void)
+{
+ LPSTR ext;
+ char path[MAX_PATH];
+ char too_long[LONG_LEN];
+
+ /* try a NULL path */
+ SetLastError(0xdeadbeef);
+ ext = PathFindExtensionA(NULL);
+ ok(ext == NULL, "Expected NULL, got %p\n", ext);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try an empty path */
+ path[0] = '\0';
+ SetLastError(0xdeadbeef);
+ ext = PathFindExtensionA(path);
+ ok(ext == path, "Expected ext == path, got %p\n", ext);
+ ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try a path without an extension */
+ lstrcpy(path, "file");
+ SetLastError(0xdeadbeef);
+ ext = PathFindExtensionA(path);
+ ok(ext == path + lstrlen(path), "Expected ext == path, got %p\n", ext);
+ ok(lstrlen(ext) == 0, "Expected length 0, got %i\n", lstrlen(ext));
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try a path with an extension */
+ lstrcpy(path, "file.txt");
+ SetLastError(0xdeadbeef);
+ ext = PathFindExtensionA(path);
+ ok(ext == path + lstrlen("file"),
+ "Expected ext == path + lstrlen(\"file\"), got %p\n", ext);
+ ok(!lstrcmp(ext, ".txt"), "Expected .txt, got %s\n", ext);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try a path with two extensions */
+ lstrcpy(path, "file.txt.doc");
+ SetLastError(0xdeadbeef);
+ ext = PathFindExtensionA(path);
+ ok(ext == path + lstrlen("file.txt"),
+ "Expected ext == path + lstrlen(\"file.txt\"), got %p\n", ext);
+ ok(!lstrcmp(ext, ".doc"), "Expected .txt, got %s\n", ext);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try a path longer than MAX_PATH without an extension*/
+ memset(too_long, 'a', LONG_LEN);
+ too_long[LONG_LEN - 1] = '\0';
+ SetLastError(0xdeadbeef);
+ ext = PathFindExtensionA(too_long);
+ ok(ext == too_long + LONG_LEN - 1, "Expected ext == too_long + LONG_LEN - 1, got %p\n", ext);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try a path longer than MAX_PATH with an extension*/
+ memset(too_long, 'a', LONG_LEN);
+ too_long[LONG_LEN - 1] = '\0';
+ lstrcpy(too_long + 300, ".abcde");
+ too_long[lstrlen(too_long)] = 'a';
+ SetLastError(0xdeadbeef);
+ ext = PathFindExtensionA(too_long);
+ ok(ext == too_long + 300, "Expected ext == too_long + 300, got %p\n", ext);
+ ok(lstrlen(ext) == LONG_LEN - 301, "Expected LONG_LEN - 301, got %i\n", lstrlen(ext));
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+}
+
+static void test_PathBuildRootA(void)
+{
+ LPSTR root;
+ char path[10];
+ char root_expected[26][4];
+ char drive;
+ int j;
+
+ /* set up the expected paths */
+ for (drive = 'A'; drive <= 'Z'; drive++)
+ sprintf(root_expected[drive - 'A'], "%c:\\", drive);
+
+ /* test the expected values */
+ for (j = 0; j < 26; j++)
+ {
+ SetLastError(0xdeadbeef);
+ lstrcpy(path, "aaaaaaaaa");
+ root = PathBuildRootA(path, j);
+ ok(root == path, "Expected root == path, got %p\n", root);
+ ok(!lstrcmp(root, root_expected[j]), "Expected %s, got %s\n", root_expected[j], root);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+ }
+
+ /* test a negative drive number */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path, "aaaaaaaaa");
+ root = PathBuildRootA(path, -1);
+ ok(root == path, "Expected root == path, got %p\n", root);
+ ok(!lstrcmp(path, "aaaaaaaaa"), "Expected aaaaaaaaa, got %s\n", path);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* test a drive number greater than 25 */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path, "aaaaaaaaa");
+ root = PathBuildRootA(path, 26);
+ ok(root == path, "Expected root == path, got %p\n", root);
+ ok(!lstrcmp(path, "aaaaaaaaa"), "Expected aaaaaaaaa, got %s\n", path);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* length of path is less than 4 */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path, "aa");
+ root = PathBuildRootA(path, 0);
+ ok(root == path, "Expected root == path, got %p\n", root);
+ ok(!lstrcmp(path, "A:\\"), "Expected A:\\, got %s\n", path);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* path is NULL */
+ SetLastError(0xdeadbeef);
+ root = PathBuildRootA(NULL, 0);
+ ok(root == NULL, "Expected root == NULL, got %p\n", root);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+}
+
+static void test_PathCommonPrefixA(void)
+{
+ char path1[MAX_PATH], path2[MAX_PATH];
+ char out[MAX_PATH];
+ int count;
+
+ /* test NULL path1 */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path2, "C:\\");
+ lstrcpy(out, "aaa");
+ count = PathCommonPrefixA(NULL, path2, out);
+ ok(count == 0, "Expected 0, got %i\n", count);
+ todo_wine
+ {
+ ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
+ }
+ ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* test NULL path2 */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path1, "C:\\");
+ lstrcpy(out, "aaa");
+ count = PathCommonPrefixA(path1, NULL, out);
+ ok(count == 0, "Expected 0, got %i\n", count);
+ todo_wine
+ {
+ ok(!lstrcmp(out, "aaa"), "Expected aaa, got %s\n", out);
+ }
+ ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* test empty path1 */
+ SetLastError(0xdeadbeef);
+ path1[0] = '\0';
+ lstrcpy(path2, "C:\\");
+ lstrcpy(out, "aaa");
+ count = PathCommonPrefixA(path1, path2, out);
+ ok(count == 0, "Expected 0, got %i\n", count);
+ ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
+ ok(lstrlen(path1) == 0, "Expected 0 length path1, got %i\n", lstrlen(path1));
+ ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* test empty path1 */
+ SetLastError(0xdeadbeef);
+ path2[0] = '\0';
+ lstrcpy(path1, "C:\\");
+ lstrcpy(out, "aaa");
+ count = PathCommonPrefixA(path1, path2, out);
+ ok(count == 0, "Expected 0, got %i\n", count);
+ ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
+ ok(lstrlen(path2) == 0, "Expected 0 length path2, got %i\n", lstrlen(path2));
+ ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* paths are legit, out is NULL */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path1, "C:\\");
+ lstrcpy(path2, "C:\\");
+ count = PathCommonPrefixA(path1, path2, NULL);
+ ok(count == 3, "Expected 3, got %i\n", count);
+ ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
+ ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* all parameters legit */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path1, "C:\\");
+ lstrcpy(path2, "C:\\");
+ lstrcpy(out, "aaa");
+ count = PathCommonPrefixA(path1, path2, out);
+ ok(count == 3, "Expected 3, got %i\n", count);
+ ok(!lstrcmp(path1, "C:\\"), "Expected C:\\, got %s\n", path1);
+ ok(!lstrcmp(path2, "C:\\"), "Expected C:\\, got %s\n", path2);
+ ok(!lstrcmp(out, "C:\\"), "Expected C:\\, got %s\n", out);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* path1 and path2 not the same, but common prefix */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path1, "C:\\one\\two");
+ lstrcpy(path2, "C:\\one\\three");
+ lstrcpy(out, "aaa");
+ count = PathCommonPrefixA(path1, path2, out);
+ ok(count == 6, "Expected 6, got %i\n", count);
+ ok(!lstrcmp(path1, "C:\\one\\two"), "Expected C:\\one\\two, got %s\n", path1);
+ ok(!lstrcmp(path2, "C:\\one\\three"), "Expected C:\\one\\three, got %s\n", path2);
+ ok(!lstrcmp(out, "C:\\one"), "Expected C:\\one, got %s\n", out);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try . prefix */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path1, "one\\.two");
+ lstrcpy(path2, "one\\.three");
+ lstrcpy(out, "aaa");
+ count = PathCommonPrefixA(path1, path2, out);
+ ok(count == 3, "Expected 3, got %i\n", count);
+ ok(!lstrcmp(path1, "one\\.two"), "Expected one\\.two, got %s\n", path1);
+ ok(!lstrcmp(path2, "one\\.three"), "Expected one\\.three, got %s\n", path2);
+ ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try .. prefix */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path1, "one\\..two");
+ lstrcpy(path2, "one\\..three");
+ lstrcpy(out, "aaa");
+ count = PathCommonPrefixA(path1, path2, out);
+ ok(count == 3, "Expected 3, got %i\n", count);
+ ok(!lstrcmp(path1, "one\\..two"), "Expected one\\..two, got %s\n", path1);
+ ok(!lstrcmp(path2, "one\\..three"), "Expected one\\..three, got %s\n", path2);
+ ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try ... prefix */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path1, "one\\...two");
+ lstrcpy(path2, "one\\...three");
+ lstrcpy(out, "aaa");
+ count = PathCommonPrefixA(path1, path2, out);
+ ok(count == 3, "Expected 3, got %i\n", count);
+ ok(!lstrcmp(path1, "one\\...two"), "Expected one\\...two, got %s\n", path1);
+ ok(!lstrcmp(path2, "one\\...three"), "Expected one\\...three, got %s\n", path2);
+ ok(!lstrcmp(out, "one"), "Expected one, got %s\n", out);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try .\ prefix */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path1, "one\\.\\two");
+ lstrcpy(path2, "one\\.\\three");
+ lstrcpy(out, "aaa");
+ count = PathCommonPrefixA(path1, path2, out);
+ ok(count == 5, "Expected 5, got %i\n", count);
+ ok(!lstrcmp(path1, "one\\.\\two"), "Expected one\\.\\two, got %s\n", path1);
+ ok(!lstrcmp(path2, "one\\.\\three"), "Expected one\\.\\three, got %s\n", path2);
+ ok(!lstrcmp(out, "one\\."), "Expected one\\., got %s\n", out);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try ..\ prefix */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path1, "one\\..\\two");
+ lstrcpy(path2, "one\\..\\three");
+ lstrcpy(out, "aaa");
+ count = PathCommonPrefixA(path1, path2, out);
+ ok(count == 6, "Expected 6, got %i\n", count);
+ ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
+ ok(!lstrcmp(path2, "one\\..\\three"), "Expected one\\..\\three, got %s\n", path2);
+ ok(!lstrcmp(out, "one\\.."), "Expected one\\.., got %s\n", out);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try ...\\ prefix */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path1, "one\\...\\two");
+ lstrcpy(path2, "one\\...\\three");
+ lstrcpy(out, "aaa");
+ count = PathCommonPrefixA(path1, path2, out);
+ ok(count == 7, "Expected 7, got %i\n", count);
+ ok(!lstrcmp(path1, "one\\...\\two"), "Expected one\\...\\two, got %s\n", path1);
+ ok(!lstrcmp(path2, "one\\...\\three"), "Expected one\\...\\three, got %s\n", path2);
+ ok(!lstrcmp(out, "one\\..."), "Expected one\\..., got %s\n", out);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try prefix that is not an msdn labeled prefix type */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path1, "same");
+ lstrcpy(path2, "same");
+ lstrcpy(out, "aaa");
+ count = PathCommonPrefixA(path1, path2, out);
+ ok(count == 4, "Expected 4, got %i\n", count);
+ ok(!lstrcmp(path1, "same"), "Expected same, got %s\n", path1);
+ ok(!lstrcmp(path2, "same"), "Expected same, got %s\n", path2);
+ ok(!lstrcmp(out, "same"), "Expected same, got %s\n", out);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try . after directory */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path1, "one\\mid.\\two");
+ lstrcpy(path2, "one\\mid.\\three");
+ lstrcpy(out, "aaa");
+ count = PathCommonPrefixA(path1, path2, out);
+ ok(count == 8, "Expected 8, got %i\n", count);
+ ok(!lstrcmp(path1, "one\\mid.\\two"), "Expected one\\mid.\\two, got %s\n", path1);
+ ok(!lstrcmp(path2, "one\\mid.\\three"), "Expected one\\mid.\\three, got %s\n", path2);
+ ok(!lstrcmp(out, "one\\mid."), "Expected one\\mid., got %s\n", out);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try . in the middle of a directory */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path1, "one\\mid.end\\two");
+ lstrcpy(path2, "one\\mid.end\\three");
+ lstrcpy(out, "aaa");
+ count = PathCommonPrefixA(path1, path2, out);
+ ok(count == 11, "Expected 11, got %i\n", count);
+ ok(!lstrcmp(path1, "one\\mid.end\\two"), "Expected one\\mid.end\\two, got %s\n", path1);
+ ok(!lstrcmp(path2, "one\\mid.end\\three"), "Expected one\\mid.end\\three, got %s\n", path2);
+ ok(!lstrcmp(out, "one\\mid.end"), "Expected one\\mid.end, got %s\n", out);
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* try comparing a .. with the expanded path */
+ SetLastError(0xdeadbeef);
+ lstrcpy(path1, "one\\..\\two");
+ lstrcpy(path2, "two");
+ lstrcpy(out, "aaa");
+ count = PathCommonPrefixA(path1, path2, out);
+ ok(count == 0, "Expected 0, got %i\n", count);
+ ok(!lstrcmp(path1, "one\\..\\two"), "Expected one\\..\\two, got %s\n", path1);
+ ok(!lstrcmp(path2, "two"), "Expected two, got %s\n", path2);
+ ok(lstrlen(out) == 0, "Expected 0 length out, got %i\n", lstrlen(out));
+ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
+}
+
+static void test_PathUnquoteSpaces(void)
+{
+ int i;
+ for(i = 0; i < sizeof(TEST_PATH_UNQUOTE_SPACES) / sizeof(TEST_PATH_UNQUOTE_SPACES[0]); i++)
+ {
+ char *path = strdupA(TEST_PATH_UNQUOTE_SPACES[i].path);
+ WCHAR *pathW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].path);
+ WCHAR *resultW = GetWideString(TEST_PATH_UNQUOTE_SPACES[i].result);
+
+ PathUnquoteSpacesA(path);
+ ok(!strcmp(path, TEST_PATH_UNQUOTE_SPACES[i].result), "%s (A): got %s expected %s\n",
+ TEST_PATH_UNQUOTE_SPACES[i].path, path,
+ TEST_PATH_UNQUOTE_SPACES[i].result);
+
+ PathUnquoteSpacesW(pathW);
+ ok(!lstrcmpW(pathW, resultW), "%s (W): strings differ\n",
+ TEST_PATH_UNQUOTE_SPACES[i].path);
+ FreeWideString(pathW);
+ FreeWideString(resultW);
+ HeapFree(GetProcessHeap(), 0, path);
+ }
+}
+
START_TEST(path)
{
- hShlwapi = LoadLibraryA("shlwapi.dll");
- if (!hShlwapi) return;
+ hShlwapi = GetModuleHandleA("shlwapi.dll");
test_UrlHash();
test_UrlGetPart();
test_PathSearchAndQualify();
test_PathCreateFromUrl();
test_PathIsUrl();
-
+
+ test_PathAddBackslash();
test_PathMakePretty();
+ test_PathMatchSpec();
/* For whatever reason, PathIsValidCharA and PathAppendA share the same
* ordinal number in some native versions. Check this to prevent a crash.
pPathIsValidCharW = (void*)GetProcAddress(hShlwapi, (LPSTR)456);
if (pPathIsValidCharW) test_PathIsValidCharW();
}
+
+ pPathCombineW = (void*)GetProcAddress(hShlwapi, "PathCombineW");
+ if (pPathCombineW)
+ test_PathCombineW();
+
+ test_PathCombineA();
+ test_PathAppendA();
+ test_PathCanonicalizeA();
+ test_PathFindExtensionA();
+ test_PathBuildRootA();
+ test_PathCommonPrefixA();
+ test_PathUnquoteSpaces();
}
<module name="shlwapi_winetest" type="win32cui" installbase="bin" installname="shlwapi_winetest.exe" allowwarnings="true">
- <include base="shlwapi_winetest">.</include>
- <define name="__USE_W32API" />
- <library>ntdll</library>
- <library>shlwapi</library>
- <library>ole32</library>
- <library>oleaut32</library>
- <library>kernel32</library>
- <library>advapi32</library>
- <file>clist.c</file>
- <file>ordinal.c</file>
- <file>shreg.c</file>
- <file>string.c</file>
- <file>testlist.c</file>
+ <include base="shlwapi_winetest">.</include>
+ <define name="__USE_W32API" />
+ <define name="_WIN32_IE">0x600</define>
+ <define name="_WIN32_WINNT">0x501</define>
+ <define name="WINVER">0x501</define>
+ <library>wine</library>
+ <library>shlwapi</library>
+ <library>advapi32</library>
+ <library>ole32</library>
+ <library>oleaut32</library>
+ <library>kernel32</library>
+ <library>uuid</library>
+ <library>ntdll</library>
+ <file>clist.c</file>
+ <file>clsid.c</file>
+ <file>generated.c</file>
+ <file>ordinal.c</file>
+ <file>path.c</file>
+ <file>shreg.c</file>
+ <file>string.c</file>
+ <file>testlist.c</file>
</module>
*
* 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 <assert.h>
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;
{
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)
{
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)
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)
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);
}
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 ******/
* 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
*/
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
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
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);
}
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;
}
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;
}
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);
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;
}
{
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");
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();
*
* 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 <stdio.h>
-#define NONAMELESSUNION
-#define NONAMELESSSTRUCT
#include "wine/test.h"
#include "winbase.h"
#include "winerror.h"
#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);
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;
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++;
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++;
}
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++;
}
{
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++;
}
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;
}
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);
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];
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]);
}
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();
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();
}
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 }