stick the winetests in the sub folder with the other regtests
authorSteven Edwards <winehacker@gmail.com>
Sat, 6 Aug 2005 18:02:57 +0000 (18:02 +0000)
committerSteven Edwards <winehacker@gmail.com>
Sat, 6 Aug 2005 18:02:57 +0000 (18:02 +0000)
svn path=/trunk/; revision=17106

39 files changed:
reactos/regtests/winetests/advapi32/crypt.c [new file with mode: 0644]
reactos/regtests/winetests/advapi32/crypt_lmhash.c [new file with mode: 0644]
reactos/regtests/winetests/advapi32/crypt_md4.c [new file with mode: 0644]
reactos/regtests/winetests/advapi32/crypt_md5.c [new file with mode: 0644]
reactos/regtests/winetests/advapi32/crypt_sha.c [new file with mode: 0644]
reactos/regtests/winetests/advapi32/registry.c [new file with mode: 0644]
reactos/regtests/winetests/advapi32/security.c [new file with mode: 0644]
reactos/regtests/winetests/advapi32/testlist.c [new file with mode: 0644]
reactos/regtests/winetests/comctl32/dpa.c [new file with mode: 0644]
reactos/regtests/winetests/comctl32/imagelist.c [new file with mode: 0644]
reactos/regtests/winetests/comctl32/mru.c [new file with mode: 0644]
reactos/regtests/winetests/comctl32/subclass.c [new file with mode: 0644]
reactos/regtests/winetests/comctl32/tab.c [new file with mode: 0644]
reactos/regtests/winetests/comctl32/testlist.c [new file with mode: 0644]
reactos/regtests/winetests/msvcrt/Makefile.in [new file with mode: 0644]
reactos/regtests/winetests/msvcrt/cpp.c [new file with mode: 0644]
reactos/regtests/winetests/msvcrt/environ.c [new file with mode: 0644]
reactos/regtests/winetests/msvcrt/file.c [new file with mode: 0644]
reactos/regtests/winetests/msvcrt/heap.c [new file with mode: 0644]
reactos/regtests/winetests/msvcrt/msvcrt_test.dsp [new file with mode: 0644]
reactos/regtests/winetests/msvcrt/printf.c [new file with mode: 0644]
reactos/regtests/winetests/msvcrt/scanf.c [new file with mode: 0644]
reactos/regtests/winetests/msvcrt/string.c [new file with mode: 0644]
reactos/regtests/winetests/msvcrt/testlist.c [new file with mode: 0644]
reactos/regtests/winetests/msvcrt/time.c [new file with mode: 0644]
reactos/regtests/winetests/version/info.c [new file with mode: 0644]
reactos/regtests/winetests/version/testlist.c [new file with mode: 0644]
reactos/regtests/winetests/winetest/config.h [new file with mode: 0644]
reactos/regtests/winetests/winetest/dist.rc [new file with mode: 0644]
reactos/regtests/winetests/winetest/gui.c [new file with mode: 0644]
reactos/regtests/winetests/winetest/main.c [new file with mode: 0644]
reactos/regtests/winetests/winetest/port.h [new file with mode: 0644]
reactos/regtests/winetests/winetest/resource.h [new file with mode: 0644]
reactos/regtests/winetests/winetest/send.c [new file with mode: 0644]
reactos/regtests/winetests/winetest/tests.rc [new file with mode: 0644]
reactos/regtests/winetests/winetest/util.c [new file with mode: 0644]
reactos/regtests/winetests/winetest/wine.ico [new file with mode: 0644]
reactos/regtests/winetests/winetest/winetest.h [new file with mode: 0644]
reactos/regtests/winetests/winetest/winetest.rc [new file with mode: 0644]

diff --git a/reactos/regtests/winetests/advapi32/crypt.c b/reactos/regtests/winetests/advapi32/crypt.c
new file mode 100644 (file)
index 0000000..087ab46
--- /dev/null
@@ -0,0 +1,764 @@
+/*
+ * Unit tests for crypt functions
+ *
+ * Copyright (c) 2004 Michael Jung
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wincrypt.h"
+#include "winerror.h"
+#include "winreg.h"
+
+#include "wine/test.h"
+
+static const char szRsaBaseProv[] = MS_DEF_PROV_A;
+static const char szNonExistentProv[] = "Wine Nonexistent Cryptographic Provider v11.2";
+static const char szKeySet[] = "wine_test_keyset";
+static const char szBadKeySet[] = "wine_test_bad_keyset";
+#define NON_DEF_PROV_TYPE 999
+
+static HMODULE hadvapi32;
+static BOOL (WINAPI *pCryptAcquireContextA)(HCRYPTPROV*,LPCSTR,LPCSTR,DWORD,DWORD);
+static BOOL (WINAPI *pCryptEnumProviderTypesA)(DWORD, DWORD*, DWORD, DWORD*, LPSTR, DWORD*);
+static BOOL (WINAPI *pCryptEnumProvidersA)(DWORD, DWORD*, DWORD, DWORD*, LPSTR, DWORD*);
+static BOOL (WINAPI *pCryptGetDefaultProviderA)(DWORD, DWORD*, DWORD, LPSTR, DWORD*);
+static BOOL (WINAPI *pCryptReleaseContext)(HCRYPTPROV, DWORD);
+static BOOL (WINAPI *pCryptSetProviderExA)(LPCSTR, DWORD, DWORD*, DWORD);
+static BOOL (WINAPI *pCryptCreateHash)(HCRYPTPROV, ALG_ID, HCRYPTKEY, DWORD, HCRYPTHASH*);
+static BOOL (WINAPI *pCryptDestroyHash)(HCRYPTHASH);
+static BOOL (WINAPI *pCryptGenRandom)(HCRYPTPROV, DWORD, BYTE*);
+static BOOL (WINAPI *pCryptContextAddRef)(HCRYPTPROV, DWORD*, DWORD dwFlags);
+static BOOL (WINAPI *pCryptGenKey)(HCRYPTPROV, ALG_ID, DWORD, HCRYPTKEY*);
+static BOOL (WINAPI *pCryptDestroyKey)(HCRYPTKEY);
+static BOOL (WINAPI *pCryptDecrypt)(HCRYPTKEY, HCRYPTHASH, BOOL, DWORD, BYTE*, DWORD*);
+static BOOL (WINAPI *pCryptDeriveKey)(HCRYPTPROV, ALG_ID, HCRYPTHASH, DWORD, HCRYPTKEY*);
+static BOOL (WINAPI *pCryptDuplicateHash)(HCRYPTHASH, DWORD*, DWORD, HCRYPTHASH*);
+static BOOL (WINAPI *pCryptDuplicateKey)(HCRYPTKEY, DWORD*, DWORD, HCRYPTKEY*);
+static BOOL (WINAPI *pCryptEncrypt)(HCRYPTKEY, HCRYPTHASH, BOOL, DWORD, BYTE*, DWORD*, DWORD);
+static BOOL (WINAPI *pCryptExportKey)(HCRYPTKEY, HCRYPTKEY, DWORD, DWORD, BYTE*, DWORD*);
+static BOOL (WINAPI *pCryptGetHashParam)(HCRYPTHASH, DWORD, BYTE*, DWORD*, DWORD);
+static BOOL (WINAPI *pCryptGetKeyParam)(HCRYPTKEY, DWORD, BYTE*, DWORD*, DWORD);
+static BOOL (WINAPI *pCryptGetProvParam)(HCRYPTPROV, DWORD, BYTE*, DWORD*, DWORD);
+static BOOL (WINAPI *pCryptGetUserKey)(HCRYPTPROV, DWORD, HCRYPTKEY*);
+static BOOL (WINAPI *pCryptHashData)(HCRYPTHASH, BYTE*, DWORD, DWORD);
+static BOOL (WINAPI *pCryptHashSessionKey)(HCRYPTHASH, HCRYPTKEY, DWORD);
+static BOOL (WINAPI *pCryptImportKey)(HCRYPTPROV, BYTE*, DWORD, HCRYPTKEY, DWORD, HCRYPTKEY*);
+static BOOL (WINAPI *pCryptSignHashW)(HCRYPTHASH, DWORD, LPCWSTR, DWORD, BYTE*, DWORD*);
+static BOOL (WINAPI *pCryptSetHashParam)(HCRYPTKEY, DWORD, BYTE*, DWORD);
+static BOOL (WINAPI *pCryptSetKeyParam)(HCRYPTKEY, DWORD, BYTE*, DWORD);
+static BOOL (WINAPI *pCryptSetProvParam)(HCRYPTPROV, DWORD, BYTE*, DWORD);
+static BOOL (WINAPI *pCryptVerifySignatureW)(HCRYPTHASH, BYTE*, DWORD, HCRYPTKEY, LPCWSTR, DWORD);
+
+static void init_function_pointers(void)
+{
+    hadvapi32 = GetModuleHandleA("advapi32.dll");
+
+    if(hadvapi32)
+    {
+        pCryptAcquireContextA = (void*)GetProcAddress(hadvapi32, "CryptAcquireContextA");
+        pCryptEnumProviderTypesA = (void*)GetProcAddress(hadvapi32, "CryptEnumProviderTypesA");
+        pCryptEnumProvidersA = (void*)GetProcAddress(hadvapi32, "CryptEnumProvidersA");
+        pCryptGetDefaultProviderA = (void*)GetProcAddress(hadvapi32, "CryptGetDefaultProviderA");
+        pCryptReleaseContext = (void*)GetProcAddress(hadvapi32, "CryptReleaseContext");
+        pCryptSetProviderExA = (void*)GetProcAddress(hadvapi32, "CryptSetProviderExA");
+        pCryptCreateHash = (void*)GetProcAddress(hadvapi32, "CryptCreateHash");
+        pCryptDestroyHash = (void*)GetProcAddress(hadvapi32, "CryptDestroyHash");
+        pCryptGenRandom = (void*)GetProcAddress(hadvapi32, "CryptGenRandom");
+        pCryptContextAddRef = (void*)GetProcAddress(hadvapi32, "CryptContextAddRef");
+        pCryptGenKey = (void*)GetProcAddress(hadvapi32, "CryptGenKey");
+        pCryptDestroyKey = (void*)GetProcAddress(hadvapi32, "CryptDestroyKey");
+        pCryptDecrypt = (void*)GetProcAddress(hadvapi32, "CryptDecrypt");
+        pCryptDeriveKey = (void*)GetProcAddress(hadvapi32, "CryptDeriveKey");
+        pCryptDuplicateHash = (void*)GetProcAddress(hadvapi32, "CryptDuplicateHash");
+        pCryptDuplicateKey = (void*)GetProcAddress(hadvapi32, "CryptDuplicateKey");
+        pCryptEncrypt = (void*)GetProcAddress(hadvapi32, "CryptEncrypt");
+        pCryptExportKey = (void*)GetProcAddress(hadvapi32, "CryptExportKey");
+        pCryptGetHashParam = (void*)GetProcAddress(hadvapi32, "CryptGetHashParam");
+        pCryptGetKeyParam = (void*)GetProcAddress(hadvapi32, "CryptGetKeyParam");
+        pCryptGetProvParam = (void*)GetProcAddress(hadvapi32, "CryptGetProvParam");
+        pCryptGetUserKey = (void*)GetProcAddress(hadvapi32, "CryptGetUserKey");
+        pCryptHashData = (void*)GetProcAddress(hadvapi32, "CryptHashData");
+        pCryptHashSessionKey = (void*)GetProcAddress(hadvapi32, "CryptHashSessionKey");
+        pCryptImportKey = (void*)GetProcAddress(hadvapi32, "CryptImportKey");
+        pCryptSignHashW = (void*)GetProcAddress(hadvapi32, "CryptSignHashW");
+        pCryptSetHashParam = (void*)GetProcAddress(hadvapi32, "CryptSetHashParam");
+        pCryptSetKeyParam = (void*)GetProcAddress(hadvapi32, "CryptSetKeyParam");
+        pCryptSetProvParam = (void*)GetProcAddress(hadvapi32, "CryptSetProvParam");
+        pCryptVerifySignatureW = (void*)GetProcAddress(hadvapi32, "CryptVerifySignatureW");
+    }
+}
+
+static void init_environment(void)
+{
+       HCRYPTPROV hProv;
+
+       /* Ensure that container "wine_test_keyset" does exist */
+       if (!pCryptAcquireContextA(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, 0))
+       {
+               pCryptAcquireContextA(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, CRYPT_NEWKEYSET);
+       }
+       pCryptReleaseContext(hProv, 0);
+
+       /* Ensure that container "wine_test_keyset" does exist in default PROV_RSA_FULL type provider */
+       if (!pCryptAcquireContextA(&hProv, szKeySet, NULL, PROV_RSA_FULL, 0))
+       {
+               pCryptAcquireContextA(&hProv, szKeySet, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET);
+       }
+       pCryptReleaseContext(hProv, 0);
+
+       /* Ensure that container "wine_test_bad_keyset" does not exist. */
+       if (pCryptAcquireContextA(&hProv, szBadKeySet, szRsaBaseProv, PROV_RSA_FULL, 0))
+       {
+               pCryptReleaseContext(hProv, 0);
+               pCryptAcquireContextA(&hProv, szBadKeySet, szRsaBaseProv, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
+       }
+}
+
+static void clean_up_environment(void)
+{
+       HCRYPTPROV hProv;
+
+       /* Remove container "wine_test_keyset" */
+       if (pCryptAcquireContextA(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, 0))
+       {
+               pCryptReleaseContext(hProv, 0);
+               pCryptAcquireContextA(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
+       }
+
+       /* Remove container "wine_test_keyset" from default PROV_RSA_FULL type provider */
+       if (pCryptAcquireContextA(&hProv, szKeySet, NULL, PROV_RSA_FULL, 0))
+       {
+               pCryptReleaseContext(hProv, 0);
+               pCryptAcquireContextA(&hProv, szKeySet, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
+       }
+}
+
+static void test_acquire_context(void)
+{
+       BOOL result;
+       HCRYPTPROV hProv;
+
+       /* Provoke all kinds of error conditions (which are easy to provoke).
+        * The order of the error tests seems to match Windows XP's rsaenh.dll CSP,
+        * but since this is likely to change between CSP versions, we don't check
+        * this. Please don't change the order of tests. */
+       result = pCryptAcquireContextA(&hProv, NULL, NULL, 0, 0);
+       ok(!result && GetLastError()==NTE_BAD_PROV_TYPE, "%ld\n", GetLastError());
+
+       result = pCryptAcquireContextA(&hProv, NULL, NULL, 1000, 0);
+       ok(!result && GetLastError()==NTE_BAD_PROV_TYPE, "%ld\n", GetLastError());
+
+       result = pCryptAcquireContextA(&hProv, NULL, NULL, NON_DEF_PROV_TYPE, 0);
+       ok(!result && GetLastError()==NTE_PROV_TYPE_NOT_DEF, "%ld\n", GetLastError());
+
+       result = pCryptAcquireContextA(&hProv, szKeySet, szNonExistentProv, PROV_RSA_FULL, 0);
+       ok(!result && GetLastError()==NTE_KEYSET_NOT_DEF, "%ld\n", GetLastError());
+
+       result = pCryptAcquireContextA(&hProv, szKeySet, szRsaBaseProv, NON_DEF_PROV_TYPE, 0);
+       ok(!result && GetLastError()==NTE_PROV_TYPE_NO_MATCH, "%ld\n", GetLastError());
+
+       /* This test fails under Win2k SP4:
+          result = TRUE, GetLastError() == ERROR_INVALID_PARAMETER
+       SetLastError(0xdeadbeef);
+       result = pCryptAcquireContextA(NULL, szKeySet, szRsaBaseProv, PROV_RSA_FULL, 0);
+       ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "%d/%ld\n", result, GetLastError());
+       */
+
+       /* Last not least, try to really acquire a context. */
+       hProv = 0;
+       SetLastError(0xdeadbeef);
+       result = pCryptAcquireContextA(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, 0);
+       ok(result && (GetLastError() == ERROR_ENVVAR_NOT_FOUND || GetLastError() == ERROR_SUCCESS || GetLastError() == ERROR_RING2_STACK_IN_USE || GetLastError() == NTE_FAIL), "%d/%ld\n", result, GetLastError());
+
+       if (hProv)
+               pCryptReleaseContext(hProv, 0);
+
+       /* Try again, witch an empty ("\0") szProvider parameter */
+       hProv = 0;
+       SetLastError(0xdeadbeef);
+       result = pCryptAcquireContextA(&hProv, szKeySet, "", PROV_RSA_FULL, 0);
+       ok(result && (GetLastError() == ERROR_ENVVAR_NOT_FOUND || GetLastError() == ERROR_SUCCESS  || GetLastError() == ERROR_RING2_STACK_IN_USE || GetLastError() == NTE_FAIL), "%d/%ld\n", result, GetLastError());
+
+       if (hProv)
+               pCryptReleaseContext(hProv, 0);
+}
+
+static void test_incorrect_api_usage(void)
+{
+    BOOL result;
+    HCRYPTPROV hProv, hProv2;
+    HCRYPTHASH hHash, hHash2;
+    HCRYPTKEY hKey, hKey2;
+    BYTE temp;
+    DWORD dwLen, dwTemp;
+
+    /* This is to document incorrect api usage in the
+     * "Uru - Ages beyond Myst Demo" installer as reported by Paul Vriens.
+     *
+     * The installer destroys a hash object after having released the context
+     * with which the hash was created. This is not allowed according to MSDN,
+     * since CryptReleaseContext destroys all hash and key objects belonging to
+     * the respective context. However, while wine used to crash, Windows is more
+     * robust here and returns an ERROR_INVALID_PARAMETER code.
+     */
+
+    result = pCryptAcquireContextA(&hProv, szBadKeySet, szRsaBaseProv,
+                                   PROV_RSA_FULL, CRYPT_NEWKEYSET);
+    ok (result, "%08lx\n", GetLastError());
+    if (!result) return;
+
+    result = pCryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash);
+    ok (result, "%ld\n", GetLastError());
+    if (!result) return;
+
+    result = pCryptGenKey(hProv, CALG_RC4, 0, &hKey);
+    ok (result, "%ld\n", GetLastError());
+    if (!result) return;
+
+    result = pCryptGenKey(hProv, CALG_RC4, 0, &hKey2);
+    ok (result, "%ld\n", GetLastError());
+    if (!result) return;
+
+    result = pCryptDestroyKey(hKey2);
+    ok (result, "%ld\n", GetLastError());
+
+    dwTemp = CRYPT_MODE_ECB;
+    result = pCryptSetKeyParam(hKey2, KP_MODE, (BYTE*)&dwTemp, sizeof(DWORD));
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    result = pCryptAcquireContextA(&hProv2, szBadKeySet, NULL, PROV_RSA_FULL,
+                                   CRYPT_DELETEKEYSET);
+    ok (result, "%ld\n", GetLastError());
+    if (!result) return;
+
+    result = pCryptReleaseContext(hProv, 0);
+    ok (result, "%ld\n", GetLastError());
+    if (!result) return;
+
+    result = pCryptReleaseContext(hProv, 0);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    result = pCryptGenRandom(hProv, 1, &temp);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+#ifdef CRASHES_ON_NT40
+    result = pCryptContextAddRef(hProv, NULL, 0);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+#endif
+
+    result = pCryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash2);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    dwLen = 1;
+    result = pCryptDecrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, &temp, &dwLen);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    dwLen = 1;
+    result = pCryptEncrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, &temp, &dwLen, 1);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    result = pCryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey2);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+#ifdef CRASHES_ON_NT40
+    result = pCryptDuplicateHash(hHash, NULL, 0, &hHash2);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    result = pCryptDuplicateKey(hKey, NULL, 0, &hKey2);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+#endif
+
+    dwLen = 1;
+    result = pCryptExportKey(hKey, (HCRYPTPROV)NULL, 0, 0, &temp, &dwLen);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    result = pCryptGenKey(hProv, CALG_RC4, 0, &hKey2);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    dwLen = 1;
+    result = pCryptGetHashParam(hHash, 0, &temp, &dwLen, 0);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    dwLen = 1;
+    result = pCryptGetKeyParam(hKey, 0, &temp, &dwLen, 0);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    dwLen = 1;
+    result = pCryptGetProvParam(hProv, 0, &temp, &dwLen, 0);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    result = pCryptGetUserKey(hProv, 0, &hKey2);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    result = pCryptHashData(hHash, &temp, 1, 0);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    result = pCryptHashSessionKey(hHash, hKey, 0);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    result = pCryptImportKey(hProv, &temp, 1, (HCRYPTKEY)NULL, 0, &hKey2);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    dwLen = 1;
+    result = pCryptSignHashW(hHash, 0, NULL, 0, &temp, &dwLen);
+    ok (!result && (GetLastError() == ERROR_INVALID_PARAMETER ||
+        GetLastError() == ERROR_CALL_NOT_IMPLEMENTED), "%ld\n", GetLastError());
+
+    result = pCryptSetKeyParam(hKey, 0, &temp, 1);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    result = pCryptSetHashParam(hHash, 0, &temp, 1);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    result = pCryptSetProvParam(hProv, 0, &temp, 1);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    result = pCryptVerifySignatureW(hHash, &temp, 1, hKey, NULL, 0);
+    ok (!result && (GetLastError() == ERROR_INVALID_PARAMETER ||
+        GetLastError() == ERROR_CALL_NOT_IMPLEMENTED), "%ld\n", GetLastError());
+
+    result = pCryptDestroyHash(hHash);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+    result = pCryptDestroyKey(hKey);
+    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+}
+
+static BOOL FindProvRegVals(DWORD dwIndex, DWORD *pdwProvType, LPSTR *pszProvName,
+                           DWORD *pcbProvName, DWORD *pdwProvCount)
+{
+       HKEY hKey;
+       HKEY subkey;
+       DWORD size = sizeof(DWORD);
+
+       if (RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider", &hKey))
+               return FALSE;
+
+       RegQueryInfoKey(hKey, NULL, NULL, NULL, pdwProvCount, pcbProvName,
+                                NULL, NULL, NULL, NULL, NULL, NULL);
+       (*pcbProvName)++;
+
+       if (!(*pszProvName = ((LPSTR)LocalAlloc(LMEM_ZEROINIT, *pcbProvName))))
+               return FALSE;
+
+       RegEnumKeyEx(hKey, dwIndex, *pszProvName, pcbProvName, NULL, NULL, NULL, NULL);
+       (*pcbProvName)++;
+
+       RegOpenKey(hKey, *pszProvName, &subkey);
+       RegQueryValueEx(subkey, "Type", NULL, NULL, (BYTE*)pdwProvType, &size);
+
+       RegCloseKey(subkey);
+       RegCloseKey(hKey);
+
+       return TRUE;
+}
+
+static void test_enum_providers(void)
+{
+       /* expected results */
+       CHAR *pszProvName = NULL;
+       DWORD cbName;
+       DWORD dwType;
+       DWORD provCount;
+       DWORD dwIndex = 0;
+
+       /* actual results */
+       CHAR *provider = NULL;
+       DWORD providerLen;
+       DWORD type;
+       DWORD count;
+       BOOL result;
+       DWORD notNull = 5;
+       DWORD notZeroFlags = 5;
+
+       if(!pCryptEnumProvidersA)
+       {
+           trace("skipping CryptEnumProviders tests\n");
+           return;
+       }
+
+       if (!FindProvRegVals(dwIndex, &dwType, &pszProvName, &cbName, &provCount))
+               return;
+
+       /* check pdwReserved flag for NULL */
+       result = pCryptEnumProvidersA(dwIndex, &notNull, 0, &type, NULL, &providerLen);
+       ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "%ld\n", GetLastError());
+
+       /* check dwFlags == 0 */
+       result = pCryptEnumProvidersA(dwIndex, NULL, notZeroFlags, &type, NULL, &providerLen);
+       ok(!result && GetLastError()==NTE_BAD_FLAGS, "%ld\n", GetLastError());
+
+       /* alloc provider to half the size required
+        * cbName holds the size required */
+       providerLen = cbName / 2;
+       if (!(provider = ((LPSTR)LocalAlloc(LMEM_ZEROINIT, providerLen))))
+               return;
+
+       result = pCryptEnumProvidersA(dwIndex, NULL, 0, &type, provider, &providerLen);
+       ok(!result && GetLastError()==ERROR_MORE_DATA, "expected %i, got %ld\n",
+               ERROR_MORE_DATA, GetLastError());
+
+       LocalFree(provider);
+
+       /* loop through the providers to get the number of providers
+        * after loop ends, count should be provCount + 1 so subtract 1
+        * to get actual number of providers */
+       count = 0;
+       while(pCryptEnumProvidersA(count++, NULL, 0, &type, NULL, &providerLen))
+               ;
+       count--;
+       ok(count==provCount, "expected %i, got %i\n", (int)provCount, (int)count);
+
+       /* loop past the actual number of providers to get the error
+        * ERROR_NO_MORE_ITEMS */
+       for (count = 0; count < provCount + 1; count++)
+               result = pCryptEnumProvidersA(count, NULL, 0, &type, NULL, &providerLen);
+       ok(!result && GetLastError()==ERROR_NO_MORE_ITEMS, "expected %i, got %ld\n",
+                       ERROR_NO_MORE_ITEMS, GetLastError());
+
+       /* check expected versus actual values returned */
+       result = pCryptEnumProvidersA(dwIndex, NULL, 0, &type, NULL, &providerLen);
+       ok(result && providerLen==cbName, "expected %i, got %i\n", (int)cbName, (int)providerLen);
+       if (!(provider = ((LPSTR)LocalAlloc(LMEM_ZEROINIT, providerLen))))
+               return;
+
+       result = pCryptEnumProvidersA(dwIndex, NULL, 0, &type, provider, &providerLen);
+       ok(result && type==dwType, "expected %ld, got %ld\n",
+               dwType, type);
+       ok(result && !strcmp(pszProvName, provider), "expected %s, got %s\n", pszProvName, provider);
+       ok(result && cbName==providerLen, "expected %ld, got %ld\n",
+               cbName, providerLen);
+
+       LocalFree(provider);
+}
+
+static BOOL FindProvTypesRegVals(DWORD dwIndex, DWORD *pdwProvType, LPSTR *pszTypeName,
+                                DWORD *pcbTypeName, DWORD *pdwTypeCount)
+{
+       HKEY hKey;
+       HKEY hSubKey;
+       PSTR ch;
+
+       if (RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types", &hKey))
+               return FALSE;
+
+       if (RegQueryInfoKey(hKey, NULL, NULL, NULL, pdwTypeCount, pcbTypeName, NULL,
+                       NULL, NULL, NULL, NULL, NULL))
+           return FALSE;
+       (*pcbTypeName)++;
+
+       if (!(*pszTypeName = ((LPSTR)LocalAlloc(LMEM_ZEROINIT, *pcbTypeName))))
+               return FALSE;
+
+       if (RegEnumKeyEx(hKey, dwIndex, *pszTypeName, pcbTypeName, NULL, NULL, NULL, NULL))
+           return FALSE;
+       (*pcbTypeName)++;
+       ch = *pszTypeName + strlen(*pszTypeName);
+       /* Convert "Type 000" to 0, etc/ */
+       *pdwProvType = *(--ch) - '0';
+       *pdwProvType += (*(--ch) - '0') * 10;
+       *pdwProvType += (*(--ch) - '0') * 100;
+
+       if (RegOpenKey(hKey, *pszTypeName, &hSubKey))
+           return FALSE;
+
+       if (RegQueryValueEx(hSubKey, "TypeName", NULL, NULL, NULL, pcbTypeName))
+            return FALSE;
+
+       if (!(*pszTypeName = ((LPSTR)LocalAlloc(LMEM_ZEROINIT, *pcbTypeName))))
+               return FALSE;
+
+       if (RegQueryValueEx(hSubKey, "TypeName", NULL, NULL, *pszTypeName, pcbTypeName))
+           return FALSE;
+
+       RegCloseKey(hSubKey);
+       RegCloseKey(hKey);
+
+       return TRUE;
+}
+
+static void test_enum_provider_types()
+{
+       /* expected values */
+       DWORD dwProvType;
+       LPSTR pszTypeName = NULL;
+       DWORD cbTypeName;
+       DWORD dwTypeCount;
+
+       /* actual values */
+       DWORD index = 0;
+       DWORD provType;
+       LPSTR typeName = NULL;
+       DWORD typeNameSize;
+       DWORD typeCount;
+       DWORD result;
+       DWORD notNull = 5;
+       DWORD notZeroFlags = 5;
+
+       if(!pCryptEnumProviderTypesA)
+       {
+           trace("skipping CryptEnumProviderTypes tests\n");
+           return;
+       }
+
+       if (!FindProvTypesRegVals(index, &dwProvType, &pszTypeName, &cbTypeName, &dwTypeCount))
+       {
+           trace("could not find provider types in registry, skipping the test\n");
+           return;
+       }
+
+       /* check pdwReserved for NULL */
+       result = pCryptEnumProviderTypesA(index, &notNull, 0, &provType, typeName, &typeNameSize);
+       ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "expected %i, got %ld\n",
+               ERROR_INVALID_PARAMETER, GetLastError());
+
+       /* check dwFlags == zero */
+       result = pCryptEnumProviderTypesA(index, NULL, notZeroFlags, &provType, typeName, &typeNameSize);
+       ok(!result && GetLastError()==NTE_BAD_FLAGS, "expected %i, got %ld\n",
+               ERROR_INVALID_PARAMETER, GetLastError());
+
+       /* alloc provider type to half the size required
+        * cbTypeName holds the size required */
+       typeNameSize = cbTypeName / 2;
+       if (!(typeName = ((LPSTR)LocalAlloc(LMEM_ZEROINIT, typeNameSize))))
+               return;
+
+       /* This test fails under Win2k SP4:
+          result = TRUE, GetLastError() == 0xdeadbeef
+       SetLastError(0xdeadbeef);
+       result = pCryptEnumProviderTypesA(index, NULL, 0, &provType, typeName, &typeNameSize);
+       ok(!result && GetLastError()==ERROR_MORE_DATA, "expected 0/ERROR_MORE_DATA, got %d/%08lx\n",
+               result, GetLastError());
+       */
+
+       LocalFree(typeName);
+
+       /* loop through the provider types to get the number of provider types
+        * after loop ends, count should be dwTypeCount + 1 so subtract 1
+        * to get actual number of provider types */
+       typeCount = 0;
+       while(pCryptEnumProviderTypesA(typeCount++, NULL, 0, &provType, NULL, &typeNameSize))
+               ;
+       typeCount--;
+       ok(typeCount==dwTypeCount, "expected %ld, got %ld\n", dwTypeCount, typeCount);
+
+       /* loop past the actual number of provider types to get the error
+        * ERROR_NO_MORE_ITEMS */
+       for (typeCount = 0; typeCount < dwTypeCount + 1; typeCount++)
+               result = pCryptEnumProviderTypesA(typeCount, NULL, 0, &provType, NULL, &typeNameSize);
+       ok(!result && GetLastError()==ERROR_NO_MORE_ITEMS, "expected %i, got %ld\n",
+                       ERROR_NO_MORE_ITEMS, GetLastError());
+
+
+       /* check expected versus actual values returned */
+       result = pCryptEnumProviderTypesA(index, NULL, 0, &provType, NULL, &typeNameSize);
+       ok(result && typeNameSize==cbTypeName, "expected %ld, got %ld\n", cbTypeName, typeNameSize);
+       if (!(typeName = ((LPSTR)LocalAlloc(LMEM_ZEROINIT, typeNameSize))))
+               return;
+
+       typeNameSize = 0xdeadbeef;
+       result = pCryptEnumProviderTypesA(index, NULL, 0, &provType, typeName, &typeNameSize);
+       ok(result, "expected TRUE, got %ld\n", result);
+       ok(provType==dwProvType, "expected %ld, got %ld\n", dwProvType, provType);
+       if (pszTypeName)
+           ok(!strcmp(pszTypeName, typeName), "expected %s, got %s\n", pszTypeName, typeName);
+       ok(typeNameSize==cbTypeName, "expected %ld, got %ld\n", cbTypeName, typeNameSize);
+
+       LocalFree(typeName);
+}
+
+static BOOL FindDfltProvRegVals(DWORD dwProvType, DWORD dwFlags, LPSTR *pszProvName, DWORD *pcbProvName)
+{
+       HKEY hKey;
+       PSTR keyname;
+       PSTR ptr;
+       DWORD user = dwFlags & CRYPT_USER_DEFAULT;
+
+       LPSTR MACHINESTR = "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types\\Type XXX";
+       LPSTR USERSTR = "Software\\Microsoft\\Cryptography\\Provider Type XXX";
+
+       keyname = LocalAlloc(LMEM_ZEROINIT, (user ? strlen(USERSTR) : strlen(MACHINESTR)) + 1);
+       if (keyname)
+       {
+               user ? strcpy(keyname, USERSTR) : strcpy(keyname, MACHINESTR);
+               ptr = keyname + strlen(keyname);
+               *(--ptr) = (dwProvType % 10) + '0';
+               *(--ptr) = ((dwProvType / 10) % 10) + '0';
+               *(--ptr) = (dwProvType / 100) + '0';
+       } else
+               return FALSE;
+
+       if (RegOpenKey((dwFlags & CRYPT_USER_DEFAULT) ?  HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
+       {
+               LocalFree(keyname);
+               return FALSE;
+       }
+       LocalFree(keyname);
+
+       if (RegQueryValueEx(hKey, "Name", NULL, NULL, *pszProvName, pcbProvName))
+       {
+               if (GetLastError() != ERROR_MORE_DATA)
+                       SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
+               return FALSE;
+       }
+
+       if (!(*pszProvName = LocalAlloc(LMEM_ZEROINIT, *pcbProvName)))
+               return FALSE;
+
+       if (RegQueryValueEx(hKey, "Name", NULL, NULL, *pszProvName, pcbProvName))
+       {
+               if (GetLastError() != ERROR_MORE_DATA)
+                       SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
+               return FALSE;
+       }
+
+       RegCloseKey(hKey);
+
+       return TRUE;
+}
+
+static void test_get_default_provider()
+{
+       /* expected results */
+       DWORD dwProvType = PROV_RSA_FULL;
+       DWORD dwFlags = CRYPT_MACHINE_DEFAULT;
+       LPSTR pszProvName = NULL;
+       DWORD cbProvName;
+
+       /* actual results */
+       DWORD provType = PROV_RSA_FULL;
+       DWORD flags = CRYPT_MACHINE_DEFAULT;
+       LPSTR provName = NULL;
+       DWORD provNameSize;
+       DWORD result;
+       DWORD notNull = 5;
+
+       if(!pCryptGetDefaultProviderA)
+       {
+           trace("skipping CryptGetDefaultProvider tests\n");
+           return;
+       }
+
+       FindDfltProvRegVals(dwProvType, dwFlags, &pszProvName, &cbProvName);
+
+       /* check pdwReserved for NULL */
+       result = pCryptGetDefaultProviderA(provType, &notNull, flags, provName, &provNameSize);
+       ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "expected %i, got %ld\n",
+               ERROR_INVALID_PARAMETER, GetLastError());
+
+       /* check for invalid flag */
+       flags = 0xdeadbeef;
+       result = pCryptGetDefaultProviderA(provType, NULL, flags, provName, &provNameSize);
+       ok(!result && GetLastError()==NTE_BAD_FLAGS, "expected %ld, got %ld\n",
+               NTE_BAD_FLAGS, GetLastError());
+       flags = CRYPT_MACHINE_DEFAULT;
+
+       /* check for invalid prov type */
+       provType = 0xdeadbeef;
+       result = pCryptGetDefaultProviderA(provType, NULL, flags, provName, &provNameSize);
+       ok(!result && (GetLastError() == NTE_BAD_PROV_TYPE ||
+                      GetLastError() == ERROR_INVALID_PARAMETER),
+               "expected NTE_BAD_PROV_TYPE or ERROR_INVALID_PARAMETER, got %ld/%ld\n",
+               result, GetLastError());
+       provType = PROV_RSA_FULL;
+
+       SetLastError(0);
+
+       /* alloc provName to half the size required
+        * cbProvName holds the size required */
+       provNameSize = cbProvName / 2;
+       if (!(provName = LocalAlloc(LMEM_ZEROINIT, provNameSize)))
+               return;
+
+       result = pCryptGetDefaultProviderA(provType, NULL, flags, provName, &provNameSize);
+       ok(!result && GetLastError()==ERROR_MORE_DATA, "expected %i, got %ld\n",
+               ERROR_MORE_DATA, GetLastError());
+
+       LocalFree(provName);
+
+       /* check expected versus actual values returned */
+       result = pCryptGetDefaultProviderA(provType, NULL, flags, NULL, &provNameSize);
+       ok(result && provNameSize==cbProvName, "expected %ld, got %ld\n", cbProvName, provNameSize);
+       provNameSize = cbProvName;
+
+       if (!(provName = LocalAlloc(LMEM_ZEROINIT, provNameSize)))
+               return;
+
+       result = pCryptGetDefaultProviderA(provType, NULL, flags, provName, &provNameSize);
+       ok(result && !strcmp(pszProvName, provName), "expected %s, got %s\n", pszProvName, provName);
+       ok(result && provNameSize==cbProvName, "expected %ld, got %ld\n", cbProvName, provNameSize);
+
+       LocalFree(provName);
+}
+
+static void test_set_provider_ex()
+{
+       DWORD result;
+       DWORD notNull = 5;
+
+       /* results */
+       LPSTR pszProvName = NULL;
+       DWORD cbProvName;
+
+       if(!pCryptGetDefaultProviderA || !pCryptSetProviderExA)
+       {
+           trace("skipping CryptSetProviderEx tests\n");
+           return;
+       }
+
+       /* check pdwReserved for NULL */
+       result = pCryptSetProviderExA(MS_DEF_PROV, PROV_RSA_FULL, &notNull, CRYPT_MACHINE_DEFAULT);
+       ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "expected %i, got %ld\n",
+               ERROR_INVALID_PARAMETER, GetLastError());
+
+       /* remove the default provider and then set it to MS_DEF_PROV/PROV_RSA_FULL */
+       result = pCryptSetProviderExA(MS_DEF_PROV, PROV_RSA_FULL, NULL, CRYPT_MACHINE_DEFAULT | CRYPT_DELETE_DEFAULT);
+       ok(result, "%ld\n", GetLastError());
+
+       result = pCryptSetProviderExA(MS_DEF_PROV, PROV_RSA_FULL, NULL, CRYPT_MACHINE_DEFAULT);
+       ok(result, "%ld\n", GetLastError());
+
+       /* call CryptGetDefaultProvider to see if they match */
+       result = pCryptGetDefaultProviderA(PROV_RSA_FULL, NULL, CRYPT_MACHINE_DEFAULT, NULL, &cbProvName);
+       if (!(pszProvName = LocalAlloc(LMEM_ZEROINIT, cbProvName)))
+               return;
+
+       result = pCryptGetDefaultProviderA(PROV_RSA_FULL, NULL, CRYPT_MACHINE_DEFAULT, pszProvName, &cbProvName);
+       ok(result && !strcmp(MS_DEF_PROV, pszProvName), "expected %s, got %s\n", MS_DEF_PROV, pszProvName);
+       ok(result && cbProvName==(strlen(MS_DEF_PROV) + 1), "expected %i, got %ld\n", (strlen(MS_DEF_PROV) + 1), cbProvName);
+
+       LocalFree(pszProvName);
+}
+
+START_TEST(crypt)
+{
+       init_function_pointers();
+       if(pCryptAcquireContextA && pCryptReleaseContext) {
+       init_environment();
+       test_acquire_context();
+       test_incorrect_api_usage();
+       clean_up_environment();
+       }
+
+       test_enum_providers();
+       test_enum_provider_types();
+       test_get_default_provider();
+       test_set_provider_ex();
+}
diff --git a/reactos/regtests/winetests/advapi32/crypt_lmhash.c b/reactos/regtests/winetests/advapi32/crypt_lmhash.c
new file mode 100644 (file)
index 0000000..e8e3eb4
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Unit tests for SystemFunction006 (LMHash?)
+ *
+ * Copyright 2004 Hans Leidekker
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+
+#include "wine/test.h"
+#include "windef.h"
+#include "winbase.h"
+
+typedef VOID (WINAPI *fnSystemFunction006)( PCSTR passwd, PSTR lmhash );
+fnSystemFunction006 pSystemFunction006;
+
+static void test_SystemFunction006()
+{
+    static unsigned char lmhash[16 + 1];
+
+    unsigned char passwd[] = { 's','e','c','r','e','t', 0, 0, 0, 0, 0, 0, 0, 0 };
+    unsigned char expect[] =
+        { 0x85, 0xf5, 0x28, 0x9f, 0x09, 0xdc, 0xa7, 0xeb,
+          0xaa, 0xd3, 0xb4, 0x35, 0xb5, 0x14, 0x04, 0xee };
+
+    pSystemFunction006( passwd, lmhash );
+
+    ok( !memcmp( lmhash, expect, sizeof(expect) ),
+        "lmhash: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+        lmhash[0], lmhash[1], lmhash[2], lmhash[3], lmhash[4], lmhash[5],
+        lmhash[6], lmhash[7], lmhash[8], lmhash[9], lmhash[10], lmhash[11],
+        lmhash[12], lmhash[13], lmhash[14], lmhash[15] );
+}
+
+START_TEST(crypt_lmhash)
+{
+    HMODULE module;
+
+    if (!(module = LoadLibrary("advapi32.dll"))) return;
+
+    pSystemFunction006 = (fnSystemFunction006)GetProcAddress( module, "SystemFunction006" );
+
+    if (!pSystemFunction006) goto out;
+
+    if (pSystemFunction006)
+        test_SystemFunction006();
+
+out:
+    FreeLibrary( module );
+}
diff --git a/reactos/regtests/winetests/advapi32/crypt_md4.c b/reactos/regtests/winetests/advapi32/crypt_md4.c
new file mode 100644 (file)
index 0000000..cee8b7d
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Unit tests for MD4 functions
+ *
+ * Copyright 2004 Hans Leidekker
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+
+#include "wine/test.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+
+typedef struct
+{
+    unsigned int buf[4];
+    unsigned int i[2];
+    unsigned char in[64];
+    unsigned char digest[16];
+} MD4_CTX;
+
+typedef VOID (WINAPI *fnMD4Init)( MD4_CTX *ctx );
+typedef VOID (WINAPI *fnMD4Update)( MD4_CTX *ctx, const unsigned char *src, const int len );
+typedef VOID (WINAPI *fnMD4Final)( MD4_CTX *ctx );
+
+fnMD4Init pMD4Init;
+fnMD4Update pMD4Update;
+fnMD4Final pMD4Final;
+
+#define ctxcmp( a, b ) memcmp( (char*)a, (char*)b, FIELD_OFFSET( MD4_CTX, in ) )
+
+void test_md4_ctx()
+{
+    static unsigned char message[] =
+        "In our Life there's If"
+        "In our beliefs there's Lie"
+        "In our business there is Sin"
+        "In our bodies, there is Die";
+
+    int size = strlen( message );
+    HMODULE module;
+
+    MD4_CTX ctx;
+    MD4_CTX ctx_initialized =
+    {
+        { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 },
+        { 0, 0 }
+    };
+
+    MD4_CTX ctx_update1 =
+    {
+        { 0x5e592ef7, 0xbdcb1567, 0x2b626d17, 0x7d1198bd },
+        { 0x00000338, 0 }
+    };
+
+    MD4_CTX ctx_update2 =
+    {
+        { 0x05dcfd65, 0xb3711c0d, 0x9e3369c2, 0x903ead11 },
+        { 0x00000670, 0 }
+    };
+
+    unsigned char expect[16] =
+        { 0x5f, 0xd3, 0x9b, 0x29, 0x47, 0x53, 0x47, 0xaf,
+          0xa5, 0xba, 0x0c, 0x05, 0xff, 0xc0, 0xc7, 0xda };
+
+    if (!(module = LoadLibrary( "advapi32.dll" ))) return;
+
+    pMD4Init = (fnMD4Init)GetProcAddress( module, "MD4Init" );
+    pMD4Update = (fnMD4Update)GetProcAddress( module, "MD4Update" );
+    pMD4Final = (fnMD4Final)GetProcAddress( module, "MD4Final" );
+
+    if (!pMD4Init || !pMD4Update || !pMD4Final) goto out;
+
+    memset( &ctx, 0, sizeof(ctx) );
+    pMD4Init( &ctx );
+    ok( !ctxcmp( &ctx, &ctx_initialized ), "invalid initialization\n" );
+
+    pMD4Update( &ctx, message, size );
+    ok( !ctxcmp( &ctx, &ctx_update1 ), "update doesn't work correctly\n" );
+
+    pMD4Update( &ctx, message, size );
+    ok( !ctxcmp( &ctx, &ctx_update2 ), "update doesn't work correctly\n" );
+
+    pMD4Final( &ctx );
+    ok( ctxcmp( &ctx, &ctx_initialized ), "context has changed\n" );
+    ok( !memcmp( ctx.digest, expect, sizeof(expect) ), "incorrect result\n" );
+
+out:
+    FreeLibrary( module );
+}
+
+START_TEST(crypt_md4)
+{
+    test_md4_ctx();
+}
diff --git a/reactos/regtests/winetests/advapi32/crypt_md5.c b/reactos/regtests/winetests/advapi32/crypt_md5.c
new file mode 100644 (file)
index 0000000..0e46e53
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Unit tests for MD5 functions
+ *
+ * Copyright 2004 Hans Leidekker
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+
+#include "wine/test.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+
+typedef struct
+{
+    unsigned int i[2];
+    unsigned int buf[4];
+    unsigned char in[64];
+    unsigned char digest[16];
+} MD5_CTX;
+
+typedef VOID (WINAPI *fnMD5Init)( MD5_CTX *ctx );
+typedef VOID (WINAPI *fnMD5Update)( MD5_CTX *ctx, const unsigned char *src, const int len );
+typedef VOID (WINAPI *fnMD5Final)( MD5_CTX *ctx );
+
+fnMD5Init pMD5Init;
+fnMD5Update pMD5Update;
+fnMD5Final pMD5Final;
+
+#define ctxcmp( a, b ) memcmp( (char*)a, (char*)b, FIELD_OFFSET( MD5_CTX, in ) )
+
+void test_md5_ctx()
+{
+    static unsigned char message[] =
+        "In our Life there's If"
+        "In our beliefs there's Lie"
+        "In our business there is Sin"
+        "In our bodies, there is Die";
+
+    int size = strlen( message );
+    HMODULE module;
+
+    MD5_CTX ctx;
+    MD5_CTX ctx_initialized =
+    {
+        { 0, 0 },
+        { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 }
+    };
+
+    MD5_CTX ctx_update1 =
+    {
+        { 0x00000338, 0 },
+        { 0x068cb64d, 0xb7a05790, 0x426979ee, 0xed67e221 }
+    };
+
+    MD5_CTX ctx_update2 =
+    {
+        { 0x00000670, 0 },
+        { 0x2f7afe58, 0xcc3e9315, 0x709c465c, 0xbf6414c8 }
+    };
+
+    unsigned char expect[16] =
+        { 0x43, 0x03, 0xdd, 0x8c, 0x60, 0xd9, 0x3a, 0x22,
+          0x0b, 0x28, 0xd0, 0xb2, 0x65, 0x93, 0xd0, 0x36 };
+
+    if (!(module = LoadLibrary( "advapi32.dll" ))) return;
+
+    pMD5Init = (fnMD5Init)GetProcAddress( module, "MD5Init" );
+    pMD5Update = (fnMD5Update)GetProcAddress( module, "MD5Update" );
+    pMD5Final = (fnMD5Final)GetProcAddress( module, "MD5Final" );
+
+    if (!pMD5Init || !pMD5Update || !pMD5Final) goto out;
+
+    memset( &ctx, 0, sizeof(ctx) );
+    pMD5Init( &ctx );
+    ok( !ctxcmp( &ctx, &ctx_initialized ), "invalid initialization\n" );
+
+    pMD5Update( &ctx, message, size );
+    ok( !ctxcmp( &ctx, &ctx_update1 ), "update doesn't work correctly\n" );
+
+    pMD5Update( &ctx, message, size );
+    ok( !ctxcmp( &ctx, &ctx_update2 ), "update doesn't work correctly\n" );
+
+    pMD5Final( &ctx );
+    ok( ctxcmp( &ctx, &ctx_initialized ), "context has changed\n" );
+    ok( !memcmp( ctx.digest, expect, sizeof(expect) ), "incorrect result\n" );
+
+out:
+    FreeLibrary( module );
+}
+
+START_TEST(crypt_md5)
+{
+    test_md5_ctx();
+}
diff --git a/reactos/regtests/winetests/advapi32/crypt_sha.c b/reactos/regtests/winetests/advapi32/crypt_sha.c
new file mode 100644 (file)
index 0000000..5cf6fdb
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Unit tests for SHA functions
+ *
+ * Copyright (c) 2004 Filip Navara
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+
+#include "wine/test.h"
+
+typedef struct {
+   ULONG Unknown[6];
+   ULONG State[5];
+   ULONG Count[2];
+   UCHAR Buffer[64];
+} SHA_CTX, *PSHA_CTX;
+
+#define ctxcmp(a,b) memcmp((char*)a, (char*)b, FIELD_OFFSET(SHA_CTX, Buffer))
+
+static void test_sha_ctx(void)
+{
+   FARPROC pA_SHAInit, pA_SHAUpdate, pA_SHAFinal;
+   static const char test_buffer[] = "In our Life there's If"
+                       "In our beliefs there's Lie"
+                       "In our business there is Sin"
+                       "In our bodies, there is Die";
+   ULONG test_buffer_size = strlen(test_buffer);
+   HMODULE hmod;
+   SHA_CTX ctx;
+   SHA_CTX ctx_initialized = {{0, 0, 0, 0, 0}, {0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0}, {0, 0}};
+   SHA_CTX ctx_update1 = {{0, 0, 0, 0, 0}, {0xdbe5eba8, 0x6b4335ca, 0xf7c94abe, 0xc9f34e31, 0x311023f0}, {0, 0x67}};
+   SHA_CTX ctx_update2 = {{0, 0, 0, 0, 0}, {0x5ecc818d, 0x52498169, 0xf6758559, 0xd035a164, 0x871dd125}, {0, 0xce}};
+   ULONG result[5];
+   ULONG result_correct[5] = {0xe014f93, 0xe09791ec, 0x6dcf96c8, 0x8e9385fc, 0x1611c1bb};
+
+   hmod = LoadLibrary("advapi32.dll");
+   pA_SHAInit = GetProcAddress(hmod, "A_SHAInit");
+   pA_SHAUpdate = GetProcAddress(hmod, "A_SHAUpdate");
+   pA_SHAFinal = GetProcAddress(hmod, "A_SHAFinal");
+
+   if (!pA_SHAInit || !pA_SHAUpdate || !pA_SHAFinal) return;
+
+   RtlZeroMemory(&ctx, sizeof(ctx));
+   pA_SHAInit(&ctx);
+   ok(!ctxcmp(&ctx, &ctx_initialized), "invalid initialization\n");
+
+   pA_SHAUpdate(&ctx, test_buffer, test_buffer_size);
+   ok(!ctxcmp(&ctx, &ctx_update1), "update doesn't work correctly\n");
+
+   pA_SHAUpdate(&ctx, test_buffer, test_buffer_size);
+   ok(!ctxcmp(&ctx, &ctx_update2), "update doesn't work correctly\n");
+
+   pA_SHAFinal(&ctx, result);
+   ok(!ctxcmp(&ctx, &ctx_initialized), "context hasn't been reinitialized\n");
+   ok(!memcmp(result, result_correct, sizeof(result)), "incorrect result\n");
+
+   FreeLibrary(hmod);
+}
+
+START_TEST(crypt_sha)
+{
+    test_sha_ctx();
+}
diff --git a/reactos/regtests/winetests/advapi32/registry.c b/reactos/regtests/winetests/advapi32/registry.c
new file mode 100644 (file)
index 0000000..8f10e06
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * Unit tests for registry functions
+ *
+ * Copyright (c) 2002 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <assert.h>
+#include <stdarg.h>
+#include "wine/test.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winerror.h"
+
+static HKEY hkey_main;
+
+static const char * sTestpath1 = "%LONGSYSTEMVAR%\\subdir1";
+static const char * sTestpath2 = "%FOO%\\subdir1";
+
+/* delete key and all its subkeys */
+static DWORD delete_key( HKEY hkey )
+{
+    char name[MAX_PATH];
+    DWORD ret;
+
+    while (!(ret = RegEnumKeyA(hkey, 0, name, sizeof(name))))
+    {
+        HKEY tmp;
+        if (!(ret = RegOpenKeyExA( hkey, name, 0, KEY_ENUMERATE_SUB_KEYS, &tmp )))
+        {
+            ret = delete_key( tmp );
+            RegCloseKey( tmp );
+        }
+        if (ret) break;
+    }
+    if (ret != ERROR_NO_MORE_ITEMS) return ret;
+    RegDeleteKeyA( hkey, "" );
+    return 0;
+}
+
+static void setup_main_key(void)
+{
+    if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main )) delete_key( hkey_main );
+
+    assert (!RegCreateKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main ));
+}
+
+static void create_test_entries(void)
+{
+    SetEnvironmentVariableA("LONGSYSTEMVAR", "bar");
+    SetEnvironmentVariableA("FOO", "ImARatherLongButIndeedNeededString");
+
+    ok(!RegSetValueExA(hkey_main,"Test1",0,REG_EXPAND_SZ, sTestpath1, strlen(sTestpath1)+1),
+        "RegSetValueExA failed\n");
+    ok(!RegSetValueExA(hkey_main,"Test2",0,REG_SZ, sTestpath1, strlen(sTestpath1)+1),
+        "RegSetValueExA failed\n");
+    ok(!RegSetValueExA(hkey_main,"Test3",0,REG_EXPAND_SZ, sTestpath2, strlen(sTestpath2)+1),
+        "RegSetValueExA failed\n");
+}
+
+static void test_enum_value(void)
+{
+    DWORD res;
+    HKEY test_key;
+    char value[20], data[20];
+    WCHAR valueW[20], dataW[20];
+    DWORD val_count, data_count, type;
+    static const WCHAR foobarW[] = {'f','o','o','b','a','r',0};
+    static const WCHAR testW[] = {'T','e','s','t',0};
+    static const WCHAR xxxW[] = {'x','x','x','x','x','x','x','x',0};
+
+    /* create the working key for new 'Test' value */
+    res = RegCreateKeyA( hkey_main, "TestKey", &test_key );
+    ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res);
+
+    /* check NULL data with zero length */
+    res = RegSetValueExA( test_key, "Test", 0, REG_SZ, NULL, 0 );
+    if (GetVersion() & 0x80000000)
+        ok( res == ERROR_INVALID_PARAMETER, "RegSetValueExA returned %ld\n", res );
+    else
+        ok( !res, "RegSetValueExA returned %ld\n", res );
+    res = RegSetValueExA( test_key, "Test", 0, REG_EXPAND_SZ, NULL, 0 );
+    ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %ld\n", res );
+    res = RegSetValueExA( test_key, "Test", 0, REG_BINARY, NULL, 0 );
+    ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %ld\n", res );
+
+    res = RegSetValueExA( test_key, "Test", 0, REG_SZ, (BYTE *)"foobar", 7 );
+    ok( res == 0, "RegSetValueExA failed error %ld\n", res );
+
+    /* overflow both name and data */
+    val_count = 2;
+    data_count = 2;
+    type = 1234;
+    strcpy( value, "xxxxxxxxxx" );
+    strcpy( data, "xxxxxxxxxx" );
+    res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, data, &data_count );
+    ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
+    ok( val_count == 2, "val_count set to %ld\n", val_count );
+    ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
+    ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+    ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
+    ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data );
+
+    /* overflow name */
+    val_count = 3;
+    data_count = 20;
+    type = 1234;
+    strcpy( value, "xxxxxxxxxx" );
+    strcpy( data, "xxxxxxxxxx" );
+    res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, data, &data_count );
+    ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
+    /* Win9x returns 2 as specified by MSDN but NT returns 3... */
+    ok( val_count == 2 || val_count == 3, "val_count set to %ld\n", val_count );
+    ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
+    ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+#if 0
+    /* v5.1.2600.0 (XP Home) does not touch value or data in this case */
+    ok( !strcmp( value, "Te" ), "value set to '%s' instead of 'Te'\n", value );
+    ok( !strcmp( data, "foobar" ), "data set to '%s' instead of 'foobar'\n", data );
+#endif
+
+    /* overflow empty name */
+    val_count = 0;
+    data_count = 20;
+    type = 1234;
+    strcpy( value, "xxxxxxxxxx" );
+    strcpy( data, "xxxxxxxxxx" );
+    res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, data, &data_count );
+    ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
+    ok( val_count == 0, "val_count set to %ld\n", val_count );
+    ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
+    ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+    ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
+#if 0
+    /* v5.1.2600.0 (XP Home) does not touch data in this case */
+    ok( !strcmp( data, "foobar" ), "data set to '%s' instead of 'foobar'\n", data );
+#endif
+
+    /* overflow data */
+    val_count = 20;
+    data_count = 2;
+    type = 1234;
+    strcpy( value, "xxxxxxxxxx" );
+    strcpy( data, "xxxxxxxxxx" );
+    res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, data, &data_count );
+    ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
+    ok( val_count == 20, "val_count set to %ld\n", val_count );
+    ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
+    ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+    ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
+    ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data );
+
+    /* no overflow */
+    val_count = 20;
+    data_count = 20;
+    type = 1234;
+    strcpy( value, "xxxxxxxxxx" );
+    strcpy( data, "xxxxxxxxxx" );
+    res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, data, &data_count );
+    ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res );
+    ok( val_count == 4, "val_count set to %ld instead of 4\n", val_count );
+    ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
+    ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+    ok( !strcmp( value, "Test" ), "value is '%s' instead of Test\n", value );
+    ok( !strcmp( data, "foobar" ), "data is '%s' instead of foobar\n", data );
+
+    /* Unicode tests */
+
+    SetLastError(0);
+    res = RegSetValueExW( test_key, testW, 0, REG_SZ, (const BYTE *)foobarW, 7*sizeof(WCHAR) );
+    if (res==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
+        return;
+    ok( res == 0, "RegSetValueExW failed error %ld\n", res );
+
+    /* overflow both name and data */
+    val_count = 2;
+    data_count = 2;
+    type = 1234;
+    memcpy( valueW, xxxW, sizeof(xxxW) );
+    memcpy( dataW, xxxW, sizeof(xxxW) );
+    res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
+    ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
+    ok( val_count == 2, "val_count set to %ld\n", val_count );
+    ok( data_count == 7*sizeof(WCHAR), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count );
+    ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+    ok( !memcmp( valueW, xxxW, sizeof(xxxW) ), "value modified\n" );
+    ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
+
+    /* overflow name */
+    val_count = 3;
+    data_count = 20;
+    type = 1234;
+    memcpy( valueW, xxxW, sizeof(xxxW) );
+    memcpy( dataW, xxxW, sizeof(xxxW) );
+    res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
+    ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
+    ok( val_count == 3, "val_count set to %ld\n", val_count );
+    ok( data_count == 7*sizeof(WCHAR), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count );
+    ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+    ok( !memcmp( valueW, xxxW, sizeof(xxxW) ), "value modified\n" );
+    ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
+
+    /* overflow data */
+    val_count = 20;
+    data_count = 2;
+    type = 1234;
+    memcpy( valueW, xxxW, sizeof(xxxW) );
+    memcpy( dataW, xxxW, sizeof(xxxW) );
+    res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
+    ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
+    ok( val_count == 4, "val_count set to %ld instead of 4\n", val_count );
+    ok( data_count == 7*sizeof(WCHAR), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count );
+    ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+    ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" );
+    ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
+
+    /* no overflow */
+    val_count = 20;
+    data_count = 20;
+    type = 1234;
+    memcpy( valueW, xxxW, sizeof(xxxW) );
+    memcpy( dataW, xxxW, sizeof(xxxW) );
+    res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
+    ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res );
+    ok( val_count == 4, "val_count set to %ld instead of 4\n", val_count );
+    ok( data_count == 7*sizeof(WCHAR), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count );
+    ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
+    ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" );
+    ok( !memcmp( dataW, foobarW, sizeof(foobarW) ), "data is not 'foobar'\n" );
+}
+
+static void test_query_value_ex()
+{
+    DWORD ret;
+    DWORD size;
+    DWORD type;
+
+    ret = RegQueryValueExA(hkey_main, "Test2", NULL, &type, NULL, &size);
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+    ok(size == strlen(sTestpath1) + 1, "(%ld,%ld)\n", (DWORD)strlen(sTestpath1) + 1, size);
+    ok(type == REG_SZ, "type %ld is not REG_SZ\n", type);
+}
+
+static void test_reg_open_key()
+{
+    DWORD ret = 0;
+    HKEY hkResult = NULL;
+    HKEY hkPreserve = NULL;
+
+    /* successful open */
+    ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+    ok(hkResult != NULL, "expected hkResult != NULL\n");
+    hkPreserve = hkResult;
+
+    /* open same key twice */
+    ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+    ok(hkResult != hkPreserve, "epxected hkResult != hkPreserve\n");
+    ok(hkResult != NULL, "hkResult != NULL\n");
+    RegCloseKey(hkResult);
+
+    /* open nonexistent key
+     * check that hkResult is set to NULL
+     */
+    hkResult = hkPreserve;
+    ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
+    ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret);
+    ok(hkResult == NULL, "expected hkResult == NULL\n");
+
+    /* open the same nonexistent key again to make sure the key wasn't created */
+    hkResult = hkPreserve;
+    ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
+    ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret);
+    ok(hkResult == NULL, "expected hkResult == NULL\n");
+
+    /* send in NULL lpSubKey
+     * check that hkResult receives the value of hKey
+     */
+    hkResult = hkPreserve;
+    ret = RegOpenKeyA(HKEY_CURRENT_USER, NULL, &hkResult);
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+    ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
+
+    /* send empty-string in lpSubKey */
+    hkResult = hkPreserve;
+    ret = RegOpenKeyA(HKEY_CURRENT_USER, "", &hkResult);
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+    ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
+
+    /* send in NULL lpSubKey and NULL hKey
+     * hkResult is set to NULL
+     */
+    hkResult = hkPreserve;
+    ret = RegOpenKeyA(NULL, NULL, &hkResult);
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+    ok(hkResult == NULL, "expected hkResult == NULL\n");
+
+    /* only send NULL hKey
+     * the value of hkResult remains unchanged
+     */
+    hkResult = hkPreserve;
+    ret = RegOpenKeyA(NULL, "Software\\Wine\\Test", &hkResult);
+    ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */
+       "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %ld\n", ret);
+    ok(hkResult == hkPreserve, "expected hkResult == hkPreserve\n");
+    RegCloseKey(hkResult);
+
+    /* send in NULL hkResult */
+    ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", NULL);
+    ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", ret);
+}
+
+static void test_reg_close_key()
+{
+    DWORD ret = 0;
+    HKEY hkHandle;
+
+    /* successfully close key
+     * hkHandle remains changed after call to RegCloseKey
+     */
+    ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkHandle);
+    ret = RegCloseKey(hkHandle);
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+
+    /* try to close the key twice */
+    ret = RegCloseKey(hkHandle); /* Windows 95 doesn't mind. */
+    ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_SUCCESS,
+       "expected ERROR_INVALID_HANDLE or ERROR_SUCCESS, got %ld\n", ret);
+
+    /* try to close a NULL handle */
+    ret = RegCloseKey(NULL);
+    ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */
+       "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %ld\n", ret);
+}
+
+static void test_reg_delete_key()
+{
+    DWORD ret;
+
+    ret = RegDeleteKey(hkey_main, NULL);
+    ok(ret == ERROR_INVALID_PARAMETER || ret == ERROR_ACCESS_DENIED,
+       "expected ERROR_INVALID_PARAMETER or ERROR_ACCESS_DENIED, got %ld\n", ret);
+}
+
+static void test_reg_save_key()
+{
+    DWORD ret;
+
+    ret = RegSaveKey(hkey_main, "saved_key", NULL);
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+}
+
+static void test_reg_load_key()
+{
+    DWORD ret;
+    HKEY hkHandle;
+
+    ret = RegLoadKey(HKEY_LOCAL_MACHINE, "Test", "saved_key");
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+
+    ret = RegOpenKey(HKEY_LOCAL_MACHINE, "Test", &hkHandle);
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+
+    RegCloseKey(hkHandle);
+}
+
+static void test_reg_unload_key()
+{
+    DWORD ret;
+
+    ret = RegUnLoadKey(HKEY_LOCAL_MACHINE, "Test");
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
+
+    DeleteFile("saved_key");
+}
+
+static BOOL set_privileges(LPCSTR privilege, BOOL set)
+{
+    TOKEN_PRIVILEGES tp;
+    HANDLE hToken;
+    LUID luid;
+
+    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
+        return FALSE;
+
+    if(!LookupPrivilegeValue(NULL, privilege, &luid))
+    {
+        CloseHandle(hToken);
+        return FALSE;
+    }
+
+    tp.PrivilegeCount = 1;
+    tp.Privileges[0].Luid = luid;
+
+    if (set)
+        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+    else
+        tp.Privileges[0].Attributes = 0;
+
+    AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
+    if (GetLastError() != ERROR_SUCCESS)
+    {
+        CloseHandle(hToken);
+        return FALSE;
+    }
+
+    CloseHandle(hToken);
+    return TRUE;
+}
+
+START_TEST(registry)
+{
+    setup_main_key();
+    create_test_entries();
+    test_enum_value();
+    test_query_value_ex();
+    test_reg_open_key();
+    test_reg_close_key();
+    test_reg_delete_key();
+
+    /* SaveKey/LoadKey require the SE_BACKUP_NAME privilege to be set */
+    if (set_privileges(SE_BACKUP_NAME, TRUE) &&
+        set_privileges(SE_RESTORE_NAME, TRUE))
+    {
+        test_reg_save_key();
+        test_reg_load_key();
+        test_reg_unload_key();
+
+        set_privileges(SE_BACKUP_NAME, FALSE);
+        set_privileges(SE_RESTORE_NAME, FALSE);
+    }
+    /* cleanup */
+    delete_key( hkey_main );
+}
diff --git a/reactos/regtests/winetests/advapi32/security.c b/reactos/regtests/winetests/advapi32/security.c
new file mode 100644 (file)
index 0000000..e4c7e44
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ * Unit tests for security functions
+ *
+ * Copyright (c) 2004 Mike McCormack
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+
+#include "wine/test.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "aclapi.h"
+#include "winnt.h"
+
+typedef BOOL (WINAPI *fnBuildTrusteeWithSidA)( TRUSTEE *trustee, PSID psid );
+typedef BOOL (WINAPI *fnBuildTrusteeWithNameA)( TRUSTEE *trustee, LPSTR str );
+typedef BOOL (WINAPI *fnConvertSidToStringSidA)( PSID pSid, LPSTR *str );
+typedef BOOL (WINAPI *fnConvertStringSidToSidA)( LPCSTR str, PSID pSid );
+typedef BOOL (WINAPI *fnGetFileSecurityA)(LPCSTR, SECURITY_INFORMATION,
+                                          PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
+
+static HMODULE hmod;
+
+fnBuildTrusteeWithSidA   pBuildTrusteeWithSidA;
+fnBuildTrusteeWithNameA  pBuildTrusteeWithNameA;
+fnConvertSidToStringSidA pConvertSidToStringSidA;
+fnConvertStringSidToSidA pConvertStringSidToSidA;
+fnGetFileSecurityA pGetFileSecurityA;
+
+struct sidRef
+{
+    SID_IDENTIFIER_AUTHORITY auth;
+    const char *refStr;
+};
+
+static void init(void)
+{
+    hmod = GetModuleHandle("advapi32.dll");
+}
+
+void test_sid()
+{
+    struct sidRef refs[] = {
+     { { {0x00,0x00,0x33,0x44,0x55,0x66} }, "S-1-860116326-1" },
+     { { {0x00,0x00,0x01,0x02,0x03,0x04} }, "S-1-16909060-1"  },
+     { { {0x00,0x00,0x00,0x01,0x02,0x03} }, "S-1-66051-1"     },
+     { { {0x00,0x00,0x00,0x00,0x01,0x02} }, "S-1-258-1"       },
+     { { {0x00,0x00,0x00,0x00,0x00,0x02} }, "S-1-2-1"         },
+     { { {0x00,0x00,0x00,0x00,0x00,0x0c} }, "S-1-12-1"        },
+    };
+    const char noSubAuthStr[] = "S-1-5";
+    unsigned int i;
+    PSID psid = NULL;
+    BOOL r;
+    LPSTR str = NULL;
+
+    pConvertSidToStringSidA = (fnConvertSidToStringSidA)
+                    GetProcAddress( hmod, "ConvertSidToStringSidA" );
+    if( !pConvertSidToStringSidA )
+        return;
+    pConvertStringSidToSidA = (fnConvertStringSidToSidA)
+                    GetProcAddress( hmod, "ConvertStringSidToSidA" );
+    if( !pConvertStringSidToSidA )
+        return;
+
+    r = pConvertStringSidToSidA( NULL, NULL );
+    ok( !r, "expected failure with NULL parameters\n" );
+    if( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED )
+        return;
+    ok( GetLastError() == ERROR_INVALID_PARAMETER,
+     "expected GetLastError() is ERROR_INVALID_PARAMETER, got %ld\n",
+     GetLastError() );
+
+    r = pConvertStringSidToSidA( refs[0].refStr, NULL );
+    ok( !r && GetLastError() == ERROR_INVALID_PARAMETER,
+     "expected GetLastError() is ERROR_INVALID_PARAMETER, got %ld\n",
+     GetLastError() );
+
+    r = pConvertStringSidToSidA( NULL, &str );
+    ok( !r && GetLastError() == ERROR_INVALID_PARAMETER,
+     "expected GetLastError() is ERROR_INVALID_PARAMETER, got %ld\n",
+     GetLastError() );
+
+    r = pConvertStringSidToSidA( noSubAuthStr, &psid );
+    ok( !r,
+     "expected failure with no sub authorities\n" );
+    ok( GetLastError() == ERROR_INVALID_SID,
+     "expected GetLastError() is ERROR_INVALID_SID, got %ld\n",
+     GetLastError() );
+
+    for( i = 0; i < sizeof(refs) / sizeof(refs[0]); i++ )
+    {
+        PISID pisid;
+
+        r = AllocateAndInitializeSid( &refs[i].auth, 1,1,0,0,0,0,0,0,0,
+         &psid );
+        ok( r, "failed to allocate sid\n" );
+        r = pConvertSidToStringSidA( psid, &str );
+        ok( r, "failed to convert sid\n" );
+        if (r)
+        {
+            ok( !strcmp( str, refs[i].refStr ),
+                "incorrect sid, expected %s, got %s\n", refs[i].refStr, str );
+            LocalFree( str );
+        }
+        if( psid )
+            FreeSid( psid );
+
+        r = pConvertStringSidToSidA( refs[i].refStr, &psid );
+        ok( r, "failed to parse sid string\n" );
+        pisid = (PISID)psid;
+        ok( pisid &&
+         !memcmp( pisid->IdentifierAuthority.Value, refs[i].auth.Value,
+         sizeof(refs[i].auth) ),
+         "string sid %s didn't parse to expected value\n"
+         "(got 0x%04x%08lx, expected 0x%04x%08lx)\n",
+         refs[i].refStr,
+         MAKEWORD( pisid->IdentifierAuthority.Value[1],
+         pisid->IdentifierAuthority.Value[0] ),
+         MAKELONG( MAKEWORD( pisid->IdentifierAuthority.Value[5],
+         pisid->IdentifierAuthority.Value[4] ),
+         MAKEWORD( pisid->IdentifierAuthority.Value[3],
+         pisid->IdentifierAuthority.Value[2] ) ),
+         MAKEWORD( refs[i].auth.Value[1], refs[i].auth.Value[0] ),
+         MAKELONG( MAKEWORD( refs[i].auth.Value[5], refs[i].auth.Value[4] ),
+         MAKEWORD( refs[i].auth.Value[3], refs[i].auth.Value[2] ) ) );
+        if( psid )
+            LocalFree( psid );
+    }
+}
+
+void test_trustee()
+{
+    TRUSTEE trustee;
+    PSID psid;
+    LPSTR str = "2jjj";
+
+    SID_IDENTIFIER_AUTHORITY auth = { {0x11,0x22,0,0,0, 0} };
+
+    pBuildTrusteeWithSidA = (fnBuildTrusteeWithSidA)
+                    GetProcAddress( hmod, "BuildTrusteeWithSidA" );
+    pBuildTrusteeWithNameA = (fnBuildTrusteeWithNameA)
+                    GetProcAddress( hmod, "BuildTrusteeWithNameA" );
+    if( !pBuildTrusteeWithSidA || !pBuildTrusteeWithNameA)
+        return;
+
+    if ( ! AllocateAndInitializeSid( &auth, 1, 42, 0,0,0,0,0,0,0,&psid ) )
+    {
+        trace( "failed to init SID\n" );
+       return;
+    }
+
+    memset( &trustee, 0xff, sizeof trustee );
+    pBuildTrusteeWithSidA( &trustee, psid );
+
+    ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
+    ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE,
+        "MultipleTrusteeOperation wrong\n");
+    ok( trustee.TrusteeForm == TRUSTEE_IS_SID, "TrusteeForm wrong\n");
+    ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
+    ok( trustee.ptstrName == (LPSTR) psid, "ptstrName wrong\n" );
+    FreeSid( psid );
+
+    /* test BuildTrusteeWithNameA */
+    memset( &trustee, 0xff, sizeof trustee );
+    pBuildTrusteeWithNameA( &trustee, str );
+
+    ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
+    ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE,
+        "MultipleTrusteeOperation wrong\n");
+    ok( trustee.TrusteeForm == TRUSTEE_IS_NAME, "TrusteeForm wrong\n");
+    ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
+    ok( trustee.ptstrName == str, "ptstrName wrong\n" );
+}
+
+/* If the first isn't defined, assume none is */
+#ifndef SE_MIN_WELL_KNOWN_PRIVILEGE
+#define SE_MIN_WELL_KNOWN_PRIVILEGE       2L
+#define SE_CREATE_TOKEN_PRIVILEGE         2L
+#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE   3L
+#define SE_LOCK_MEMORY_PRIVILEGE          4L
+#define SE_INCREASE_QUOTA_PRIVILEGE       5L
+#define SE_MACHINE_ACCOUNT_PRIVILEGE      6L
+#define SE_TCB_PRIVILEGE                  7L
+#define SE_SECURITY_PRIVILEGE             8L
+#define SE_TAKE_OWNERSHIP_PRIVILEGE       9L
+#define SE_LOAD_DRIVER_PRIVILEGE         10L
+#define SE_SYSTEM_PROFILE_PRIVILEGE      11L
+#define SE_SYSTEMTIME_PRIVILEGE          12L
+#define SE_PROF_SINGLE_PROCESS_PRIVILEGE 13L
+#define SE_INC_BASE_PRIORITY_PRIVILEGE   14L
+#define SE_CREATE_PAGEFILE_PRIVILEGE     15L
+#define SE_CREATE_PERMANENT_PRIVILEGE    16L
+#define SE_BACKUP_PRIVILEGE              17L
+#define SE_RESTORE_PRIVILEGE             18L
+#define SE_SHUTDOWN_PRIVILEGE            19L
+#define SE_DEBUG_PRIVILEGE               20L
+#define SE_AUDIT_PRIVILEGE               21L
+#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE  22L
+#define SE_CHANGE_NOTIFY_PRIVILLEGE      23L
+#define SE_REMOTE_SHUTDOWN_PRIVILEGE     24L
+#define SE_UNDOCK_PRIVILEGE              25L
+#define SE_SYNC_AGENT_PRIVILEGE          26L
+#define SE_ENABLE_DELEGATION_PRIVILEGE   27L
+#define SE_MANAGE_VOLUME_PRIVILEGE       28L
+#define SE_IMPERSONATE_PRIVILEGE         29L
+#define SE_CREATE_GLOBAL_PRIVILEGE       30L
+#define SE_MAX_WELL_KNOWN_PRIVILEGE      SE_CREATE_GLOBAL_PRIVILEGE
+#endif /* ndef SE_MIN_WELL_KNOWN_PRIVILEGE */
+
+static void test_allocateLuid(void)
+{
+    BOOL (WINAPI *pAllocateLocallyUniqueId)(PLUID);
+    LUID luid1, luid2;
+    BOOL ret;
+
+    pAllocateLocallyUniqueId = (void*)GetProcAddress(hmod, "AllocateLocallyUniqueId");
+    if (!pAllocateLocallyUniqueId) return;
+
+    ret = pAllocateLocallyUniqueId(&luid1);
+    if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+        return;
+
+    ok(ret,
+     "AllocateLocallyUniqueId failed: %ld\n", GetLastError());
+    ret = pAllocateLocallyUniqueId(&luid2);
+    ok( ret,
+     "AllocateLocallyUniqueId failed: %ld\n", GetLastError());
+    ok(luid1.LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE || luid1.HighPart != 0,
+     "AllocateLocallyUniqueId returned a well-known LUID\n");
+    ok(luid1.LowPart != luid2.LowPart || luid1.HighPart != luid2.HighPart,
+     "AllocateLocallyUniqueId returned non-unique LUIDs\n");
+    ret = pAllocateLocallyUniqueId(NULL);
+    ok( !ret && GetLastError() == ERROR_NOACCESS,
+     "AllocateLocallyUniqueId(NULL) didn't return ERROR_NOACCESS: %ld\n",
+     GetLastError());
+}
+
+static void test_lookupPrivilegeName(void)
+{
+    BOOL (WINAPI *pLookupPrivilegeNameA)(LPSTR, PLUID, LPSTR, LPDWORD);
+    char buf[MAX_PATH]; /* arbitrary, seems long enough */
+    DWORD cchName = sizeof(buf);
+    LUID luid = { 0, 0 };
+    LONG i;
+    BOOL ret;
+
+    /* check whether it's available first */
+    pLookupPrivilegeNameA = (void*)GetProcAddress(hmod, "LookupPrivilegeNameA");
+    if (!pLookupPrivilegeNameA) return;
+    luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
+    ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
+    if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+        return;
+
+    /* check with a short buffer */
+    cchName = 0;
+    luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
+    ret = pLookupPrivilegeNameA(NULL, &luid, NULL, &cchName);
+    ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+     "LookupPrivilegeNameA didn't fail with ERROR_INSUFFICIENT_BUFFER: %ld\n",
+     GetLastError());
+    ok(cchName == strlen("SeCreateTokenPrivilege") + 1,
+     "LookupPrivilegeNameA returned an incorrect required length for\n"
+     "SeCreateTokenPrivilege (got %ld, expected %d)\n", cchName,
+     strlen("SeCreateTokenPrivilege") + 1);
+    /* check a known value and its returned length on success */
+    cchName = sizeof(buf);
+    ok(pLookupPrivilegeNameA(NULL, &luid, buf, &cchName) &&
+     cchName == strlen("SeCreateTokenPrivilege"),
+     "LookupPrivilegeNameA returned an incorrect output length for\n"
+     "SeCreateTokenPrivilege (got %ld, expected %d)\n", cchName,
+     (int)strlen("SeCreateTokenPrivilege"));
+    /* check known values */
+    for (i = SE_MIN_WELL_KNOWN_PRIVILEGE; i < SE_MAX_WELL_KNOWN_PRIVILEGE; i++)
+    {
+        luid.LowPart = i;
+        cchName = sizeof(buf);
+        ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
+        ok( ret || GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
+         "LookupPrivilegeNameA(0.%ld) failed: %ld\n", i, GetLastError());
+    }
+    /* check a bogus LUID */
+    luid.LowPart = 0xdeadbeef;
+    cchName = sizeof(buf);
+    ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
+    ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
+     "LookupPrivilegeNameA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %ld\n",
+     GetLastError());
+    /* check on a bogus system */
+    luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
+    cchName = sizeof(buf);
+    ret = pLookupPrivilegeNameA("b0gu5.Nam3", &luid, buf, &cchName);
+    ok( !ret && GetLastError() == RPC_S_SERVER_UNAVAILABLE,
+     "LookupPrivilegeNameA didn't fail with RPC_S_SERVER_UNAVAILABLE: %ld\n",
+     GetLastError());
+}
+
+struct NameToLUID
+{
+    const char *name;
+    DWORD lowPart;
+};
+
+static void test_lookupPrivilegeValue(void)
+{
+    static const struct NameToLUID privs[] = {
+     { "SeCreateTokenPrivilege", SE_CREATE_TOKEN_PRIVILEGE },
+     { "SeAssignPrimaryTokenPrivilege", SE_ASSIGNPRIMARYTOKEN_PRIVILEGE },
+     { "SeLockMemoryPrivilege", SE_LOCK_MEMORY_PRIVILEGE },
+     { "SeIncreaseQuotaPrivilege", SE_INCREASE_QUOTA_PRIVILEGE },
+     { "SeMachineAccountPrivilege", SE_MACHINE_ACCOUNT_PRIVILEGE },
+     { "SeTcbPrivilege", SE_TCB_PRIVILEGE },
+     { "SeSecurityPrivilege", SE_SECURITY_PRIVILEGE },
+     { "SeTakeOwnershipPrivilege", SE_TAKE_OWNERSHIP_PRIVILEGE },
+     { "SeLoadDriverPrivilege", SE_LOAD_DRIVER_PRIVILEGE },
+     { "SeSystemProfilePrivilege", SE_SYSTEM_PROFILE_PRIVILEGE },
+     { "SeSystemtimePrivilege", SE_SYSTEMTIME_PRIVILEGE },
+     { "SeProfileSingleProcessPrivilege", SE_PROF_SINGLE_PROCESS_PRIVILEGE },
+     { "SeIncreaseBasePriorityPrivilege", SE_INC_BASE_PRIORITY_PRIVILEGE },
+     { "SeCreatePagefilePrivilege", SE_CREATE_PAGEFILE_PRIVILEGE },
+     { "SeCreatePermanentPrivilege", SE_CREATE_PERMANENT_PRIVILEGE },
+     { "SeBackupPrivilege", SE_BACKUP_PRIVILEGE },
+     { "SeRestorePrivilege", SE_RESTORE_PRIVILEGE },
+     { "SeShutdownPrivilege", SE_SHUTDOWN_PRIVILEGE },
+     { "SeDebugPrivilege", SE_DEBUG_PRIVILEGE },
+     { "SeAuditPrivilege", SE_AUDIT_PRIVILEGE },
+     { "SeSystemEnvironmentPrivilege", SE_SYSTEM_ENVIRONMENT_PRIVILEGE },
+     { "SeChangeNotifyPrivilege", SE_CHANGE_NOTIFY_PRIVILLEGE },
+     { "SeRemoteShutdownPrivilege", SE_REMOTE_SHUTDOWN_PRIVILEGE },
+     { "SeUndockPrivilege", SE_UNDOCK_PRIVILEGE },
+     { "SeSyncAgentPrivilege", SE_SYNC_AGENT_PRIVILEGE },
+     { "SeEnableDelegationPrivilege", SE_ENABLE_DELEGATION_PRIVILEGE },
+     { "SeManageVolumePrivilege", SE_MANAGE_VOLUME_PRIVILEGE },
+     { "SeImpersonatePrivilege", SE_IMPERSONATE_PRIVILEGE },
+     { "SeCreateGlobalPrivilege", SE_CREATE_GLOBAL_PRIVILEGE },
+    };
+    BOOL (WINAPI *pLookupPrivilegeValueA)(LPCSTR, LPCSTR, PLUID);
+    int i;
+    LUID luid;
+    BOOL ret;
+
+    /* check whether it's available first */
+    pLookupPrivilegeValueA = (void*)GetProcAddress(hmod, "LookupPrivilegeValueA");
+    if (!pLookupPrivilegeValueA) return;
+    ret = pLookupPrivilegeValueA(NULL, "SeCreateTokenPrivilege", &luid);
+    if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+        return;
+
+    /* check a bogus system name */
+    ret = pLookupPrivilegeValueA("b0gu5.Nam3", "SeCreateTokenPrivilege", &luid);
+    ok( !ret && GetLastError() == RPC_S_SERVER_UNAVAILABLE,
+     "LookupPrivilegeValueA didn't fail with RPC_S_SERVER_UNAVAILABLE: %ld\n",
+     GetLastError());
+    /* check a NULL string */
+    ret = pLookupPrivilegeValueA(NULL, 0, &luid);
+    ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
+     "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %ld\n",
+     GetLastError());
+    /* check a bogus privilege name */
+    ret = pLookupPrivilegeValueA(NULL, "SeBogusPrivilege", &luid);
+    ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
+     "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %ld\n",
+     GetLastError());
+    /* check case insensitive */
+    ret = pLookupPrivilegeValueA(NULL, "sEcREATEtOKENpRIVILEGE", &luid);
+    ok( ret,
+     "LookupPrivilegeValueA(NULL, sEcREATEtOKENpRIVILEGE, &luid) failed: %ld\n",
+     GetLastError());
+    for (i = 0; i < sizeof(privs) / sizeof(privs[0]); i++)
+    {
+        /* Not all privileges are implemented on all Windows versions, so
+         * don't worry if the call fails
+         */
+        if (pLookupPrivilegeValueA(NULL, privs[i].name, &luid))
+        {
+            ok(luid.LowPart == privs[i].lowPart,
+             "LookupPrivilegeValueA returned an invalid LUID for %s\n",
+             privs[i].name);
+        }
+    }
+}
+
+static void test_luid(void)
+{
+    test_allocateLuid();
+    test_lookupPrivilegeName();
+    test_lookupPrivilegeValue();
+}
+
+static void test_FileSecurity(void)
+{
+    char directory[MAX_PATH];
+    DWORD retval, outSize;
+    BOOL result;
+    BYTE buffer[0x40];
+
+    pGetFileSecurityA = (fnGetFileSecurityA)
+                    GetProcAddress( hmod, "GetFileSecurityA" );
+    if( !pGetFileSecurityA )
+        return;
+
+    retval = GetTempPathA(sizeof(directory), directory);
+    if (!retval) {
+        trace("GetTempPathA failed\n");
+        return;
+    }
+
+    strcpy(directory, "\\Should not exist");
+
+    SetLastError(NO_ERROR);
+    result = GetFileSecurityA( directory,OWNER_SECURITY_INFORMATION,
+                              (PSECURITY_DESCRIPTOR)buffer,0x40,&outSize);
+    ok(!result, "GetFileSecurityA should fail for not existing directories/files\n");
+    ok( (GetLastError() == ERROR_FILE_NOT_FOUND ) ||
+        (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) ,
+        "last error ERROR_FILE_NOT_FOUND / ERROR_CALL_NOT_IMPLEMENTED (98) "
+        "expected, got %ld\n", GetLastError());
+}
+
+START_TEST(security)
+{
+    init();
+    if (!hmod) return;
+    test_sid();
+    test_trustee();
+    test_luid();
+    test_FileSecurity();
+}
diff --git a/reactos/regtests/winetests/advapi32/testlist.c b/reactos/regtests/winetests/advapi32/testlist.c
new file mode 100644 (file)
index 0000000..a262e99
--- /dev/null
@@ -0,0 +1,27 @@
+/* Automatically generated file; DO NOT EDIT!! */
+
+/* stdarg.h is needed for Winelib */
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "windef.h"
+#include "winbase.h"
+
+extern void func_registry(void);
+extern void func_security(void);
+
+struct test
+{
+    const char *name;
+    void (*func)(void);
+};
+
+static const struct test winetest_testlist[] =
+{
+    { "registry", func_registry },
+    { "security", func_security },
+    { 0, 0 }
+};
+
+#define WINETEST_WANT_MAIN
+#include "wine/test.h"
diff --git a/reactos/regtests/winetests/comctl32/dpa.c b/reactos/regtests/winetests/comctl32/dpa.c
new file mode 100644 (file)
index 0000000..33d7841
--- /dev/null
@@ -0,0 +1,439 @@
+/*
+ * Unit tests for DPA functions
+ *
+ * Copyright 2003 Uwe Bonnes
+ * Copyright 2005 Felix Nawothnig
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define COBJMACROS
+
+#include <stdarg.h>
+
+#include "windows.h"
+#include "commctrl.h"
+#include "objidl.h"
+
+#include "wine/test.h"
+
+#define DPAM_NOSORT 0x1
+#define DPAM_INSERT 0x4
+#define DPAM_DELETE 0x8
+
+typedef struct _ITEMDATA
+{
+    INT   iPos;
+    PVOID pvData;
+} ITEMDATA, *LPITEMDATA;
+
+typedef PVOID   (CALLBACK *PFNDPAMERGE)(UINT,PVOID,PVOID,LPARAM);
+typedef HRESULT (CALLBACK *PFNDPASTM)(LPITEMDATA,IStream*,LPARAM);
+
+static HDPA    (WINAPI *pDPA_Clone)(const HDPA,const HDPA);
+static HDPA    (WINAPI *pDPA_Create)(INT);
+static HDPA    (WINAPI *pDPA_CreateEx)(INT,HANDLE);
+static PVOID   (WINAPI *pDPA_DeleteAllPtrs)(const HDPA);
+static PVOID   (WINAPI *pDPA_DeletePtr)(const HDPA,INT);
+static BOOL    (WINAPI *pDPA_Destroy)(const HDPA);
+static VOID    (WINAPI *pDPA_DestroyCallback)(HDPA,PFNDPAENUMCALLBACK,PVOID);
+static VOID    (WINAPI *pDPA_EnumCallback)(HDPA,PFNDPAENUMCALLBACK,PVOID); 
+static INT     (WINAPI *pDPA_GetPtr)(const HDPA,INT);
+static INT     (WINAPI *pDPA_GetPtrIndex)(const HDPA,PVOID);
+static BOOL    (WINAPI *pDPA_Grow)(HDPA,INT);
+static INT     (WINAPI *pDPA_InsertPtr)(const HDPA,INT,PVOID);
+static HRESULT (WINAPI *pDPA_LoadStream)(HDPA*,PFNDPASTM,IStream*,LPARAM);
+static BOOL    (WINAPI *pDPA_Merge)(const HDPA,const HDPA,DWORD,PFNDPACOMPARE,PFNDPAMERGE,LPARAM);
+static HRESULT (WINAPI *pDPA_SaveStream)(HDPA,PFNDPASTM,IStream*,LPARAM);
+static INT     (WINAPI *pDPA_Search)(HDPA,PVOID,INT,PFNDPACOMPARE,LPARAM,UINT);
+static BOOL    (WINAPI *pDPA_SetPtr)(const HDPA,INT,PVOID);
+static BOOL    (WINAPI *pDPA_Sort)(const HDPA,PFNDPACOMPARE,LPARAM);
+
+#define COMCTL32_GET_PROC(func, ord) \
+  ((p ## func = (PVOID)GetProcAddress(hcomctl32,(LPCSTR)ord)) ? 1 \
+   : (trace( #func " not exported\n"), 0)) 
+
+static BOOL InitFunctionPtrs(HMODULE hcomctl32)
+{
+    /* 4.00+ */
+    if(COMCTL32_GET_PROC(DPA_Clone, 331) &&
+       COMCTL32_GET_PROC(DPA_Create, 328) &&
+       COMCTL32_GET_PROC(DPA_CreateEx, 340) &&
+       COMCTL32_GET_PROC(DPA_DeleteAllPtrs, 337) &&
+       COMCTL32_GET_PROC(DPA_DeletePtr, 336) &&
+       COMCTL32_GET_PROC(DPA_Destroy, 329) &&
+       COMCTL32_GET_PROC(DPA_GetPtr, 332) &&
+       COMCTL32_GET_PROC(DPA_GetPtrIndex, 333) &&
+       COMCTL32_GET_PROC(DPA_Grow, 330) &&
+       COMCTL32_GET_PROC(DPA_InsertPtr, 334) &&
+       COMCTL32_GET_PROC(DPA_Search, 339) &&
+       COMCTL32_GET_PROC(DPA_SetPtr, 335) &&
+       COMCTL32_GET_PROC(DPA_Sort, 338))
+    {
+        /* 4.71+ */
+        COMCTL32_GET_PROC(DPA_DestroyCallback, 386) &&
+        COMCTL32_GET_PROC(DPA_EnumCallback, 385) &&
+        COMCTL32_GET_PROC(DPA_LoadStream, 9) &&
+        COMCTL32_GET_PROC(DPA_Merge, 11) &&
+        COMCTL32_GET_PROC(DPA_SaveStream, 10);
+
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/* Callbacks */
+static INT CALLBACK CB_CmpLT(PVOID p1, PVOID p2, LPARAM lp)
+{
+    ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
+    return p1 < p2 ? -1 : p1 > p2 ? 1 : 0;
+}
+
+static INT CALLBACK CB_CmpGT(PVOID p1, PVOID p2, LPARAM lp)
+{
+    ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
+    return p1 > p2 ? -1 : p1 < p2 ? 1 : 0;
+}
+
+static PVOID CALLBACK CB_MergeInsertSrc(UINT op, PVOID p1, PVOID p2, LPARAM lp)
+{
+    ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
+    return p1;
+}        
+
+static PVOID CALLBACK CB_MergeDeleteOddSrc(UINT op, PVOID p1, PVOID p2, LPARAM lp)
+{
+    ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
+    return ((PCHAR)p2)+1;
+}
+
+static INT nEnum;
+
+static INT CALLBACK CB_EnumFirstThree(PVOID pItem, PVOID lp)
+{   
+    INT i;
+
+    i = pDPA_GetPtrIndex(lp, pItem);
+    ok(i == nEnum, "i=%d nEnum=%d\n", i, nEnum);
+    nEnum++;
+    pDPA_SetPtr(lp, i, (PVOID)7);
+    return pItem != (PVOID)3;
+}
+
+static HRESULT CALLBACK CB_Save(LPITEMDATA pInfo, IStream *pStm, LPARAM lp)
+{
+    HRESULT hRes;
+    
+    ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
+    hRes = IStream_Write(pStm, &pInfo->iPos, sizeof(INT), NULL);
+    ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+    hRes = IStream_Write(pStm, &pInfo->pvData, sizeof(PVOID), NULL);
+    ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+    return S_OK;
+}
+
+static HRESULT CALLBACK CB_Load(LPITEMDATA pInfo, IStream *pStm, LPARAM lp)
+{
+    HRESULT hRes;
+    INT iOldPos;
+    
+    iOldPos = pInfo->iPos;
+    ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
+    hRes = IStream_Read(pStm, &pInfo->iPos, sizeof(INT), NULL);
+    ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+    ok(pInfo->iPos == iOldPos, "iPos=%d iOldPos=%d\n", pInfo->iPos, iOldPos);
+    hRes = IStream_Read(pStm, &pInfo->pvData, sizeof(PVOID), NULL);
+    ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+    return S_OK;
+}
+
+static BOOL CheckDPA(HDPA dpa, DWORD dwIn, PDWORD pdwOut)
+{
+    DWORD dwOut = 0;
+    INT i;
+
+    for(i = 0; i < 8;)
+    {
+        ULONG_PTR ulItem = (ULONG_PTR)pDPA_GetPtr(dpa, i++);
+        if(!ulItem) break;
+        dwOut = dwOut << 4 | (ulItem & 0xf);
+    }
+    
+    *pdwOut = dwOut;
+
+    if(dwOut != dwIn)
+    {
+        pDPA_DeleteAllPtrs(dpa);
+        
+        do
+        {
+            pDPA_InsertPtr(dpa, 0, (PVOID)(dwIn & 0xf));
+            dwIn >>= 4;
+        }
+        while(dwIn);
+        
+        return FALSE;
+    }
+    
+    return TRUE;
+}
+
+static void test_dpa(void)
+{
+    SYSTEM_INFO si;
+    HANDLE hHeap;
+    HDPA dpa, dpa2, dpa3;
+    INT ret, i;
+    PVOID p;
+    DWORD dw, dw2, dw3;
+    HRESULT hRes;
+    
+    GetSystemInfo(&si);
+    hHeap = HeapCreate(0, 1, 2);
+    ok(hHeap != NULL, "error=%ld\n", GetLastError());
+    dpa3 = pDPA_CreateEx(0, hHeap);
+    ok(dpa3 != NULL, "\n");
+    ret = pDPA_Grow(dpa3, si.dwPageSize + 1);
+    todo_wine ok(!ret && GetLastError() == ERROR_NOT_ENOUGH_MEMORY, 
+       "ret=%d error=%ld\n", ret, GetLastError());
+        
+    dpa = pDPA_Create(0);
+    ok(dpa != NULL, "\n");
+
+    /* Set item with out of bound index */
+    ok(pDPA_SetPtr(dpa, 1, (PVOID)6), "\n");
+    /* Fill the greated gap */
+    ok(pDPA_SetPtr(dpa, 0, (PVOID)5), "\n");
+    ok(CheckDPA(dpa, 0x56, &dw), "dw=0x%lx\n", dw);
+    
+    /* Prepend item */
+    ret = pDPA_InsertPtr(dpa, 1, (PVOID)1);
+    ok(ret == 1, "ret=%d\n", ret);
+    /* Append item using correct index */
+    ret = pDPA_InsertPtr(dpa, 3, (PVOID)3);
+    ok(ret == 3, "ret=%d\n", ret);
+    /* Append item using out of bound index */
+    ret = pDPA_InsertPtr(dpa, 5, (PVOID)2);
+    ok(ret == 4, "ret=%d\n", ret);
+    /* Append item using DPA_APPEND */ 
+    ret = pDPA_InsertPtr(dpa, DPA_APPEND, (PVOID)4);
+    ok(ret == 5, "ret=%d\n", ret);
+
+    ok(CheckDPA(dpa, 0x516324, &dw), "dw=0x%lx\n", dw);
+
+    for(i = 1; i <= 6; i++)
+    {
+        INT j, k;
+        k = pDPA_GetPtrIndex(dpa, (PVOID)i);
+        /* Linear searches should work on unsorted DPAs */
+        j = pDPA_Search(dpa, (PVOID)i, 0, CB_CmpLT, 0xdeadbeef, 0);
+        ok(j == k, "j=%d k=%d\n", j, k);
+    }
+
+    /* Sort DPA */
+    ok(pDPA_Sort(dpa, CB_CmpGT, 0xdeadbeef), "\n");
+    ok(CheckDPA(dpa, 0x654321, &dw), "dw=0x%lx\n", dw);
+    
+    /* Clone into a new DPA */
+    dpa2 = pDPA_Clone(dpa, NULL);
+    ok(dpa2 != NULL, "\n");
+    /* The old data should have been preserved */
+    ok(CheckDPA(dpa2, 0x654321, &dw2), "dw=0x%lx\n", dw2);
+    ok(pDPA_Sort(dpa, CB_CmpLT, 0xdeadbeef), "\n");
+    
+    /* Test if the DPA itself was really copied */
+    ok(CheckDPA(dpa,  0x123456, &dw),  "dw=0x%lx\n",  dw );
+    ok(CheckDPA(dpa2, 0x654321, &dw2), "dw2=0x%lx\n", dw2);
+
+    /* Clone into an old DPA */
+    p = NULL; SetLastError(ERROR_SUCCESS);
+    p = pDPA_Clone(dpa, dpa3);
+    ok(p == dpa3, "p=%p\n", p);
+    ok(CheckDPA(dpa3, 0x123456, &dw3), "dw3=0x%lx\n", dw3);
+
+    for(i = 1; i <= 6; i++)
+    {
+        INT j;
+
+        /* The array is in order so ptr == index+1 */
+        j = pDPA_GetPtrIndex(dpa, (PVOID)i);
+        ok(j+1 == i, "j=%d i=%d\n", j, i);
+        j = pDPA_Search(dpa, (PVOID)i, 0, CB_CmpLT, 0xdeadbeef, DPAS_SORTED);
+        ok(j+1 == i, "j=%d i=%d\n", j, i);
+
+        /* Linear searches respect iStart ... */
+        j = pDPA_Search(dpa, (PVOID)i, i+1, CB_CmpLT, 0xdeadbeef, 0);
+        ok(j == DPA_ERR, "j=%d\n", j);
+        /* ... but for a binary search it's ignored */
+        j = pDPA_Search(dpa, (PVOID)i, i+1, CB_CmpLT, 0xdeadbeef, DPAS_SORTED);
+        todo_wine ok(j+1 == i, "j=%d i=%d\n", j, i);
+    }
+    
+    /* Try to get the index of a nonexistent item */
+    i = pDPA_GetPtrIndex(dpa, (PVOID)7);
+    ok(i == DPA_ERR, "i=%d\n", i);
+    
+    /* Try to delete out of bound indexes */
+    p = pDPA_DeletePtr(dpa, -1);
+    ok(p == NULL, "p=%p\n", p);
+    p = pDPA_DeletePtr(dpa, 6);
+    ok(p == NULL, "p=%p\n", p);
+
+    /* Delete the third item */
+    p = pDPA_DeletePtr(dpa, 2);
+    ok(p == (PVOID)3, "p=%p\n", p);
+    ok(CheckDPA(dpa, 0x12456, &dw), "dw=0x%lx\n", dw);
+
+    /* Check where to re-insert the deleted item */
+    i = pDPA_Search(dpa, (PVOID)3, 0, 
+                    CB_CmpLT, 0xdeadbeef, DPAS_SORTED|DPAS_INSERTAFTER);
+    ok(i == 2, "i=%d\n", i);
+    /* DPAS_INSERTBEFORE works just like DPAS_INSERTAFTER */
+    i = pDPA_Search(dpa, (PVOID)3, 0,
+                    CB_CmpLT, 0xdeadbeef, DPAS_SORTED|DPAS_INSERTBEFORE);
+    ok(i == 2, "i=%d\n", i);
+    /* without DPAS_INSERTBEFORE/AFTER */
+    i = pDPA_Search(dpa, (PVOID)3, 0,
+                    CB_CmpLT, 0xdeadbeef, DPAS_SORTED);
+    ok(i == -1, "i=%d\n", i);
+
+    /* Re-insert the item */
+    ret = pDPA_InsertPtr(dpa, 2, (PVOID)3);
+    ok(ret == 2, "ret=%d i=%d\n", ret, 2);
+    ok(CheckDPA(dpa, 0x123456, &dw), "dw=0x%lx\n", dw);
+    
+    /* When doing a binary search while claiming reverse order all indexes
+     * should be bogus */
+    for(i = 0; i < 6; i++)
+    {
+        INT j = pDPA_Search(dpa, (PVOID)i, 0, CB_CmpGT, 0xdeadbeef,
+                            DPAS_SORTED|DPAS_INSERTBEFORE);
+        ok(j != i, "i=%d\n", i);
+    }
+
+    if(pDPA_Merge)
+    {
+        /* Delete all even entries from dpa */
+        p = pDPA_DeletePtr(dpa, 1);
+        p = pDPA_DeletePtr(dpa, 2);
+        p = pDPA_DeletePtr(dpa, 3);
+        ok(CheckDPA(dpa, 0x135, &dw), "dw=0x%lx\n", dw);
+    
+        /* Delete all odd entries from dpa2 */
+        pDPA_Merge(dpa2, dpa, DPAM_DELETE, 
+                   CB_CmpLT, CB_MergeDeleteOddSrc, 0xdeadbeef);
+        todo_wine ok(CheckDPA(dpa2, 0x246, &dw2), "dw=0x%lx\n", dw2);
+    
+        /* Merge dpa3 into dpa2 and dpa */
+        pDPA_Merge(dpa, dpa3, DPAM_INSERT|DPAM_NOSORT, 
+                   CB_CmpLT, CB_MergeInsertSrc, 0xdeadbeef);
+        pDPA_Merge(dpa2, dpa3, DPAM_INSERT|DPAM_NOSORT, 
+                   CB_CmpLT, CB_MergeInsertSrc, 0xdeadbeef);
+    
+        ok(CheckDPA(dpa,  0x123456, &dw ), "dw=0x%lx\n",  dw);
+        ok(CheckDPA(dpa2, 0x123456, &dw2), "dw2=0x%lx\n", dw2);
+        ok(CheckDPA(dpa3, 0x123456, &dw3), "dw3=0x%lx\n", dw3);
+    }
+
+    if(pDPA_EnumCallback)
+    {
+        nEnum = 0;
+        pDPA_EnumCallback(dpa2, CB_EnumFirstThree, (PVOID)dpa2);
+        ok(CheckDPA(dpa2, 0x777456, &dw2), "dw=0x%lx\n", dw2);
+        ok(nEnum == 3, "nEnum=%d\n", nEnum);
+    }
+    
+    /* Setting item with huge index should work */
+    ok(pDPA_SetPtr(dpa2, 0x12345, (PVOID)0xdeadbeef), "\n");
+    ret = pDPA_GetPtrIndex(dpa2, (PVOID)0xdeadbeef);
+    ok(ret == 0x12345, "ret=%d\n", ret);
+          
+    pDPA_DeleteAllPtrs(dpa2);
+    ok(CheckDPA(dpa2, 0, &dw2), "dw2=0x%lx\n", dw2);
+    pDPA_Destroy(dpa2);
+
+    if(pDPA_DestroyCallback)
+    {
+        nEnum = 0;
+        pDPA_DestroyCallback(dpa3, CB_EnumFirstThree, dpa3);
+        ok(nEnum == 3, "nEnum=%d\n", nEnum);
+    }
+    else pDPA_Destroy(dpa3);
+
+    if(!pDPA_SaveStream)
+        goto skip_stream_tests;
+
+    hRes = CoInitialize(NULL);
+    if(hRes == S_OK)
+    {
+        static const WCHAR szStg[] = { 'S','t','g',0 };
+        IStorage* pStg = NULL;
+        IStream* pStm = NULL;
+        LARGE_INTEGER liZero;
+        DWORD dwMode;
+        liZero.QuadPart = 0;
+
+        dwMode = STGM_DIRECT|STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE;
+        hRes = StgCreateDocfile(NULL, dwMode|STGM_DELETEONRELEASE, 0, &pStg);
+        ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+
+        hRes = IStorage_CreateStream(pStg, szStg, dwMode, 0, 0, &pStm);
+        ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+
+        hRes = pDPA_SaveStream(dpa, CB_Save, pStm, 0xdeadbeef);
+        todo_wine ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+        pDPA_Destroy(dpa);
+        
+        hRes = IStream_Seek(pStm, liZero, STREAM_SEEK_SET, NULL);
+        ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+        hRes = pDPA_LoadStream(&dpa, CB_Load, pStm, 0xdeadbeef);
+        todo_wine ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+        todo_wine ok(CheckDPA(dpa, 0x123456, &dw), "dw=0x%lx\n", dw);
+        pDPA_Destroy(dpa);
+
+        ret = IStream_Release(pStm);
+        ok(!ret, "ret=%d\n", ret);
+       
+        ret = IStorage_Release(pStg);
+        ok(!ret, "ret=%d\n", ret);
+
+        CoUninitialize();
+    }
+    else ok(0, "hResult: %ld\n", hRes);
+
+skip_stream_tests:
+    pDPA_Destroy(dpa);
+}
+
+START_TEST(dpa)
+{
+    HMODULE hcomctl32;
+
+    hcomctl32 = GetModuleHandleA("comctl32.dll");
+
+    if(!hcomctl32)
+    {
+        ok(0, "error=%ld\n", GetLastError());
+        return;
+    }
+
+    if(InitFunctionPtrs(hcomctl32))
+        test_dpa();
+    else
+        trace("skipping tests\n");
+
+    FreeLibrary(hcomctl32);
+}
diff --git a/reactos/regtests/winetests/comctl32/imagelist.c b/reactos/regtests/winetests/comctl32/imagelist.c
new file mode 100644 (file)
index 0000000..161c4d2
--- /dev/null
@@ -0,0 +1,560 @@
+/* Unit test suite for imagelist control.
+ *
+ * Copyright 2004 Michael Stefaniuc
+ * Copyright 2002 Mike McCormack for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <assert.h>
+#include <windows.h>
+#include <wine/commctrl.h>
+#include <stdio.h>
+
+#include "wine/test.h"
+
+#undef VISIBLE
+
+#ifdef VISIBLE
+#define WAIT Sleep (1000)
+#define REDRAW(hwnd) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW)
+#else
+#define WAIT
+#define REDRAW(hwnd)
+#endif
+
+
+static BOOL (WINAPI *pImageList_DrawIndirect)(IMAGELISTDRAWPARAMS*) = NULL;
+
+static HDC desktopDC;
+static HINSTANCE hinst;
+
+/* These macros build cursor/bitmap data in 4x4 pixel blocks */
+#define B(x,y) ((x?0xf0:0)|(y?0xf:0))
+#define ROW1(a,b,c,d,e,f,g,h) B(a,b),B(c,d),B(e,f),B(g,h)
+#define ROW32(a,b,c,d,e,f,g,h) ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h), \
+  ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h)
+#define ROW2(a,b,c,d,e,f,g,h,i,j,k,l) ROW1(a,b,c,d,e,f,g,h),B(i,j),B(k,l)
+#define ROW48(a,b,c,d,e,f,g,h,i,j,k,l) ROW2(a,b,c,d,e,f,g,h,i,j,k,l), \
+  ROW2(a,b,c,d,e,f,g,h,i,j,k,l), ROW2(a,b,c,d,e,f,g,h,i,j,k,l), \
+  ROW2(a,b,c,d,e,f,g,h,i,j,k,l)
+
+static const BYTE empty_bits[48*48/8];
+
+static const BYTE icon_bits[32*32/8] =
+{
+  ROW32(0,0,0,0,0,0,0,0),
+  ROW32(0,0,1,1,1,1,0,0),
+  ROW32(0,1,1,1,1,1,1,0),
+  ROW32(0,1,1,0,0,1,1,0),
+  ROW32(0,1,1,0,0,1,1,0),
+  ROW32(0,1,1,1,1,1,1,0),
+  ROW32(0,0,1,1,1,1,0,0),
+  ROW32(0,0,0,0,0,0,0,0)
+};
+
+static const BYTE bitmap_bits[48*48/8] =
+{
+  ROW48(0,0,0,0,0,0,0,0,0,0,0,0),
+  ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
+  ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
+  ROW48(0,1,0,0,0,0,0,0,1,0,1,0),
+  ROW48(0,1,0,0,0,0,0,1,0,0,1,0),
+  ROW48(0,1,0,0,0,0,1,0,0,0,1,0),
+  ROW48(0,1,0,0,0,1,0,0,0,0,1,0),
+  ROW48(0,1,0,0,1,0,0,0,0,0,1,0),
+  ROW48(0,1,0,1,0,0,0,0,0,0,1,0),
+  ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
+  ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
+  ROW48(0,0,0,0,0,0,0,0,0,0,0,0)
+};
+
+static HIMAGELIST createImageList(int cx, int cy)
+{
+    /* Create an ImageList and put an image into it */
+    HIMAGELIST himl = ImageList_Create(cx, cy, ILC_COLOR, 1, 1);
+    HBITMAP hbm = CreateBitmap(48, 48, 1, 1, bitmap_bits);
+    ImageList_Add(himl, hbm, NULL);
+    return himl;
+}
+
+static HWND create_a_window(void)
+{
+    char className[] = "bmwnd";
+    char winName[]   = "Test Bitmap";
+    HWND hWnd;
+    static int registered = 0;
+
+    if (!registered)
+    {
+        WNDCLASSA cls;
+
+        cls.style         = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
+        cls.lpfnWndProc   = DefWindowProcA;
+        cls.cbClsExtra    = 0;
+        cls.cbWndExtra    = 0;
+        cls.hInstance     = 0;
+        cls.hIcon         = LoadIconA (0, (LPSTR)IDI_APPLICATION);
+        cls.hCursor       = LoadCursorA (0, (LPSTR)IDC_ARROW);
+        cls.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
+        cls.lpszMenuName  = 0;
+        cls.lpszClassName = className;
+
+        RegisterClassA (&cls);
+        registered = 1;
+    }
+
+    /* Setup window */
+    hWnd = CreateWindowA (className, winName,
+       WS_OVERLAPPEDWINDOW ,
+       CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
+       0, hinst, 0);
+
+#ifdef VISIBLE
+    ShowWindow (hWnd, SW_SHOW);
+#endif
+    REDRAW(hWnd);
+    WAIT;
+
+    return hWnd;
+}
+
+static HDC show_image(HWND hwnd, HIMAGELIST himl, int idx, int size,
+                      LPCSTR loc, BOOL clear)
+{
+    HDC hdc = NULL;
+#ifdef VISIBLE
+    if (!himl) return NULL;
+
+    SetWindowText(hwnd, loc);
+    hdc = GetDC(hwnd);
+    ImageList_Draw(himl, idx, hdc, 0, 0, ILD_TRANSPARENT);
+
+    REDRAW(hwnd);
+    WAIT;
+
+    if (clear)
+    {
+        BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
+        ReleaseDC(hwnd, hdc);
+        hdc = NULL;
+    }
+#endif /* VISIBLE */
+    return hdc;
+}
+
+/* Useful for checking differences */
+#if 0
+static void dump_bits(const BYTE *p, const BYTE *q, int size)
+{
+  int i, j;
+
+  size /= 8;
+
+  for (i = 0; i < size * 2; i++)
+  {
+      printf("|");
+      for (j = 0; j < size; j++)
+          printf("%c%c", p[j] & 0xf0 ? 'X' : ' ', p[j] & 0xf ? 'X' : ' ');
+      printf(" -- ");
+      for (j = 0; j < size; j++)
+          printf("%c%c", q[j] & 0xf0 ? 'X' : ' ', q[j] & 0xf ? 'X' : ' ');
+      printf("|\n");
+      p += size * 4;
+      q += size * 4;
+  }
+  printf("\n");
+}
+#endif
+
+static void check_bits(HWND hwnd, HIMAGELIST himl, int idx, int size,
+                       const BYTE *checkbits, LPCSTR loc)
+{
+#ifdef VISIBLE
+    BYTE bits[100*100/8];
+    COLORREF c;
+    HDC hdc;
+    int x, y, i = -1;
+
+    if (!himl) return;
+
+    memset(bits, 0, sizeof(bits));
+    hdc = show_image(hwnd, himl, idx, size, loc, FALSE);
+
+    c = GetPixel(hdc, 0, 0);
+
+    for (y = 0; y < size; y ++)
+    {
+        for (x = 0; x < size; x++)
+        {
+            if (!(x & 0x7)) i++;
+            if (GetPixel(hdc, x, y) != c) bits[i] |= (0x80 >> (x & 0x7));
+        }
+    }
+
+    BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
+    ReleaseDC(hwnd, hdc);
+
+    ok (memcmp(bits, checkbits, (size * size)/8) == 0,
+        "%s: bits different\n", loc);
+    if (memcmp(bits, checkbits, (size * size)/8))
+        dump_bits(bits, checkbits, size);
+#endif /* VISIBLE */
+}
+
+static void testHotspot (void)
+{
+    struct hotspot {
+        int dx;
+        int dy;
+    };
+
+#define SIZEX1 47
+#define SIZEY1 31
+#define SIZEX2 11
+#define SIZEY2 17
+#define HOTSPOTS_MAX 4       /* Number of entries in hotspots */
+    static const struct hotspot hotspots[HOTSPOTS_MAX] = {
+        { 10, 7 },
+        { SIZEX1, SIZEY1 },
+        { -9, -8 },
+        { -7, 35 }
+    };
+    int i, j, ret;
+    HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
+    HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
+    HWND hwnd = create_a_window();
+
+
+    for (i = 0; i < HOTSPOTS_MAX; i++) {
+        for (j = 0; j < HOTSPOTS_MAX; j++) {
+            int dx1 = hotspots[i].dx;
+            int dy1 = hotspots[i].dy;
+            int dx2 = hotspots[j].dx;
+            int dy2 = hotspots[j].dy;
+            int correctx, correcty, newx, newy;
+            char loc[256];
+            HIMAGELIST himlNew;
+            POINT ppt;
+
+            ret = ImageList_BeginDrag(himl1, 0, dx1, dy1);
+            ok(ret != 0, "BeginDrag failed for { %d, %d }\n", dx1, dy1);
+            sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
+            show_image(hwnd, himl1, 0, max(SIZEX1, SIZEY1), loc, TRUE);
+
+            /* check merging the dragged image with a second image */
+            ret = ImageList_SetDragCursorImage(himl2, 0, dx2, dy2);
+            ok(ret != 0, "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
+                    dx1, dy1, dx2, dy2);
+            sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
+            show_image(hwnd, himl2, 0, max(SIZEX2, SIZEY2), loc, TRUE);
+
+            /* check new hotspot, it should be the same like the old one */
+            himlNew = ImageList_GetDragImage(NULL, &ppt);
+            ok(ppt.x == dx1 && ppt.y == dy1,
+                    "Expected drag hotspot [%d,%d] got [%ld,%ld]\n",
+                    dx1, dy1, ppt.x, ppt.y);
+            /* check size of new dragged image */
+            ImageList_GetIconSize(himlNew, &newx, &newy);
+            correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
+            correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
+            ok(newx == correctx && newy == correcty,
+                    "Expected drag image size [%d,%d] got [%d,%d]\n",
+                    correctx, correcty, newx, newy);
+            sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
+            show_image(hwnd, himlNew, 0, max(correctx, correcty), loc, TRUE);
+            ImageList_EndDrag();
+        }
+    }
+#undef SIZEX1
+#undef SIZEY1
+#undef SIZEX2
+#undef SIZEY2
+#undef HOTSPOTS_MAX
+    DestroyWindow(hwnd);
+}
+
+static BOOL DoTest1(void)
+{
+    HIMAGELIST himl ;
+
+    HICON hicon1 ;
+    HICON hicon2 ;
+    HICON hicon3 ;
+
+    /* create an imagelist to play with */
+    himl = ImageList_Create(84,84,0x10,0,3);
+    ok(himl!=0,"failed to create imagelist\n");
+
+    /* load the icons to add to the image list */
+    hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
+    ok(hicon1 != 0, "no hicon1\n");
+    hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
+    ok(hicon2 != 0, "no hicon2\n");
+    hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
+    ok(hicon3 != 0, "no hicon3\n");
+
+    /* remove when nothing exists */
+    ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
+    /* removing everything from an empty imagelist should succeed */
+    ok(ImageList_RemoveAll(himl),"removed nonexistent icon\n");
+
+    /* add three */
+    ok(0==ImageList_AddIcon(himl, hicon1),"failed to add icon1\n");
+    ok(1==ImageList_AddIcon(himl, hicon2),"failed to add icon2\n");
+    ok(2==ImageList_AddIcon(himl, hicon3),"failed to add icon3\n");
+
+    /* remove an index out of range */
+    ok(!ImageList_Remove(himl,4711),"removed nonexistent icon\n");
+
+    /* remove three */
+    ok(ImageList_Remove(himl,0),"can't remove 0\n");
+    ok(ImageList_Remove(himl,0),"can't remove 0\n");
+    ok(ImageList_Remove(himl,0),"can't remove 0\n");
+
+    /* remove one extra */
+    ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
+
+    /* destroy it */
+    ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
+
+    /* icons should be deleted by the imagelist */
+    ok(!DeleteObject(hicon1),"icon 1 wasn't deleted\n");
+    ok(!DeleteObject(hicon2),"icon 2 wasn't deleted\n");
+    ok(!DeleteObject(hicon3),"icon 3 wasn't deleted\n");
+
+    return TRUE;
+}
+
+static BOOL DoTest2(void)
+{
+    HIMAGELIST himl ;
+
+    HICON hicon1 ;
+    HICON hicon2 ;
+    HICON hicon3 ;
+
+    /* create an imagelist to play with */
+    himl = ImageList_Create(84,84,0x10,0,3);
+    ok(himl!=0,"failed to create imagelist\n");
+
+    /* load the icons to add to the image list */
+    hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
+    ok(hicon1 != 0, "no hicon1\n");
+    hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
+    ok(hicon2 != 0, "no hicon2\n");
+    hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
+    ok(hicon3 != 0, "no hicon3\n");
+
+    /* add three */
+    ok(0==ImageList_AddIcon(himl, hicon1),"failed to add icon1\n");
+    ok(1==ImageList_AddIcon(himl, hicon2),"failed to add icon2\n");
+    ok(2==ImageList_AddIcon(himl, hicon3),"failed to add icon3\n");
+
+    /* destroy it */
+    ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
+
+    /* icons should be deleted by the imagelist */
+    ok(!DeleteObject(hicon1),"icon 1 wasn't deleted\n");
+    ok(!DeleteObject(hicon2),"icon 2 wasn't deleted\n");
+    ok(!DeleteObject(hicon3),"icon 3 wasn't deleted\n");
+
+    return TRUE;
+}
+
+static BOOL DoTest3(void)
+{
+    HIMAGELIST himl;
+
+    HBITMAP hbm1;
+    HBITMAP hbm2;
+    HBITMAP hbm3;
+
+    IMAGELISTDRAWPARAMS imldp;
+    HDC hdc;
+    HWND hwndfortest;
+
+    if (!pImageList_DrawIndirect)
+    {
+        HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
+        pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
+        if (!pImageList_DrawIndirect)
+        {
+            trace("ImageList_DrawIndirect not available, skipping test\n");
+            return TRUE;
+        }
+    }
+
+    hwndfortest = create_a_window();
+    hdc = GetDC(hwndfortest);
+    ok(hdc!=NULL, "couldn't get DC\n");
+
+    /* create an imagelist to play with */
+    himl = ImageList_Create(48,48,0x10,0,3);
+    ok(himl!=0,"failed to create imagelist\n");
+
+    /* load the icons to add to the image list */
+    hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
+    ok(hbm1 != 0, "no bitmap 1\n");
+    hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
+    ok(hbm2 != 0, "no bitmap 2\n");
+    hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
+    ok(hbm3 != 0, "no bitmap 3\n");
+
+    /* add three */
+    ok(0==ImageList_Add(himl, hbm1, 0),"failed to add bitmap 1\n");
+    ok(1==ImageList_Add(himl, hbm2, 0),"failed to add bitmap 2\n");
+
+    ok(ImageList_SetImageCount(himl,3),"Setimage count failed\n");
+    /*ok(2==ImageList_Add(himl, hbm3, NULL),"failed to add bitmap 3\n"); */
+    ok(ImageList_Replace(himl, 2, hbm3, 0),"failed to replace bitmap 3\n");
+
+    memset(&imldp, 0, sizeof (imldp));
+    ok(!pImageList_DrawIndirect(&imldp), "zero data succeeded!\n");
+    imldp.cbSize = sizeof (imldp);
+    ok(!pImageList_DrawIndirect(&imldp), "zero hdc succeeded!\n");
+    imldp.hdcDst = hdc;
+    ok(!pImageList_DrawIndirect(&imldp),"zero himl succeeded!\n");
+    imldp.himl = himl;
+    if (!pImageList_DrawIndirect(&imldp))
+    {
+      /* Earlier versions of native comctl32 use a smaller structure */
+      imldp.cbSize -= 3 * sizeof(DWORD);
+      ok(pImageList_DrawIndirect(&imldp),"DrawIndirect should succeed\n");
+    }
+    REDRAW(hwndfortest);
+    WAIT;
+
+    imldp.fStyle = SRCCOPY;
+    imldp.rgbBk = CLR_DEFAULT;
+    imldp.rgbFg = CLR_DEFAULT;
+    imldp.y = 100;
+    imldp.x = 100;
+    ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
+    imldp.i ++;
+    ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
+    imldp.i ++;
+    ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
+    imldp.i ++;
+    ok(!pImageList_DrawIndirect(&imldp),"should fail\n");
+
+    /* remove three */
+    ok(ImageList_Remove(himl, 0), "removing 1st bitmap\n");
+    ok(ImageList_Remove(himl, 0), "removing 2nd bitmap\n");
+    ok(ImageList_Remove(himl, 0), "removing 3rd bitmap\n");
+
+    /* destroy it */
+    ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
+
+    /* bitmaps should not be deleted by the imagelist */
+    ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
+    ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
+    ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
+
+    ReleaseDC(hwndfortest, hdc);
+    DestroyWindow(hwndfortest);
+
+    return TRUE;
+}
+
+static void testMerge(void)
+{
+    HIMAGELIST himl1, himl2, hmerge;
+    HICON hicon1;
+    HWND hwnd = create_a_window();
+
+    himl1 = ImageList_Create(32,32,0,0,3);
+    ok(himl1 != NULL,"failed to create himl1\n");
+
+    himl2 = ImageList_Create(32,32,0,0,3);
+    ok(himl2 != NULL,"failed to create himl2\n");
+
+    hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
+    ok(hicon1 != NULL, "failed to create hicon1\n");
+
+    if (!himl1 || !himl2 || !hicon1)
+        return;
+
+    ok(0==ImageList_AddIcon(himl2, hicon1),"add icon1 to himl2 failed\n");
+    check_bits(hwnd, himl2, 0, 32, icon_bits, "add icon1 to himl2");
+
+    /* If himl1 has no images, merge still succeeds */
+    hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
+    ok(hmerge != NULL, "merge himl1,-1 failed\n");
+    check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,-1");
+    if (hmerge) ImageList_Destroy(hmerge);
+
+    hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
+    ok(hmerge != NULL,"merge himl1,0 failed\n");
+    check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,0");
+    if (hmerge) ImageList_Destroy(hmerge);
+
+    /* Same happens if himl2 is empty */
+    ImageList_Destroy(himl2);
+    himl2 = ImageList_Create(32,32,0,0,3);
+    ok(himl2 != NULL,"failed to recreate himl2\n");
+    if (!himl2)
+        return;
+
+    hmerge = ImageList_Merge(himl1, -1, himl2, -1, 0, 0);
+    ok(hmerge != NULL, "merge himl2,-1 failed\n");
+    check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,-1");
+    if (hmerge) ImageList_Destroy(hmerge);
+
+    hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
+    ok(hmerge != NULL, "merge himl2,0 failed\n");
+    check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,0");
+    if (hmerge) ImageList_Destroy(hmerge);
+
+    /* Now try merging an image with itself */
+    ok(0==ImageList_AddIcon(himl2, hicon1),"re-add icon1 to himl2 failed\n");
+
+    hmerge = ImageList_Merge(himl2, 0, himl2, 0, 0, 0);
+    ok(hmerge != NULL, "merge himl2 with itself failed\n");
+    check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2 with itself");
+    if (hmerge) ImageList_Destroy(hmerge);
+
+    /* Try merging 2 different image lists */
+    ok(0==ImageList_AddIcon(himl1, hicon1),"add icon1 to himl1 failed\n");
+
+    hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
+    ok(hmerge != NULL, "merge himl1 with himl2 failed\n");
+    check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2");
+    if (hmerge) ImageList_Destroy(hmerge);
+
+    hmerge = ImageList_Merge(himl1, 0, himl2, 0, 8, 16);
+    ok(hmerge != NULL, "merge himl1 with himl2 8,16 failed\n");
+    check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2, 8,16");
+    if (hmerge) ImageList_Destroy(hmerge);
+
+    ImageList_Destroy(himl1);
+    ImageList_Destroy(himl2);
+    DeleteObject(hicon1);
+    DestroyWindow(hwnd);
+}
+
+START_TEST(imagelist)
+{
+    desktopDC=GetDC(NULL);
+    hinst = GetModuleHandleA(NULL);
+
+    InitCommonControls();
+
+    testHotspot();
+    DoTest1();
+    DoTest2();
+    DoTest3();
+    testMerge();
+}
diff --git a/reactos/regtests/winetests/comctl32/mru.c b/reactos/regtests/winetests/comctl32/mru.c
new file mode 100644 (file)
index 0000000..2d9987c
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * comctl32 MRU unit tests
+ *
+ * Copyright (C) 2004 Jon Griffiths <jon_p_griffiths@yahoo.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "commctrl.h"
+#include "shlwapi.h"
+
+#include "wine/test.h"
+
+/* Keys for testing MRU functions */
+#define REG_TEST_BASEKEYA    "Software\\Wine"
+#define REG_TEST_BASESUBKEYA "Test"
+#define REG_TEST_KEYA    REG_TEST_BASEKEYA "\\" REG_TEST_BASESUBKEYA
+#define REG_TEST_SUBKEYA "MRUTest"
+#define REG_TEST_FULLKEY REG_TEST_KEYA "\\" REG_TEST_SUBKEYA
+
+/* Undocumented MRU structures & functions */
+typedef struct tagCREATEMRULISTA
+{
+    DWORD   cbSize;
+    DWORD   nMaxItems;
+    DWORD   dwFlags;
+    HKEY    hKey;
+    LPCSTR  lpszSubKey;
+    PROC    lpfnCompare;
+} CREATEMRULISTA, *LPCREATEMRULISTA;
+
+#define MRUF_STRING_LIST  0
+#define MRUF_BINARY_LIST  1
+#define MRUF_DELAYED_SAVE 2
+
+#define LIST_SIZE 3 /* Max entries for each mru */
+
+static CREATEMRULISTA mruA =
+{
+    sizeof(CREATEMRULISTA),
+    LIST_SIZE,
+    0,
+    NULL,
+    REG_TEST_SUBKEYA,
+    NULL
+};
+
+static HMODULE hComctl32;
+static HANDLE (WINAPI *pCreateMRUListA)(LPCREATEMRULISTA);
+static void   (WINAPI *pFreeMRUList)(HANDLE);
+static INT    (WINAPI *pAddMRUStringA)(HANDLE,LPCSTR);
+/*
+static INT    (WINAPI *pFindMRUStringA)(HANDLE,LPCSTR,LPINT);
+static INT    (WINAPI *pEnumMRUList)(HANDLE,INT,LPVOID,DWORD);
+*/
+
+static BOOL create_reg_entries(void)
+{
+    HKEY hKey = NULL;
+
+    ok(!RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_FULLKEY, &hKey),
+       "Couldn't create test key \"%s\"\n", REG_TEST_KEYA);
+    if (!hKey) return FALSE;
+    RegCloseKey(hKey);
+    return TRUE;
+}
+
+static void delete_reg_entries(void)
+{
+    HKEY hKey;
+
+    if (RegOpenKeyExA(HKEY_CURRENT_USER, REG_TEST_BASEKEYA, 0, KEY_ALL_ACCESS,
+                      &hKey))
+        return;
+    SHDeleteKeyA(hKey, REG_TEST_BASESUBKEYA);
+    RegCloseKey(hKey);
+}
+
+static void check_reg_entries(const char *mrulist, const char**items)
+{
+    char buff[128];
+    HKEY hKey = NULL;
+    DWORD type, size, ret;
+    size_t i;
+
+    ok(!RegOpenKeyA(HKEY_CURRENT_USER, REG_TEST_FULLKEY, &hKey),
+       "Couldn't open test key \"%s\"\n", REG_TEST_FULLKEY);
+    if (!hKey) return;
+
+    type = REG_SZ;
+    size = sizeof(buff);
+    buff[0] = '\0';
+    ret = RegQueryValueExA(hKey, "MRUList", NULL, &type, (LPBYTE)buff, &size);
+
+    ok(!ret && buff[0], "Checking MRU: got %ld from RegQueryValueExW\n", ret);
+    if(ret || !buff[0]) return;
+
+    ok(strcmp(buff, mrulist) == 0, "Checking MRU: Expected list %s, got %s\n",
+       mrulist, buff);
+    if(strcmp(buff, mrulist)) return;
+
+    for (i = 0; i < strlen(mrulist); i++)
+    {
+        char name[2];
+        name[0] = mrulist[i];
+        name[1] = '\0';
+        type = REG_SZ;
+        size = sizeof(buff);
+        buff[0] = '\0';
+        ret = RegQueryValueExA(hKey, name, NULL, &type, (LPBYTE)buff, &size);
+        ok(!ret && buff[0],
+           "Checking MRU item %d ('%c'): got %ld from RegQueryValueExW\n",
+           i, mrulist[i], ret);
+        if(ret || !buff[0]) return;
+        ok(!strcmp(buff, items[mrulist[i]-'a']),
+           "Checking MRU item %d ('%c'): expected \"%s\", got \"%s\"\n",
+           i, mrulist[i], buff, items[mrulist[i] - 'a']);
+    }
+}
+
+static INT CALLBACK cmp_mru_strA(LPCVOID data1, LPCVOID data2)
+{
+    return lstrcmpiA(data1, data2);
+}
+
+static HANDLE create_mruA(HKEY hKey, DWORD flags, PROC cmp)
+{
+    mruA.dwFlags = flags;
+    mruA.lpfnCompare = cmp;
+    mruA.hKey = hKey;
+
+    SetLastError(0);
+    return pCreateMRUListA(&mruA);
+}
+
+static void test_MRUListA(void)
+{
+    const char *checks[LIST_SIZE+1];
+    HANDLE hMRU;
+    HKEY hKey;
+    INT iRet;
+
+    pCreateMRUListA = (void*)GetProcAddress(hComctl32,(LPCSTR)151);
+    pFreeMRUList = (void*)GetProcAddress(hComctl32,(LPCSTR)152);
+    pAddMRUStringA = (void*)GetProcAddress(hComctl32,(LPCSTR)153);
+    if (!pCreateMRUListA || !pFreeMRUList || !pAddMRUStringA)
+        return;
+
+#if 0 /* Create (NULL) - crashes native */
+    hMRU = pCreateMRUListA(NULL);
+#endif
+
+    /* Create (size too small) */
+    mruA.cbSize = sizeof(mruA) - 2;
+    hMRU = create_mruA(NULL, MRUF_STRING_LIST, cmp_mru_strA);
+    ok (!hMRU && !GetLastError(),
+        "CreateMRUListA(too small) expected NULL,0 got %p,%ld\n",
+        hMRU, GetLastError());
+    mruA.cbSize = sizeof(mruA);
+
+    /* Create (size too big) */
+    mruA.cbSize = sizeof(mruA) + 2;
+    hMRU = create_mruA(NULL, MRUF_STRING_LIST, cmp_mru_strA);
+    ok (!hMRU && !GetLastError(),
+        "CreateMRUListA(too big) expected NULL,0 got %p,%ld\n",
+        hMRU, GetLastError());
+    mruA.cbSize = sizeof(mruA);
+
+    /* Create (NULL hKey) */
+    hMRU = create_mruA(NULL, MRUF_STRING_LIST, cmp_mru_strA);
+    ok (!hMRU && !GetLastError(),
+        "CreateMRUListA(NULL key) expected NULL,0 got %p,%ld\n",
+        hMRU, GetLastError());
+
+    /* Create (NULL name) */
+    mruA.lpszSubKey = NULL;
+    hMRU = create_mruA(NULL, MRUF_STRING_LIST, cmp_mru_strA);
+    ok (!hMRU && !GetLastError(),
+        "CreateMRUListA(NULL name) expected NULL,0 got %p,%ld\n",
+        hMRU, GetLastError());
+    mruA.lpszSubKey = REG_TEST_SUBKEYA;
+
+    /* Create a string MRU */
+    ok(!RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_KEYA, &hKey),
+       "Couldn't create test key \"%s\"\n", REG_TEST_KEYA);
+    if (!hKey)
+        return;
+    hMRU = create_mruA(hKey, MRUF_STRING_LIST, cmp_mru_strA);
+    ok(hMRU && !GetLastError(),
+       "CreateMRUListA(string) expected non-NULL,0 got %p,%ld\n",
+       hMRU, GetLastError());
+
+    if (hMRU)
+    {
+        checks[0] = "Test 1";
+        checks[1] = "Test 2";
+        checks[2] = "Test 3";
+        checks[3] = "Test 4";
+
+        /* Add (NULL list) */
+        SetLastError(0);
+        iRet = pAddMRUStringA(NULL, checks[0]);
+        ok(iRet == -1 && !GetLastError(),
+           "AddMRUStringA(NULL list) expected -1,0 got %d,%ld\n",
+           iRet, GetLastError());
+
+        /* Add (NULL string) */
+#if 0
+       /* Some native versions crash when passed NULL or fail to SetLastError()  */
+        SetLastError(0);
+        iRet = pAddMRUStringA(hMRU, NULL);
+        ok(iRet == 0 && GetLastError() == ERROR_INVALID_PARAMETER,
+           "AddMRUStringA(NULL str) expected 0,ERROR_INVALID_PARAMETER got %d,%ld\n",
+           iRet, GetLastError());
+#endif
+
+        /* Add 3 strings. Check the registry is correct after each add */
+        SetLastError(0);
+        iRet = pAddMRUStringA(hMRU, checks[0]);
+        ok(iRet == 0 && !GetLastError(),
+           "AddMRUStringA(1) expected 0,0 got %d,%ld\n",
+           iRet, GetLastError());
+        check_reg_entries("a", checks);
+
+        SetLastError(0);
+        iRet = pAddMRUStringA(hMRU, checks[1]);
+        ok(iRet == 1 && !GetLastError(),
+           "AddMRUStringA(2) expected 1,0 got %d,%ld\n",
+           iRet, GetLastError());
+        check_reg_entries("ba", checks);
+
+        SetLastError(0);
+        iRet = pAddMRUStringA(hMRU, checks[2]);
+        ok(iRet == 2 && !GetLastError(),
+           "AddMRUStringA(2) expected 2,0 got %d,%ld\n",
+           iRet, GetLastError());
+        check_reg_entries("cba", checks);
+
+        /* Add a duplicate of the 2nd string - it should move to the front,
+         * but keep the same index in the registry.
+         */
+        SetLastError(0);
+        iRet = pAddMRUStringA(hMRU, checks[1]);
+        ok(iRet == 1 && !GetLastError(),
+           "AddMRUStringA(re-add 1) expected 1,0 got %d,%ld\n",
+           iRet, GetLastError());
+        check_reg_entries("bca", checks);
+
+        /* Add a new string - replaces the oldest string + moves to the front */
+        SetLastError(0);
+        iRet = pAddMRUStringA(hMRU, checks[3]);
+        ok(iRet == 0 && !GetLastError(),
+           "AddMRUStringA(add new) expected 0,0 got %d,%ld\n",
+           iRet, GetLastError());
+        checks[0] = checks[3];
+        check_reg_entries("abc", checks);
+
+        /* Finished with this MRU */
+        pFreeMRUList(hMRU);
+    }
+
+    /* Free (NULL list) - Doesn't crash */
+    pFreeMRUList(NULL);
+}
+
+START_TEST(mru)
+{
+    hComctl32 = GetModuleHandleA("comctl32.dll");
+    if (!hComctl32)
+        return;
+
+    delete_reg_entries();
+    if (!create_reg_entries())
+        return;
+
+    test_MRUListA();
+
+    delete_reg_entries();
+}
diff --git a/reactos/regtests/winetests/comctl32/subclass.c b/reactos/regtests/winetests/comctl32/subclass.c
new file mode 100644 (file)
index 0000000..b192d4d
--- /dev/null
@@ -0,0 +1,298 @@
+/* Unit tests for subclassed windows.
+ *
+ * Copyright 2004 Kevin Koltzau
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <assert.h>
+#include <stdarg.h>
+
+#define _WIN32_WINNT 0x0501 /* For SetWindowSubclass/etc */
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "commctrl.h"
+
+#include "wine/test.h"
+
+static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
+static BOOL (WINAPI *pRemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
+static LRESULT (WINAPI *pDefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
+
+#define SEND_NEST   0x01
+#define DELETE_SELF 0x02
+#define DELETE_PREV 0x04
+
+struct message {
+    int procnum;           /* WndProc id message is expected from */
+    WPARAM wParam;         /* expected value of wParam */
+};
+
+static int sequence_cnt, sequence_size;
+static struct message* sequence;
+
+static const struct message Sub_BasicTest[] = {
+    { 2, 1 },
+    { 1, 1 },
+    { 2, 2 },
+    { 1, 2 },
+    { 0 }
+};
+
+static const struct message Sub_DeletedTest[] = {
+    { 2, 1 },
+    { 1, 1 },
+    { 0 }
+};
+
+static const struct message Sub_AfterDeletedTest[] = {
+    { 1, 1 },
+    { 0 }
+};
+
+static const struct message Sub_OldAfterNewTest[] = {
+    { 3, 1 },
+    { 2, 1 },
+    { 1, 1 },
+    { 3, 2 },
+    { 2, 2 },
+    { 1, 2 },
+    { 0 }
+};
+
+static const struct message Sub_MixTest[] = {
+    { 3, 1 },
+    { 4, 1 },
+    { 2, 1 },
+    { 1, 1 },
+    { 0 }
+};
+
+static const struct message Sub_MixAndNestTest[] = {
+    { 3, 1 },
+    { 4, 1 },
+    { 3, 2 },
+    { 4, 2 },
+    { 2, 2 },
+    { 1, 2 },
+    { 2, 1 },
+    { 1, 1 },
+    { 0 }
+};
+
+static const struct message Sub_MixNestDelTest[] = {
+    { 3, 1 },
+    { 4, 1 },
+    { 3, 2 },
+    { 2, 2 },
+    { 1, 2 },
+    { 2, 1 },
+    { 1, 1 },
+    { 0 }
+};
+
+static const struct message Sub_MixDelPrevTest[] = {
+    { 3, 1 },
+    { 5, 1 },
+    { 2, 1 },
+    { 1, 1 },
+    { 0 }
+};
+
+static void add_message(const struct message *msg)
+{
+    if (!sequence)
+    {
+        sequence_size = 10;
+        sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
+    }
+    if (sequence_cnt == sequence_size)
+    {
+        sequence_size *= 2;
+        sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
+    }
+    assert(sequence);
+
+    sequence[sequence_cnt].wParam  = msg->wParam;
+    sequence[sequence_cnt].procnum = msg->procnum;
+
+    sequence_cnt++;
+}
+
+static void flush_sequence(void)
+{
+    HeapFree(GetProcessHeap(), 0, sequence);
+    sequence = 0;
+    sequence_cnt = sequence_size = 0;
+}
+
+static void ok_sequence(const struct message *expected, const char *context)
+{
+    static const struct message end_of_sequence = { 0, 0 };
+    const struct message *actual;
+
+    add_message(&end_of_sequence);
+
+    actual = sequence;
+
+    while(expected->procnum && actual->procnum)
+    {
+        ok(expected->procnum == actual->procnum,
+            "%s: the procnum %d was expected, but got procnum %d instead\n",
+            context, expected->procnum, actual->procnum);
+        ok(expected->wParam == actual->wParam,
+            "%s: in procnum %d expecting wParam 0x%x got 0x%x\n",
+            context, expected->procnum, expected->wParam, actual->wParam);
+        expected++;
+        actual++;
+    }
+    ok(!expected->procnum, "Received fewer messages than expected\n");
+    ok(!actual->procnum, "Received more messages than expected\n");
+    flush_sequence();
+}
+
+static LRESULT WINAPI WndProc1(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    struct message msg;
+    
+    if(message == WM_USER) {
+        msg.wParam = wParam;
+        msg.procnum = 1;
+        add_message(&msg);
+    }
+    return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+
+static WNDPROC origProc3;
+static LRESULT WINAPI WndProc3(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    struct message msg;
+    
+    if(message == WM_USER) {
+        msg.wParam = wParam;
+        msg.procnum = 3;
+        add_message(&msg);
+    }
+    return CallWindowProc(origProc3, hwnd, message, wParam, lParam);
+}
+
+static LRESULT WINAPI WndProcSub(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR uldSubclass, DWORD_PTR dwRefData)
+{
+    struct message msg;
+    
+    if(message == WM_USER) {
+        msg.wParam = wParam;
+        msg.procnum = uldSubclass;
+        add_message(&msg);
+        
+        if(lParam) {
+            if(dwRefData & DELETE_SELF) {
+                pRemoveWindowSubclass(hwnd, WndProcSub, uldSubclass);
+                pRemoveWindowSubclass(hwnd, WndProcSub, uldSubclass);
+            }
+            if(dwRefData & DELETE_PREV)
+                pRemoveWindowSubclass(hwnd, WndProcSub, uldSubclass-1);
+            if(dwRefData & SEND_NEST)
+                SendMessage(hwnd, WM_USER, wParam+1, 0);
+        }
+    }
+    return pDefSubclassProc(hwnd, message, wParam, lParam);
+}
+
+static void test_subclass(void)
+{
+    HWND hwnd = CreateWindowExA(0, "TestSubclass", "Test subclass", WS_OVERLAPPEDWINDOW,
+                           100, 100, 200, 200, 0, 0, 0, NULL);
+    assert(hwnd);
+
+    pSetWindowSubclass(hwnd, WndProcSub, 2, 0);
+    SendMessage(hwnd, WM_USER, 1, 0);
+    SendMessage(hwnd, WM_USER, 2, 0);
+    ok_sequence(Sub_BasicTest, "Basic");
+
+    pSetWindowSubclass(hwnd, WndProcSub, 2, DELETE_SELF);
+    SendMessage(hwnd, WM_USER, 1, 1);
+    ok_sequence(Sub_DeletedTest, "Deleted");
+
+    SendMessage(hwnd, WM_USER, 1, 0);
+    ok_sequence(Sub_AfterDeletedTest, "After Deleted");
+
+    pSetWindowSubclass(hwnd, WndProcSub, 2, 0);
+    origProc3 = (WNDPROC)SetWindowLong(hwnd, GWL_WNDPROC, (LONG)WndProc3);
+    SendMessage(hwnd, WM_USER, 1, 0);
+    SendMessage(hwnd, WM_USER, 2, 0);
+    ok_sequence(Sub_OldAfterNewTest, "Old after New");
+
+    pSetWindowSubclass(hwnd, WndProcSub, 4, 0);
+    SendMessage(hwnd, WM_USER, 1, 0);
+    ok_sequence(Sub_MixTest, "Mix");
+
+    /* Now the fun starts */
+    pSetWindowSubclass(hwnd, WndProcSub, 4, SEND_NEST);
+    SendMessage(hwnd, WM_USER, 1, 1);
+    ok_sequence(Sub_MixAndNestTest, "Mix and nest");
+
+    pSetWindowSubclass(hwnd, WndProcSub, 4, SEND_NEST | DELETE_SELF);
+    SendMessage(hwnd, WM_USER, 1, 1);
+    ok_sequence(Sub_MixNestDelTest, "Mix, nest, del");
+
+    pSetWindowSubclass(hwnd, WndProcSub, 4, 0);
+    pSetWindowSubclass(hwnd, WndProcSub, 5, DELETE_PREV);
+    SendMessage(hwnd, WM_USER, 1, 1);
+    ok_sequence(Sub_MixDelPrevTest, "Mix and del prev");
+
+    DestroyWindow(hwnd);
+}
+
+static BOOL RegisterWindowClasses(void)
+{
+    WNDCLASSA cls;
+
+    cls.style = 0;
+    cls.lpfnWndProc = WndProc1;
+    cls.cbClsExtra = 0;
+    cls.cbWndExtra = 0;
+    cls.hInstance = GetModuleHandleA(0);
+    cls.hIcon = 0;
+    cls.hCursor = NULL;
+    cls.hbrBackground = NULL;
+    cls.lpszMenuName = NULL;
+    cls.lpszClassName = "TestSubclass";
+    if(!RegisterClassA(&cls)) return FALSE;
+    
+    return TRUE;
+}
+
+START_TEST(subclass)
+{
+    HMODULE hdll;
+    
+    hdll = GetModuleHandleA("comctl32.dll");
+    assert(hdll);
+    pSetWindowSubclass = (void*)GetProcAddress(hdll, "SetWindowSubclass");
+    pRemoveWindowSubclass = (void*)GetProcAddress(hdll, "RemoveWindowSubclass");
+    pDefSubclassProc = (void*)GetProcAddress(hdll, "DefSubclassProc");
+    
+    if(!pSetWindowSubclass || !pRemoveWindowSubclass || !pDefSubclassProc)
+        return;
+
+    if(!RegisterWindowClasses()) assert(0);
+
+    test_subclass();
+}
diff --git a/reactos/regtests/winetests/comctl32/tab.c b/reactos/regtests/winetests/comctl32/tab.c
new file mode 100644 (file)
index 0000000..a711e7e
--- /dev/null
@@ -0,0 +1,199 @@
+/* Unit test suite for tab control.
+ *
+ * Copyright 2003 Vitaliy Margolen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <assert.h>
+#include <windows.h>
+#include <commctrl.h>
+
+#include "wine/test.h"
+
+#undef VISIBLE
+
+#define TAB_DEFAULT_WIDTH 96
+#define TAB_PADDING_X 2
+#define TAB_PADDING_Y 2
+
+#define TCS_BOTTOM              0x0002
+
+#ifdef VISIBLE
+#define WAIT Sleep (1000)
+#define REDRAW(hwnd) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW)
+#define trace_tab(str) trace(str)
+#else
+#define WAIT
+#define REDRAW(hwnd)
+#define trace_tab(str)
+#endif
+
+static HWND
+create_tabcontrol (DWORD style)
+{
+    HWND handle;
+    TCITEM tcNewTab;
+
+    handle = CreateWindow (
+       WC_TABCONTROLA,
+       "TestTab",
+       WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style,
+        10, 10, 300, 100,
+        NULL, NULL, NULL, 0);
+
+    assert (handle);
+    
+    SetWindowLong(handle, GWL_STYLE, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style);
+
+    tcNewTab.mask = TCIF_TEXT | TCIF_IMAGE;
+    tcNewTab.pszText = "Tab 1";
+    tcNewTab.iImage = 0;
+    SendMessage (handle, TCM_INSERTITEM, 0, (LPARAM) &tcNewTab);
+    tcNewTab.pszText = "Wide Tab 2";
+    tcNewTab.iImage = 1;
+    SendMessage (handle, TCM_INSERTITEM, 1, (LPARAM) &tcNewTab);
+    tcNewTab.pszText = "T 3";
+    tcNewTab.iImage = 2;
+    SendMessage (handle, TCM_INSERTITEM, 2, (LPARAM) &tcNewTab);
+
+#ifdef VISIBLE
+    ShowWindow (handle, SW_SHOW);
+#endif
+    REDRAW(handle);
+    WAIT;
+
+    return handle;
+}
+
+static void CheckSize(HWND hwnd, INT width, INT height)
+{
+    RECT rTab, r1;
+
+    r1.left=r1.top=r1.right=r1.bottom=0;
+    SendMessage (hwnd, TCM_GETITEMRECT, 0, (LPARAM) &rTab);
+    SendMessage (hwnd, TCM_ADJUSTRECT, FALSE, (LPARAM) &r1);
+    /* trace ("Got (%ld,%ld)-(%ld,%ld)\n", rTab.left, rTab.top, rTab.right, rTab.bottom); */
+    trace (" (%ld,%ld)-(%ld,%ld)\n", r1.left, r1.top, r1.right, r1.bottom);
+    if ((width  >= 0) && (height < 0))
+       ok (width  == rTab.right  - rTab.left, "Expected [%d] got [%ld]\n",  width,  rTab.right  - rTab.left);
+    else if ((height >= 0) && (width  < 0))
+       ok (height == rTab.bottom - rTab.top,  "Expected [%d] got [%ld]\n",  height, rTab.bottom - rTab.top);
+    else
+       ok ((width  == rTab.right  - rTab.left) &&
+           (height == rTab.bottom - rTab.top ),
+           "Expected [%d,%d] got [%ld,%ld]\n", width, height, rTab.right - rTab.left, rTab.bottom - rTab.top);
+}
+
+static void TabCheckSetSize(HWND hwnd, INT SetWidth, INT SetHeight, INT ExpWidth, INT ExpHeight)
+{
+    SendMessage (hwnd, TCM_SETITEMSIZE, 0,
+       (LPARAM) MAKELPARAM((SetWidth >= 0) ? SetWidth:0, (SetHeight >= 0) ? SetHeight:0));
+    REDRAW(hwnd);
+    CheckSize(hwnd, ExpWidth, ExpHeight);
+    WAIT;
+}
+
+START_TEST(tab)
+{
+    HWND hwTab;
+    HIMAGELIST himl = ImageList_Create(21, 21, ILC_COLOR, 3, 4);
+
+    InitCommonControls();
+
+
+    hwTab = create_tabcontrol(TCS_FIXEDWIDTH);
+
+    trace_tab ("Testing TCS_FIXEDWIDTH tabs no icon...\n");
+    trace_tab ("  default width...\n");
+    CheckSize(hwTab, TAB_DEFAULT_WIDTH, -1);
+    trace_tab ("  set size...\n");
+    TabCheckSetSize(hwTab, 50, 20, 50, 20);
+    WAIT;
+    trace_tab ("  min size...\n");
+    TabCheckSetSize(hwTab, 0, 1, 0, 1);
+    WAIT;
+
+    SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
+
+    trace_tab ("Testing TCS_FIXEDWIDTH tabs with icon...\n");
+    trace_tab ("  set size > icon...\n");
+    TabCheckSetSize(hwTab, 50, 30, 50, 30);
+    trace_tab ("  set size < icon...\n");
+    TabCheckSetSize(hwTab, 20, 20, 25, 20);
+    trace_tab ("  min size...\n");
+    TabCheckSetSize(hwTab, 0, 1, 25, 1);
+
+    DestroyWindow (hwTab);
+
+    trace_tab ("Testing TCS_FIXEDWIDTH buttons no icon...\n");
+    hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BUTTONS);
+
+    trace_tab ("  default width...\n");
+    CheckSize(hwTab, TAB_DEFAULT_WIDTH, -1);
+    trace_tab ("  set size 1...\n");
+    TabCheckSetSize(hwTab, 20, 20, 20, 20);
+    trace_tab ("  set size 2...\n");
+    TabCheckSetSize(hwTab, 10, 50, 10, 50);
+    trace_tab ("  min size...\n");
+    TabCheckSetSize(hwTab, 0, 1, 0, 1);
+
+    SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
+
+    trace_tab ("Testing TCS_FIXEDWIDTH buttons with icon...\n");
+    trace_tab ("  set size > icon...\n");
+    TabCheckSetSize(hwTab, 50, 30, 50, 30);
+    trace_tab ("  set size < icon...\n");
+    TabCheckSetSize(hwTab, 20, 20, 25, 20);
+    trace_tab ("  min size...\n");
+    TabCheckSetSize(hwTab, 0, 1, 25, 1);
+    trace_tab (" Add padding...\n");
+    SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4));
+    trace_tab ("  min size...\n");
+    TabCheckSetSize(hwTab, 0, 1, 25, 1);
+
+    DestroyWindow (hwTab);
+
+    hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BOTTOM);
+    trace_tab ("Testing TCS_FIXEDWIDTH | TCS_BOTTOM tabs no icon...\n");
+
+    trace_tab ("  default width...\n");
+    CheckSize(hwTab, TAB_DEFAULT_WIDTH, -1);
+    trace_tab ("  set size 1...\n");
+    TabCheckSetSize(hwTab, 20, 20, 20, 20);
+    trace_tab ("  set size 2...\n");
+    TabCheckSetSize(hwTab, 10, 50, 10, 50);
+    trace_tab ("  min size...\n");
+    TabCheckSetSize(hwTab, 0, 1, 0, 1);
+
+    SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
+    
+    trace_tab ("Testing TCS_FIXEDWIDTH | TCS_BOTTOM tabs with icon...\n");
+    trace_tab ("  set size > icon...\n");
+    TabCheckSetSize(hwTab, 50, 30, 50, 30);
+    trace_tab ("  set size < icon...\n");
+    TabCheckSetSize(hwTab, 20, 20, 25, 20);
+    trace_tab ("  min size...\n");
+    TabCheckSetSize(hwTab, 0, 1, 25, 1);
+    trace_tab (" Add padding...\n");
+    SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4));
+    trace_tab ("  min size...\n");
+    TabCheckSetSize(hwTab, 0, 1, 25, 1);
+
+    DestroyWindow (hwTab);
+
+
+    ImageList_Destroy(himl);
+}
diff --git a/reactos/regtests/winetests/comctl32/testlist.c b/reactos/regtests/winetests/comctl32/testlist.c
new file mode 100644 (file)
index 0000000..7f4c23e
--- /dev/null
@@ -0,0 +1,31 @@
+/* Automatically generated file; DO NOT EDIT!! */
+
+/* stdarg.h is needed for Winelib */
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "windef.h"
+#include "winbase.h"
+
+extern void func_dpa(void);
+extern void func_mru(void);
+extern void func_subclass(void);
+extern void func_tab(void);
+
+struct test
+{
+    const char *name;
+    void (*func)(void);
+};
+
+static const struct test winetest_testlist[] =
+{
+    { "dpa", func_dpa },
+    { "mru", func_mru },
+    { "subclass", func_subclass },
+    { "tab", func_tab },
+    { 0, 0 }
+};
+
+#define WINETEST_WANT_MAIN
+#include "wine/test.h"
diff --git a/reactos/regtests/winetests/msvcrt/Makefile.in b/reactos/regtests/winetests/msvcrt/Makefile.in
new file mode 100644 (file)
index 0000000..fd8ae0d
--- /dev/null
@@ -0,0 +1,21 @@
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+TESTDLL   = msvcrt.dll
+IMPORTS   = msvcrt
+EXTRAINCL = -I$(TOPSRCDIR)/include/msvcrt -I$(SRCDIR)/..
+
+CTESTS = \
+       cpp.c \
+       environ.c \
+       file.c \
+       heap.c \
+       printf.c \
+       scanf.c \
+       string.c \
+       time.c
+
+@MAKE_TEST_RULES@
+
+### Dependencies:
diff --git a/reactos/regtests/winetests/msvcrt/cpp.c b/reactos/regtests/winetests/msvcrt/cpp.c
new file mode 100644 (file)
index 0000000..0f36067
--- /dev/null
@@ -0,0 +1,831 @@
+/* Unit test suite for msvcrt C++ objects
+ *
+ * Copyright 2003 Jon Griffiths
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * NOTES
+ * This tests is only valid for ix86 platforms, on others it's a no-op.
+ * Some tests cannot be checked with ok(), for example the dtors. We simply
+ * call them to ensure we don't crash ;-)
+ *
+ * If we build this test with VC++ in debug mode, we will fail in _chkstk()
+ * or at program exit malloc() checking if these methods haven't been
+ * implemented correctly (they have).
+ *
+ * Tested with a range of native msvcrt's from v4 -> v7.
+ */
+#include "wine/test.h"
+#include "winbase.h"
+#include "winnt.h"
+
+#ifndef __i386__
+/* Skip these tests for non x86 platforms */
+START_TEST(cpp)
+{
+}
+#else
+
+typedef struct __exception
+{
+  void *vtable;
+  char *name;
+  int   do_free;
+} exception;
+
+typedef struct __type_info
+{
+  void *vtable;
+  char *name;
+  char  mangled[16];
+} type_info;
+
+/* Function pointers. We need to use these to call these funcs as __thiscall */
+static HMODULE hMsvcrt;
+
+static void* (*poperator_new)(unsigned int);
+static void  (*poperator_delete)(void*);
+static void* (*pmalloc)(unsigned int);
+static void  (*pfree)(void*);
+
+/* exception */
+static void (WINAPI *pexception_ctor)(exception*,LPCSTR*);
+static void (WINAPI *pexception_copy_ctor)(exception*,exception*);
+static void (WINAPI *pexception_default_ctor)(exception*);
+static void (WINAPI *pexception_dtor)(exception*);
+static exception* (WINAPI *pexception_opequals)(exception*,exception*);
+static char* (WINAPI *pexception_what)(exception*);
+static void* (WINAPI *pexception_vtable)(exception*);
+static void (WINAPI *pexception_vector_dtor)(exception*,unsigned int);
+static void (WINAPI *pexception_scalar_dtor)(exception*,unsigned int);
+
+/* bad_typeid */
+static void (WINAPI *pbad_typeid_ctor)(exception*,LPCSTR);
+static void (WINAPI *pbad_typeid_ctor_closure)(exception*);
+static void (WINAPI *pbad_typeid_copy_ctor)(exception*,exception*);
+static void (WINAPI *pbad_typeid_dtor)(exception*);
+static exception* (WINAPI *pbad_typeid_opequals)(exception*,exception*);
+static char* (WINAPI *pbad_typeid_what)(exception*);
+static void* (WINAPI *pbad_typeid_vtable)(exception*);
+static void (WINAPI *pbad_typeid_vector_dtor)(exception*,unsigned int);
+static void (WINAPI *pbad_typeid_scalar_dtor)(exception*,unsigned int);
+
+/* bad_cast */
+static void (WINAPI *pbad_cast_ctor)(exception*,LPCSTR*);
+static void (WINAPI *pbad_cast_ctor2)(exception*,LPCSTR);
+static void (WINAPI *pbad_cast_ctor_closure)(exception*);
+static void (WINAPI *pbad_cast_copy_ctor)(exception*,exception*);
+static void (WINAPI *pbad_cast_dtor)(exception*);
+static exception* (WINAPI *pbad_cast_opequals)(exception*,exception*);
+static char* (WINAPI *pbad_cast_what)(exception*);
+static void* (WINAPI *pbad_cast_vtable)(exception*);
+static void (WINAPI *pbad_cast_vector_dtor)(exception*,unsigned int);
+static void (WINAPI *pbad_cast_scalar_dtor)(exception*,unsigned int);
+
+/* __non_rtti_object */
+static void (WINAPI *p__non_rtti_object_ctor)(exception*,LPCSTR);
+static void (WINAPI *p__non_rtti_object_copy_ctor)(exception*,exception*);
+static void (WINAPI *p__non_rtti_object_dtor)(exception*);
+static exception* (WINAPI *p__non_rtti_object_opequals)(exception*,exception*);
+static char* (WINAPI *p__non_rtti_object_what)(exception*);
+static void* (WINAPI *p__non_rtti_object_vtable)(exception*);
+static void (WINAPI *p__non_rtti_object_vector_dtor)(exception*,unsigned int);
+static void (WINAPI *p__non_rtti_object_scalar_dtor)(exception*,unsigned int);
+
+/* type_info */
+static void  (WINAPI *ptype_info_dtor)(type_info*);
+static char* (WINAPI *ptype_info_raw_name)(type_info*);
+static char* (WINAPI *ptype_info_name)(type_info*);
+static int   (WINAPI *ptype_info_before)(type_info*,type_info*);
+static int   (WINAPI *ptype_info_opequals_equals)(type_info*,type_info*);
+static int   (WINAPI *ptype_info_opnot_equals)(type_info*,type_info*);
+
+/* RTTI */
+static type_info* (*p__RTtypeid)(void*);
+static void* (*p__RTCastToVoid)(void*);
+static void* (*p__RTDynamicCast)(void*,int,void*,void*,int);
+
+/* _very_ early native versions have serious RTTI bugs, so we check */
+static void* bAncientVersion;
+
+/* Emulate a __thiscall */
+#ifdef _MSC_VER
+inline static void* do_call_func1(void *func, void *_this)
+{
+  volatile void* retval = 0;
+  __asm
+  {
+    push ecx
+    mov ecx, _this
+    call func
+    mov retval, eax
+    pop ecx
+  }
+  return (void*)retval;
+}
+
+inline static void* do_call_func2(void *func, void *_this, void* arg)
+{
+  volatile void* retval = 0;
+  __asm
+  {
+    push ecx
+    push arg
+    mov ecx, _this
+    call func
+    mov retval, eax
+    pop ecx
+  }
+  return (void*)retval;
+}
+#else
+static void* do_call_func1(void *func, void *_this)
+{
+  void* ret;
+  __asm__ __volatile__ ("call *%1"
+                        : "=a" (ret)
+                        : "g" (func), "c" (_this)
+                        : "memory" );
+  return ret;
+}
+static void* do_call_func2(void *func, void *_this, void* arg)
+{
+  void* ret;
+  __asm__ __volatile__ ("pushl %2\n\tcall *%1"
+                        : "=a" (ret)
+                        : "r" (func), "g" (arg), "c" (_this)
+                        : "memory" );
+  return ret;
+}
+#endif
+
+#define call_func1(x,y)   do_call_func1((void*)x,(void*)y)
+#define call_func2(x,y,z) do_call_func2((void*)x,(void*)y,(void*)z)
+
+/* Some exports are only available in later versions */
+#define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y)
+#define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y)
+
+static void InitFunctionPtrs()
+{
+  hMsvcrt = LoadLibraryA("msvcrt.dll");
+  ok(hMsvcrt != 0, "LoadLibraryA failed\n");
+  if (hMsvcrt)
+  {
+    SETNOFAIL(poperator_new, "??_U@YAPAXI@Z");
+    SETNOFAIL(poperator_delete, "??_V@YAXPAX@Z");
+    SET(pmalloc, "malloc");
+    SET(pfree, "free");
+
+    if (!poperator_new)
+      poperator_new = pmalloc;
+    if (!poperator_delete)
+      poperator_delete = pfree;
+
+    SET(pexception_ctor, "??0exception@@QAE@ABQBD@Z");
+    SET(pexception_copy_ctor, "??0exception@@QAE@ABV0@@Z");
+    SET(pexception_default_ctor, "??0exception@@QAE@XZ");
+    SET(pexception_dtor, "??1exception@@UAE@XZ");
+    SET(pexception_opequals, "??4exception@@QAEAAV0@ABV0@@Z");
+    SET(pexception_what, "?what@exception@@UBEPBDXZ");
+    SET(pexception_vtable, "??_7exception@@6B@");
+    SET(pexception_vector_dtor, "??_Eexception@@UAEPAXI@Z");
+    SET(pexception_scalar_dtor, "??_Gexception@@UAEPAXI@Z");
+
+    SET(pbad_typeid_ctor, "??0bad_typeid@@QAE@PBD@Z");
+    SETNOFAIL(pbad_typeid_ctor_closure, "??_Fbad_typeid@@QAEXXZ");
+    SET(pbad_typeid_copy_ctor, "??0bad_typeid@@QAE@ABV0@@Z");
+    SET(pbad_typeid_dtor, "??1bad_typeid@@UAE@XZ");
+    SET(pbad_typeid_opequals, "??4bad_typeid@@QAEAAV0@ABV0@@Z");
+    SET(pbad_typeid_what, "?what@exception@@UBEPBDXZ");
+    SET(pbad_typeid_vtable, "??_7bad_typeid@@6B@");
+    SET(pbad_typeid_vector_dtor, "??_Ebad_typeid@@UAEPAXI@Z");
+    SET(pbad_typeid_scalar_dtor, "??_Gbad_typeid@@UAEPAXI@Z");
+
+    SETNOFAIL(pbad_cast_ctor, "??0bad_cast@@QAE@ABQBD@Z");
+    if (!pbad_cast_ctor)
+      SET(pbad_cast_ctor, "??0bad_cast@@AAE@PBQBD@Z");
+    SETNOFAIL(pbad_cast_ctor2, "??0bad_cast@@QAE@PBD@Z");
+    SETNOFAIL(pbad_cast_ctor_closure, "??_Fbad_cast@@QAEXXZ");
+    SET(pbad_cast_copy_ctor, "??0bad_cast@@QAE@ABV0@@Z");
+    SET(pbad_cast_dtor, "??1bad_cast@@UAE@XZ");
+    SET(pbad_cast_opequals, "??4bad_cast@@QAEAAV0@ABV0@@Z");
+    SET(pbad_cast_what, "?what@exception@@UBEPBDXZ");
+    SET(pbad_cast_vtable, "??_7bad_cast@@6B@");
+    SET(pbad_cast_vector_dtor, "??_Ebad_cast@@UAEPAXI@Z");
+    SET(pbad_cast_scalar_dtor, "??_Gbad_cast@@UAEPAXI@Z");
+
+    SET(p__non_rtti_object_ctor, "??0__non_rtti_object@@QAE@PBD@Z");
+    SET(p__non_rtti_object_copy_ctor, "??0__non_rtti_object@@QAE@ABV0@@Z");
+    SET(p__non_rtti_object_dtor, "??1__non_rtti_object@@UAE@XZ");
+    SET(p__non_rtti_object_opequals, "??4__non_rtti_object@@QAEAAV0@ABV0@@Z");
+    SET(p__non_rtti_object_what, "?what@exception@@UBEPBDXZ");
+    SET(p__non_rtti_object_vtable, "??_7__non_rtti_object@@6B@");
+    SET(p__non_rtti_object_vector_dtor, "??_E__non_rtti_object@@UAEPAXI@Z");
+    SET(p__non_rtti_object_scalar_dtor, "??_G__non_rtti_object@@UAEPAXI@Z");
+
+    SET(ptype_info_dtor, "??1type_info@@UAE@XZ");
+    SET(ptype_info_raw_name, "?raw_name@type_info@@QBEPBDXZ");
+#ifndef __REACTOS__
+    SET(ptype_info_name, "?name@type_info@@QBEPBDXZ");
+#endif
+    SET(ptype_info_before, "?before@type_info@@QBEHABV1@@Z");
+    SET(ptype_info_opequals_equals, "??8type_info@@QBEHABV0@@Z");
+    SET(ptype_info_opnot_equals, "??9type_info@@QBEHABV0@@Z");
+
+    SET(p__RTtypeid, "__RTtypeid");
+    SET(p__RTCastToVoid, "__RTCastToVoid");
+    SET(p__RTDynamicCast, "__RTDynamicCast");
+
+    /* Extremely early versions export logic_error, and crash in RTTI */
+    SETNOFAIL(bAncientVersion, "??0logic_error@@QAE@ABQBD@Z");
+  }
+}
+
+static void test_exception(void)
+{
+  static const char* e_name = "An exception name";
+  char* name;
+  exception e, e2, e3, *pe;
+
+  if (!poperator_new || !poperator_delete ||
+      !pexception_ctor || !pexception_copy_ctor || !pexception_default_ctor ||
+      !pexception_dtor || !pexception_opequals || !pexception_what ||
+      !pexception_vtable || !pexception_vector_dtor || !pexception_scalar_dtor)
+    return;
+
+  /* 'const char*&' ctor */
+  memset(&e, 0, sizeof(e));
+  call_func2(pexception_ctor, &e, &e_name);
+  ok(e.vtable != NULL, "Null exception vtable for e\n");
+  ok(e.name && e.name != e_name && !strcmp(e.name, "An exception name"), "Bad name '%s' for e\n", e.name);
+  ok(e.do_free == 1, "do_free set to %d for e\n", e.do_free);
+
+  /* Copy ctor */
+  memset(&e2, 0, sizeof(e2));
+  call_func2(pexception_copy_ctor, &e2, &e);
+  ok(e2.vtable != NULL, "Null exception vtable for e2\n");
+  ok(e2.name && e2.name != e.name && !strcmp(e2.name, "An exception name"), "Bad exception name for e2\n");
+  ok(e2.do_free == 1, "do_free set to %d for e2\n", e2.do_free);
+
+  /* Default ctor */
+  memset(&e3, 1, sizeof(e3));
+  call_func1(pexception_default_ctor, &e3);
+  ok(e3.vtable != NULL, "Null exception vtable for e3\n");
+  ok(e3.name == NULL, "Bad exception name for e3\n");
+  ok(e3.do_free == 0, "do_free set to %d for e3\n", e3.do_free);
+
+  ok(e.vtable == e2.vtable && e.vtable == e3.vtable, "exception vtables differ!\n");
+
+  /* Test calling the dtors */
+  call_func1(pexception_dtor, &e2);
+  call_func1(pexception_dtor, &e3);
+
+  /* Operator equals */
+  memset(&e2, 0, sizeof(e2));
+  pe = call_func2(pexception_opequals, &e2, &e);
+  ok(e2.vtable != NULL, "Null exception vtable for e2\n");
+  ok(e2.name && e2.name != e.name && !strcmp(e2.name, "An exception name"), "Bad exception name for e2\n");
+  ok(e2.do_free == 1, "do_free set to %d for e2\n", e2.do_free);
+  ok(pe == &e2, "opequals didn't return e2\n");
+
+  /* what() */
+  name = call_func1(pexception_what, &e2);
+  ok(e2.name == name, "Bad exception name from e2::what()\n");
+
+  /* vtable ptr */
+  ok(e2.vtable == pexception_vtable, "Bad vtable for e2\n");
+  call_func1(pexception_dtor, &e2);
+
+  /* new() */
+  pe = poperator_new(sizeof(exception));
+  ok(pe != NULL, "new() failed\n");
+  if (pe)
+  {
+    call_func2(pexception_ctor, pe, &e_name);
+    /* scalar dtor */
+    call_func2(pexception_scalar_dtor, pe, 0); /* Shouldn't delete pe */
+    pe->name = NULL;
+    pe->do_free = 0;
+    call_func2(pexception_scalar_dtor, pe, 1); /* Should delete pe */
+  }
+
+  pe = poperator_new(sizeof(exception));
+  ok(pe != NULL, "new() failed\n");
+  if (pe)
+  {
+    /* vector dtor, single element */
+    call_func2(pexception_ctor, pe, &e_name);
+    call_func2(pexception_vector_dtor, pe, 1); /* Should delete pe as single element*/
+  }
+
+  pe = poperator_new(sizeof(exception) * 4 + sizeof(int));
+  ok(pe != NULL, "new() failed\n");
+  if (pe)
+  {
+    /* vector dtor, multiple elements */
+    char name[] = "a constant";
+    *((int*)pe) = 3;
+    pe = (exception*)((int*)pe + 1);
+    call_func2(pexception_ctor, &pe[0], &e_name);
+    call_func2(pexception_ctor, &pe[1], &e_name);
+    call_func2(pexception_ctor, &pe[2], &e_name);
+    pe[3].name = name;
+    pe[3].do_free = 1; /* Crash if we try to free this */
+    call_func2(pexception_vector_dtor, pe, 3); /* Should delete all 3 and then pe block */
+  }
+
+  /* test our exported vtable is kosher */
+  pe = (void*)pexception_vtable; /* Use the exception struct to get vtable ptrs */
+  pexception_vector_dtor = (void*)pe->vtable;
+  pexception_what = (void*)pe->name;
+
+  name = call_func1(pexception_what, &e);
+  ok(e.name == name, "Bad exception name from vtable e::what()\n");
+
+  if (p__RTtypeid && !bAncientVersion)
+  {
+    /* Check the rtti */
+    type_info *ti = p__RTtypeid(&e);
+    ok (ti && ti->mangled &&
+        !strcmp(ti->mangled, ".?AVexception@@"), "bad rtti for e\n");
+
+    if (ti)
+    {
+      /* Check the returned type_info has rtti too */
+      type_info *ti2 = p__RTtypeid(ti);
+      ok (ti2 != NULL && !strcmp(ti2->mangled, ".?AVtype_info@@"), "bad rtti for e's type_info\n");
+    }
+  }
+
+  call_func2(pexception_vector_dtor, &e, 0); /* Should delete e.name, but not e */
+}
+
+/* This test is basically a cut 'n' paste of the exception test. but it verifies that
+ * bad_typeid works the exact same way... */
+static void test_bad_typeid(void)
+{
+  static const char* e_name = "A bad_typeid name";
+  char* name;
+  exception e, e2, e3, *pe;
+
+  if (!poperator_new || !poperator_delete ||
+      !pbad_typeid_ctor || !pbad_typeid_copy_ctor ||
+      !pbad_typeid_dtor || !pbad_typeid_opequals || !pbad_typeid_what ||
+      !pbad_typeid_vtable || !pbad_typeid_vector_dtor || !pbad_typeid_scalar_dtor)
+    return;
+
+  /* 'const char*' ctor */
+  memset(&e, 0, sizeof(e));
+  call_func2(pbad_typeid_ctor, &e, e_name);
+  ok(e.vtable != NULL, "Null bad_typeid vtable for e\n");
+  ok(e.name && e.name != e_name && !strcmp(e.name, "A bad_typeid name"), "Bad name '%s' for e\n", e.name);
+  ok(e.do_free == 1, "do_free set to %d for e\n", e.do_free);
+
+  /* Copy ctor */
+  memset(&e2, 0, sizeof(e2));
+  call_func2(pbad_typeid_copy_ctor, &e2, &e);
+  ok(e2.vtable != NULL, "Null bad_typeid vtable for e2\n");
+  ok(e2.name && e2.name != e.name && !strcmp(e2.name, "A bad_typeid name"), "Bad name '%s' for e2\n", e2.name);
+  ok(e2.do_free == 1, "do_free set to %d for e2\n", e2.do_free);
+
+  /* Ctor closure */
+  if (pbad_typeid_ctor_closure)
+  {
+    memset(&e3, 1, sizeof(e3));
+    call_func1(pbad_typeid_ctor_closure, &e3);
+    ok(e3.vtable != NULL, "Null bad_typeid vtable for e3\n");
+    ok(e3.name && !strcmp(e3.name, "bad typeid"), "Bad bad_typeid name for e3\n");
+    ok(e3.do_free == 1, "do_free set to %d for e3\n", e3.do_free);
+    ok(e.vtable == e3.vtable, "bad_typeid closure vtables differ!\n");
+    call_func1(pbad_typeid_dtor, &e3);
+  }
+  ok(e.vtable == e2.vtable, "bad_typeid vtables differ!\n");
+
+  /* Test calling the dtors */
+  call_func1(pbad_typeid_dtor, &e2);
+
+  /* Operator equals */
+  memset(&e2, 1, sizeof(e2));
+  pe = call_func2(pbad_typeid_opequals, &e2, &e);
+  ok(e2.vtable != NULL, "Null bad_typeid vtable for e2\n");
+  ok(e2.name && e2.name != e.name && !strcmp(e2.name, "A bad_typeid name"), "Bad bad_typeid name for e2\n");
+  ok(e2.do_free == 1, "do_free set to %d for e2\n", e2.do_free);
+  ok(pe == &e2, "opequals didn't return e2\n");
+
+  /* what() */
+  name = call_func1(pbad_typeid_what, &e2);
+  ok(e2.name == name, "Bad bad_typeid name from e2::what()\n");
+
+  /* vtable ptr */
+  ok(e2.vtable == pexception_vtable, "Bad vtable for e2\n");
+  call_func1(pbad_typeid_dtor, &e2);
+
+  /* new() */
+  pe = poperator_new(sizeof(exception));
+  ok(pe != NULL, "new() failed\n");
+  if (pe)
+  {
+    call_func2(pbad_typeid_ctor, pe, e_name);
+    /* scalar dtor */
+    call_func2(pbad_typeid_scalar_dtor, pe, 0); /* Shouldn't delete pe */
+    pe->name = NULL;
+    pe->do_free = 0;
+    call_func2(pbad_typeid_scalar_dtor, pe, 1); /* Should delete pe */
+  }
+
+  pe = poperator_new(sizeof(exception));
+  ok(pe != NULL, "new() failed\n");
+  if (pe)
+  {
+    /* vector dtor, single element */
+    call_func2(pbad_typeid_ctor, pe, e_name);
+    call_func2(pbad_typeid_vector_dtor, pe, 1); /* Should delete pe as single element*/
+  }
+
+  pe = poperator_new(sizeof(exception) * 4 + sizeof(int));
+  ok(pe != NULL, "new() failed\n");
+  if (pe)
+  {
+    /* vector dtor, multiple elements */
+    *((int*)pe) = 3;
+    pe = (exception*)((int*)pe + 1);
+    call_func2(pbad_typeid_ctor, &pe[0], e_name);
+    call_func2(pbad_typeid_ctor, &pe[1], e_name);
+    call_func2(pbad_typeid_ctor, &pe[2], e_name);
+    pe[3].name = 0;
+    pe[3].do_free = 1; /* Crash if we try to free this element */
+    call_func2(pbad_typeid_vector_dtor, pe, 3); /* Should delete all 3 and then pe block */
+  }
+
+  /* test our exported vtable is kosher */
+  pe = (void*)pbad_typeid_vtable; /* Use the exception struct to get vtable ptrs */
+  pbad_typeid_vector_dtor = (void*)pe->vtable;
+  pbad_typeid_what = (void*)pe->name;
+
+  name = call_func1(pbad_typeid_what, &e);
+  ok(e.name == name, "Bad bad_typeid name from vtable e::what()\n");
+
+  if (p__RTtypeid && !bAncientVersion)
+  {
+    /* Check the rtti */
+    type_info *ti = p__RTtypeid(&e);
+    ok (ti != NULL && !strcmp(ti->mangled, ".?AVbad_typeid@@"), "bad rtti for e (%s)\n",
+        !ti ? "null" : ti->mangled);
+  }
+
+  call_func2(pbad_typeid_vector_dtor, &e, 0); /* Should delete e.name, but not e */
+}
+
+
+/* Ditto for this test... */
+static void test_bad_cast(void)
+{
+  static const char* e_name = "A bad_cast name";
+  char* name;
+  exception e, e2, e3, *pe;
+
+  if (!poperator_new || !poperator_delete ||
+      !pbad_cast_ctor || !pbad_cast_copy_ctor ||
+      !pbad_cast_dtor || !pbad_cast_opequals || !pbad_cast_what ||
+      !pbad_cast_vtable || !pbad_cast_vector_dtor || !pbad_cast_scalar_dtor)
+    return;
+
+  if (pbad_cast_ctor2)
+  {
+    /* 'const char*' ctor */
+    memset(&e, 0, sizeof(e));
+    call_func2(pbad_cast_ctor2, &e, e_name);
+    ok(e.vtable != NULL, "Null bad_cast vtable for e\n");
+    ok(e.name && e.name != e_name && !strcmp(e.name, "A bad_cast name"), "Bad name '%s' for e\n", e.name);
+    ok(e.do_free == 1, "do_free set to %d for e\n", e.do_free);
+    call_func1(pbad_cast_dtor, &e);
+  }
+
+  /* 'const char*&' ctor */
+  memset(&e, 0, sizeof(e));
+  call_func2(pbad_cast_ctor, &e, &e_name);
+  ok(e.vtable != NULL, "Null bad_cast vtable for e\n");
+  ok(e.name && e.name != e_name && !strcmp(e.name, "A bad_cast name"), "Bad name '%s' for e\n", e.name);
+  ok(e.do_free == 1, "do_free set to %d for e\n", e.do_free);
+
+  /* Copy ctor */
+  memset(&e2, 0, sizeof(e2));
+  call_func2(pbad_cast_copy_ctor, &e2, &e);
+  ok(e2.vtable != NULL, "Null bad_cast vtable for e2\n");
+  ok(e2.name && e2.name != e.name && !strcmp(e2.name, "A bad_cast name"), "Bad name '%s' for e2\n", e2.name);
+  ok(e2.do_free == 1, "do_free set to %d for e2\n", e2.do_free);
+
+  /* Ctor closure */
+  if (pbad_cast_ctor_closure)
+  {
+    memset(&e3, 1, sizeof(e3));
+    call_func1(pbad_cast_ctor_closure, &e3);
+    ok(e3.vtable != NULL, "Null bad_cast vtable for e3\n");
+    ok(e3.name && !strcmp(e3.name, "bad cast"), "Bad bad_cast name for e3\n");
+    ok(e3.do_free == 1, "do_free set to %d for e3\n", e3.do_free);
+    ok(e.vtable == e3.vtable, "bad_cast closure vtables differ!\n");
+    call_func1(pbad_cast_dtor, &e3);
+  }
+  ok(e.vtable == e2.vtable, "bad_cast vtables differ!\n");
+
+  /* Test calling the dtors */
+  call_func1(pbad_cast_dtor, &e2);
+
+  /* Operator equals */
+  memset(&e2, 1, sizeof(e2));
+  pe = call_func2(pbad_cast_opequals, &e2, &e);
+  ok(e2.vtable != NULL, "Null bad_cast vtable for e2\n");
+  ok(e2.name && e2.name != e.name && !strcmp(e2.name, "A bad_cast name"), "Bad bad_cast name for e2\n");
+  ok(e2.do_free == 1, "do_free set to %d for e2\n", e2.do_free);
+  ok(pe == &e2, "opequals didn't return e2\n");
+
+  /* what() */
+  name = call_func1(pbad_cast_what, &e2);
+  ok(e2.name == name, "Bad bad_cast name from e2::what()\n");
+
+  /* vtable ptr */
+  ok(e2.vtable == pexception_vtable, "Bad vtable for e2\n");
+  call_func1(pbad_cast_dtor, &e2);
+
+  /* new() */
+  pe = poperator_new(sizeof(exception));
+  ok(pe != NULL, "new() failed\n");
+  if (pe)
+  {
+    call_func2(pbad_cast_ctor, pe, &e_name);
+    /* scalar dtor */
+    call_func2(pbad_cast_scalar_dtor, pe, 0); /* Shouldn't delete pe */
+    pe->name = NULL;
+    pe->do_free = 0;
+    call_func2(pbad_cast_scalar_dtor, pe, 1); /* Should delete pe */
+  }
+
+  pe = poperator_new(sizeof(exception));
+  ok(pe != NULL, "new() failed\n");
+  if (pe)
+  {
+    /* vector dtor, single element */
+    call_func2(pbad_cast_ctor, pe, &e_name);
+    call_func2(pbad_cast_vector_dtor, pe, 1); /* Should delete pe as single element*/
+  }
+
+  pe = poperator_new(sizeof(exception) * 4 + sizeof(int));
+  ok(pe != NULL, "new() failed\n");
+  if (pe)
+  {
+    /* vector dtor, multiple elements */
+    *((int*)pe) = 3;
+    pe = (exception*)((int*)pe + 1);
+    call_func2(pbad_cast_ctor, &pe[0], &e_name);
+    call_func2(pbad_cast_ctor, &pe[1], &e_name);
+    call_func2(pbad_cast_ctor, &pe[2], &e_name);
+    pe[3].name = 0;
+    pe[3].do_free = 1; /* Crash if we try to free this element */
+    call_func2(pbad_cast_vector_dtor, pe, 3); /* Should delete all 3 and then pe block */
+  }
+
+  /* test our exported vtable is kosher */
+  pe = (void*)pbad_cast_vtable; /* Use the exception struct to get vtable ptrs */
+  pbad_cast_vector_dtor = (void*)pe->vtable;
+  pbad_cast_what = (void*)pe->name;
+
+  name = call_func1(pbad_cast_what, &e);
+  ok(e.name == name, "Bad bad_cast name from vtable e::what()\n");
+
+  if (p__RTtypeid && !bAncientVersion)
+  {
+    /* Check the rtti */
+    type_info *ti = p__RTtypeid(&e);
+    ok (ti != NULL && !strcmp(ti->mangled, ".?AVbad_cast@@"), "bad rtti for e\n");
+  }
+  call_func2(pbad_cast_vector_dtor, &e, 0); /* Should delete e.name, but not e */
+}
+
+/* ... and this one */
+static void test___non_rtti_object(void)
+{
+  static const char* e_name = "A __non_rtti_object name";
+  char* name;
+  exception e, e2, *pe;
+
+  if (!poperator_new || !poperator_delete ||
+      !p__non_rtti_object_ctor || !p__non_rtti_object_copy_ctor ||
+      !p__non_rtti_object_dtor || !p__non_rtti_object_opequals || !p__non_rtti_object_what ||
+      !p__non_rtti_object_vtable || !p__non_rtti_object_vector_dtor || !p__non_rtti_object_scalar_dtor)
+    return;
+
+  /* 'const char*' ctor */
+  memset(&e, 0, sizeof(e));
+  call_func2(p__non_rtti_object_ctor, &e, e_name);
+  ok(e.vtable != NULL, "Null __non_rtti_object vtable for e\n");
+  ok(e.name && e.name != e_name && !strcmp(e.name, "A __non_rtti_object name"), "Bad name '%s' for e\n", e.name);
+  ok(e.do_free == 1, "do_free set to %d for e\n", e.do_free);
+
+  /* Copy ctor */
+  memset(&e2, 0, sizeof(e2));
+  call_func2(p__non_rtti_object_copy_ctor, &e2, &e);
+  ok(e2.vtable != NULL, "Null __non_rtti_object vtable for e2\n");
+  ok(e2.name && e2.name != e.name && !strcmp(e2.name, "A __non_rtti_object name"), "Bad name '%s' for e2\n", e2.name);
+  ok(e2.do_free == 1, "do_free set to %d for e2\n", e2.do_free);
+  ok(e.vtable == e2.vtable, "__non_rtti_object vtables differ!\n");
+
+  /* Test calling the dtors */
+  call_func1(p__non_rtti_object_dtor, &e2);
+
+  /* Operator equals */
+  memset(&e2, 1, sizeof(e2));
+  pe = call_func2(p__non_rtti_object_opequals, &e2, &e);
+  ok(e2.vtable != NULL, "Null __non_rtti_object vtable for e2\n");
+  ok(e2.name && e2.name != e.name && !strcmp(e2.name, "A __non_rtti_object name"), "Bad __non_rtti_object name for e2\n");
+  ok(e2.do_free == 1, "do_free set to %d for e2\n", e2.do_free);
+  ok(pe == &e2, "opequals didn't return e2\n");
+
+  /* what() */
+  name = call_func1(p__non_rtti_object_what, &e2);
+  ok(e2.name == name, "Bad __non_rtti_object name from e2::what()\n");
+
+  /* vtable ptr */
+  ok(e2.vtable == pexception_vtable, "Bad vtable for e2\n");
+  call_func1(p__non_rtti_object_dtor, &e2);
+
+  /* new() */
+  pe = poperator_new(sizeof(exception));
+  ok(pe != NULL, "new() failed\n");
+  if (pe)
+  {
+    call_func2(p__non_rtti_object_ctor, pe, e_name);
+    /* scalar dtor */
+    call_func2(p__non_rtti_object_scalar_dtor, pe, 0); /* Shouldn't delete pe */
+    pe->name = NULL;
+    pe->do_free = 0;
+    call_func2(p__non_rtti_object_scalar_dtor, pe, 1); /* Should delete pe */
+  }
+
+  pe = poperator_new(sizeof(exception));
+  ok(pe != NULL, "new() failed\n");
+  if (pe)
+  {
+    /* vector dtor, single element */
+    call_func2(p__non_rtti_object_ctor, pe, e_name);
+    call_func2(p__non_rtti_object_vector_dtor, pe, 1); /* Should delete pe as single element*/
+  }
+
+  pe = poperator_new(sizeof(exception) * 4 + sizeof(int));
+  ok(pe != NULL, "new() failed\n");
+  if (pe)
+  {
+    /* vector dtor, multiple elements */
+    *((int*)pe) = 3;
+    pe = (exception*)((int*)pe + 1);
+    call_func2(p__non_rtti_object_ctor, &pe[0], e_name);
+    call_func2(p__non_rtti_object_ctor, &pe[1], e_name);
+    call_func2(p__non_rtti_object_ctor, &pe[2], e_name);
+    pe[3].name = 0;
+    pe[3].do_free = 1; /* Crash if we try to free this element */
+    call_func2(p__non_rtti_object_vector_dtor, pe, 3); /* Should delete all 3 and then pe block */
+  }
+
+  /* test our exported vtable is kosher */
+  pe = (void*)p__non_rtti_object_vtable; /* Use the exception struct to get vtable ptrs */
+  p__non_rtti_object_vector_dtor = (void*)pe->vtable;
+  p__non_rtti_object_what = (void*)pe->name;
+
+  name = call_func1(p__non_rtti_object_what, &e);
+  ok(e.name == name, "Bad __non_rtti_object name from vtable e::what()\n");
+
+  if (p__RTtypeid && !bAncientVersion)
+  {
+    /* Check the rtti */
+    type_info *ti = p__RTtypeid(&e);
+    ok (ti != NULL && !strcmp(ti->mangled, ".?AV__non_rtti_object@@"), "bad rtti for e\n");
+  }
+  call_func2(p__non_rtti_object_vector_dtor, &e, 0); /* Should delete e.name, but not e */
+}
+
+
+static void test_type_info(void)
+{
+  static type_info t1 = { NULL, NULL,{'.','?','A','V','t','e','s','t','1','@','@',0,0,0,0,0 } };
+  static type_info t1_1 = { NULL, NULL,{'?','?','A','V','t','e','s','t','1','@','@',0,0,0,0,0 } };
+  static type_info t2 = { NULL, NULL, {'.','?','A','V','t','e','s','t','2','@','@',0,0,0,0,0 } };
+  char* name;
+  int res;
+
+  if (!pmalloc || !pfree || !ptype_info_dtor || !ptype_info_raw_name ||
+      !ptype_info_name || !ptype_info_before ||
+      !ptype_info_opequals_equals || !ptype_info_opnot_equals)
+    return;
+
+  /* Test calling the dtors */
+  call_func1(ptype_info_dtor, &t1); /* No effect, since name is NULL */
+  t1.name = pmalloc(64);
+  strcpy(t1.name, "foo");
+  call_func1(ptype_info_dtor, &t1); /* Frees t1.name using 'free' */
+
+  /* raw_name */
+  t1.name = NULL;
+  name = call_func1(ptype_info_raw_name, &t1);
+
+  /* FIXME: This fails on native; it shouldn't though - native bug?
+   * ok(name && !strcmp(name, t1.mangled), "bad raw_name '%s' for t1 (expected '%s')\n", name, t1.mangled);
+   */
+  ok(t1.name == NULL, "raw_name() set name for t1\n");
+
+  /* name */
+  t1.name = NULL;
+  name = call_func1(ptype_info_name, &t1);
+  ok(name && t1.name && !strcmp(name, t1.name), "bad name '%s' for t1\n", name);
+
+  ok(t1.name && !strcmp(t1.name, "class test1"), "demangled to '%s' for t1\n", t1.name);
+  call_func1(ptype_info_dtor, &t1);
+
+  /* before */
+  t1.name = NULL;
+  res = (int)call_func2(ptype_info_before, &t1, &t1);
+  ok(res == 0, "expected 0, got %d\n", res);
+  res = (int)call_func2(ptype_info_before, &t2, &t1);
+  ok(res == 0, "expected 0, got %d\n", res);
+  res = (int)call_func2(ptype_info_before, &t1, &t2);
+  ok(res == 1, "expected 1, got %d\n", res);
+  /* Doesn't check first char */
+  res = (int)call_func2(ptype_info_before, &t1, &t1_1);
+  ok(res == 0, "expected 0, got %d\n", res);
+
+  /* opequals_equals */
+  t1.name = NULL;
+  res = (int)call_func2(ptype_info_opequals_equals, &t1, &t1);
+  ok(res == 1, "expected 1, got %d\n", res);
+  res = (int)call_func2(ptype_info_opequals_equals, &t1, &t2);
+  ok(res == 0, "expected 0, got %d\n", res);
+  res = (int)call_func2(ptype_info_opequals_equals, &t2, &t1);
+  ok(res == 0, "expected 0, got %d\n", res);
+
+  /* opnot_equals */
+  t1.name = NULL;
+  res = (int)call_func2(ptype_info_opnot_equals, &t1, &t1);
+  ok(res == 0, "expected 0, got %d\n", res);
+  res = (int)call_func2(ptype_info_opnot_equals, &t1, &t2);
+  ok(res == 1, "expected 1, got %d\n", res);
+  res = (int)call_func2(ptype_info_opnot_equals, &t2, &t1);
+  ok(res == 1, "expected 1, got %d\n", res);
+}
+
+/* Test RTTI functions */
+static void test_rtti(void)
+{
+  static const char* e_name = "name";
+  type_info *ti,*bti;
+  exception e,b;
+  void *casted;
+
+  if (bAncientVersion ||
+      !p__RTCastToVoid || !p__RTtypeid || !pexception_ctor || !pbad_typeid_ctor || !p__RTDynamicCast)
+    return;
+
+  call_func2(pexception_ctor, &e, &e_name);
+  call_func2(pbad_typeid_ctor, &b, e_name);
+
+  /* dynamic_cast to void* */
+  casted = p__RTCastToVoid(&e);
+  ok (casted == (void*)&e, "failed cast to void\n");
+
+  /* dynamic_cast up */
+  ti = p__RTtypeid(&e);
+  bti = p__RTtypeid(&b);
+
+  casted = p__RTDynamicCast(&b, 0, NULL, ti, 0);
+  ok (casted == (void*)&b, "failed cast from bad_cast to exception\n");
+
+  /* dynamic_cast down */
+  casted = p__RTDynamicCast(&e, 0, NULL, bti, 0);
+  ok (casted == NULL, "Cast succeeded\n");
+}
+
+START_TEST(cpp)
+{
+  InitFunctionPtrs();
+
+  test_exception();
+  test_bad_typeid();
+  test_bad_cast();
+  test___non_rtti_object();
+  test_type_info();
+  test_rtti();
+
+  if (hMsvcrt)
+    FreeLibrary(hMsvcrt);
+}
+#endif /* __i386__ */
diff --git a/reactos/regtests/winetests/msvcrt/environ.c b/reactos/regtests/winetests/msvcrt/environ.c
new file mode 100644 (file)
index 0000000..5dfa267
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Unit tests for C library environment routines
+ *
+ * Copyright 2004 Mike Hearn <mh@codeweavers.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "wine/test.h"
+#include <stdlib.h>
+
+START_TEST(environ)
+{
+#ifndef __REACTOS__
+    ok( _putenv("cat=") == 0, "_putenv failed on deletion of non-existent environment variable\n" );
+#endif
+    ok( _putenv("cat=dog") == 0, "failed setting cat=dog\n" );
+    ok( strcmp(getenv("cat"), "dog") == 0, "getenv did not return 'dog'\n" );
+    ok( _putenv("cat=") == 0, "failed deleting cat\n" );
+
+    ok( _putenv("=") == -1, "should not accept '=' as input\n" );
+#ifndef __REACTOS__
+    ok( _putenv("=dog") == -1, "should not accept '=dog' as input\n" );
+#endif
+    ok( getenv("nonexistent") == NULL, "getenv should fail with nonexistent var name\n" );
+}
diff --git a/reactos/regtests/winetests/msvcrt/file.c b/reactos/regtests/winetests/msvcrt/file.c
new file mode 100644 (file)
index 0000000..4b1568e
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * Unit test suite for file functions
+ *
+ * Copyright 2002 Bill Currie
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "wine/test.h"
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <windef.h>
+#include <winbase.h>
+#include <winnls.h>
+#include <process.h>
+#include <errno.h>
+
+static void test_fdopen( void )
+{
+    static const char buffer[] = {0,1,2,3,4,5,6,7,8,9};
+    char ibuf[10];
+    int fd;
+    FILE *file;
+
+    fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
+    write (fd, buffer, sizeof (buffer));
+    close (fd);
+
+    fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
+    lseek (fd, 5, SEEK_SET);
+    file = fdopen (fd, "rb");
+    ok (fread (ibuf, 1, sizeof (buffer), file) == 5, "read wrong byte count\n");
+    ok (memcmp (ibuf, buffer + 5, 5) == 0, "read wrong bytes\n");
+    fclose (file);
+    unlink ("fdopen.tst");
+}
+
+static void test_fileops( void )
+{
+    static const char outbuffer[] = "0,1,2,3,4,5,6,7,8,9";
+    char buffer[256];
+    WCHAR wbuffer[256];
+    int fd;
+    FILE *file;
+
+    fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
+    write (fd, outbuffer, sizeof (outbuffer));
+    close (fd);
+
+    fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
+    file = fdopen (fd, "rb");
+    ok(strlen(outbuffer) == (sizeof(outbuffer)-1),"strlen/sizeof error\n");
+    ok(fgets(buffer,sizeof(buffer),file) !=0,"fgets failed unexpected\n");
+    ok(fgets(buffer,sizeof(buffer),file) ==0,"fgets didn't signal EOF\n");
+    ok(feof(file) !=0,"feof doesn't signal EOF\n");
+    rewind(file);
+    ok(fgets(buffer,strlen(outbuffer),file) !=0,"fgets failed unexpected\n");
+    ok(lstrlenA(buffer) == strlen(outbuffer) -1,"fgets didn't read right size\n");
+    ok(fgets(buffer,sizeof(outbuffer),file) !=0,"fgets failed unexpected\n");
+    ok(strlen(buffer) == 1,"fgets dropped chars\n");
+    ok(buffer[0] == outbuffer[strlen(outbuffer)-1],"fgets exchanged chars\n");
+    fclose (file);
+    fd = open ("fdopen.tst", O_RDONLY | O_TEXT);
+    file = fdopen (fd, "rt"); /* open in TEXT mode */
+    ok(fgetws(wbuffer,sizeof(wbuffer),file) !=0,"fgetws failed unexpected\n");
+    ok(fgetws(wbuffer,sizeof(wbuffer),file) ==0,"fgetws didn't signal EOF\n");
+    ok(feof(file) !=0,"feof doesn't signal EOF\n");
+    rewind(file);
+    ok(fgetws(wbuffer,strlen(outbuffer),file) !=0,"fgetws failed unexpected\n");
+    ok(lstrlenW(wbuffer) == (strlen(outbuffer) -1),"fgetws didn't read right size\n");
+    ok(fgetws(wbuffer,sizeof(outbuffer),file) !=0,"fgets failed unexpected\n");
+    ok(lstrlenW(wbuffer) == 1,"fgets dropped chars\n");
+    fclose (file);
+    unlink ("fdopen.tst");
+}
+
+static WCHAR* AtoW( char* p )
+{
+    WCHAR* buffer;
+    DWORD len = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
+    buffer = malloc( len * sizeof(WCHAR) );
+    MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, len );
+    return buffer;
+}
+
+static void test_fgetwc( void )
+{
+#define LLEN 512
+
+  char* tempf;
+  FILE *tempfh;
+  static const char mytext[]= "This is test_fgetwc\n";
+  WCHAR wtextW[LLEN+1];
+  WCHAR *mytextW = NULL, *aptr, *wptr;
+  BOOL diff_found = FALSE;
+  unsigned int i;
+
+  tempf=_tempnam(".","wne");
+  tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
+  fputs(mytext,tempfh);
+  fclose(tempfh);
+  tempfh = fopen(tempf,"rt");
+  fgetws(wtextW,LLEN,tempfh);
+  mytextW = AtoW ((char*)mytext);
+  aptr = mytextW;
+  wptr = wtextW;
+
+  for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
+    {
+      diff_found |= (*aptr != *wptr);
+    }
+  ok(!(diff_found), "fgetwc difference found in TEXT mode\n");
+  if(mytextW) free (mytextW);
+  fclose(tempfh);
+  unlink(tempf);
+}
+
+static void test_file_put_get( void )
+{
+  char* tempf;
+  FILE *tempfh;
+  static const char mytext[]=  "This is a test_file_put_get\n";
+  static const char dostext[]= "This is a test_file_put_get\r\n";
+  char btext[LLEN];
+  WCHAR wtextW[LLEN+1];
+  WCHAR *mytextW = NULL, *aptr, *wptr;
+  BOOL diff_found = FALSE;
+  unsigned int i;
+
+  tempf=_tempnam(".","wne");
+  tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
+  fputs(mytext,tempfh);
+  fclose(tempfh);
+  tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
+  fgets(btext,LLEN,tempfh);
+  ok( strlen(mytext) + 1 == strlen(btext),"TEXT/BINARY mode not handled for write\n");
+  ok( btext[strlen(mytext)-1] == '\r', "CR not written\n");
+  fclose(tempfh);
+  tempfh = fopen(tempf,"wb"); /* open in BINARY mode */
+  fputs(dostext,tempfh);
+  fclose(tempfh);
+  tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
+  fgets(btext,LLEN,tempfh);
+  ok(strcmp(btext, mytext) == 0,"_O_TEXT read doesn't strip CR\n");
+  fclose(tempfh);
+  tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
+  fgets(btext,LLEN,tempfh);
+  ok(strcmp(btext, dostext) == 0,"_O_BINARY read doesn't preserve CR\n");
+
+  fclose(tempfh);
+  tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
+  fgetws(wtextW,LLEN,tempfh);
+  mytextW = AtoW ((char*)mytext);
+  aptr = mytextW;
+  wptr = wtextW;
+
+  for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
+    {
+      diff_found |= (*aptr != *wptr);
+    }
+  ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
+  if(mytextW) free (mytextW);
+  fclose(tempfh);
+  unlink(tempf);
+}
+
+static void test_file_write_read( void )
+{
+  char* tempf;
+  int tempfd;
+  static const char mytext[]=  "This is test_file_write_read\nsecond line\n";
+  static const char dostext[]= "This is test_file_write_read\r\nsecond line\r\n";
+  char btext[LLEN];
+
+  tempf=_tempnam(".","wne");
+  ok((tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_TEXT|_O_RDWR,
+                     _S_IREAD | _S_IWRITE)) != -1,
+     "Can't open '%s': %d\n", tempf, errno); /* open in TEXT mode */
+  ok(_write(tempfd,mytext,strlen(mytext)) == lstrlenA(mytext),
+     "_write _O_TEXT bad return value\n");
+  _close(tempfd);
+  tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
+  ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
+     "_read _O_BINARY got bad length\n");
+  ok( memcmp(dostext,btext,strlen(dostext)) == 0,
+      "problems with _O_TEXT _write / _O_BINARY _read\n");
+  ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
+  _close(tempfd);
+  tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
+  ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
+     "_read _O_TEXT got bad length\n");
+  ok( memcmp(mytext,btext,strlen(mytext)) == 0,
+      "problems with _O_TEXT _write / _read\n");
+  _close(tempfd);
+  ok(unlink(tempf) !=-1 ,"Can't unlink '%s': %d\n", tempf, errno);
+
+  tempf=_tempnam(".","wne");
+  ok((tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,0)) != -1,
+     "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
+  ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
+     "_write _O_BINARY bad return value\n");
+  _close(tempfd);
+  tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
+  ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
+     "_read _O_BINARY got bad length\n");
+  ok( memcmp(dostext,btext,strlen(dostext)) == 0,
+      "problems with _O_BINARY _write / _read\n");
+  ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
+  _close(tempfd);
+  tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
+  ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
+     "_read _O_TEXT got bad length\n");
+  ok( memcmp(mytext,btext,strlen(mytext)) == 0,
+      "problems with _O_BINARY _write / _O_TEXT _read\n");
+  _close(tempfd);
+
+  ok(_chmod (tempf, _S_IREAD | _S_IWRITE) == 0,
+     "Can't chmod '%s' to read-write: %d\n", tempf, errno);
+  ok(unlink(tempf) !=-1 ,"Can't unlink '%s': %d\n", tempf, errno);
+}
+
+static void test_file_inherit_child(const char* fd_s)
+{
+    int fd = atoi(fd_s);
+    char buffer[32];
+
+    ok(write(fd, "Success", 8) == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno));
+    lseek(fd, 0, SEEK_SET);
+    ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n");
+    ok(memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
+}
+
+static void test_file_inherit_child_no(const char* fd_s)
+{
+    int fd = atoi(fd_s);
+
+    ok(write(fd, "Success", 8) == -1 && errno == EBADF, 
+       "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
+}
+static void test_file_inherit( const char* selfname )
+{
+    int                        fd;
+    const char*                arg_v[5];
+    char               buffer[16];
+
+    fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
+    ok(fd != -1, "Couldn't create test file\n ");
+    arg_v[0] = selfname;
+    arg_v[1] = "tests/file.c";
+    arg_v[2] = buffer; sprintf(buffer, "%d", fd);
+    arg_v[3] = 0;
+    _spawnvp(_P_WAIT, selfname, arg_v);
+    ok(tell(fd) == 8, "bad position %lu expecting 8\n", tell(fd));
+    lseek(fd, 0, SEEK_SET);
+    ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
+    close (fd);
+    ok(unlink("fdopen.tst") != 1, "Couldn't unlink\n");
+    
+    fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
+    ok(fd != -1, "Couldn't create test file\n ");
+    arg_v[0] = selfname;
+    arg_v[1] = "tests/file.c";
+    arg_v[2] = buffer; sprintf(buffer, "%d", fd);
+    arg_v[3] = buffer;
+    arg_v[4] = 0;
+    _spawnvp(_P_WAIT, selfname, arg_v);
+    ok(tell(fd) == 0, "bad position %lu expecting 0\n", tell(fd));
+    ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
+    close (fd);
+    ok(unlink("fdopen.tst") != 1, "Couldn't unlink\n");
+}
+
+static void test_tmpnam( void )
+{
+  char name[MAX_PATH] = "abc";
+  char *res;
+
+  res = tmpnam(NULL);
+  ok(res != NULL, "tmpnam returned NULL\n");
+  ok(res[0] == '\\', "first character is not a backslash\n");
+  ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
+  ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
+
+  res = tmpnam(name);
+  ok(res != NULL, "tmpnam returned NULL\n");
+  ok(res == name, "supplied buffer was not used\n");
+  ok(res[0] == '\\', "first character is not a backslash\n");
+  ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
+  ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
+}
+
+
+
+START_TEST(file)
+{
+    int arg_c;
+    char** arg_v;
+
+    arg_c = winetest_get_mainargs( &arg_v );
+
+    if (arg_c >= 3)
+    {
+       if (arg_c == 3) test_file_inherit_child(arg_v[2]); else test_file_inherit_child_no(arg_v[2]);
+        return;
+    }
+
+    test_fdopen();
+    test_fileops();
+    test_fgetwc();
+    test_file_put_get();
+    test_file_write_read();
+    test_file_inherit(arg_v[0]);
+    test_tmpnam();
+}
diff --git a/reactos/regtests/winetests/msvcrt/heap.c b/reactos/regtests/winetests/msvcrt/heap.c
new file mode 100644 (file)
index 0000000..a1ae0c5
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Unit test suite for memory functions
+ *
+ * Copyright 2003 Dimitrie O. Paun
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdlib.h>
+#include "wine/test.h"
+
+START_TEST(heap)
+{
+    void *mem;
+
+    mem = malloc(0);
+    ok(mem != NULL, "memory not allocated for size 0\n");
+
+    mem = realloc(NULL, 10);
+    ok(mem != NULL, "memory not allocated\n");
+    
+    mem = realloc(mem, 20);
+    ok(mem != NULL, "memory not reallocated\n");
+    mem = realloc(mem, 0);
+    ok(mem == NULL, "memory not freed\n");
+    
+    mem = realloc(NULL, 0);
+    ok(mem != NULL, "memory not (re)allocated for size 0\n");
+}
diff --git a/reactos/regtests/winetests/msvcrt/msvcrt_test.dsp b/reactos/regtests/winetests/msvcrt/msvcrt_test.dsp
new file mode 100644 (file)
index 0000000..1e27830
--- /dev/null
@@ -0,0 +1,107 @@
+# Microsoft Developer Studio Project File - Name="msvcrt_test" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=msvcrt_test - Win32 Wine Headers\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "msvcrt_test.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "msvcrt_test.mak" CFG="msvcrt_test - Win32 Wine Headers"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "msvcrt_test - Win32 MSVC Headers" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "msvcrt_test - Win32 Wine Headers" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+!IF  "$(CFG)" == "msvcrt_test - Win32 MSVC Headers"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Output\Win32_MSVC_Headers"\r
+# PROP BASE Intermediate_Dir "Output\Win32_MSVC_Headers"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Output\Win32_MSVC_Headers"\r
+# PROP Intermediate_Dir "Output\Win32_MSVC_Headers"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WINVER=0x0501" /D "_WIN32_WINNT=0x0501" /D "_WIN32_IE=0x0600" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ  /c\r
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ..\..\..\Output\\Win32_MSVC_Headers /D "WINVER=0x0501" /D "_WIN32_WINNT=0x0501" /D "_WIN32_IE=0x0600" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_MSVCRT_TEST_" /D "__WINE_USE_NATIVE_HEADERS" /D __WINETEST_OUTPUT_DIR=\"Output\\Win32_MSVC_Headers\" /D "__i386__" /D "_X86_" /D inline=__inline /FR /FD /GZ /c\r
+# ADD BASE RSC /l 0x41d /d "_DEBUG"\r
+# ADD RSC /l 0x41d /i "..\..\..\Output\\Win32_MSVC_Headers" /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+\r
+!ELSEIF  "$(CFG)" == "msvcrt_test - Win32 Wine Headers"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Output\Win32_Wine_Headers"\r
+# PROP BASE Intermediate_Dir "Output\Win32_Wine_Headers"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Output\Win32_Wine_Headers"\r
+# PROP Intermediate_Dir "Output\Win32_Wine_Headers"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WINVER=0x0501" /D "_WIN32_WINNT=0x0501" /D "_WIN32_IE=0x0600" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ  /c\r
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ..\..\..\Output\\Win32_Wine_Headers /I ..\..\..\include /D "WINVER=0x0501" /D "_WIN32_WINNT=0x0501" /D "_WIN32_IE=0x0600" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_MSVCRT_TEST_" /D __WINETEST_OUTPUT_DIR=\"Output\\Win32_Wine_Headers\" /D "__i386__" /D "_X86_" /D inline=__inline /FR /FD /GZ /c\r
+# ADD BASE RSC /l 0x41d /d "_DEBUG"\r
+# ADD RSC /l 0x41d /i "..\..\..\Output\\Win32_Wine_Headers" /i "..\..\..\include" /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "msvcrt_test - Win32 MSVC Headers"\r
+# Name "msvcrt_test - Win32 Wine Headers"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=.\cpp.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\\\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\testlist.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# End Group\r
+# Begin Group "Resource Files"\r
+\r
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/reactos/regtests/winetests/msvcrt/printf.c b/reactos/regtests/winetests/msvcrt/printf.c
new file mode 100644 (file)
index 0000000..2cfc502
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Conformance tests for *printf functions.
+ *
+ * Copyright 2002 Uwe Bonnes
+ * Copyright 2004 Aneurin Price
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <stdio.h>
+
+#include "wine/test.h"
+
+static void test_sprintf( void )
+{
+    char buffer[100];
+    const char *I64d = "%I64d";
+    const char *O4c = "%04c";
+    const char *O4s = "%04s";
+    const char *hash012p = "%#012p";
+    double pnumber=789456123;
+/**    WCHAR widestring[]={'w','i','d','e','s','t','r','i','n','g',0};**/
+    sprintf(buffer,"%+#23.15e",pnumber);
+    todo_wine
+      {
+        ok(strstr(buffer,"e+008") != 0,"Sprintf different \"%s\"\n",buffer);
+      }
+    sprintf(buffer,I64d,((ULONGLONG)0xffffffff)*0xffffffff);
+    todo_wine
+      {
+        ok(strlen(buffer) == 11,"Problem with long long \"%s\"\n",buffer);
+      }
+    sprintf(buffer,"%lld",((ULONGLONG)0xffffffff)*0xffffffff);
+    todo_wine
+      {
+        ok(strlen(buffer) == 1,"Problem with \"ll\" interpretation \"%s\"\n",buffer);
+      }
+/** This one actually crashes WINE at the moment, when using builtin msvcrt.dll.
+    sprintf(buffer,"%S",widestring);
+    todo_wine
+      {
+        ok(strlen(buffer) == 10,"Problem with \"%%S\" interpretation \"%s\"\n",buffer);
+      }
+ **/
+    sprintf(buffer,O4c,'1');
+    todo_wine
+      {
+        ok(!strcmp(buffer,"0001"),"Character not zero-prefixed \"%s\"\n",buffer);
+      }
+    sprintf(buffer,"%p",(void *)57);
+    todo_wine
+      {
+        ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
+      }
+    sprintf(buffer,hash012p,(void *)57);
+    todo_wine
+      {
+        ok(!strcmp(buffer,"  0X00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
+      }
+    sprintf(buffer,O4s,"foo");/**Warning again**/
+    todo_wine
+      {
+        ok(!strcmp(buffer,"0foo"),"String not zero-prefixed \"%s\"\n",buffer);
+      }
+}
+
+static void test_swprintf( void )
+{
+    wchar_t buffer[100];
+    const wchar_t I64d[] = {'%','I','6','4','d',0};
+    double pnumber=789456123;
+    const wchar_t TwentyThreePoint15e[]= {'%','+','#','2','3','.','1','5','e',0};
+    const wchar_t e008[] = {'e','+','0','0','8',0};
+    const char string[]={'s','t','r','i','n','g',0};
+    const wchar_t S[]={'%','S',0};
+    swprintf(buffer,TwentyThreePoint15e,pnumber);
+    todo_wine
+      {
+        ok(wcsstr(buffer,e008) != 0,"Sprintf different\n");
+      }
+    swprintf(buffer,I64d,((ULONGLONG)0xffffffff)*0xffffffff);
+    todo_wine
+      {
+        ok(wcslen(buffer) == 11,"Problem with long long\n");
+      }
+    swprintf(buffer,S,string);
+      ok(wcslen(buffer) == 6,"Problem with \"%%S\" interpretation\n");
+}
+
+static void test_fwprintf( void )
+{
+    const char *string="not a wide string";
+    todo_wine
+      {
+        ok(fwprintf(fopen("nul","r+"),(wchar_t *)string) == -1,"Non-wide string should not be printed by fwprintf\n");
+      }
+}
+
+static void test_snprintf (void)
+{
+    struct snprintf_test {
+        const char *format;
+        int expected;
+        struct {
+            int retval;
+            int render;
+        } todo;
+    };
+    /* Pre-2.1 libc behaviour, not C99 compliant. */
+    const struct snprintf_test tests[] = {{"short", 5, {0, 0}},
+                                          {"justfit", 7, {0, 0}},
+                                          {"justfits", 8, {0, 1}},
+                                          {"muchlonger", -1, {1, 1}}};
+    char buffer[8];
+    const int bufsiz = sizeof buffer;
+    unsigned int i;
+
+    for (i = 0; i < sizeof tests / sizeof tests[0]; i++) {
+        const char *fmt  = tests[i].format;
+        const int expect = tests[i].expected;
+        const int n      = _snprintf (buffer, bufsiz, fmt);
+        const int valid  = n < 0 ? bufsiz : (n == bufsiz ? n : n+1);
+
+        todo (tests[i].todo.retval ? "wine" : "none")
+            ok (n == expect, "\"%s\": expected %d, returned %d\n",
+                fmt, expect, n);
+        todo (tests[i].todo.render ? "wine" : "none")
+            ok (!memcmp (fmt, buffer, valid),
+                "\"%s\": rendered \"%.*s\"\n", fmt, valid, buffer);
+    };
+}
+
+START_TEST(printf)
+{
+    test_sprintf();
+    test_swprintf();
+    test_fwprintf();
+    test_snprintf();
+}
diff --git a/reactos/regtests/winetests/msvcrt/scanf.c b/reactos/regtests/winetests/msvcrt/scanf.c
new file mode 100644 (file)
index 0000000..f2a27ff
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Unit test suite for *scanf functions.
+ *
+ * Copyright 2002 Uwe Bonnes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+
+#include "wine/test.h"
+
+static void test_sscanf( void )
+{
+    char buffer[100], buffer1[100];
+    char format[20];
+    int result, ret;
+    float res1= -82.6267f, res2= 27.76f, res11, res12;
+    static const char pname[]=" St. Petersburg, Florida\n";
+    int hour=21,min=59,sec=20;
+    int  number,number_so_far;
+
+
+    /* check EOF */
+    strcpy(buffer,"");
+    ret = sscanf(buffer, "%d", &result);
+    ok( ret == EOF,"sscanf returns %x instead of %x\n", ret, EOF );
+
+    /* check %x */
+    strcpy(buffer,"0x519");
+    ok( sscanf(buffer, "%x", &result) == 1, "sscanf failed\n"  );
+    ok( result == 0x519,"sscanf reads %x instead of %x\n", result, 0x519 );
+
+    strcpy(buffer,"0x51a");
+    ok( sscanf(buffer, "%x", &result) == 1, "sscanf failed\n" );
+    ok( result == 0x51a ,"sscanf reads %x instead of %x\n", result, 0x51a );
+
+    strcpy(buffer,"0x51g");
+    ok( sscanf(buffer, "%x", &result) == 1, "sscanf failed\n" );
+    ok( result == 0x51, "sscanf reads %x instead of %x\n", result, 0x51 );
+
+    /* check % followed by any char */
+    strcpy(buffer,"\"%12@");
+    strcpy(format,"%\"%%%d%@");  /* work around gcc format check */
+    ok( sscanf(buffer, format, &result) == 1, "sscanf failed\n" );
+    ok( result == 12, "sscanf reads %x instead of %x\n", result, 12 );
+
+    /* Check float */
+    ret = sprintf(buffer,"%f %f",res1, res2);
+    ret = sscanf(buffer,"%f%f",&res11, &res12);
+    ok( (res11 == res1) && (res12 == res2), "Error reading floats\n");
+
+    /* check strings */
+    ret = sprintf(buffer," %s", pname);
+    ret = sscanf(buffer,"%*c%[^\n]",buffer1);
+    ok( ret == 1, "Error with format \"%s\"\n","%*c%[^\n]");
+    ok( strncmp(pname,buffer1,strlen(buffer1)) == 0, "Error with \"%s\" \"%s\"\n",pname, buffer1);
+
+    ret = sscanf("abcefgdh","%*[a-cg-e]%c",&buffer[0]);
+    ok( ret == 1, "Error with format \"%s\"\n","%*[a-cg-e]%c");
+    ok( buffer[0] == 'd', "Error with \"abcefgdh\" \"%c\"\n", buffer[0]);
+
+    ret = sscanf("abcefgdh","%*[a-cd-dg-e]%c",&buffer[0]);
+    ok( ret == 1, "Error with format \"%s\"\n","%*[a-cd-dg-e]%c");
+    ok( buffer[0] == 'h', "Error with \"abcefgdh\" \"%c\"\n", buffer[0]);
+
+    /* check digits */
+    ret = sprintf(buffer,"%d:%d:%d",hour,min,sec);
+    ret = sscanf(buffer,"%d%n",&number,&number_so_far);
+    ok(ret == 1 , "problem with format arg \"%%d%%n\"\n");
+    ok(number == hour,"Read wrong arg %d instead of %d\n",number, hour);
+    ok(number_so_far == 2,"Read wrong arg for \"%%n\" %d instead of 2\n",number_so_far);
+
+    ret = sscanf(buffer+2,"%*c%n",&number_so_far);
+    ok(ret == 0 , "problem with format arg \"%%*c%%n\"\n");
+    ok(number_so_far == 1,"Read wrong arg for \"%%n\" %d instead of 2\n",number_so_far);
+
+    /* Check %i according to bug 1878 */
+    strcpy(buffer,"123");
+    ret = sscanf(buffer, "%i", &result);
+    ok( ret == 1 , "Wrong number of arguments read\n");
+    ok(result == 123, "Wrong number read\n");
+    ret = sscanf(buffer, "%d", &result);
+    ok( ret == 1 , "Wrong number of arguments read\n");
+    ok(result == 123, "Wrong number read\n");
+}
+
+START_TEST(scanf)
+{
+    test_sscanf();
+}
diff --git a/reactos/regtests/winetests/msvcrt/string.c b/reactos/regtests/winetests/msvcrt/string.c
new file mode 100644 (file)
index 0000000..8449610
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Unit test suite for string functions.
+ *
+ * Copyright 2004 Uwe Bonnes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "wine/test.h"
+#include "winbase.h"
+#include <string.h>
+#include <stdlib.h>
+
+static void* (*pmemcpy)(void *, const void *, size_t n);
+static int* (*pmemcmp)(void *, const void *, size_t n);
+
+#define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y)
+#define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y)
+
+
+START_TEST(string)
+{
+    void *mem;
+    static const char xilstring[]="c:/xilinx";
+    int nLen=strlen(xilstring);
+    HMODULE hMsvcrt = LoadLibraryA("msvcrt.dll");
+    ok(hMsvcrt != 0, "LoadLibraryA failed\n");
+    SET(pmemcpy,"memcpy");
+    SET(pmemcmp,"memcmp");
+
+    /* MSVCRT memcpy behaves like memmove for overlapping moves,
+       MFC42 CString::Insert seems to rely on that behaviour */
+    mem = malloc(100);
+    ok(mem != NULL, "memory not allocated for size 0\n");
+    strcpy((char*)mem,xilstring);
+    pmemcpy((char*)mem+5, mem,nLen+1);
+    ok(pmemcmp((char*)mem+5,xilstring, nLen) == 0, 
+       "Got result %s\n",(char*)mem+5);
+}
diff --git a/reactos/regtests/winetests/msvcrt/testlist.c b/reactos/regtests/winetests/msvcrt/testlist.c
new file mode 100644 (file)
index 0000000..4876646
--- /dev/null
@@ -0,0 +1,39 @@
+/* Automatically generated file; DO NOT EDIT!! */
+
+/* stdarg.h is needed for Winelib */
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "windef.h"
+#include "winbase.h"
+
+extern void func_cpp(void);
+extern void func_environ(void);
+extern void func_file(void);
+extern void func_heap(void);
+extern void func_printf(void);
+extern void func_scanf(void);
+extern void func_string(void);
+extern void func_time(void);
+
+struct test
+{
+    const char *name;
+    void (*func)(void);
+};
+
+static const struct test winetest_testlist[] =
+{
+    { "cpp", func_cpp },
+    { "environ", func_environ },
+    { "file", func_file },
+    { "heap", func_heap },
+    { "printf", func_printf },
+    { "scanf", func_scanf },
+    { "string", func_string },
+    { "time", func_time },
+    { 0, 0 }
+};
+
+#define WINETEST_WANT_MAIN
+#include "wine/test.h"
diff --git a/reactos/regtests/winetests/msvcrt/time.c b/reactos/regtests/winetests/msvcrt/time.c
new file mode 100644 (file)
index 0000000..7254102
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Unit test suite for time functions.
+ *
+ * Copyright 2004 Uwe Bonnes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "wine/test.h"
+#include "winbase.h"
+#include "time.h"
+
+#include <stdlib.h> /*setenv*/
+#include <stdio.h> /*printf*/
+
+#define SECSPERDAY         86400
+#define SECSPERHOUR        3600
+#define SECSPERMIN         60
+#define MINSPERHOUR        60
+#define HOURSPERDAY        24
+
+static void test_gmtime()
+{
+    time_t gmt = (time_t)NULL;
+    struct tm* gmt_tm = gmtime(&gmt);
+    if(gmt_tm == 0)
+       {
+           ok(0,"gmtime() error\n");
+           return;
+       }
+    ok(((gmt_tm->tm_year == 70) && (gmt_tm->tm_mon  == 0) && (gmt_tm->tm_yday  == 0) &&
+       (gmt_tm->tm_mday ==  1) && (gmt_tm->tm_wday == 4) && (gmt_tm->tm_hour  == 0) &&
+       (gmt_tm->tm_min  ==  0) && (gmt_tm->tm_sec  == 0) && (gmt_tm->tm_isdst == 0)),
+       "Wrong date:Year %4d mon %2d yday %3d mday %2d wday %1d hour%2d min %2d sec %2d dst %2d\n",
+       gmt_tm->tm_year, gmt_tm->tm_mon, gmt_tm->tm_yday, gmt_tm->tm_mday, gmt_tm->tm_wday, 
+       gmt_tm->tm_hour, gmt_tm->tm_min, gmt_tm->tm_sec, gmt_tm->tm_isdst); 
+  
+}
+static void test_mktime()
+{
+    TIME_ZONE_INFORMATION tzinfo;
+    DWORD res =  GetTimeZoneInformation(&tzinfo);
+    struct tm my_tm, sav_tm;
+    time_t nulltime, local_time;
+    char TZ_env[256];
+    int secs;
+
+    ok (res != TIME_ZONE_ID_INVALID, "GetTimeZoneInformation failed\n");
+    /* Bias may be positive or negative, to use offset of one day */
+    secs= SECSPERDAY - (tzinfo.Bias +
+      ( res == TIME_ZONE_ID_STANDARD ? tzinfo.StandardBias :
+      ( res == TIME_ZONE_ID_DAYLIGHT ? tzinfo.DaylightBias : 0 ))) * SECSPERMIN;
+    my_tm.tm_mday = 1 + secs/SECSPERDAY;
+    secs = secs % SECSPERDAY;
+    my_tm.tm_hour = secs / SECSPERHOUR;
+    secs = secs % SECSPERHOUR;
+    my_tm.tm_min = secs / SECSPERMIN;
+    secs = secs % SECSPERMIN;
+    my_tm.tm_sec = secs;
+
+    my_tm.tm_year = 70;
+    my_tm.tm_mon  =  0;
+    my_tm.tm_isdst=  0;
+
+    sav_tm = my_tm;
+  
+    local_time = mktime(&my_tm);
+    ok(((DWORD)local_time == SECSPERDAY), "mktime returned 0x%08lx\n",(DWORD)local_time);
+    /* now test some unnormalized struct tm's */
+    my_tm = sav_tm;
+    my_tm.tm_sec += 60;
+    my_tm.tm_min -= 1;
+    local_time = mktime(&my_tm);
+    ok(((DWORD)local_time == SECSPERDAY), "Unnormalized mktime returned 0x%08lx\n",(DWORD)local_time);
+    ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
+        my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
+        my_tm.tm_sec == sav_tm.tm_sec
+            , "mktime returned %3d-%02d-%02d %02d:%02d expected  %3d-%02d-%02d %02d:%02d.\n",
+            my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday,
+            my_tm.tm_hour,my_tm.tm_sec,
+            sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday,
+            sav_tm.tm_hour,sav_tm.tm_sec);
+    my_tm = sav_tm;
+    my_tm.tm_min -= 60;
+    my_tm.tm_hour += 1;
+    local_time = mktime(&my_tm);
+    ok(((DWORD)local_time == SECSPERDAY), "Unnormalized mktime returned 0x%08lx\n",(DWORD)local_time);
+    ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
+        my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
+        my_tm.tm_sec == sav_tm.tm_sec
+            , "mktime returned %3d-%02d-%02d %02d:%02d expected  %3d-%02d-%02d %02d:%02d.\n",
+            my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday,
+            my_tm.tm_hour,my_tm.tm_sec,
+            sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday,
+            sav_tm.tm_hour,sav_tm.tm_sec);
+    my_tm = sav_tm;
+    my_tm.tm_mon -= 12;
+    my_tm.tm_year += 1;
+    local_time = mktime(&my_tm);
+    ok(((DWORD)local_time == SECSPERDAY), "Unnormalized mktime returned 0x%08lx\n",(DWORD)local_time);
+    ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
+        my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
+        my_tm.tm_sec == sav_tm.tm_sec
+            , "mktime returned %3d-%02d-%02d %02d:%02d expected  %3d-%02d-%02d %02d:%02d.\n",
+            my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday,
+            my_tm.tm_hour,my_tm.tm_sec,
+            sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday,
+            sav_tm.tm_hour,sav_tm.tm_sec);
+    my_tm = sav_tm;
+    my_tm.tm_mon += 12;
+    my_tm.tm_year -= 1;
+    local_time = mktime(&my_tm);
+    ok(((DWORD)local_time == SECSPERDAY), "Unnormalized mktime returned 0x%08lx\n",(DWORD)local_time);
+    ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
+        my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
+        my_tm.tm_sec == sav_tm.tm_sec
+            , "mktime returned %3d-%02d-%02d %02d:%02d expected  %3d-%02d-%02d %02d:%02d.\n",
+            my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday,
+            my_tm.tm_hour,my_tm.tm_sec,
+            sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday,
+            sav_tm.tm_hour,sav_tm.tm_sec);
+    /* now a bad time example */
+    my_tm = sav_tm;
+    my_tm.tm_year -= 1;
+    local_time = mktime(&my_tm);
+    ok((local_time == -1), "(bad time) mktime returned 0x%08lx\n",(DWORD)local_time);
+
+    my_tm = sav_tm;
+    /* TEST that we are independent from the TZ variable */
+    /*Argh, msvcrt doesn't have setenv() */
+    _snprintf(TZ_env,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
+    putenv("TZ=GMT");
+    nulltime = mktime(&my_tm);
+    ok(((DWORD)nulltime == SECSPERDAY),"mktime returned 0x%08lx\n",(DWORD)nulltime);
+    putenv(TZ_env);
+}
+static void test_localtime()
+{
+    TIME_ZONE_INFORMATION tzinfo;
+    DWORD res =  GetTimeZoneInformation(&tzinfo);
+    time_t gmt = (time_t)(SECSPERDAY + (tzinfo.Bias +
+      ( res == TIME_ZONE_ID_STANDARD ? tzinfo.StandardBias :
+      ( res == TIME_ZONE_ID_DAYLIGHT ? tzinfo.DaylightBias : 0 ))) * SECSPERMIN);
+
+    char TZ_env[256];
+    struct tm* lt;
+    
+    ok (res != TIME_ZONE_ID_INVALID, "GetTimeZoneInformation failed\n");
+    lt = localtime(&gmt);
+    ok(((lt->tm_year == 70) && (lt->tm_mon  == 0) && (lt->tm_yday  == 1) &&
+       (lt->tm_mday ==  2) && (lt->tm_wday == 5) && (lt->tm_hour  == 0) &&
+       (lt->tm_min  ==  0) && (lt->tm_sec  == 0) && (lt->tm_isdst ==
+                                                      (res == TIME_ZONE_ID_DAYLIGHT))),
+       "Wrong date:Year %4d mon %2d yday %3d mday %2d wday %1d hour%2d min %2d sec %2d dst %2d\n",
+       lt->tm_year, lt->tm_mon, lt->tm_yday, lt->tm_mday, lt->tm_wday, lt->tm_hour, 
+       lt->tm_min, lt->tm_sec, lt->tm_isdst); 
+
+    _snprintf(TZ_env,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
+    putenv("TZ=GMT");
+    lt = localtime(&gmt);
+    ok(((lt->tm_year == 70) && (lt->tm_mon  == 0) && (lt->tm_yday  == 1) &&
+       (lt->tm_mday ==  2) && (lt->tm_wday == 5) && (lt->tm_hour  == 0) &&
+       (lt->tm_min  ==  0) && (lt->tm_sec  == 0) && (lt->tm_isdst ==
+                                                      (res == TIME_ZONE_ID_DAYLIGHT))),
+       "Wrong date:Year %4d mon %2d yday %3d mday %2d wday %1d hour%2d min %2d sec %2d dst %2d\n",
+       lt->tm_year, lt->tm_mon, lt->tm_yday, lt->tm_mday, lt->tm_wday, lt->tm_hour, 
+       lt->tm_min, lt->tm_sec, lt->tm_isdst); 
+    putenv(TZ_env);
+}
+
+
+START_TEST(time)
+{
+    test_gmtime();
+    test_mktime();
+    test_localtime();
+}
diff --git a/reactos/regtests/winetests/version/info.c b/reactos/regtests/winetests/version/info.c
new file mode 100644 (file)
index 0000000..4e42185
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2004 Stefan Leichter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "wine/test.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winver.h"
+
+#define MY_LAST_ERROR -1L
+#define EXPECT_BAD_PATH__NOT_FOUND \
+    ok( (ERROR_PATH_NOT_FOUND == GetLastError()) || \
+       (ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) || \
+       (ERROR_FILE_NOT_FOUND == GetLastError()) || \
+       (ERROR_BAD_PATHNAME == GetLastError()), \
+       "Last error wrong! ERROR_RESOURCE_DATA_NOT_FOUND/ERROR_BAD_PATHNAME (98)/" \
+       "ERROR_PATH_NOT_FOUND (NT4)/ERROR_FILE_NOT_FOUND (2k3)" \
+       "expected, got 0x%08lx\n", GetLastError());
+#define EXPECT_INVALID__NOT_FOUND \
+    ok( (ERROR_PATH_NOT_FOUND == GetLastError()) || \
+       (ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) || \
+       (ERROR_FILE_NOT_FOUND == GetLastError()) || \
+       (ERROR_INVALID_PARAMETER == GetLastError()), \
+       "Last error wrong! ERROR_RESOURCE_DATA_NOT_FOUND/ERROR_INVALID_PARAMETER (98)/" \
+       "ERROR_PATH_NOT_FOUND (NT4)/ERROR_FILE_NOT_FOUND (2k3)" \
+       "expected, got 0x%08lx\n", GetLastError());
+
+static void test_info_size(void)
+{   DWORD hdl, retval;
+
+    SetLastError(MY_LAST_ERROR);
+    retval = GetFileVersionInfoSizeA( NULL, NULL);
+    ok( !retval,
+       "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08lx\n",
+       retval);
+    EXPECT_INVALID__NOT_FOUND;
+
+    hdl = 0x55555555;
+    SetLastError(MY_LAST_ERROR);
+    retval = GetFileVersionInfoSizeA( NULL, &hdl);
+    ok( !retval,
+       "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08lx\n",
+       retval);
+    EXPECT_INVALID__NOT_FOUND;
+    ok( hdl == 0L,
+       "Handle wrong! 0L expected, got 0x%08lx\n", hdl);
+
+    SetLastError(MY_LAST_ERROR);
+    retval = GetFileVersionInfoSizeA( "", NULL);
+    ok( !retval,
+       "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08lx\n",
+       retval);
+    EXPECT_BAD_PATH__NOT_FOUND;
+
+    hdl = 0x55555555;
+    SetLastError(MY_LAST_ERROR);
+    retval = GetFileVersionInfoSizeA( "", &hdl);
+    ok( !retval,
+       "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08lx\n",
+       retval);
+    EXPECT_BAD_PATH__NOT_FOUND;
+    ok( hdl == 0L,
+       "Handle wrong! 0L expected, got 0x%08lx\n", hdl);
+
+    SetLastError(MY_LAST_ERROR);
+    retval = GetFileVersionInfoSizeA( "kernel32.dll", NULL);
+    ok( retval,
+       "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08lx\n",
+       retval);
+    ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
+       "Last error wrong! NO_ERROR/0x%08lx (NT4)  expected, got 0x%08lx\n",
+       MY_LAST_ERROR, GetLastError());
+
+    hdl = 0x55555555;
+    SetLastError(MY_LAST_ERROR);
+    retval = GetFileVersionInfoSizeA( "kernel32.dll", &hdl);
+    ok( retval,
+       "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08lx\n",
+       retval);
+    ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
+       "Last error wrong! NO_ERROR/0x%08lx (NT4)  expected, got 0x%08lx\n",
+       MY_LAST_ERROR, GetLastError());
+    ok( hdl == 0L,
+       "Handle wrong! 0L expected, got 0x%08lx\n", hdl);
+
+    SetLastError(MY_LAST_ERROR);
+    retval = GetFileVersionInfoSizeA( "notexist.dll", NULL);
+    ok( !retval,
+       "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08lx\n",
+       retval);
+    ok( (ERROR_FILE_NOT_FOUND == GetLastError()) ||
+       (ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) ||
+       (MY_LAST_ERROR == GetLastError()),
+       "Last error wrong! ERROR_FILE_NOT_FOUND/ERROR_RESOURCE_DATA_NOT_FOUND "
+       "(XP)/0x%08lx (NT4) expected, got 0x%08lx\n", MY_LAST_ERROR, GetLastError());
+}
+
+static void VersionDwordLong2String(DWORDLONG Version, LPSTR lpszVerString)
+{
+    WORD a, b, c, d;
+
+    a = (WORD)(Version >> 48);
+    b = (WORD)((Version >> 32) & 0xffff);
+    c = (WORD)((Version >> 16) & 0xffff);
+    d = (WORD)(Version & 0xffff);
+
+    sprintf(lpszVerString, "%d.%d.%d.%d", a, b, c, d);
+
+    return;
+}
+
+static void test_info(void)
+{
+    DWORD hdl, retval;
+    PVOID pVersionInfo = NULL;
+    BOOL boolret;
+    VS_FIXEDFILEINFO *pFixedVersionInfo;
+    UINT uiLength;
+    char VersionString[MAX_PATH];
+    DWORDLONG dwlVersion;
+
+    hdl = 0x55555555;
+    SetLastError(MY_LAST_ERROR);
+    retval = GetFileVersionInfoSizeA( "kernel32.dll", &hdl);
+    ok( retval,
+       "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08lx\n",
+       retval);
+    ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
+       "Last error wrong! NO_ERROR/0x%08lx (NT4)  expected, got 0x%08lx\n",
+       MY_LAST_ERROR, GetLastError());
+    ok( hdl == 0L,
+       "Handle wrong! 0L expected, got 0x%08lx\n", hdl);
+
+    if ( retval == 0 || hdl != 0)
+        return;
+
+    pVersionInfo = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, retval );
+    ok(pVersionInfo != 0, "HeapAlloc failed\n" );
+    if (pVersionInfo == 0)
+        return;
+
+    boolret = GetFileVersionInfoA( "kernel32.dll", 0, retval, 0);
+    ok (!boolret, "GetFileVersionInfoA should have failed: GetLastError = 0x%08lx\n", GetLastError());
+    ok ((GetLastError() == ERROR_INVALID_DATA) || (GetLastError() == ERROR_BAD_PATHNAME),
+        "Last error wrong! ERROR_INVALID_DATA/ERROR_BAD_PATHNAME (ME) expected, got 0x%08lx\n",
+        GetLastError());
+
+    boolret = GetFileVersionInfoA( "kernel32.dll", 0, retval, pVersionInfo );
+    ok (boolret, "GetFileVersionInfoA failed: GetLastError = 0x%08lx\n", GetLastError());
+    if (!boolret)
+        return;
+
+    boolret = VerQueryValueA( pVersionInfo, "\\", (LPVOID *)&pFixedVersionInfo, &uiLength );
+    ok (boolret, "VerQueryValueA failed: GetLastError = 0x%08lx\n", GetLastError());
+    if (!boolret)
+        return;
+
+    dwlVersion = (((DWORDLONG)pFixedVersionInfo->dwFileVersionMS) << 32) +
+        pFixedVersionInfo->dwFileVersionLS;
+
+    VersionDwordLong2String(dwlVersion, VersionString);
+
+    trace("kernel32.dll version: %s\n", VersionString);
+
+    boolret = VerQueryValueA( pVersionInfo, "\\", (LPVOID *)&pFixedVersionInfo, 0);
+    ok (boolret, "VerQueryValue failed: GetLastError = 0x%08lx\n", GetLastError());
+}
+
+START_TEST(info)
+{
+    test_info_size();
+    test_info();
+}
diff --git a/reactos/regtests/winetests/version/testlist.c b/reactos/regtests/winetests/version/testlist.c
new file mode 100644 (file)
index 0000000..55b47ea
--- /dev/null
@@ -0,0 +1,25 @@
+/* Automatically generated file; DO NOT EDIT!! */
+
+/* stdarg.h is needed for Winelib */
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "windef.h"
+#include "winbase.h"
+
+extern void func_info(void);
+
+struct test
+{
+    const char *name;
+    void (*func)(void);
+};
+
+static const struct test winetest_testlist[] =
+{
+    { "info", func_info },
+    { 0, 0 }
+};
+
+#define WINETEST_WANT_MAIN
+#include "wine/test.h"
diff --git a/reactos/regtests/winetests/winetest/config.h b/reactos/regtests/winetests/winetest/config.h
new file mode 100644 (file)
index 0000000..949acf8
--- /dev/null
@@ -0,0 +1,949 @@
+/* include/config.h.  Generated by configure.  */
+/* include/config.h.in.  Generated from configure.ac by autoheader.  */
+
+#define __WINE_CONFIG_H
+
+/* Specifies the compiler flag that forces a short wchar_t */
+#define CC_FLAG_SHORT_WCHAR "-fshort-wchar"
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have ALSA 1.x including devel headers */
+/* #undef HAVE_ALSA */
+
+/* Define to 1 if you have the <alsa/asoundlib.h> header file. */
+/* #undef HAVE_ALSA_ASOUNDLIB_H */
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+/* #undef HAVE_ARPA_INET_H */
+
+/* Define to 1 if you have the <arpa/nameser.h> header file. */
+/* #undef HAVE_ARPA_NAMESER_H */
+
+/* Define if you have ARTS sound server */
+/* #undef HAVE_ARTS */
+
+/* Define if the assembler keyword .size is accepted */
+/* #undef HAVE_ASM_DOT_SIZE */
+
+/* Define to 1 if you have the <audio/audiolib.h> header file. */
+/* #undef HAVE_AUDIO_AUDIOLIB_H */
+
+/* Define to 1 if you have the <audio/soundlib.h> header file. */
+/* #undef HAVE_AUDIO_SOUNDLIB_H */
+
+/* Define to 1 if you have the <capi20.h> header file. */
+/* #undef HAVE_CAPI20_H */
+
+/* Define if you have capi4linux libs and headers */
+/* #undef HAVE_CAPI4LINUX */
+
+/* Define to 1 if you have the `chsize' function. */
+#define HAVE_CHSIZE 1
+
+/* Define to 1 if you have the `clone' function. */
+/* #undef HAVE_CLONE */
+
+/* Define to 1 if you have the `connect' function. */
+/* #undef HAVE_CONNECT */
+
+/* Define if we have linux/input.h AND it contains the INPUT event API */
+/* #undef HAVE_CORRECT_LINUXINPUT_H */
+
+/* Define to 1 if you have the <cups/cups.h> header file. */
+/* #undef HAVE_CUPS_CUPS_H */
+
+/* Define to 1 if you have the <curses.h> header file. */
+/* #undef HAVE_CURSES_H */
+
+/* Define to 1 if you have the <direct.h> header file. */
+#define HAVE_DIRECT_H 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+/* #undef HAVE_DLFCN_H */
+
+/* Define if you have dlopen */
+/* #undef HAVE_DLOPEN */
+
+/* Define to 1 if you have the <elf.h> header file. */
+/* #undef HAVE_ELF_H */
+
+/* Define to 1 if you have the `epoll_create' function. */
+/* #undef HAVE_EPOLL_CREATE */
+
+/* Define to 1 if you have the `ffs' function. */
+/* #undef HAVE_FFS */
+
+/* Define to 1 if you have the `finite' function. */
+#define HAVE_FINITE 1
+
+/* Define to 1 if you have the <float.h> header file. */
+#define HAVE_FLOAT_H 1
+
+/* Define to 1 if you have the <fontconfig/fontconfig.h> header file. */
+/* #undef HAVE_FONTCONFIG_FONTCONFIG_H */
+
+/* Define to 1 if you have the `fork' function. */
+/* #undef HAVE_FORK */
+
+/* Define to 1 if you have the `fpclass' function. */
+#define HAVE_FPCLASS 1
+
+/* Define if FreeType 2 is installed */
+/* #undef HAVE_FREETYPE */
+
+/* Define to 1 if you have the <freetype/freetype.h> header file. */
+/* #undef HAVE_FREETYPE_FREETYPE_H */
+
+/* Define to 1 if you have the <freetype/ftglyph.h> header file. */
+/* #undef HAVE_FREETYPE_FTGLYPH_H */
+
+/* Define to 1 if you have the <freetype/ftnames.h> header file. */
+/* #undef HAVE_FREETYPE_FTNAMES_H */
+
+/* Define to 1 if you have the <freetype/ftoutln.h> header file. */
+/* #undef HAVE_FREETYPE_FTOUTLN_H */
+
+/* Define to 1 if you have the <freetype/ftsnames.h> header file. */
+/* #undef HAVE_FREETYPE_FTSNAMES_H */
+
+/* Define if you have the <freetype/fttrigon.h> header file. */
+/* #undef HAVE_FREETYPE_FTTRIGON_H */
+
+/* Define to 1 if you have the <freetype/ftwinfnt.h> header file. */
+/* #undef HAVE_FREETYPE_FTWINFNT_H */
+
+/* Define to 1 if you have the <freetype/internal/sfnt.h> header file. */
+/* #undef HAVE_FREETYPE_INTERNAL_SFNT_H */
+
+/* Define to 1 if you have the <freetype/ttnameid.h> header file. */
+/* #undef HAVE_FREETYPE_TTNAMEID_H */
+
+/* Define to 1 if you have the <freetype/tttables.h> header file. */
+/* #undef HAVE_FREETYPE_TTTABLES_H */
+
+/* Define to 1 if the system has the type `fsblkcnt_t'. */
+/* #undef HAVE_FSBLKCNT_T */
+
+/* Define to 1 if the system has the type `fsfilcnt_t'. */
+/* #undef HAVE_FSFILCNT_T */
+
+/* Define to 1 if you have the `fstatfs' function. */
+/* #undef HAVE_FSTATFS */
+
+/* Define to 1 if you have the `fstatvfs' function. */
+/* #undef HAVE_FSTATVFS */
+
+/* Define to 1 if you have the <ft2build.h> header file. */
+/* #undef HAVE_FT2BUILD_H */
+
+/* Define to 1 if you have the `ftruncate' function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have the `futimes' function. */
+/* #undef HAVE_FUTIMES */
+
+/* Define to 1 if you have the `gethostbyname' function. */
+/* #undef HAVE_GETHOSTBYNAME */
+
+/* Define to 1 if you have the `getnetbyname' function. */
+/* #undef HAVE_GETNETBYNAME */
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#define HAVE_GETOPT_H 1
+
+/* Define to 1 if you have the `getopt_long' function. */
+#define HAVE_GETOPT_LONG 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define to 1 if you have the `getprotobyname' function. */
+/* #undef HAVE_GETPROTOBYNAME */
+
+/* Define to 1 if you have the `getprotobynumber' function. */
+/* #undef HAVE_GETPROTOBYNUMBER */
+
+/* Define to 1 if you have the `getpwuid' function. */
+/* #undef HAVE_GETPWUID */
+
+/* Define to 1 if you have the `getservbyport' function. */
+/* #undef HAVE_GETSERVBYPORT */
+
+/* Define to 1 if you have the `gettid' function. */
+/* #undef HAVE_GETTID */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+/* #undef HAVE_GETTIMEOFDAY */
+
+/* Define to 1 if you have the `getuid' function. */
+/* #undef HAVE_GETUID */
+
+/* Define to 1 if you have the <gif_lib.h> header file. */
+/* #undef HAVE_GIF_LIB_H */
+
+/* Define to 1 if you have the <GL/glext.h> header file. */
+/* #undef HAVE_GL_GLEXT_H */
+
+/* Define to 1 if you have the <GL/glx.h> header file. */
+/* #undef HAVE_GL_GLX_H */
+
+/* Define to 1 if you have the <GL/gl.h> header file. */
+/* #undef HAVE_GL_GL_H */
+
+/* Define to 1 if the ICU libraries are installed */
+/* #undef HAVE_ICU */
+
+/* Define to 1 if you have the <ieeefp.h> header file. */
+/* #undef HAVE_IEEEFP_H */
+
+/* Define to 1 if you have the `inet_aton' function. */
+/* #undef HAVE_INET_ATON */
+
+/* Define to 1 if you have the `inet_network' function. */
+/* #undef HAVE_INET_NETWORK */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <io.h> header file. */
+#define HAVE_IO_H 1
+
+/* Define if IPX should use netipx/ipx.h from libc */
+/* #undef HAVE_IPX_GNU */
+
+/* Define if IPX includes are taken from Linux kernel */
+/* #undef HAVE_IPX_LINUX */
+
+/* Define to 1 if you have the `iswalnum' function. */
+#define HAVE_ISWALNUM 1
+
+/* Define to 1 if you have the <jack/jack.h> header file. */
+/* #undef HAVE_JACK_JACK_H */
+
+/* Define to 1 if you have the <jpeglib.h> header file. */
+/* #undef HAVE_JPEGLIB_H */
+
+/* Define to 1 if you have the <lcms.h> header file. */
+/* #undef HAVE_LCMS_H */
+
+/* Define to 1 if you have the <lcms/lcms.h> header file. */
+/* #undef HAVE_LCMS_LCMS_H */
+
+/* Define if you have libaudioIO */
+/* #undef HAVE_LIBAUDIOIO */
+
+/* Define to 1 if you have the <libaudioio.h> header file. */
+/* #undef HAVE_LIBAUDIOIO_H */
+
+/* Define if you have the curses library (-lcurses) */
+/* #undef HAVE_LIBCURSES */
+
+/* Define to 1 if you have the `i386' library (-li386). */
+/* #undef HAVE_LIBI386 */
+
+/* Define if you have the ncurses library (-lncurses) */
+/* #undef HAVE_LIBNCURSES */
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+/* #undef HAVE_LIBNSL */
+
+/* Define to 1 if you have the `ossaudio' library (-lossaudio). */
+/* #undef HAVE_LIBOSSAUDIO */
+
+/* Define to 1 if you have the `poll' library (-lpoll). */
+/* #undef HAVE_LIBPOLL */
+
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+/* #undef HAVE_LIBRESOLV */
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define to 1 if you have the `w' library (-lw). */
+/* #undef HAVE_LIBW */
+
+/* Define to 1 if you have the `xpg4' library (-lxpg4). */
+/* #undef HAVE_LIBXPG4 */
+
+/* Define if you have the Xrandr library */
+/* #undef HAVE_LIBXRANDR */
+
+/* Define if you have the X Shape extension */
+/* #undef HAVE_LIBXSHAPE */
+
+/* Define if you have the Xxf86dga library version 2 */
+/* #undef HAVE_LIBXXF86DGA2 */
+
+/* Define if you have the Xxf86vm library */
+/* #undef HAVE_LIBXXF86VM */
+
+/* Define if you have the X Shm extension */
+/* #undef HAVE_LIBXXSHM */
+
+/* Define to 1 if you have the <link.h> header file. */
+/* #undef HAVE_LINK_H */
+
+/* Define if <linux/joystick.h> defines the Linux 2.2 joystick API */
+/* #undef HAVE_LINUX_22_JOYSTICK_API */
+
+/* Define to 1 if you have the <linux/capi.h> header file. */
+/* #undef HAVE_LINUX_CAPI_H */
+
+/* Define to 1 if you have the <linux/cdrom.h> header file. */
+/* #undef HAVE_LINUX_CDROM_H */
+
+/* Define to 1 if you have the <linux/compiler.h> header file. */
+/* #undef HAVE_LINUX_COMPILER_H */
+
+/* Define if Linux-style gethostbyname_r and gethostbyaddr_r are available */
+/* #undef HAVE_LINUX_GETHOSTBYNAME_R_6 */
+
+/* Define to 1 if you have the <linux/hdreg.h> header file. */
+/* #undef HAVE_LINUX_HDREG_H */
+
+/* Define to 1 if you have the <linux/input.h> header file. */
+/* #undef HAVE_LINUX_INPUT_H */
+
+/* Define to 1 if you have the <linux/ioctl.h> header file. */
+/* #undef HAVE_LINUX_IOCTL_H */
+
+/* Define to 1 if you have the <linux/joystick.h> header file. */
+/* #undef HAVE_LINUX_JOYSTICK_H */
+
+/* Define to 1 if you have the <linux/major.h> header file. */
+/* #undef HAVE_LINUX_MAJOR_H */
+
+/* Define to 1 if you have the <linux/param.h> header file. */
+/* #undef HAVE_LINUX_PARAM_H */
+
+/* Define to 1 if you have the <linux/serial.h> header file. */
+/* #undef HAVE_LINUX_SERIAL_H */
+
+/* Define to 1 if you have the <linux/ucdrom.h> header file. */
+/* #undef HAVE_LINUX_UCDROM_H */
+
+/* Define to 1 if the system has the type `long long'. */
+#define HAVE_LONG_LONG 1
+
+/* Define to 1 if you have the `lstat' function. */
+/* #undef HAVE_LSTAT */
+
+/* Define to 1 if you have the <machine/cpu.h> header file. */
+/* #undef HAVE_MACHINE_CPU_H */
+
+/* Define to 1 if you have the <machine/soundcard.h> header file. */
+/* #undef HAVE_MACHINE_SOUNDCARD_H */
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mmap' function. */
+/* #undef HAVE_MMAP */
+
+/* Define to 1 if you have the <mntent.h> header file. */
+/* #undef HAVE_MNTENT_H */
+
+/* Define to 1 if the system has the type `mode_t'. */
+#define HAVE_MODE_T 1
+
+/* Define if you have NAS including devel headers */
+/* #undef HAVE_NAS */
+
+/* Define to 1 if you have the <ncurses.h> header file. */
+/* #undef HAVE_NCURSES_H */
+
+/* Define to 1 if you have the <netdb.h> header file. */
+/* #undef HAVE_NETDB_H */
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+/* #undef HAVE_NETINET_IN_H */
+
+/* Define to 1 if you have the <netinet/in_systm.h> header file. */
+/* #undef HAVE_NETINET_IN_SYSTM_H */
+
+/* Define to 1 if you have the <netinet/tcp_fsm.h> header file. */
+/* #undef HAVE_NETINET_TCP_FSM_H */
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+/* #undef HAVE_NETINET_TCP_H */
+
+/* Define to 1 if you have the <net/if_arp.h> header file. */
+/* #undef HAVE_NET_IF_ARP_H */
+
+/* Define to 1 if you have the <net/if_dl.h> header file. */
+/* #undef HAVE_NET_IF_DL_H */
+
+/* Define to 1 if you have the <net/if.h> header file. */
+/* #undef HAVE_NET_IF_H */
+
+/* Define to 1 if you have the <net/if_types.h> header file. */
+/* #undef HAVE_NET_IF_TYPES_H */
+
+/* Define to 1 if you have the <net/route.h> header file. */
+/* #undef HAVE_NET_ROUTE_H */
+
+/* Define to 1 if the system has the type `off_t'. */
+#define HAVE_OFF_T 1
+
+/* Define if OpenGL is present on the system */
+/* #undef HAVE_OPENGL */
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+/* #undef HAVE_OPENSSL_SSL_H */
+
+/* Define if you have the Open Sound system */
+/* #undef HAVE_OSS */
+
+/* Define if you have the Open Sound system (MIDI interface) */
+/* #undef HAVE_OSS_MIDI */
+
+/* Define to 1 if you have the `pclose' function. */
+#define HAVE_PCLOSE 1
+
+/* Define to 1 if the system has the type `pid_t'. */
+#define HAVE_PID_T 1
+
+/* Define to 1 if you have the `popen' function. */
+#define HAVE_POPEN 1
+
+/* Define if we can use ppdev.h for parallel port access */
+/* #undef HAVE_PPDEV */
+
+/* Define to 1 if you have the `pread' function. */
+/* #undef HAVE_PREAD */
+
+/* Define to 1 if you have the <process.h> header file. */
+#define HAVE_PROCESS_H 1
+
+/* Define to 1 if you have the `pthread_getattr_np' function. */
+/* #undef HAVE_PTHREAD_GETATTR_NP */
+
+/* Define to 1 if you have the `pthread_get_stackaddr_np' function. */
+/* #undef HAVE_PTHREAD_GET_STACKADDR_NP */
+
+/* Define to 1 if you have the `pthread_get_stacksize_np' function. */
+/* #undef HAVE_PTHREAD_GET_STACKSIZE_NP */
+
+/* Define to 1 if you have the <pthread.h> header file. */
+/* #undef HAVE_PTHREAD_H */
+
+/* Define to 1 if the system has the type `pthread_rwlockattr_t'. */
+/* #undef HAVE_PTHREAD_RWLOCKATTR_T */
+
+/* Define to 1 if the system has the type `pthread_rwlock_t'. */
+/* #undef HAVE_PTHREAD_RWLOCK_T */
+
+/* Define to 1 if you have the <pwd.h> header file. */
+/* #undef HAVE_PWD_H */
+
+/* Define to 1 if you have the `pwrite' function. */
+/* #undef HAVE_PWRITE */
+
+/* Define to 1 if you have the `readlink' function. */
+/* #undef HAVE_READLINK */
+
+/* Define to 1 if you have the <regex.h> header file. */
+/* #undef HAVE_REGEX_H */
+
+/* Define to 1 if you have the <resolv.h> header file. */
+/* #undef HAVE_RESOLV_H */
+
+/* Define to 1 if you have the `rfork' function. */
+/* #undef HAVE_RFORK */
+
+/* Define if we have SANE development environment */
+/* #undef HAVE_SANE */
+
+/* Define to 1 if you have the <sched.h> header file. */
+/* #undef HAVE_SCHED_H */
+
+/* Define to 1 if you have the `sched_yield' function. */
+/* #undef HAVE_SCHED_YIELD */
+
+/* Define to 1 if you have the <scsi/scsi.h> header file. */
+/* #undef HAVE_SCSI_SCSI_H */
+
+/* Define to 1 if you have the <scsi/scsi_ioctl.h> header file. */
+/* #undef HAVE_SCSI_SCSI_IOCTL_H */
+
+/* Define to 1 if you have the <scsi/sg.h> header file. */
+/* #undef HAVE_SCSI_SG_H */
+
+/* Define to 1 if you have the `select' function. */
+/* #undef HAVE_SELECT */
+
+/* Define to 1 if you have the `sendmsg' function. */
+/* #undef HAVE_SENDMSG */
+
+/* Define to 1 if you have the `settimeofday' function. */
+/* #undef HAVE_SETTIMEOFDAY */
+
+/* Define if sigaddset is supported */
+/* #undef HAVE_SIGADDSET */
+
+/* Define to 1 if you have the `sigaltstack' function. */
+/* #undef HAVE_SIGALTSTACK */
+
+/* Define to 1 if `si_fd' is member of `siginfo_t'. */
+/* #undef HAVE_SIGINFO_T_SI_FD */
+
+/* Define to 1 if you have the `sigprocmask' function. */
+/* #undef HAVE_SIGPROCMASK */
+
+/* Define to 1 if you have the sigsetjmp (and siglongjmp) function */
+/* #undef HAVE_SIGSETJMP */
+
+/* Define to 1 if the system has the type `sigset_t'. */
+/* #undef HAVE_SIGSET_T */
+
+/* Define to 1 if the system has the type `size_t'. */
+#define HAVE_SIZE_T 1
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the <soundcard.h> header file. */
+/* #undef HAVE_SOUNDCARD_H */
+
+/* Define to 1 if you have the `spawnvp' function. */
+#define HAVE_SPAWNVP 1
+
+/* Define to 1 if the system has the type `ssize_t'. */
+#define HAVE_SSIZE_T 1
+
+/* Define to 1 if you have the `statfs' function. */
+/* #undef HAVE_STATFS */
+
+/* Define to 1 if you have the `statvfs' function. */
+/* #undef HAVE_STATVFS */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if `msg_accrights' is member of `struct msghdr'. */
+/* #undef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
+
+/* Define to 1 if `name' is member of `struct option'. */
+#define HAVE_STRUCT_OPTION_NAME 1
+
+/* Define to 1 if `sa_len' is member of `struct sockaddr'. */
+/* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */
+
+/* Define to 1 if `sun_len' is member of `struct sockaddr_un'. */
+/* #undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
+
+/* Define to 1 if `f_bavail' is member of `struct statfs'. */
+/* #undef HAVE_STRUCT_STATFS_F_BAVAIL */
+
+/* Define to 1 if `f_bfree' is member of `struct statfs'. */
+/* #undef HAVE_STRUCT_STATFS_F_BFREE */
+
+/* Define to 1 if `f_favail' is member of `struct statfs'. */
+/* #undef HAVE_STRUCT_STATFS_F_FAVAIL */
+
+/* Define to 1 if `f_ffree' is member of `struct statfs'. */
+/* #undef HAVE_STRUCT_STATFS_F_FFREE */
+
+/* Define to 1 if `f_frsize' is member of `struct statfs'. */
+/* #undef HAVE_STRUCT_STATFS_F_FRSIZE */
+
+/* Define to 1 if `f_namelen' is member of `struct statfs'. */
+/* #undef HAVE_STRUCT_STATFS_F_NAMELEN */
+
+/* Define to 1 if `f_blocks' is member of `struct statvfs'. */
+/* #undef HAVE_STRUCT_STATVFS_F_BLOCKS */
+
+/* Define to 1 if `st_blocks' is member of `struct stat'. */
+/* #undef HAVE_STRUCT_STAT_ST_BLOCKS */
+
+/* Define to 1 if you have the <syscall.h> header file. */
+/* #undef HAVE_SYSCALL_H */
+
+/* Define to 1 if you have the <sys/asoundlib.h> header file. */
+/* #undef HAVE_SYS_ASOUNDLIB_H */
+
+/* Define to 1 if you have the <sys/cdio.h> header file. */
+/* #undef HAVE_SYS_CDIO_H */
+
+/* Define to 1 if you have the <sys/elf32.h> header file. */
+/* #undef HAVE_SYS_ELF32_H */
+
+/* Define to 1 if you have the <sys/epoll.h> header file. */
+/* #undef HAVE_SYS_EPOLL_H */
+
+/* Define to 1 if you have the <sys/errno.h> header file. */
+/* #undef HAVE_SYS_ERRNO_H */
+
+/* Define to 1 if you have the <sys/exec_elf.h> header file. */
+/* #undef HAVE_SYS_EXEC_ELF_H */
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+/* #undef HAVE_SYS_FILIO_H */
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+/* #undef HAVE_SYS_IOCTL_H */
+
+/* Define to 1 if you have the <sys/ipc.h> header file. */
+/* #undef HAVE_SYS_IPC_H */
+
+/* Define to 1 if you have the <sys/link.h> header file. */
+/* #undef HAVE_SYS_LINK_H */
+
+/* Define to 1 if you have the <sys/lwp.h> header file. */
+/* #undef HAVE_SYS_LWP_H */
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+/* #undef HAVE_SYS_MMAN_H */
+
+/* Define to 1 if you have the <sys/modem.h> header file. */
+/* #undef HAVE_SYS_MODEM_H */
+
+/* Define to 1 if you have the <sys/mount.h> header file. */
+/* #undef HAVE_SYS_MOUNT_H */
+
+/* Define to 1 if you have the <sys/msg.h> header file. */
+/* #undef HAVE_SYS_MSG_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+/* #undef HAVE_SYS_POLL_H */
+
+/* Define to 1 if you have the <sys/ptrace.h> header file. */
+/* #undef HAVE_SYS_PTRACE_H */
+
+/* Define to 1 if you have the <sys/reg.h> header file. */
+/* #undef HAVE_SYS_REG_H */
+
+/* Define to 1 if you have the <sys/scsiio.h> header file. */
+/* #undef HAVE_SYS_SCSIIO_H */
+
+/* Define to 1 if you have the <sys/shm.h> header file. */
+/* #undef HAVE_SYS_SHM_H */
+
+/* Define to 1 if you have the <sys/signal.h> header file. */
+/* #undef HAVE_SYS_SIGNAL_H */
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+/* #undef HAVE_SYS_SOCKET_H */
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+/* #undef HAVE_SYS_SOCKIO_H */
+
+/* Define to 1 if you have the <sys/soundcard.h> header file. */
+/* #undef HAVE_SYS_SOUNDCARD_H */
+
+/* Define to 1 if you have the <sys/statfs.h> header file. */
+/* #undef HAVE_SYS_STATFS_H */
+
+/* Define to 1 if you have the <sys/statvfs.h> header file. */
+/* #undef HAVE_SYS_STATVFS_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/strtio.h> header file. */
+/* #undef HAVE_SYS_STRTIO_H */
+
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+/* #undef HAVE_SYS_SYSCALL_H */
+
+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+/* #undef HAVE_SYS_SYSCTL_H */
+
+/* Define to 1 if you have the <sys/times.h> header file. */
+/* #undef HAVE_SYS_TIMES_H */
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+/* #undef HAVE_SYS_UIO_H */
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+/* #undef HAVE_SYS_UN_H */
+
+/* Define to 1 if you have the <sys/user.h> header file. */
+/* #undef HAVE_SYS_USER_H */
+
+/* Define to 1 if you have the <sys/vfs.h> header file. */
+/* #undef HAVE_SYS_VFS_H */
+
+/* Define to 1 if you have the <sys/vm86.h> header file. */
+/* #undef HAVE_SYS_VM86_H */
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+/* #undef HAVE_SYS_WAIT_H */
+
+/* Define to 1 if you have the `tcgetattr' function. */
+/* #undef HAVE_TCGETATTR */
+
+/* Define to 1 if you have the <termios.h> header file. */
+/* #undef HAVE_TERMIOS_H */
+
+/* Define to 1 if you have the `timegm' function. */
+/* #undef HAVE_TIMEGM */
+
+/* Define to 1 if you have the <ucontext.h> header file. */
+/* #undef HAVE_UCONTEXT_H */
+
+/* Define to 1 if you have the <unicode/ubidi.h> header file. */
+/* #undef HAVE_UNICODE_UBIDI_H */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `usleep' function. */
+/* #undef HAVE_USLEEP */
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if you have the <valgrind/memcheck.h> header file. */
+/* #undef HAVE_VALGRIND_MEMCHECK_H */
+
+/* Define if we have va_copy */
+#define HAVE_VA_COPY 1
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define to 1 if you have the `wait4' function. */
+/* #undef HAVE_WAIT4 */
+
+/* Define to 1 if you have the `waitpid' function. */
+/* #undef HAVE_WAITPID */
+
+/* Define to 1 if you have the <X11/extensions/shape.h> header file. */
+/* #undef HAVE_X11_EXTENSIONS_SHAPE_H */
+
+/* Define to 1 if you have the <X11/extensions/xf86dga.h> header file. */
+/* #undef HAVE_X11_EXTENSIONS_XF86DGA_H */
+
+/* Define to 1 if you have the <X11/extensions/xf86vmode.h> header file. */
+/* #undef HAVE_X11_EXTENSIONS_XF86VMODE_H */
+
+/* Define to 1 if you have the <X11/extensions/XInput.h> header file. */
+/* #undef HAVE_X11_EXTENSIONS_XINPUT_H */
+
+/* Define to 1 if you have the <X11/extensions/Xrandr.h> header file. */
+/* #undef HAVE_X11_EXTENSIONS_XRANDR_H */
+
+/* Define to 1 if you have the <X11/extensions/Xrender.h> header file. */
+/* #undef HAVE_X11_EXTENSIONS_XRENDER_H */
+
+/* Define to 1 if you have the <X11/extensions/XShm.h> header file. */
+/* #undef HAVE_X11_EXTENSIONS_XSHM_H */
+
+/* Define to 1 if you have the <X11/XKBlib.h> header file. */
+/* #undef HAVE_X11_XKBLIB_H */
+
+/* Define to 1 if you have the <X11/Xlib.h> header file. */
+/* #undef HAVE_X11_XLIB_H */
+
+/* Define to 1 if you have the <X11/Xutil.h> header file. */
+/* #undef HAVE_X11_XUTIL_H */
+
+/* Define if you have the XKB extension */
+/* #undef HAVE_XKB */
+
+/* Define if Xrender has the XRenderSetPictureTransform function */
+/* #undef HAVE_XRENDERSETPICTURETRANSFORM */
+
+/* Define to 1 if you have the `_lwp_create' function. */
+/* #undef HAVE__LWP_CREATE */
+
+/* Define to 1 if you have the `_lwp_self' function. */
+/* #undef HAVE__LWP_SELF */
+
+/* Define to 1 if you have the `_pclose' function. */
+#define HAVE__PCLOSE 1
+
+/* Define to 1 if you have the `_popen' function. */
+#define HAVE__POPEN 1
+
+/* Define to 1 if you have the `_snprintf' function. */
+#define HAVE__SNPRINTF 1
+
+/* Define to 1 if you have the `_spawnvp' function. */
+#define HAVE__SPAWNVP 1
+
+/* Define to 1 if you have the `_stricmp' function. */
+#define HAVE__STRICMP 1
+
+/* Define to 1 if you have the `_strnicmp' function. */
+#define HAVE__STRNICMP 1
+
+/* Define to 1 if you have the `_vsnprintf' function. */
+#define HAVE__VSNPRINTF 1
+
+/* Define if we have __va_copy */
+#define HAVE___VA_COPY 1
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "wine-devel@winehq.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "Wine"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "Wine 20050211"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "wine"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "20050211"
+
+/* Define to the soname of the libcapi20 library. */
+/* #undef SONAME_LIBCAPI20 */
+
+/* Define to the soname of the libcrypto library. */
+/* #undef SONAME_LIBCRYPTO */
+
+/* Define to the soname of the libcups library. */
+/* #undef SONAME_LIBCUPS */
+
+/* Define to the soname of the libcurses library. */
+/* #undef SONAME_LIBCURSES */
+
+/* Define to the soname of the libfontconfig library. */
+/* #undef SONAME_LIBFONTCONFIG */
+
+/* Define to the soname of the libfreetype library. */
+/* #undef SONAME_LIBFREETYPE */
+
+/* Define to the soname of the libgif library. */
+/* #undef SONAME_LIBGIF */
+
+/* Define to the soname of the libGL library. */
+/* #undef SONAME_LIBGL */
+
+/* Define to the soname of the libjack library. */
+/* #undef SONAME_LIBJACK */
+
+/* Define to the soname of the libjpeg library. */
+/* #undef SONAME_LIBJPEG */
+
+/* Define to the soname of the liblcms library. */
+/* #undef SONAME_LIBLCMS */
+
+/* Define to the soname of the libncurses library. */
+/* #undef SONAME_LIBNCURSES */
+
+/* Define to the soname of the libssl library. */
+/* #undef SONAME_LIBSSL */
+
+/* Define to the soname of the libtxc_dxtn library. */
+/* #undef SONAME_LIBTXC_DXTN */
+
+/* Define to the soname of the libungif library. */
+/* #undef SONAME_LIBUNGIF */
+
+/* Define to the soname of the libX11 library. */
+/* #undef SONAME_LIBX11 */
+
+/* Define to the soname of the libXext library. */
+/* #undef SONAME_LIBXEXT */
+
+/* Define to the soname of the libXi library. */
+/* #undef SONAME_LIBXI */
+
+/* Define to the soname of the libXrandr library. */
+/* #undef SONAME_LIBXRANDR */
+
+/* Define to the soname of the libXrender library. */
+/* #undef SONAME_LIBXRENDER */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+       STACK_DIRECTION > 0 => grows toward higher addresses
+       STACK_DIRECTION < 0 => grows toward lower addresses
+       STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define if the struct statfs is defined by <sys/mount.h> */
+/* #undef STATFS_DEFINED_BY_SYS_MOUNT */
+
+/* Define if the struct statfs is defined by <sys/statfs.h> */
+/* #undef STATFS_DEFINED_BY_SYS_STATFS */
+
+/* Define if the struct statfs is defined by <sys/vfs.h> */
+/* #undef STATFS_DEFINED_BY_SYS_VFS */
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if the X Window System is missing or not being used. */
+#define X_DISPLAY_MISSING 1
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+   `char[]'. */
+#define YYTEXT_POINTER 1
+
+/* Set this to 64 to enable 64-bit file support on Linux */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define to a macro to generate an assembly function directive */
+#define __ASM_FUNC(name) ".def " __ASM_NAME(name) "; .scl 2; .type 32; .endef"
+
+/* Define to a macro to generate an assembly name from a C symbol */
+#define __ASM_NAME(name) "_" name
+
+/* Define to the assembler keyword used to specify a word value */
+#define __ASM_SHORT ".short"
+
+/* Define to the assembler keyword used to specify an ASCII string */
+#define __ASM_STRING ".string"
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
diff --git a/reactos/regtests/winetests/winetest/dist.rc b/reactos/regtests/winetests/winetest/dist.rc
new file mode 100644 (file)
index 0000000..50a2288
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Resources for the binary we distribute to testers
+ *
+ * Copyright 2004 Ferenc Wagner
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "winetest.rc"
+
+WINE_BUILD STRINGRES "build.id"
+BUILD_INFO STRINGRES "build.nfo"
+TESTS_URL  STRINGRES "tests.url"
diff --git a/reactos/regtests/winetests/winetest/gui.c b/reactos/regtests/winetests/winetest/gui.c
new file mode 100644 (file)
index 0000000..d766a62
--- /dev/null
@@ -0,0 +1,528 @@
+/*
+ * GUI support
+ *
+ * Copyright 2004 Ferenc Wagner
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <windows.h>
+#include <commctrl.h>
+
+#include "resource.h"
+#include "winetest.h"
+
+/* Event object to signal successful window creation to main thread.
+ */
+static HANDLE initEvent;
+
+/* Dialog handle
+ */
+static HWND dialog;
+
+/* Progress data for the text* functions and for scaling.
+ */
+static unsigned int progressMax, progressCurr;
+static double progressScale;
+
+/* Progress group counter for the gui* functions.
+ */
+static int progressGroup;
+
+static WNDPROC DefEditProc;
+
+static int
+MBdefault (int uType)
+{
+    static const int matrix[][4] = {{IDOK,    0,        0,        0},
+                                    {IDOK,    IDCANCEL, 0,        0},
+                                    {IDABORT, IDRETRY,  IDIGNORE, 0},
+                                    {IDYES,   IDNO,     IDCANCEL, 0},
+                                    {IDYES,   IDNO,     0,        0},
+                                    {IDRETRY, IDCANCEL, 0,        0}};
+    int type = uType & MB_TYPEMASK;
+    int def  = (uType & MB_DEFMASK) / MB_DEFBUTTON2;
+
+    return matrix[type][def];
+}
+
+/* report (R_STATUS, fmt, ...) */
+static int
+textStatus (va_list ap)
+{
+    char *str = vstrmake (NULL, ap);
+
+    fputs (str, stderr);
+    fputc ('\n', stderr);
+    free (str);
+    return 0;
+}
+
+static int
+guiStatus (va_list ap)
+{
+    size_t len;
+    char *str = vstrmake (&len, ap);
+
+    if (len > 128) str[129] = 0;
+    SetDlgItemText (dialog, IDC_SB, str);
+    free (str);
+    return 0;
+}
+
+/* report (R_PROGRESS, barnum, steps) */
+static int
+textProgress (va_list ap)
+{
+    progressGroup = va_arg (ap, int);
+    progressMax = va_arg (ap, int);
+    progressCurr = 0;
+    return 0;
+}
+
+static int
+guiProgress (va_list ap)
+{
+    unsigned int max;
+    HWND pb;
+
+    progressGroup = va_arg (ap, int);
+    progressMax = max = va_arg (ap, int);
+    progressCurr = 0;
+    if (max > 0xffff) {
+        progressScale = (double)0xffff / max;
+        max = 0xffff;
+    }
+    else progressScale = 1;
+    pb = GetDlgItem (dialog, IDC_PB0 + progressGroup * 2);
+    SendMessage (pb, PBM_SETRANGE, 0, MAKELPARAM (0, max));
+    SendMessage (pb, PBM_SETSTEP, (WPARAM)1, 0);
+    return 0;
+}
+
+/* report (R_STEP, fmt, ...) */
+static int
+textStep (va_list ap)
+{
+    char *str = vstrmake (NULL, ap);
+
+    progressCurr++;
+    fputs (str, stderr);
+    fprintf (stderr, " (%d of %d)\n", progressCurr, progressMax);
+    free (str);
+    return 0;
+}
+
+static int
+guiStep (va_list ap)
+{
+    const int pgID = IDC_ST0 + progressGroup * 2;
+    char *str = vstrmake (NULL, ap);
+    
+    progressCurr++;
+    SetDlgItemText (dialog, pgID, str);
+    SendDlgItemMessage (dialog, pgID+1, PBM_SETPOS,
+                        (WPARAM)(progressScale * progressCurr), 0);
+    free (str);
+    return 0;
+}
+
+/* report (R_DELTA, inc, fmt, ...) */
+static int
+textDelta (va_list ap)
+{
+    const int inc = va_arg (ap, int);
+    char *str = vstrmake (NULL, ap);
+
+    progressCurr += inc;
+    fputs (str, stderr);
+    fprintf (stderr, " (%d of %d)\n", progressCurr, progressMax);
+    free (str);
+    return 0;
+}
+
+static int
+guiDelta (va_list ap)
+{
+    const int inc = va_arg (ap, int);
+    const int pgID = IDC_ST0 + progressGroup * 2;
+    char *str = vstrmake (NULL, ap);
+
+    progressCurr += inc;
+    SetDlgItemText (dialog, pgID, str);
+    SendDlgItemMessage (dialog, pgID+1, PBM_SETPOS,
+                        (WPARAM)(progressScale * progressCurr), 0);
+    free (str);
+    return 0;
+}
+
+/* report (R_TAG) */
+static int
+textTag (va_list ap)
+{
+    fputs ("Tag: ", stderr);
+    fputs (tag, stderr);
+    fputc ('\n', stderr);
+    return 0;
+}
+
+static int
+guiTag (va_list ap)
+{
+    SetDlgItemText (dialog, IDC_TAG, tag);
+    return 0;
+}
+
+/* report (R_DIR, fmt, ...) */
+static int
+textDir (va_list ap)
+{
+    char *str = vstrmake (NULL, ap);
+
+    fputs ("Temporary directory: ", stderr);
+    fputs (str, stderr);
+    fputc ('\n', stderr);
+    free (str);
+    return 0;
+}
+
+static int
+guiDir (va_list ap)
+{
+    char *str = vstrmake (NULL, ap);
+
+    SetDlgItemText (dialog, IDC_DIR, str);
+    free (str);
+    return 0;
+}
+
+/* report (R_OUT, fmt, ...) */
+static int
+textOut (va_list ap)
+{
+    char *str = vstrmake (NULL, ap);
+
+    fputs ("Log file: ", stderr);
+    fputs (str, stderr);
+    fputc ('\n', stderr);
+    free (str);
+    return 0;
+}
+
+static int
+guiOut (va_list ap)
+{
+    char *str = vstrmake (NULL, ap);
+
+    SetDlgItemText (dialog, IDC_OUT, str);
+    free (str);
+    return 0;
+}
+
+/* report (R_WARNING, fmt, ...) */
+static int
+textWarning (va_list ap)
+{
+    fputs ("Warning: ", stderr);
+    textStatus (ap);
+    return 0;
+}
+
+static int
+guiWarning (va_list ap)
+{
+    char *str = vstrmake (NULL, ap);
+
+    MessageBox (dialog, str, "Warning", MB_ICONWARNING | MB_OK);
+    free (str);
+    return 0;
+}
+
+/* report (R_ERROR, fmt, ...) */
+static int
+textError (va_list ap)
+{
+    fputs ("Error: ", stderr);
+    textStatus (ap);
+    return 0;
+}
+
+static int
+guiError (va_list ap)
+{
+    char *str = vstrmake (NULL, ap);
+
+    MessageBox (dialog, str, "Error", MB_ICONERROR | MB_OK);
+    free (str);
+    return 0;
+}
+
+/* report (R_FATAL, fmt, ...) */
+static int
+textFatal (va_list ap)
+{
+    textError (ap);
+    exit (1);
+}
+
+static int
+guiFatal (va_list ap)
+{
+    guiError (ap);
+    exit (1);
+}
+
+/* report (R_ASK, type, fmt, ...) */
+static int
+textAsk (va_list ap)
+{
+    int uType = va_arg (ap, int);
+    int ret = MBdefault (uType);
+    char *str = vstrmake (NULL, ap);
+
+    fprintf (stderr, "Question of type %d: %s\n"
+             "Returning default: %d\n", uType, str, ret);
+    free (str);
+    return ret;
+}
+
+static int
+guiAsk (va_list ap)
+{
+    int uType = va_arg (ap, int);
+    char *str = vstrmake (NULL, ap);
+    int ret = MessageBox (dialog, str, "Question",
+                          MB_ICONQUESTION | uType);
+
+    free (str);
+    return ret;
+}
+
+static BOOL CALLBACK
+EditTagProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    switch (msg) {
+    case WM_CHAR:
+        if (wParam == 8) break; /* backspace is OK */
+        if (GetWindowTextLengthA (hwnd) == MAXTAGLEN ||
+            !goodtagchar (wParam)) return TRUE;
+        break;
+    }
+    return CallWindowProcA (DefEditProc, hwnd, msg, wParam, lParam);
+}
+
+static BOOL CALLBACK
+AskTagProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    int len;
+
+    switch (msg) {
+    case WM_INITDIALOG:
+        DefEditProc = (WNDPROC)SetWindowLongPtr
+            (GetDlgItem (hwnd, IDC_TAG), GWLP_WNDPROC, (LONG_PTR)EditTagProc);
+        return TRUE;
+    case WM_COMMAND:
+        switch (LOWORD (wParam)) {
+        case IDOK:
+            len = GetWindowTextLengthA (GetDlgItem (hwnd, IDC_TAG));
+            tag = xmalloc (len+1);
+            GetDlgItemTextA (hwnd, IDC_TAG, tag, len+1);
+            EndDialog (hwnd, IDOK);
+            return TRUE;
+        case IDABORT:
+            EndDialog (hwnd, IDABORT);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+int
+guiAskTag (void)
+{
+    return DialogBox (GetModuleHandle (NULL),
+                      MAKEINTRESOURCE (IDD_TAG),
+                      dialog, AskTagProc);
+}
+
+/* Quiet functions */
+static int
+qNoOp (va_list ap)
+{
+    return 0;
+}
+
+static int
+qFatal (va_list ap)
+{
+    exit (1);
+}
+
+static int
+qAsk (va_list ap)
+{
+    return MBdefault (va_arg (ap, int));
+}
+
+static BOOL CALLBACK
+AboutProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    switch (msg) {
+    case WM_COMMAND:
+        switch (LOWORD (wParam)) {
+        case IDCANCEL:
+            EndDialog (hwnd, IDCANCEL);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+static BOOL CALLBACK
+DlgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    switch (msg) {
+    case WM_INITDIALOG:
+        SendMessage (hwnd, WM_SETICON, ICON_SMALL,
+                     (LPARAM)LoadIcon (GetModuleHandle (NULL),
+                                       MAKEINTRESOURCE (IDI_WINE)));
+        SendMessage (hwnd, WM_SETICON, ICON_BIG,
+                     (LPARAM)LoadIcon (GetModuleHandle (NULL),
+                                       MAKEINTRESOURCE (IDI_WINE)));
+        dialog = hwnd;
+        if (!SetEvent (initEvent)) {
+            report (R_STATUS, "Can't signal main thread: %d",
+                    GetLastError ());
+            EndDialog (hwnd, 2);
+        }
+        return TRUE;
+    case WM_CLOSE:
+        EndDialog (hwnd, 3);
+        return TRUE;
+    case WM_COMMAND:
+        switch (LOWORD (wParam)) {
+        case IDHELP:
+            DialogBox (GetModuleHandle (NULL),
+                       MAKEINTRESOURCE (IDD_ABOUT), hwnd, AboutProc);
+            return TRUE;
+        case IDABORT:
+            report (R_WARNING, "Not implemented");
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+static DWORD WINAPI
+DlgThreadProc (LPVOID param)
+{
+    int ret;
+
+    InitCommonControls ();
+    ret = DialogBox (GetModuleHandle (NULL),
+                     MAKEINTRESOURCE (IDD_STATUS),
+                     NULL, DlgProc);
+    switch (ret) {
+    case 0:
+        report (R_WARNING, "Invalid parent handle");
+        break;
+    case 1:
+        report (R_WARNING, "DialogBox failed: %d",
+                GetLastError ());
+        break;
+    case 3:
+        exit (0);
+    default:
+        report (R_STATUS, "Dialog exited: %d", ret);
+    }
+    return 0;
+}
+
+int
+report (enum report_type t, ...)
+{
+    typedef int r_fun_t (va_list);
+
+    va_list ap;
+    int ret = 0;
+    static r_fun_t * const text_funcs[] =
+        {textStatus, textProgress, textStep, textDelta,
+         textTag, textDir, textOut,
+         textWarning, textError, textFatal, textAsk};
+    static r_fun_t * const GUI_funcs[] =
+        {guiStatus, guiProgress, guiStep, guiDelta,
+         guiTag, guiDir, guiOut,
+         guiWarning, guiError, guiFatal, guiAsk};
+    static r_fun_t * const quiet_funcs[] =
+        {qNoOp, qNoOp, qNoOp, qNoOp,
+         qNoOp, qNoOp, qNoOp,
+         qNoOp, qNoOp, qFatal, qAsk};
+    static r_fun_t * const * funcs = NULL;
+
+    switch (t) {
+    case R_TEXTMODE:
+        funcs = text_funcs;
+        return 0;
+    case R_QUIET:
+        funcs = quiet_funcs;
+        return 0;
+    default:
+        break;
+    }
+
+    if (!funcs) {
+        HANDLE DlgThread;
+        DWORD DlgThreadID;
+
+        funcs = text_funcs;
+        initEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+        if (!initEvent)
+            report (R_STATUS, "Can't create event object: %d",
+                    GetLastError ());
+        else {
+            DlgThread = CreateThread (NULL, 0, DlgThreadProc,
+                                      NULL, 0, &DlgThreadID);
+            if (!DlgThread)
+                report (R_STATUS, "Can't create GUI thread: %d",
+                        GetLastError ());
+            else {
+                DWORD ret = WaitForSingleObject (initEvent, INFINITE);
+                switch (ret) {
+                case WAIT_OBJECT_0:
+                    funcs = GUI_funcs;
+                    break;
+                case WAIT_TIMEOUT:
+                    report (R_STATUS, "GUI creation timed out");
+                    break;
+                case WAIT_FAILED:
+                    report (R_STATUS, "Wait for GUI failed: %d",
+                            GetLastError ());
+                    break;
+                default:
+                    report (R_STATUS, "Wait returned %d",
+                            ret);
+                    break;
+                }
+            }
+        }
+    }
+        
+    va_start (ap, t);
+    if (t < sizeof text_funcs / sizeof text_funcs[0] &&
+        t < sizeof GUI_funcs / sizeof GUI_funcs[0]) ret = funcs[t](ap);
+    else report (R_WARNING, "unimplemented report type: %d", t);
+    va_end (ap);
+    return ret;
+}
diff --git a/reactos/regtests/winetests/winetest/main.c b/reactos/regtests/winetests/winetest/main.c
new file mode 100644 (file)
index 0000000..01b2e91
--- /dev/null
@@ -0,0 +1,651 @@
+/*
+ * Wine Conformance Test EXE
+ *
+ * Copyright 2003, 2004 Jakob Eriksson   (for Solid Form Sweden AB)
+ * Copyright 2003 Dimitrie O. Paun
+ * Copyright 2003 Ferenc Wagner
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * This program is dedicated to Anna Lindh,
+ * Swedish Minister of Foreign Affairs.
+ * Anna was murdered September 11, 2003.
+ *
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+#include <windows.h>
+
+#include "winetest.h"
+#include "resource.h"
+
+struct wine_test
+{
+    char *name;
+    int resource;
+    int subtest_count;
+    char **subtests;
+    char *exename;
+};
+
+struct rev_info
+{
+    const char* file;
+    const char* rev;
+};
+
+char *tag = NULL;
+static struct wine_test *wine_tests;
+static struct rev_info *rev_infos = NULL;
+static const char whitespace[] = " \t\r\n";
+
+static int running_under_wine (void)
+{
+    HMODULE module = GetModuleHandleA("ntdll.dll");
+
+    if (!module) return 0;
+    return (GetProcAddress(module, "wine_server_call") != NULL);
+}
+
+static int running_on_visible_desktop (void)
+{
+    HWND desktop;
+    HMODULE huser32 = GetModuleHandle("user32.dll");
+    FARPROC pGetProcessWindowStation = GetProcAddress(huser32, "GetProcessWindowStation");
+    FARPROC pGetUserObjectInformationA = GetProcAddress(huser32, "GetUserObjectInformationA");
+
+    desktop = GetDesktopWindow();
+    if (!GetWindowLongPtrW(desktop, GWLP_WNDPROC)) /* Win9x */
+        return IsWindowVisible(desktop);
+
+    if (pGetProcessWindowStation && pGetUserObjectInformationA)
+    {
+        DWORD len;
+        HWINSTA wstation;
+        USEROBJECTFLAGS uoflags;
+
+        wstation = (HWINSTA)pGetProcessWindowStation();
+        assert(pGetUserObjectInformationA(wstation, UOI_FLAGS, &uoflags, sizeof(uoflags), &len));
+        return (uoflags.dwFlags & WSF_VISIBLE) != 0;
+    }
+    return IsWindowVisible(desktop);
+}
+
+static void print_version (void)
+{
+    OSVERSIONINFOEX ver;
+    BOOL ext;
+
+    ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+    if (!(ext = GetVersionEx ((OSVERSIONINFO *) &ver)))
+    {
+       ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+       if (!GetVersionEx ((OSVERSIONINFO *) &ver))
+           report (R_FATAL, "Can't get OS version.");
+    }
+
+    xprintf ("    bRunningUnderWine=%d\n", running_under_wine ());
+    xprintf ("    bRunningOnVisibleDesktop=%d\n", running_on_visible_desktop ());
+    xprintf ("    dwMajorVersion=%ld\n    dwMinorVersion=%ld\n"
+             "    dwBuildNumber=%ld\n    PlatformId=%ld\n    szCSDVersion=%s\n",
+             ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,
+             ver.dwPlatformId, ver.szCSDVersion);
+
+    if (!ext) return;
+
+    xprintf ("    wServicePackMajor=%d\n    wServicePackMinor=%d\n"
+             "    wSuiteMask=%d\n    wProductType=%d\n    wReserved=%d\n",
+             ver.wServicePackMajor, ver.wServicePackMinor, ver.wSuiteMask,
+             ver.wProductType, ver.wReserved);
+}
+
+static inline int is_dot_dir(const char* x)
+{
+    return ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))));
+}
+
+static void remove_dir (const char *dir)
+{
+    HANDLE  hFind;
+    WIN32_FIND_DATA wfd;
+    char path[MAX_PATH];
+    size_t dirlen = strlen (dir);
+
+    /* Make sure the directory exists before going further */
+    memcpy (path, dir, dirlen);
+    strcpy (path + dirlen++, "\\*");
+    hFind = FindFirstFile (path, &wfd);
+    if (hFind == INVALID_HANDLE_VALUE) return;
+
+    do {
+        char *lp = wfd.cFileName;
+
+        if (!lp[0]) lp = wfd.cAlternateFileName; /* ? FIXME not (!lp) ? */
+        if (is_dot_dir (lp)) continue;
+        strcpy (path + dirlen, lp);
+        if (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)
+            remove_dir(path);
+        else if (!DeleteFile (path))
+            report (R_WARNING, "Can't delete file %s: error %d",
+                    path, GetLastError ());
+    } while (FindNextFile (hFind, &wfd));
+    FindClose (hFind);
+    if (!RemoveDirectory (dir))
+        report (R_WARNING, "Can't remove directory %s: error %d",
+                dir, GetLastError ());
+}
+
+static const char* get_test_source_file(const char* test, const char* subtest)
+{
+    static const char* special_dirs[][2] = {
+       { "gdi32", "gdi"}, { "kernel32", "kernel" },
+        { "msacm32", "msacm" },
+       { "user32", "user" }, { "winspool.drv", "winspool" },
+       { "ws2_32", "winsock" }, { 0, 0 }
+    };
+    static char buffer[MAX_PATH];
+    int i;
+
+    for (i = 0; special_dirs[i][0]; i++) {
+       if (strcmp(test, special_dirs[i][0]) == 0) {
+           test = special_dirs[i][1];
+           break;
+       }
+    }
+
+    snprintf(buffer, sizeof(buffer), "dlls/%s/tests/%s.c", test, subtest);
+    return buffer;
+}
+
+static const char* get_file_rev(const char* file)
+{
+    const struct rev_info* rev;
+    for(rev = rev_infos; rev->file; rev++) {
+       if (strcmp(rev->file, file) == 0) return rev->rev;
+    }
+
+    return "-";
+}
+
+static void extract_rev_infos (void)
+{
+    char revinfo[256], *p;
+    int size = 0, i;
+    unsigned int len;
+    HMODULE module = GetModuleHandle (NULL);
+
+    for (i = 0; TRUE; i++) {
+       if (i >= size) {
+           size += 100;
+           rev_infos = xrealloc (rev_infos, size * sizeof (*rev_infos));
+       }
+       memset(rev_infos + i, 0, sizeof(rev_infos[i]));
+
+        len = LoadStringA (module, REV_INFO+i, revinfo, sizeof(revinfo));
+        if (len == 0) break; /* end of revision info */
+       if (len >= sizeof(revinfo) - 1) 
+           report (R_FATAL, "Revision info too long.");
+       if(!(p = strrchr(revinfo, ':')))
+           report (R_FATAL, "Revision info malformed (i=%d)", i);
+       *p = 0;
+       rev_infos[i].file = strdup(revinfo);
+       rev_infos[i].rev = strdup(p + 1);
+    }
+}
+
+static void* extract_rcdata (int id, int type, DWORD* size)
+{
+    HRSRC rsrc;
+    HGLOBAL hdl;
+    LPVOID addr;
+    
+    if (!(rsrc = FindResource (NULL, (LPTSTR)id, MAKEINTRESOURCE(type))) ||
+        !(*size = SizeofResource (0, rsrc)) ||
+        !(hdl = LoadResource (0, rsrc)) ||
+        !(addr = LockResource (hdl)))
+        return NULL;
+    return addr;
+}
+
+/* Fills in the name and exename fields */
+static void
+extract_test (struct wine_test *test, const char *dir, int id)
+{
+    BYTE* code;
+    DWORD size;
+    FILE* fout;
+    int strlen, bufflen = 128;
+    char *exepos;
+
+    code = extract_rcdata (id, TESTRES, &size);
+    if (!code) report (R_FATAL, "Can't find test resource %d: %d",
+                       id, GetLastError ());
+    test->name = xmalloc (bufflen);
+    while ((strlen = LoadStringA (NULL, id, test->name, bufflen))
+           == bufflen - 1) {
+        bufflen *= 2;
+        test->name = xrealloc (test->name, bufflen);
+    }
+    if (!strlen) report (R_FATAL, "Can't read name of test %d.", id);
+    test->exename = strmake (NULL, "%s/%s", dir, test->name);
+    exepos = strstr (test->name, "_test.exe");
+    if (!exepos) report (R_FATAL, "Not an .exe file: %s", test->name);
+    *exepos = 0;
+    test->name = xrealloc (test->name, exepos - test->name + 1);
+    report (R_STEP, "Extracting: %s", test->name);
+
+    if (!(fout = fopen (test->exename, "wb")) ||
+        (fwrite (code, size, 1, fout) != 1) ||
+        fclose (fout)) report (R_FATAL, "Failed to write file %s.",
+                               test->exename);
+}
+
+/* Run a command for MS milliseconds.  If OUT != NULL, also redirect
+   stdout to there.
+
+   Return the exit status, -2 if can't create process or the return
+   value of WaitForSingleObject.
+ */
+static int
+run_ex (char *cmd, const char *out, DWORD ms)
+{
+    STARTUPINFO si;
+    PROCESS_INFORMATION pi;
+    int fd, oldstdout = -1;
+    DWORD wait, status;
+
+    GetStartupInfo (&si);
+    si.wShowWindow = SW_HIDE;
+    si.dwFlags = STARTF_USESHOWWINDOW;
+
+    if (out) {
+        fd = open (out, O_WRONLY | O_CREAT, 0666);
+        if (-1 == fd)
+            report (R_FATAL, "Can't open '%s': %d", out, errno);
+        oldstdout = dup (1);
+        if (-1 == oldstdout)
+            report (R_FATAL, "Can't save stdout: %d", errno);
+        if (-1 == dup2 (fd, 1))
+            report (R_FATAL, "Can't redirect stdout: %d", errno);
+        close (fd);
+    }
+
+    if (!CreateProcessA (NULL, cmd, NULL, NULL, TRUE, 0,
+                         NULL, NULL, &si, &pi)) {
+        status = -2;
+    } else {
+        CloseHandle (pi.hThread);
+        wait = WaitForSingleObject (pi.hProcess, ms);
+        if (wait == WAIT_OBJECT_0) {
+            GetExitCodeProcess (pi.hProcess, &status);
+        } else {
+            switch (wait) {
+            case WAIT_FAILED:
+                report (R_ERROR, "Wait for '%s' failed: %d", cmd,
+                        GetLastError ());
+                break;
+            case WAIT_TIMEOUT:
+                report (R_ERROR, "Process '%s' timed out.", cmd);
+                break;
+            default:
+                report (R_ERROR, "Wait returned %d", wait);
+            }
+            status = wait;
+            if (!TerminateProcess (pi.hProcess, 257))
+                report (R_ERROR, "TerminateProcess failed: %d",
+                        GetLastError ());
+            wait = WaitForSingleObject (pi.hProcess, 5000);
+            switch (wait) {
+            case WAIT_FAILED:
+                report (R_ERROR,
+                        "Wait for termination of '%s' failed: %d",
+                        cmd, GetLastError ());
+                break;
+            case WAIT_OBJECT_0:
+                break;
+            case WAIT_TIMEOUT:
+                report (R_ERROR, "Can't kill process '%s'", cmd);
+                break;
+            default:
+                report (R_ERROR, "Waiting for termination: %d",
+                        wait);
+            }
+        }
+        CloseHandle (pi.hProcess);
+    }
+
+    if (out) {
+        close (1);
+        if (-1 == dup2 (oldstdout, 1))
+            report (R_FATAL, "Can't recover stdout: %d", errno);
+        close (oldstdout);
+    }
+    return status;
+}
+
+static void
+get_subtests (const char *tempdir, struct wine_test *test, int id)
+{
+    char *subname, *cmd;
+    FILE *subfile;
+    size_t total;
+    char buffer[8192], *index;
+    static const char header[] = "Valid test names:";
+    int allocated;
+
+    test->subtest_count = 0;
+
+    subname = tempnam (0, "sub");
+    if (!subname) report (R_FATAL, "Can't name subtests file.");
+
+    extract_test (test, tempdir, id);
+    cmd = strmake (NULL, "%s --list", test->exename);
+    run_ex (cmd, subname, 5000);
+    free (cmd);
+
+    subfile = fopen (subname, "r");
+    if (!subfile) {
+        report (R_ERROR, "Can't open subtests output of %s: %d",
+                test->name, errno);
+        goto quit;
+    }
+    total = fread (buffer, 1, sizeof buffer, subfile);
+    fclose (subfile);
+    if (sizeof buffer == total) {
+        report (R_ERROR, "Subtest list of %s too big.",
+                test->name, sizeof buffer);
+        goto quit;
+    }
+    buffer[total] = 0;
+
+    index = strstr (buffer, header);
+    if (!index) {
+        report (R_ERROR, "Can't parse subtests output of %s",
+                test->name);
+        goto quit;
+    }
+    index += sizeof header;
+
+    allocated = 10;
+    test->subtests = xmalloc (allocated * sizeof(char*));
+    index = strtok (index, whitespace);
+    while (index) {
+        if (test->subtest_count == allocated) {
+            allocated *= 2;
+            test->subtests = xrealloc (test->subtests,
+                                       allocated * sizeof(char*));
+        }
+        test->subtests[test->subtest_count++] = strdup (index);
+        index = strtok (NULL, whitespace);
+    }
+    test->subtests = xrealloc (test->subtests,
+                               test->subtest_count * sizeof(char*));
+
+ quit:
+    if (remove (subname))
+        report (R_WARNING, "Can't delete file '%s': %d",
+                subname, errno);
+    free (subname);
+}
+
+static void
+run_test (struct wine_test* test, const char* subtest)
+{
+    int status;
+    const char* file = get_test_source_file(test->name, subtest);
+    const char* rev = get_file_rev(file);
+    char *cmd = strmake (NULL, "%s %s", test->exename, subtest);
+
+    xprintf ("%s:%s start %s %s\n", test->name, subtest, file, rev);
+    status = run_ex (cmd, NULL, 120000);
+    free (cmd);
+    xprintf ("%s:%s done (%d)\n", test->name, subtest, status);
+}
+
+static BOOL CALLBACK
+EnumTestFileProc (HMODULE hModule, LPCTSTR lpszType,
+                  LPTSTR lpszName, LONG_PTR lParam)
+{
+    (*(int*)lParam)++;
+    return TRUE;
+}
+
+static char *
+run_tests (char *logname)
+{
+    int nr_of_files = 0, nr_of_tests = 0, i;
+    char *tempdir, *shorttempdir;
+    int logfile;
+    char *strres, *eol, *nextline;
+    DWORD strsize;
+
+    SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
+
+    if (!logname) {
+        logname = tempnam (0, "res");
+        if (!logname) report (R_FATAL, "Can't name logfile.");
+    }
+    report (R_OUT, logname);
+
+    logfile = open (logname, O_WRONLY | O_CREAT | O_EXCL | O_APPEND,
+                    0666);
+    if (-1 == logfile) {
+        if (EEXIST == errno)
+            report (R_FATAL, "File %s already exists.", logname);
+        else report (R_FATAL, "Could not open logfile: %d", errno);
+    }
+    if (-1 == dup2 (logfile, 1))
+        report (R_FATAL, "Can't redirect stdout: %d", errno);
+    close (logfile);
+
+    tempdir = tempnam (0, "wct");
+    if (!tempdir)
+        report (R_FATAL, "Can't name temporary dir (check %%TEMP%%).");
+    shorttempdir = strdup (tempdir);
+    if (shorttempdir) {         /* try stable path for ZoneAlarm */
+        strstr (shorttempdir, "wct")[3] = 0;
+        if (CreateDirectoryA (shorttempdir, NULL)) {
+            free (tempdir);
+            tempdir = shorttempdir;
+        } else free (shorttempdir);
+    }
+    if (tempdir != shorttempdir && !CreateDirectoryA (tempdir, NULL))
+        report (R_FATAL, "Could not create directory: %s", tempdir);
+    report (R_DIR, tempdir);
+
+    xprintf ("Version 3\n");
+    strres = extract_rcdata (WINE_BUILD, STRINGRES, &strsize);
+    xprintf ("Tests from build ");
+    if (strres) xprintf ("%.*s", strsize, strres);
+    else xprintf ("-\n");
+    strres = extract_rcdata (TESTS_URL, STRINGRES, &strsize);
+    xprintf ("Archive: ");
+    if (strres) xprintf ("%.*s", strsize, strres);
+    else xprintf ("-\n");
+    xprintf ("Tag: %s\n", tag);
+    xprintf ("Build info:\n");
+    strres = extract_rcdata (BUILD_INFO, STRINGRES, &strsize);
+    while (strres) {
+        eol = memchr (strres, '\n', strsize);
+        if (!eol) {
+            nextline = NULL;
+            eol = strres + strsize;
+        } else {
+            strsize -= eol - strres + 1;
+            nextline = strsize?eol+1:NULL;
+            if (eol > strres && *(eol-1) == '\r') eol--;
+        }
+        xprintf ("    %.*s\n", eol-strres, strres);
+        strres = nextline;
+    }
+    xprintf ("Operating system version:\n");
+    print_version ();
+    xprintf ("Test output:\n" );
+
+    report (R_STATUS, "Counting tests");
+    if (!EnumResourceNames (NULL, MAKEINTRESOURCE(TESTRES),
+                            EnumTestFileProc, (LPARAM)&nr_of_files))
+        report (R_FATAL, "Can't enumerate test files: %d",
+                GetLastError ());
+    wine_tests = xmalloc (nr_of_files * sizeof wine_tests[0]);
+
+    report (R_STATUS, "Extracting tests");
+    report (R_PROGRESS, 0, nr_of_files);
+    for (i = 0; i < nr_of_files; i++) {
+        get_subtests (tempdir, wine_tests+i, i);
+        nr_of_tests += wine_tests[i].subtest_count;
+    }
+    report (R_DELTA, 0, "Extracting: Done");
+
+    report (R_STATUS, "Running tests");
+    report (R_PROGRESS, 1, nr_of_tests);
+    for (i = 0; i < nr_of_files; i++) {
+        struct wine_test *test = wine_tests + i;
+        int j;
+
+       for (j = 0; j < test->subtest_count; j++) {
+            report (R_STEP, "Running: %s:%s", test->name,
+                    test->subtests[j]);
+           run_test (test, test->subtests[j]);
+        }
+    }
+    report (R_DELTA, 0, "Running: Done");
+
+    report (R_STATUS, "Cleaning up");
+    close (1);
+    remove_dir (tempdir);
+    free (tempdir);
+    free (wine_tests);
+
+    return logname;
+}
+
+static void
+usage (void)
+{
+    fprintf (stderr, "\
+Usage: winetest [OPTION]...\n\n\
+  -c       console mode, no GUI\n\
+  -e       preserve the environment\n\
+  -h       print this message and exit\n\
+  -q       quiet mode, no output at all\n\
+  -o FILE  put report into FILE, do not submit\n\
+  -s FILE  submit FILE, do not run tests\n\
+  -t TAG   include TAG of characters [-.0-9a-zA-Z] in the report\n");
+}
+
+int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInst,
+                    LPSTR cmdLine, int cmdShow)
+{
+    char *logname = NULL;
+    const char *cp, *submit = NULL;
+    int reset_env = 1;
+    int interactive = 1;
+
+    /* initialize the revision information first */
+    extract_rev_infos();
+
+    cmdLine = strtok (cmdLine, whitespace);
+    while (cmdLine) {
+        if (cmdLine[0] != '-' || cmdLine[2]) {
+            report (R_ERROR, "Not a single letter option: %s", cmdLine);
+            usage ();
+            exit (2);
+        }
+        switch (cmdLine[1]) {
+        case 'c':
+            report (R_TEXTMODE);
+            interactive = 0;
+            break;
+        case 'e':
+            reset_env = 0;
+            break;
+        case 'h':
+            usage ();
+            exit (0);
+        case 'q':
+            report (R_QUIET);
+            interactive = 0;
+            break;
+        case 's':
+            submit = strtok (NULL, whitespace);
+            if (tag)
+                report (R_WARNING, "ignoring tag for submission");
+            send_file (submit);
+            break;
+        case 'o':
+            logname = strtok (NULL, whitespace);
+            break;
+        case 't':
+            tag = strtok (NULL, whitespace);
+            if (strlen (tag) > MAXTAGLEN)
+                report (R_FATAL, "tag is too long (maximum %d characters)",
+                        MAXTAGLEN);
+            cp = findbadtagchar (tag);
+            if (cp) {
+                report (R_ERROR, "invalid char in tag: %c", *cp);
+                usage ();
+                exit (2);
+            }
+            break;
+        default:
+            report (R_ERROR, "invalid option: -%c", cmdLine[1]);
+            usage ();
+            exit (2);
+        }
+        cmdLine = strtok (NULL, whitespace);
+    }
+    if (!submit) {
+        report (R_STATUS, "Starting up");
+
+        if (!running_on_visible_desktop ())
+            report (R_FATAL, "Tests must be run on a visible desktop");
+
+        if (reset_env && (putenv ("WINETEST_PLATFORM=windows") ||
+                          putenv ("WINETEST_DEBUG=1") || 
+                          putenv ("WINETEST_INTERACTIVE=0") ||
+                          putenv ("WINETEST_REPORT_SUCCESS=0")))
+            report (R_FATAL, "Could not reset environment: %d", errno);
+
+        if (!tag) {
+            if (!interactive)
+                report (R_FATAL, "Please specify a tag (-t option) if "
+                        "running noninteractive!");
+            if (guiAskTag () == IDABORT) exit (1);
+        }
+        report (R_TAG);
+
+        if (!logname) {
+            logname = run_tests (NULL);
+            if (report (R_ASK, MB_YESNO, "Do you want to submit the "
+                        "test results?") == IDYES)
+                if (!send_file (logname) && remove (logname))
+                    report (R_WARNING, "Can't remove logfile: %d.", errno);
+            free (logname);
+        } else run_tests (logname);
+        report (R_STATUS, "Finished");
+    }
+    exit (0);
+}
diff --git a/reactos/regtests/winetests/winetest/port.h b/reactos/regtests/winetests/winetest/port.h
new file mode 100644 (file)
index 0000000..5b3d858
--- /dev/null
@@ -0,0 +1,469 @@
+/*
+ * Wine porting definitions
+ *
+ * Copyright 1996 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __WINE_WINE_PORT_H
+#define __WINE_WINE_PORT_H
+
+#ifndef __WINE_CONFIG_H
+# error You must include config.h to use this header
+#endif
+
+#define _GNU_SOURCE  /* for pread/pwrite */
+#include <fcntl.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_DIRECT_H
+# include <direct.h>
+#endif
+#ifdef HAVE_IO_H
+# include <io.h>
+#endif
+#ifdef HAVE_PROCESS_H
+# include <process.h>
+#endif
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+
+/****************************************************************
+ * Type definitions
+ */
+
+#ifndef HAVE_MODE_T
+typedef int mode_t;
+#endif
+#ifndef HAVE_OFF_T
+typedef long off_t;
+#endif
+#ifndef HAVE_PID_T
+typedef int pid_t;
+#endif
+#ifndef HAVE_SIZE_T
+typedef unsigned int size_t;
+#endif
+#ifndef HAVE_SSIZE_T
+typedef int ssize_t;
+#endif
+#ifndef HAVE_FSBLKCNT_T
+typedef unsigned long fsblkcnt_t;
+#endif
+#ifndef HAVE_FSFILCNT_T
+typedef unsigned long fsfilcnt_t;
+#endif
+
+#ifndef HAVE_STRUCT_STATVFS_F_BLOCKS
+struct statvfs
+{
+    unsigned long f_bsize;
+    unsigned long f_frsize;
+    fsblkcnt_t    f_blocks;
+    fsblkcnt_t    f_bfree;
+    fsblkcnt_t    f_bavail;
+    fsfilcnt_t    f_files;
+    fsfilcnt_t    f_ffree;
+    fsfilcnt_t    f_favail;
+    unsigned long f_fsid;
+    unsigned long f_flag;
+    unsigned long f_namemax;
+};
+#endif /* HAVE_STRUCT_STATVFS_F_BLOCKS */
+
+
+/****************************************************************
+ * Macro definitions
+ */
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#else
+#define RTLD_LAZY    0x001
+#define RTLD_NOW     0x002
+#define RTLD_GLOBAL  0x100
+#endif
+
+#if !defined(HAVE_FTRUNCATE) && defined(HAVE_CHSIZE)
+#define ftruncate chsize
+#endif
+
+#if !defined(HAVE_POPEN) && defined(HAVE__POPEN)
+#define popen _popen
+#endif
+
+#if !defined(HAVE_PCLOSE) && defined(HAVE__PCLOSE)
+#define pclose _pclose
+#endif
+
+#if !defined(HAVE_SNPRINTF) && defined(HAVE__SNPRINTF)
+#define snprintf _snprintf
+#endif
+
+#if !defined(HAVE_VSNPRINTF) && defined(HAVE__VSNPRINTF)
+#define vsnprintf _vsnprintf
+#endif
+
+#ifndef S_ISLNK
+# define S_ISLNK(mod) (0)
+#endif
+
+#ifndef S_ISSOCK
+# define S_ISSOCK(mod) (0)
+#endif
+
+#ifndef S_ISDIR
+# define S_ISDIR(mod) (((mod) & _S_IFMT) == _S_IFDIR)
+#endif
+
+#ifndef S_ISCHR
+# define S_ISCHR(mod) (((mod) & _S_IFMT) == _S_IFCHR)
+#endif
+
+#ifndef S_ISFIFO
+# define S_ISFIFO(mod) (((mod) & _S_IFMT) == _S_IFIFO)
+#endif
+
+#ifndef S_ISREG
+# define S_ISREG(mod) (((mod) & _S_IFMT) == _S_IFREG)
+#endif
+
+#ifndef S_IWUSR
+# define S_IWUSR 0
+#endif
+
+/* So we open files in 64 bit access mode on Linux */
+#ifndef O_LARGEFILE
+# define O_LARGEFILE 0
+#endif
+
+#ifndef O_NONBLOCK
+# define O_NONBLOCK 0
+#endif
+
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+#if !defined(S_IXUSR) && defined(S_IEXEC)
+# define S_IXUSR S_IEXEC
+#endif
+#if !defined(S_IXGRP) && defined(S_IEXEC)
+# define S_IXGRP S_IEXEC
+#endif
+#if !defined(S_IXOTH) && defined(S_IEXEC)
+# define S_IXOTH S_IEXEC
+#endif
+
+
+/****************************************************************
+ * Constants
+ */
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#ifndef M_PI_2
+#define M_PI_2 1.570796326794896619
+#endif
+
+
+/* Macros to define assembler functions somewhat portably */
+
+#if defined(__GNUC__) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(__APPLE__)
+# define __ASM_GLOBAL_FUNC(name,code) \
+      __asm__( ".text\n\t" \
+               ".align 4\n\t" \
+               ".globl " __ASM_NAME(#name) "\n\t" \
+               __ASM_FUNC(#name) "\n" \
+               __ASM_NAME(#name) ":\n\t" \
+               code \
+               "\n\t.previous" );
+#else  /* defined(__GNUC__) && !defined(__MINGW32__) && !defined(__APPLE__)  */
+# define __ASM_GLOBAL_FUNC(name,code) \
+      void __asm_dummy_##name(void) { \
+          asm( ".align 4\n\t" \
+               ".globl " __ASM_NAME(#name) "\n\t" \
+               __ASM_FUNC(#name) "\n" \
+               __ASM_NAME(#name) ":\n\t" \
+               code ); \
+      }
+#endif  /* __GNUC__ */
+
+
+/* Constructor functions */
+
+#ifdef __GNUC__
+# define DECL_GLOBAL_CONSTRUCTOR(func) \
+    static void func(void) __attribute__((constructor)); \
+    static void func(void)
+#elif defined(__i386__)
+# define DECL_GLOBAL_CONSTRUCTOR(func) \
+    static void __dummy_init_##func(void) { \
+        asm(".section .init,\"ax\"\n\t" \
+            "call " #func "\n\t" \
+            ".previous"); } \
+    static void func(void)
+#elif defined(__sparc__)
+# define DECL_GLOBAL_CONSTRUCTOR(func) \
+    static void __dummy_init_##func(void) { \
+        asm("\t.section \".init\",#alloc,#execinstr\n" \
+            "\tcall " #func "\n" \
+            "\tnop\n" \
+            "\t.section \".text\",#alloc,#execinstr\n" ); } \
+    static void func(void)
+#else
+# error You must define the DECL_GLOBAL_CONSTRUCTOR macro for your platform
+#endif
+
+
+/* Register functions */
+
+#ifdef __i386__
+#define DEFINE_REGS_ENTRYPOINT( name, fn, args, pop_args ) \
+    __ASM_GLOBAL_FUNC( name, \
+                       "call " __ASM_NAME("__wine_call_from_32_regs") "\n\t" \
+                       ".long " __ASM_NAME(#fn) "\n\t" \
+                       ".byte " #args "," #pop_args )
+/* FIXME: add support for other CPUs */
+#endif  /* __i386__ */
+
+
+/****************************************************************
+ * Function definitions (only when using libwine_port)
+ */
+
+#ifndef NO_LIBWINE_PORT
+
+#ifndef HAVE_FSTATVFS
+int fstatvfs( int fd, struct statvfs *buf );
+#endif
+
+#ifndef HAVE_GETOPT_LONG
+extern char *optarg;
+extern int optind;
+extern int opterr;
+extern int optopt;
+struct option;
+
+#ifndef HAVE_STRUCT_OPTION_NAME
+struct option
+{
+    const char *name;
+    int has_arg;
+    int *flag;
+    int val;
+};
+#endif
+
+extern int getopt_long (int ___argc, char *const *___argv,
+                        const char *__shortopts,
+                        const struct option *__longopts, int *__longind);
+extern int getopt_long_only (int ___argc, char *const *___argv,
+                             const char *__shortopts,
+                             const struct option *__longopts, int *__longind);
+#endif  /* HAVE_GETOPT_LONG */
+
+#ifndef HAVE_FFS
+int ffs( int x );
+#endif
+
+#ifndef HAVE_FUTIMES
+struct timeval;
+int futimes(int fd, const struct timeval tv[2]);
+#endif
+
+#ifndef HAVE_GETPAGESIZE
+size_t getpagesize(void);
+#endif  /* HAVE_GETPAGESIZE */
+
+#ifndef HAVE_GETTID
+pid_t gettid(void);
+#endif /* HAVE_GETTID */
+
+#ifndef HAVE_LSTAT
+int lstat(const char *file_name, struct stat *buf);
+#endif /* HAVE_LSTAT */
+
+#ifndef HAVE_MEMMOVE
+void *memmove(void *dest, const void *src, size_t len);
+#endif /* !defined(HAVE_MEMMOVE) */
+
+#ifndef HAVE_PREAD
+ssize_t pread( int fd, void *buf, size_t count, off_t offset );
+#endif /* HAVE_PREAD */
+
+#ifndef HAVE_PWRITE
+ssize_t pwrite( int fd, const void *buf, size_t count, off_t offset );
+#endif /* HAVE_PWRITE */
+
+#ifndef HAVE_READLINK
+int readlink( const char *path, char *buf, size_t size );
+#endif /* HAVE_READLINK */
+
+#ifndef HAVE_SIGSETJMP
+# include <setjmp.h>
+typedef jmp_buf sigjmp_buf;
+int sigsetjmp( sigjmp_buf buf, int savesigs );
+void siglongjmp( sigjmp_buf buf, int val );
+#endif /* HAVE_SIGSETJMP */
+
+#ifndef HAVE_STATVFS
+int statvfs( const char *path, struct statvfs *buf );
+#endif
+
+#ifndef HAVE_STRNCASECMP
+# ifndef HAVE__STRNICMP
+int strncasecmp(const char *str1, const char *str2, size_t n);
+# else
+# define strncasecmp _strnicmp
+# endif
+#endif /* !defined(HAVE_STRNCASECMP) */
+
+#ifndef HAVE_STRERROR
+const char *strerror(int err);
+#endif /* !defined(HAVE_STRERROR) */
+
+#ifndef HAVE_STRCASECMP
+# ifndef HAVE__STRICMP
+int strcasecmp(const char *str1, const char *str2);
+# else
+# define strcasecmp _stricmp
+# endif
+#endif /* !defined(HAVE_STRCASECMP) */
+
+#ifndef HAVE_USLEEP
+int usleep (unsigned int useconds);
+#endif /* !defined(HAVE_USLEEP) */
+
+#ifdef __i386__
+static inline void *memcpy_unaligned( void *dst, const void *src, size_t size )
+{
+    return memcpy( dst, src, size );
+}
+#else
+extern void *memcpy_unaligned( void *dst, const void *src, size_t size );
+#endif /* __i386__ */
+
+extern int mkstemps(char *template, int suffix_len);
+
+/* Process creation flags */
+#ifndef _P_WAIT
+# define _P_WAIT    0
+# define _P_NOWAIT  1
+# define _P_OVERLAY 2
+# define _P_NOWAITO 3
+# define _P_DETACH  4
+#endif
+#ifndef HAVE_SPAWNVP
+extern int spawnvp(int mode, const char *cmdname, const char * const argv[]);
+#endif
+
+/* Interlocked functions */
+
+#if defined(__i386__) && defined(__GNUC__)
+
+extern inline long interlocked_cmpxchg( long *dest, long xchg, long compare );
+extern inline void *interlocked_cmpxchg_ptr( void **dest, void *xchg, void *compare );
+extern inline long interlocked_xchg( long *dest, long val );
+extern inline void *interlocked_xchg_ptr( void **dest, void *val );
+extern inline long interlocked_xchg_add( long *dest, long incr );
+
+extern inline long interlocked_cmpxchg( long *dest, long xchg, long compare )
+{
+    long ret;
+    __asm__ __volatile__( "lock; cmpxchgl %2,(%1)"
+                          : "=a" (ret) : "r" (dest), "r" (xchg), "0" (compare) : "memory" );
+    return ret;
+}
+
+extern inline void *interlocked_cmpxchg_ptr( void **dest, void *xchg, void *compare )
+{
+    void *ret;
+    __asm__ __volatile__( "lock; cmpxchgl %2,(%1)"
+                          : "=a" (ret) : "r" (dest), "r" (xchg), "0" (compare) : "memory" );
+    return ret;
+}
+
+extern inline long interlocked_xchg( long *dest, long val )
+{
+    long ret;
+    __asm__ __volatile__( "lock; xchgl %0,(%1)"
+                          : "=r" (ret) : "r" (dest), "0" (val) : "memory" );
+    return ret;
+}
+
+extern inline void *interlocked_xchg_ptr( void **dest, void *val )
+{
+    void *ret;
+    __asm__ __volatile__( "lock; xchgl %0,(%1)"
+                          : "=r" (ret) : "r" (dest), "0" (val) : "memory" );
+    return ret;
+}
+
+extern inline long interlocked_xchg_add( long *dest, long incr )
+{
+    long ret;
+    __asm__ __volatile__( "lock; xaddl %0,(%1)"
+                          : "=r" (ret) : "r" (dest), "0" (incr) : "memory" );
+    return ret;
+}
+
+#else  /* __i386___ && __GNUC__ */
+
+extern long interlocked_cmpxchg( long *dest, long xchg, long compare );
+extern void *interlocked_cmpxchg_ptr( void **dest, void *xchg, void *compare );
+extern long interlocked_xchg( long *dest, long val );
+extern void *interlocked_xchg_ptr( void **dest, void *val );
+extern long interlocked_xchg_add( long *dest, long incr );
+
+#endif  /* __i386___ && __GNUC__ */
+
+#else /* NO_LIBWINE_PORT */
+
+#define __WINE_NOT_PORTABLE(func) func##_is_not_portable func##_is_not_portable
+
+#define ffs                     __WINE_NOT_PORTABLE(ffs)
+#define fstatvfs                __WINE_NOT_PORTABLE(fstatvfs)
+#define futimes                 __WINE_NOT_PORTABLE(futimes)
+#define getopt_long             __WINE_NOT_PORTABLE(getopt_long)
+#define getopt_long_only        __WINE_NOT_PORTABLE(getopt_long_only)
+#define getpagesize             __WINE_NOT_PORTABLE(getpagesize)
+#define interlocked_cmpxchg     __WINE_NOT_PORTABLE(interlocked_cmpxchg)
+#define interlocked_cmpxchg_ptr __WINE_NOT_PORTABLE(interlocked_cmpxchg_ptr)
+#define interlocked_xchg        __WINE_NOT_PORTABLE(interlocked_xchg)
+#define interlocked_xchg_ptr    __WINE_NOT_PORTABLE(interlocked_xchg_ptr)
+#define interlocked_xchg_add    __WINE_NOT_PORTABLE(interlocked_xchg_add)
+#define lstat                   __WINE_NOT_PORTABLE(lstat)
+#define memcpy_unaligned        __WINE_NOT_PORTABLE(memcpy_unaligned)
+#define memmove                 __WINE_NOT_PORTABLE(memmove)
+#define pread                   __WINE_NOT_PORTABLE(pread)
+#define pwrite                  __WINE_NOT_PORTABLE(pwrite)
+#define spawnvp                 __WINE_NOT_PORTABLE(spawnvp)
+#define statvfs                 __WINE_NOT_PORTABLE(statvfs)
+#define strcasecmp              __WINE_NOT_PORTABLE(strcasecmp)
+#define strerror                __WINE_NOT_PORTABLE(strerror)
+#define strncasecmp             __WINE_NOT_PORTABLE(strncasecmp)
+#define usleep                  __WINE_NOT_PORTABLE(usleep)
+
+#endif /* NO_LIBWINE_PORT */
+
+#endif /* !defined(__WINE_WINE_PORT_H) */
diff --git a/reactos/regtests/winetests/winetest/resource.h b/reactos/regtests/winetests/winetest/resource.h
new file mode 100644 (file)
index 0000000..32c58a9
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Resource definitions
+ *
+ * Copyright 2004 Ferenc Wagner
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define IDI_WINE 1
+
+#define IDD_STATUS 100
+#define IDD_ABOUT  101
+#define IDD_TAG    102
+
+#define IDC_ST0 1000
+#define IDC_PB0 1001
+#define IDC_ST1 1002
+#define IDC_PB1 1003
+#define IDC_ST2 1004
+#define IDC_PB2 1005
+
+#define IDC_DIR 2000
+#define IDC_OUT 2001
+#define IDC_TAG 2002
+
+#define IDC_SB  3000
+
+#define IDC_EDIT  4000
+#define IDC_ABOUT 4001
+
+/* Resource types */
+
+#define TESTRES   1000
+#define STRINGRES 1001
+
+/* String resources */
+
+#define WINE_BUILD 10000
+#define BUILD_INFO 10001
+#define TESTS_URL  10002
+
+/* Revision info strings start from this index: */
+#define REV_INFO 30000
diff --git a/reactos/regtests/winetests/winetest/send.c b/reactos/regtests/winetests/winetest/send.c
new file mode 100644 (file)
index 0000000..2e6e11c
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * HTTP handling functions.
+ *
+ * Copyright 2003 Ferenc Wagner
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <winsock.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "winetest.h"
+
+static SOCKET
+open_http (const char *server)
+{
+    WSADATA wsad;
+    struct sockaddr_in sa;
+    SOCKET s;
+
+    report (R_STATUS, "Opening HTTP connection to %s", server);
+    if (WSAStartup (MAKEWORD (2,2), &wsad)) return INVALID_SOCKET;
+
+    sa.sin_family = AF_INET;
+    sa.sin_port = htons (80);
+    sa.sin_addr.s_addr = inet_addr (server);
+    if (sa.sin_addr.s_addr == INADDR_NONE) {
+        struct hostent *host = gethostbyname (server);
+        if (!host) {
+            report (R_ERROR, "Hostname lookup failed for %s", server);
+            goto failure;
+        }
+        sa.sin_addr.s_addr = ((struct in_addr *)host->h_addr)->s_addr;
+    }
+    s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (s == INVALID_SOCKET) {
+        report (R_ERROR, "Can't open network socket: %d",
+                WSAGetLastError ());
+        goto failure;
+    }
+    if (!connect (s, (struct sockaddr*)&sa, sizeof (struct sockaddr_in)))
+        return s;
+
+    report (R_ERROR, "Can't connect: %d", WSAGetLastError ());
+    closesocket (s);
+ failure:
+    WSACleanup ();
+    return INVALID_SOCKET;
+}
+
+static int
+close_http (SOCKET s)
+{
+    int ret;
+
+    ret = closesocket (s);
+    return (WSACleanup () || ret);
+}
+
+static int
+send_buf (SOCKET s, const char *buf, size_t length)
+{
+    int sent;
+
+    while (length > 0) {
+        sent = send (s, buf, length, 0);
+        if (sent == SOCKET_ERROR) return 1;
+        buf += sent;
+        length -= sent;
+    }
+    return 0;
+}
+
+static int
+send_str (SOCKET s, ...)
+{
+    va_list ap;
+    char *p;
+    int ret;
+    size_t len;
+
+    va_start (ap, s);
+    p = vstrmake (&len, ap);
+    va_end (ap);
+    if (!p) return 1;
+    ret = send_buf (s, p, len);
+    free (p);
+    return ret;
+}
+
+int
+send_file (const char *name)
+{
+    SOCKET s;
+    FILE *f;
+#define BUFLEN 8192
+    unsigned char buffer[BUFLEN+1];
+    size_t bytes_read, total, filesize;
+    char *str;
+    int ret;
+
+    /* RFC 2616 */
+#define SEP "--8<--cut-here--8<--"
+    static const char head[] = "POST /submit HTTP/1.0\r\n"
+        "Host: test.winehq.org\r\n"
+        "User-Agent: Winetest Shell\r\n"
+        "Content-Type: multipart/form-data; boundary=\"" SEP "\"\r\n"
+        "Content-Length: %u\r\n\r\n";
+    static const char body1[] = "--" SEP "\r\n"
+        "Content-Disposition: form-data; name=\"reportfile\"; filename=\"%s\"\r\n"
+        "Content-Type: application/octet-stream\r\n\r\n";
+    static const char body2[] = "\r\n--" SEP "\r\n"
+        "Content-Disposition: form-data; name=\"submit\"\r\n\r\n"
+        "Upload File\r\n"
+        "--" SEP "--\r\n";
+
+    s = open_http ("test.winehq.org");
+    if (s == INVALID_SOCKET) return 1;
+
+    f = fopen (name, "rb");
+    if (!f) {
+        report (R_WARNING, "Can't open file '%s': %d", name, errno);
+        goto abort1;
+    }
+    fseek (f, 0, SEEK_END);
+    filesize = ftell (f);
+    if (filesize > 1024*1024) {
+        report (R_WARNING,
+                "File too big (%.1f MB > 1 MB); submitting partial report.",
+                filesize/1024.0/1024);
+        filesize = 1024*1024;
+    }
+    fseek (f, 0, SEEK_SET);
+
+    report (R_STATUS, "Sending header");
+    str = strmake (&total, body1, name);
+    ret = send_str (s, head, filesize + total + sizeof body2 - 1) ||
+        send_buf (s, str, total);
+    free (str);
+    if (ret) {
+        report (R_WARNING, "Error sending header: %d, %d",
+                errno, WSAGetLastError ());
+        goto abort2;
+    }
+
+    report (R_STATUS, "Sending %u bytes of data", filesize);
+    report (R_PROGRESS, 2, filesize);
+    total = 0;
+    while (total < filesize && (bytes_read = fread (buffer, 1, BUFLEN/2, f))) {
+        if ((signed)bytes_read == -1) {
+            report (R_WARNING, "Error reading log file: %d", errno);
+            goto abort2;
+        }
+        total += bytes_read;
+        if (total > filesize) bytes_read -= total - filesize;
+        if (send_buf (s, buffer, bytes_read)) {
+            report (R_WARNING, "Error sending body: %d, %d",
+                    errno, WSAGetLastError ());
+            goto abort2;
+        }
+        report (R_DELTA, bytes_read, "Network transfer: In progress");
+    }
+    fclose (f);
+
+    if (send_buf (s, body2, sizeof body2 - 1)) {
+        report (R_WARNING, "Error sending trailer: %d, %d",
+                errno, WSAGetLastError ());
+        goto abort2;
+    }
+    report (R_DELTA, 0, "Network transfer: Done");
+
+    total = 0;
+    while ((bytes_read = recv (s, buffer+total, BUFLEN-total, 0))) {
+        if ((signed)bytes_read == SOCKET_ERROR) {
+            report (R_WARNING, "Error receiving reply: %d, %d",
+                    errno, WSAGetLastError ());
+            goto abort1;
+        }
+        total += bytes_read;
+        if (total == BUFLEN) {
+            report (R_WARNING, "Buffer overflow");
+            goto abort1;
+        }
+    }
+    if (close_http (s)) {
+        report (R_WARNING, "Error closing connection: %d, %d",
+                errno, WSAGetLastError ());
+        return 1;
+    }
+
+    str = strmake (&bytes_read, "Received %s (%d bytes).\n",
+                   name, filesize);
+    ret = memcmp (str, buffer + total - bytes_read, bytes_read);
+    free (str);
+    if (ret) {
+        buffer[total] = 0;
+        str = strstr (buffer, "\r\n\r\n");
+        if (!str) str = buffer;
+        else str = str + 4;
+        report (R_ERROR, "Can't submit logfile '%s'. "
+                "Server response: %s", name, str);
+    }
+    return ret;
+
+ abort2:
+    fclose (f);
+ abort1:
+    close_http (s);
+    return 1;
+}
diff --git a/reactos/regtests/winetests/winetest/tests.rc b/reactos/regtests/winetests/winetest/tests.rc
new file mode 100644 (file)
index 0000000..0450c18
--- /dev/null
@@ -0,0 +1,8 @@
+/* Automatically generated -- do not edit! */
+#include "resource.h"
+STRINGTABLE {
+0 "advapi32_test.exe"
+1 "comctl32_test.exe"
+}
+0 TESTRES "../../../../../output-i386/regtests/winetest/advapi32/advapi32_test.exe"
+1 TESTRES "output-i386/regtests/winetest/comctl32/comctl32_test.exe"
diff --git a/reactos/regtests/winetests/winetest/util.c b/reactos/regtests/winetests/winetest/util.c
new file mode 100644 (file)
index 0000000..72a7c65
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Utility functions.
+ *
+ * Copyright 2003 Dimitrie O. Paun
+ * Copyright 2003 Ferenc Wagner
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "winetest.h"
+
+void *xmalloc (size_t len)
+{
+    void *p = malloc (len);
+
+    if (!p) report (R_FATAL, "Out of memory.");
+    return p;
+}
+
+void *xrealloc (void *op, size_t len)
+{
+    void *p = realloc (op, len);
+
+    if (len && !p) report (R_FATAL, "Out of memory.");
+    return p;
+}
+
+static char *vstrfmtmake (size_t *lenp, const char *fmt, va_list ap)
+{
+    size_t size = 1000;
+    char *p, *q;
+    int n;
+
+    p = malloc (size);
+    if (!p) return NULL;
+    while (1) {
+        n = vsnprintf (p, size, fmt, ap);
+        if (n < 0) size *= 2;   /* Windows */
+        else if ((unsigned)n >= size) size = n+1; /* glibc */
+        else break;
+        q = realloc (p, size);
+        if (!q) {
+          free (p);
+          return NULL;
+       }
+       p = q;
+    }
+    if (lenp) *lenp = n;
+    return p;
+}
+
+char *vstrmake (size_t *lenp, va_list ap)
+{
+    const char *fmt;
+
+    fmt = va_arg (ap, const char*);
+    return vstrfmtmake (lenp, fmt, ap);
+}
+
+char *strmake (size_t *lenp, ...)
+{
+    va_list ap;
+    char *p;
+
+    va_start (ap, lenp);
+    p = vstrmake (lenp, ap);
+    if (!p) report (R_FATAL, "Out of memory.");
+    va_end (ap);
+    return p;
+}
+
+void xprintf (const char *fmt, ...)
+{
+    va_list ap;
+    size_t size;
+    ssize_t written;
+    char *buffer, *head;
+
+    va_start (ap, fmt);
+    buffer = vstrfmtmake (&size, fmt, ap);
+    head = buffer;
+    va_end (ap);
+    while ((written = write (1, head, size)) != size) {
+        if (written == -1)
+            report (R_FATAL, "Can't write logs: %d", errno);
+        head += written;
+        size -= written;
+    }
+    free (buffer);
+}
+
+int
+goodtagchar (char c)
+{
+    return (('a'<=c && c<='z') ||
+            ('A'<=c && c<='Z') ||
+            ('0'<=c && c<='9') ||
+            c=='-' || c=='.');
+}
+
+const char *
+findbadtagchar (const char *tag)
+{
+    while (*tag)
+        if (goodtagchar (*tag)) tag++;
+        else return tag;
+    return NULL;
+}
diff --git a/reactos/regtests/winetests/winetest/wine.ico b/reactos/regtests/winetests/winetest/wine.ico
new file mode 100644 (file)
index 0000000..fc394c9
Binary files /dev/null and b/reactos/regtests/winetests/winetest/wine.ico differ
diff --git a/reactos/regtests/winetests/winetest/winetest.h b/reactos/regtests/winetests/winetest/winetest.h
new file mode 100644 (file)
index 0000000..2f2c58a
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * winetest definitions
+ *
+ * Copyright 2003 Dimitrie O. Paun
+ * Copyright 2003 Ferenc Wagner
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __WINETESTS_H
+#define __WINETESTS_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+void fatal (const char* msg);
+void warning (const char* msg);
+void *xmalloc (size_t len);
+void *xrealloc (void *op, size_t len);
+void xprintf (const char *fmt, ...);
+char *vstrmake (size_t *lenp, va_list ap);
+char *strmake (size_t *lenp, ...);
+int goodtagchar (char c);
+const char *findbadtagchar (const char *tag);
+
+int send_file (const char *name);
+
+/* GUI definitions */
+
+#include <windows.h>
+
+enum report_type {
+    R_STATUS = 0,
+    R_PROGRESS,
+    R_STEP,
+    R_DELTA,
+    R_TAG,
+    R_DIR,
+    R_OUT,
+    R_WARNING,
+    R_ERROR,
+    R_FATAL,
+    R_ASK,
+    R_TEXTMODE,
+    R_QUIET
+};
+
+#define MAXTAGLEN 20
+extern char *tag;
+int guiAskTag (void);
+int report (enum report_type t, ...);
+
+#endif /* __WINETESTS_H */
diff --git a/reactos/regtests/winetests/winetest/winetest.rc b/reactos/regtests/winetests/winetest/winetest.rc
new file mode 100644 (file)
index 0000000..6846067
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Winetest resources
+ *
+ * Copyright 2004 Ferenc Wagner
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <windows.h>
+#include <winres.h>
+#include "resource.h"
+#include "tests.rc"
+
+IDD_TAG DIALOG 0, 0, 150, 65
+STYLE WS_POPUP
+CAPTION "No tag supplied"
+BEGIN
+    CTEXT "Please supply a tag for your report.  You can use letters, digits, dashes and periods."
+        IDC_STATIC, 10, 5, 130, 30
+    EDITTEXT IDC_TAG, 35, 30, 80, 10, ES_AUTOHSCROLL
+    DEFPUSHBUTTON "Start", IDOK, 25, 45, 40, 14
+    PUSHBUTTON    "Abort", IDABORT, 85, 45, 40, 14
+END
+
+IDD_STATUS DIALOG 0, 0, 160, 150
+STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
+CAPTION "Wine Test Shell"
+BEGIN
+    LTEXT   "Extracting:",       IDC_ST0,        10,   5, 140, 10
+    CONTROL "PB0", IDC_PB0, PROGRESS_CLASS, 0,    5,  15, 150, 10
+    LTEXT   "Running:",          IDC_ST1,        10,  30, 140, 10
+    CONTROL "PB1", IDC_PB1, PROGRESS_CLASS, 0,    5,  40, 150, 15
+    LTEXT   "Network transfer:", IDC_ST2,        10,  60, 140, 10
+    CONTROL "PB2", IDC_PB2, PROGRESS_CLASS, 0,    5,  70, 150, 10
+                                               
+    LTEXT   "Tag:",               IDC_STATIC,    10,  89, 100, 10
+    EDITTEXT                      IDC_TAG,       25,  88, 125, 10,
+             ES_READONLY
+    LTEXT   "Working directory:", IDC_STATIC,    10, 100, 100, 10
+    EDITTEXT                      IDC_DIR,       71,  99,  79, 10,
+             ES_READONLY | ES_AUTOHSCROLL
+    LTEXT   "Output file:",       IDC_STATIC,    10, 111, 100, 10
+    EDITTEXT                      IDC_OUT,       46, 110, 104, 10,
+             ES_READONLY | ES_AUTOHSCROLL
+
+    DEFPUSHBUTTON "About", IDHELP,               20, 123,  30, 14
+    PUSHBUTTON    "Edit",  IDCANCEL,             65, 123,  30, 14,
+                   WS_DISABLED
+    PUSHBUTTON    "Stop",  IDABORT,             110, 123,  30, 14
+
+    CONTROL "Created", IDC_SB, STATUSCLASSNAME, 0, 0,0,0,0
+END
+
+IDD_ABOUT DIALOG 0, 0, 150, 60
+STYLE WS_POPUP
+CAPTION "About Wine Test Shell"
+BEGIN
+    CTEXT "This program extracts and runs a series of tests which check Wine's conformance to the Windows API.",
+        IDC_STATIC, 10, 5, 130, 30
+    DEFPUSHBUTTON "Close", IDCANCEL, 55, 40, 40, 14
+END
+
+/* BINRES wine.ico */
+IDI_WINE ICON "wine.ico"
+/* {
+ '00 00 01 00 02 00 20 20 10 00 00 00 00 00 E8 02'
+ '00 00 26 00 00 00 10 10 10 00 00 00 00 00 28 01'
+ '00 00 0E 03 00 00 28 00 00 00 20 00 00 00 40 00'
+ '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00'
+ '00 00 00 00 00 00 10 00 00 00 00 00 00 00 39 02'
+ 'B1 00 23 02 6C 00 0F 03 29 00 1B 02 51 00 FF FF'
+ 'FF 00 1B 1A 1B 00 1E 02 63 00 33 02 A1 00 08 08'
+ '08 00 14 03 3C 00 0C 04 1E 00 2E 02 8E 00 10 0F'
+ '10 00 2A 02 82 00 29 02 7D 00 03 02 04 00 44 44'
+ '44 44 44 44 44 44 55 44 44 44 44 44 44 44 44 44'
+ '44 44 44 44 8F FF 84 44 44 44 44 44 44 44 44 44'
+ '44 44 44 8F F8 F8 44 44 44 44 44 44 44 44 44 44'
+ '44 44 8F FF F5 44 44 44 44 44 44 44 44 44 44 44'
+ '44 5C F8 C8 F5 44 44 44 44 44 44 44 44 44 44 44'
+ '44 44 44 44 85 44 44 44 44 44 44 44 44 44 44 44'
+ '44 44 44 44 4C 44 44 44 44 44 44 44 44 44 44 44'
+ '44 44 44 44 4C 44 44 44 44 44 44 44 44 44 44 44'
+ '44 44 44 44 45 54 44 44 44 44 44 44 44 44 44 44'
+ '44 44 44 44 45 F4 44 44 44 44 44 44 44 44 44 44'
+ '44 44 44 44 45 FF 44 44 44 44 44 44 44 44 44 44'
+ '44 44 44 44 48 FF F4 44 44 44 44 44 44 44 44 44'
+ '44 44 44 44 48 23 9A 84 44 44 44 44 44 44 44 44'
+ '44 44 44 44 42 B7 7E AF 44 44 44 44 44 44 44 44'
+ '44 44 44 44 49 00 00 EA C4 44 44 44 44 44 44 44'
+ '44 44 44 44 46 00 00 01 F4 44 44 44 44 44 44 44'
+ '44 44 44 44 46 00 00 00 9F 44 44 44 44 44 44 44'
+ '44 44 44 44 46 00 70 00 EF 44 44 44 44 44 44 44'
+ '44 44 44 44 43 00 00 00 79 F4 44 44 44 44 44 44'
+ '44 44 44 44 49 00 00 00 0E F4 44 44 44 44 44 44'
+ '44 44 44 44 42 00 00 00 07 24 44 44 44 44 44 44'
+ '44 44 44 44 43 B0 00 00 00 34 44 44 44 44 44 44'
+ '44 44 44 44 4C 30 00 00 00 1F 44 44 44 44 44 44'
+ '44 44 44 44 48 27 E1 1D B1 2C 44 44 44 44 44 44'
+ '44 44 44 44 44 A9 CC CF F8 48 C4 44 44 44 44 44'
+ '44 44 44 44 44 58 44 44 44 45 C4 44 44 44 44 44'
+ '44 44 44 44 44 4C 44 44 44 44 84 44 44 44 44 44'
+ '44 44 44 44 44 48 44 44 44 44 C4 44 44 44 44 44'
+ '44 44 44 44 44 48 C4 44 44 44 C4 44 44 44 44 44'
+ '44 44 44 44 44 44 F4 44 44 4C C4 44 44 44 44 44'
+ '44 44 44 44 44 44 84 44 F8 84 44 44 44 44 44 44'
+ '44 44 44 44 44 44 48 F8 44 44 44 44 44 44 FF FF'
+ '3F FF FF F0 7F FF FF C0 FF FF FF 03 FF FF FC 03'
+ 'FF FF FF F3 FF FF FF FB FF FF FF FB FF FF FF F9'
+ 'FF FF FF F9 FF FF FF F8 FF FF FF F8 7F FF FF F8'
+ '1F FF FF F8 0F FF FF F8 07 FF FF F8 07 FF FF F8'
+ '03 FF FF F8 03 FF FF F8 01 FF FF F8 01 FF FF F8'
+ '01 FF FF F8 01 FF FF F8 00 FF FF F8 00 FF FF FC'
+ '02 7F FF FC FE 7F FF FE FF 7F FF FE FF 7F FF FE'
+ '7F 7F FF FF 7E 7F FF FF 71 FF FF FF 8F FF 28 00'
+ '00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00'
+ '00 00 80 00 00 00 00 00 00 00 00 00 00 00 10 00'
+ '00 00 00 00 00 00 3A 02 B1 00 0A 06 14 00 12 03'
+ '33 00 FF FF FF 00 12 12 12 00 0B 0B 0B 00 1B 1B'
+ '1B 00 25 02 6F 00 2E 02 92 00 1A 02 52 00 36 02'
+ 'A6 00 15 03 3E 00 04 04 05 00 13 11 19 00 1E 02'
+ '62 00 2A 02 82 00 33 33 33 CC 43 33 33 33 33 33'
+ 'CC 5C 33 33 33 33 33 36 C5 53 33 33 33 33 33 33'
+ '33 43 33 33 33 33 33 33 33 65 33 33 33 33 33 33'
+ '33 DC 33 33 33 33 33 33 33 17 EC 33 33 33 33 33'
+ '33 B0 07 53 33 33 33 33 33 90 00 B3 33 33 33 33'
+ '33 B0 00 FC 33 33 33 33 33 BA 00 A2 33 33 33 33'
+ '33 C7 88 82 33 33 33 33 33 3D D5 14 43 33 33 33'
+ '33 35 33 33 53 33 33 33 33 33 53 33 53 33 33 33'
+ '33 33 C5 5C 33 33 FC 7F 00 00 F0 FF 00 00 E1 FF'
+ '00 00 FD FF 00 00 FC FF 00 00 FC FF 00 00 FC 3F'
+ '00 00 FC 1F 00 00 FC 1F 00 00 FC 0F 00 00 FC 0F'
+ '00 00 FC 0F 00 00 FE 07 00 00 FE F7 00 00 FF 77'
+ '00 00 FF 0F 00 00'
+} */