diff --git a/reactos/lib/advapi32/winetests/crypt.c b/reactos/lib/advapi32/winetests/crypt.c index 3e0f4a7d48a..ed68658c259 100644 --- a/reactos/lib/advapi32/winetests/crypt.c +++ b/reactos/lib/advapi32/winetests/crypt.c @@ -1,575 +1,764 @@ -/* - * Unit tests for crypt functions - * - * Copyright (c) 2004 Michael Jung - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#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 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"); - } -} - - -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), "%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), "%d/%ld\n", result, GetLastError()); - - if (hProv) - pCryptReleaseContext(hProv, 0); -} - -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(); - clean_up_environment(); - } - - test_enum_providers(); - test_enum_provider_types(); - test_get_default_provider(); - test_set_provider_ex(); -} +/* + * 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 + +#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(); +} diff --git a/reactos/lib/advapi32/winetests/crypt_lmhash.c b/reactos/lib/advapi32/winetests/crypt_lmhash.c index d8879539de4..ff352c454de 100644 --- a/reactos/lib/advapi32/winetests/crypt_lmhash.c +++ b/reactos/lib/advapi32/winetests/crypt_lmhash.c @@ -1,63 +1,63 @@ -/* - * Unit tests for SystemFunction006 (LMHash?) - * - * Copyright 2004 Hans Leidekker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#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 ); -} +/* + * 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 + +#include "wine/test.h" +#include "windef.h" +#include "winbase.h" + +typedef VOID (WINAPI *fnSystemFunction006)( PCSTR passwd, PSTR lmhash ); +fnSystemFunction006 pSystemFunction006; + +static void test_SystemFunction006() +{ + static unsigned char lmhash[16 + 1]; + + unsigned char passwd[] = { 's','e','c','r','e','t', 0, 0, 0, 0, 0, 0, 0, 0 }; + unsigned char expect[] = + { 0x85, 0xf5, 0x28, 0x9f, 0x09, 0xdc, 0xa7, 0xeb, + 0xaa, 0xd3, 0xb4, 0x35, 0xb5, 0x14, 0x04, 0xee }; + + pSystemFunction006( passwd, lmhash ); + + ok( !memcmp( lmhash, expect, sizeof(expect) ), + "lmhash: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + lmhash[0], lmhash[1], lmhash[2], lmhash[3], lmhash[4], lmhash[5], + lmhash[6], lmhash[7], lmhash[8], lmhash[9], lmhash[10], lmhash[11], + lmhash[12], lmhash[13], lmhash[14], lmhash[15] ); +} + +START_TEST(crypt_lmhash) +{ + HMODULE module; + + if (!(module = LoadLibrary("advapi32.dll"))) return; + + pSystemFunction006 = (fnSystemFunction006)GetProcAddress( module, "SystemFunction006" ); + + if (!pSystemFunction006) goto out; + + if (pSystemFunction006) + test_SystemFunction006(); + +out: + FreeLibrary( module ); +} diff --git a/reactos/lib/advapi32/winetests/crypt_md4.c b/reactos/lib/advapi32/winetests/crypt_md4.c index 391a2b74302..c18f958b11c 100644 --- a/reactos/lib/advapi32/winetests/crypt_md4.c +++ b/reactos/lib/advapi32/winetests/crypt_md4.c @@ -1,109 +1,109 @@ -/* - * Unit tests for MD4 functions - * - * Copyright 2004 Hans Leidekker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#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(); -} +/* + * 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 + +#include "wine/test.h" +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +typedef struct +{ + unsigned int buf[4]; + unsigned int i[2]; + unsigned char in[64]; + unsigned char digest[16]; +} MD4_CTX; + +typedef VOID (WINAPI *fnMD4Init)( MD4_CTX *ctx ); +typedef VOID (WINAPI *fnMD4Update)( MD4_CTX *ctx, const unsigned char *src, const int len ); +typedef VOID (WINAPI *fnMD4Final)( MD4_CTX *ctx ); + +fnMD4Init pMD4Init; +fnMD4Update pMD4Update; +fnMD4Final pMD4Final; + +#define ctxcmp( a, b ) memcmp( (char*)a, (char*)b, FIELD_OFFSET( MD4_CTX, in ) ) + +void test_md4_ctx() +{ + static unsigned char message[] = + "In our Life there's If" + "In our beliefs there's Lie" + "In our business there is Sin" + "In our bodies, there is Die"; + + int size = strlen( message ); + HMODULE module; + + MD4_CTX ctx; + MD4_CTX ctx_initialized = + { + { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 }, + { 0, 0 } + }; + + MD4_CTX ctx_update1 = + { + { 0x5e592ef7, 0xbdcb1567, 0x2b626d17, 0x7d1198bd }, + { 0x00000338, 0 } + }; + + MD4_CTX ctx_update2 = + { + { 0x05dcfd65, 0xb3711c0d, 0x9e3369c2, 0x903ead11 }, + { 0x00000670, 0 } + }; + + unsigned char expect[16] = + { 0x5f, 0xd3, 0x9b, 0x29, 0x47, 0x53, 0x47, 0xaf, + 0xa5, 0xba, 0x0c, 0x05, 0xff, 0xc0, 0xc7, 0xda }; + + if (!(module = LoadLibrary( "advapi32.dll" ))) return; + + pMD4Init = (fnMD4Init)GetProcAddress( module, "MD4Init" ); + pMD4Update = (fnMD4Update)GetProcAddress( module, "MD4Update" ); + pMD4Final = (fnMD4Final)GetProcAddress( module, "MD4Final" ); + + if (!pMD4Init || !pMD4Update || !pMD4Final) goto out; + + memset( &ctx, 0, sizeof(ctx) ); + pMD4Init( &ctx ); + ok( !ctxcmp( &ctx, &ctx_initialized ), "invalid initialization\n" ); + + pMD4Update( &ctx, message, size ); + ok( !ctxcmp( &ctx, &ctx_update1 ), "update doesn't work correctly\n" ); + + pMD4Update( &ctx, message, size ); + ok( !ctxcmp( &ctx, &ctx_update2 ), "update doesn't work correctly\n" ); + + pMD4Final( &ctx ); + ok( ctxcmp( &ctx, &ctx_initialized ), "context has changed\n" ); + ok( !memcmp( ctx.digest, expect, sizeof(expect) ), "incorrect result\n" ); + +out: + FreeLibrary( module ); +} + +START_TEST(crypt_md4) +{ + test_md4_ctx(); +} diff --git a/reactos/lib/advapi32/winetests/crypt_md5.c b/reactos/lib/advapi32/winetests/crypt_md5.c index 68afd60c5c6..106ccdf2895 100644 --- a/reactos/lib/advapi32/winetests/crypt_md5.c +++ b/reactos/lib/advapi32/winetests/crypt_md5.c @@ -1,109 +1,109 @@ -/* - * Unit tests for MD5 functions - * - * Copyright 2004 Hans Leidekker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#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(); -} +/* + * 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 + +#include "wine/test.h" +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +typedef struct +{ + unsigned int i[2]; + unsigned int buf[4]; + unsigned char in[64]; + unsigned char digest[16]; +} MD5_CTX; + +typedef VOID (WINAPI *fnMD5Init)( MD5_CTX *ctx ); +typedef VOID (WINAPI *fnMD5Update)( MD5_CTX *ctx, const unsigned char *src, const int len ); +typedef VOID (WINAPI *fnMD5Final)( MD5_CTX *ctx ); + +fnMD5Init pMD5Init; +fnMD5Update pMD5Update; +fnMD5Final pMD5Final; + +#define ctxcmp( a, b ) memcmp( (char*)a, (char*)b, FIELD_OFFSET( MD5_CTX, in ) ) + +void test_md5_ctx() +{ + static unsigned char message[] = + "In our Life there's If" + "In our beliefs there's Lie" + "In our business there is Sin" + "In our bodies, there is Die"; + + int size = strlen( message ); + HMODULE module; + + MD5_CTX ctx; + MD5_CTX ctx_initialized = + { + { 0, 0 }, + { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 } + }; + + MD5_CTX ctx_update1 = + { + { 0x00000338, 0 }, + { 0x068cb64d, 0xb7a05790, 0x426979ee, 0xed67e221 } + }; + + MD5_CTX ctx_update2 = + { + { 0x00000670, 0 }, + { 0x2f7afe58, 0xcc3e9315, 0x709c465c, 0xbf6414c8 } + }; + + unsigned char expect[16] = + { 0x43, 0x03, 0xdd, 0x8c, 0x60, 0xd9, 0x3a, 0x22, + 0x0b, 0x28, 0xd0, 0xb2, 0x65, 0x93, 0xd0, 0x36 }; + + if (!(module = LoadLibrary( "advapi32.dll" ))) return; + + pMD5Init = (fnMD5Init)GetProcAddress( module, "MD5Init" ); + pMD5Update = (fnMD5Update)GetProcAddress( module, "MD5Update" ); + pMD5Final = (fnMD5Final)GetProcAddress( module, "MD5Final" ); + + if (!pMD5Init || !pMD5Update || !pMD5Final) goto out; + + memset( &ctx, 0, sizeof(ctx) ); + pMD5Init( &ctx ); + ok( !ctxcmp( &ctx, &ctx_initialized ), "invalid initialization\n" ); + + pMD5Update( &ctx, message, size ); + ok( !ctxcmp( &ctx, &ctx_update1 ), "update doesn't work correctly\n" ); + + pMD5Update( &ctx, message, size ); + ok( !ctxcmp( &ctx, &ctx_update2 ), "update doesn't work correctly\n" ); + + pMD5Final( &ctx ); + ok( ctxcmp( &ctx, &ctx_initialized ), "context has changed\n" ); + ok( !memcmp( ctx.digest, expect, sizeof(expect) ), "incorrect result\n" ); + +out: + FreeLibrary( module ); +} + +START_TEST(crypt_md5) +{ + test_md5_ctx(); +} diff --git a/reactos/lib/advapi32/winetests/crypt_sha.c b/reactos/lib/advapi32/winetests/crypt_sha.c index a3642356a89..5cf6fdb64c9 100644 --- a/reactos/lib/advapi32/winetests/crypt_sha.c +++ b/reactos/lib/advapi32/winetests/crypt_sha.c @@ -1,81 +1,81 @@ -/* - * Unit tests for SHA functions - * - * Copyright (c) 2004 Filip Navara - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#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(); -} +/* + * 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 + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +#include "wine/test.h" + +typedef struct { + ULONG Unknown[6]; + ULONG State[5]; + ULONG Count[2]; + UCHAR Buffer[64]; +} SHA_CTX, *PSHA_CTX; + +#define ctxcmp(a,b) memcmp((char*)a, (char*)b, FIELD_OFFSET(SHA_CTX, Buffer)) + +static void test_sha_ctx(void) +{ + FARPROC pA_SHAInit, pA_SHAUpdate, pA_SHAFinal; + static const char test_buffer[] = "In our Life there's If" + "In our beliefs there's Lie" + "In our business there is Sin" + "In our bodies, there is Die"; + ULONG test_buffer_size = strlen(test_buffer); + HMODULE hmod; + SHA_CTX ctx; + SHA_CTX ctx_initialized = {{0, 0, 0, 0, 0}, {0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0}, {0, 0}}; + SHA_CTX ctx_update1 = {{0, 0, 0, 0, 0}, {0xdbe5eba8, 0x6b4335ca, 0xf7c94abe, 0xc9f34e31, 0x311023f0}, {0, 0x67}}; + SHA_CTX ctx_update2 = {{0, 0, 0, 0, 0}, {0x5ecc818d, 0x52498169, 0xf6758559, 0xd035a164, 0x871dd125}, {0, 0xce}}; + ULONG result[5]; + ULONG result_correct[5] = {0xe014f93, 0xe09791ec, 0x6dcf96c8, 0x8e9385fc, 0x1611c1bb}; + + hmod = LoadLibrary("advapi32.dll"); + pA_SHAInit = GetProcAddress(hmod, "A_SHAInit"); + pA_SHAUpdate = GetProcAddress(hmod, "A_SHAUpdate"); + pA_SHAFinal = GetProcAddress(hmod, "A_SHAFinal"); + + if (!pA_SHAInit || !pA_SHAUpdate || !pA_SHAFinal) return; + + RtlZeroMemory(&ctx, sizeof(ctx)); + pA_SHAInit(&ctx); + ok(!ctxcmp(&ctx, &ctx_initialized), "invalid initialization\n"); + + pA_SHAUpdate(&ctx, test_buffer, test_buffer_size); + ok(!ctxcmp(&ctx, &ctx_update1), "update doesn't work correctly\n"); + + pA_SHAUpdate(&ctx, test_buffer, test_buffer_size); + ok(!ctxcmp(&ctx, &ctx_update2), "update doesn't work correctly\n"); + + pA_SHAFinal(&ctx, result); + ok(!ctxcmp(&ctx, &ctx_initialized), "context hasn't been reinitialized\n"); + ok(!memcmp(result, result_correct, sizeof(result)), "incorrect result\n"); + + FreeLibrary(hmod); +} + +START_TEST(crypt_sha) +{ + test_sha_ctx(); +} diff --git a/reactos/lib/advapi32/winetests/registry.c b/reactos/lib/advapi32/winetests/registry.c index 0416a3ee742..bd26bb6b25a 100644 --- a/reactos/lib/advapi32/winetests/registry.c +++ b/reactos/lib/advapi32/winetests/registry.c @@ -1,358 +1,451 @@ -/* - * 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 -#include -#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, NULL ); - 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; - 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}; - - /* check NULL data with zero length */ - res = RegSetValueExA( hkey_main, "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( hkey_main, "Test", 0, REG_EXPAND_SZ, NULL, 0 ); - ok( !res, "RegSetValueExA returned %ld\n", res ); - res = RegSetValueExA( hkey_main, "Test", 0, REG_BINARY, NULL, 0 ); - ok( !res, "RegSetValueExA returned %ld\n", res ); - - res = RegSetValueExA( hkey_main, "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( hkey_main, 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( hkey_main, 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( hkey_main, 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( hkey_main, 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( hkey_main, 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( hkey_main, testW, 0, REG_SZ, (const BYTE *)foobarW, 7*sizeof(WCHAR) ); - if (res==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED) - goto CLEANUP; - 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( hkey_main, 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( hkey_main, 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( hkey_main, 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( hkey_main, 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" ); - -CLEANUP: - /* cleanup */ - RegDeleteValueA( hkey_main, "Test" ); -} - -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 && hkResult != NULL, - "expected hkResult != hkPreserve and 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, "expected ERROR_INVALID_HANDLE, 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); - ok(ret == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", ret); - - /* try to close a NULL handle */ - ret = RegCloseKey(NULL); - ok(ret == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", ret); -} - -START_TEST(registry) -{ - setup_main_key(); - create_test_entries(); - test_enum_value(); - test_query_value_ex(); - test_reg_open_key(); - test_reg_close_key(); - - /* cleanup */ - delete_key( hkey_main ); -} +/* + * 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 +#include +#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(); +#if 0 + 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); + } +#endif + /* cleanup */ + delete_key( hkey_main ); +} diff --git a/reactos/lib/advapi32/winetests/security.c b/reactos/lib/advapi32/winetests/security.c index ad8a4e16777..cc7f5379e15 100644 --- a/reactos/lib/advapi32/winetests/security.c +++ b/reactos/lib/advapi32/winetests/security.c @@ -1,408 +1,443 @@ -/* - * 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 - -#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 ); - -static HMODULE hmod; - -fnBuildTrusteeWithSidA pBuildTrusteeWithSidA; -fnBuildTrusteeWithNameA pBuildTrusteeWithNameA; -fnConvertSidToStringSidA pConvertSidToStringSidA; -fnConvertStringSidToSidA pConvertStringSidToSidA; - -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" ); - ok( !strcmp( str, refs[i].refStr ), - "incorrect sid, expected %s, got %s\n", refs[i].refStr, str ); - if( 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(); -} - -START_TEST(security) -{ - init(); - if (!hmod) return; - test_sid(); - test_trustee(); - test_luid(); -} +/* + * 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 + +#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 = pGetFileSecurityA( directory,OWNER_SECURITY_INFORMATION,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(); +}