--- /dev/null
+/*
+ * 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, ¬Null, 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, ¬Null, 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, ¬Null, 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, ¬Null, 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();
+}
--- /dev/null
+/*
+ * 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 );
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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 );
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/* 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"
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/* 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();
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/* 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();
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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"
--- /dev/null
+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:
--- /dev/null
+/* 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__ */
--- /dev/null
+/*
+ * 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" );
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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");
+}
--- /dev/null
+# 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
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/* 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"
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/* 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"
--- /dev/null
+/* 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
--- /dev/null
+/*
+ * 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"
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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) */
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/* 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"
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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'
+} */