Author: jimtabor Date: Tue Dec 9 13:26:45 2008 New Revision: 37982
URL: http://svn.reactos.org/svn/reactos?rev=37982&view=rev Log: - Sync to date wine AdvApi32 cross tests.
Modified: trunk/rostests/winetests/advapi32/cred.c trunk/rostests/winetests/advapi32/crypt.c trunk/rostests/winetests/advapi32/registry.c trunk/rostests/winetests/advapi32/security.c trunk/rostests/winetests/advapi32/service.c
Modified: trunk/rostests/winetests/advapi32/cred.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/cred.c?... ============================================================================== --- trunk/rostests/winetests/advapi32/cred.c [iso-8859-1] (original) +++ trunk/rostests/winetests/advapi32/cred.c [iso-8859-1] Tue Dec 9 13:26:45 2008 @@ -97,12 +97,19 @@
SetLastError(0xdeadbeef); ret = pCredWriteA(&new_cred, 0); - ok(!ret, "CredWrite with username without domain should have failed\n"); - ok(GetLastError() == ERROR_BAD_USERNAME || - GetLastError() == ERROR_NO_SUCH_LOGON_SESSION || /* Vista */ - broken(GetLastError() == ERROR_IO_PENDING), - "CredWrite with username without domain should return ERROR_BAD_USERNAME" - "or ERROR_NO_SUCH_LOGON_SESSION not %d\n", GetLastError()); + if (ret) + { + /* Vista */ + ok(GetLastError() == ERROR_IO_PENDING, + "Expected ERROR_IO_PENDING, got %d\n", GetLastError()); + } + else + { + ok(GetLastError() == ERROR_BAD_USERNAME || + GetLastError() == ERROR_NO_SUCH_LOGON_SESSION, /* Vista */ + "CredWrite with username without domain should return ERROR_BAD_USERNAME" + "or ERROR_NO_SUCH_LOGON_SESSION not %d\n", GetLastError()); + }
new_cred.UserName = NULL; SetLastError(0xdeadbeef);
Modified: trunk/rostests/winetests/advapi32/crypt.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/crypt.c... ============================================================================== --- trunk/rostests/winetests/advapi32/crypt.c [iso-8859-1] (original) +++ trunk/rostests/winetests/advapi32/crypt.c [iso-8859-1] Tue Dec 9 13:26:45 2008 @@ -274,11 +274,11 @@ ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
dwLen = 1; - result = pCryptDecrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, &temp, &dwLen); + result = pCryptDecrypt(hKey, 0, TRUE, 0, &temp, &dwLen); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
dwLen = 1; - result = pCryptEncrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, &temp, &dwLen, 1); + result = pCryptEncrypt(hKey, 0, TRUE, 0, &temp, &dwLen, 1); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
result = pCryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey2); @@ -293,7 +293,7 @@ #endif
dwLen = 1; - result = pCryptExportKey(hKey, (HCRYPTPROV)NULL, 0, 0, &temp, &dwLen); + result = pCryptExportKey(hKey, 0, 0, 0, &temp, &dwLen); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
result = pCryptGenKey(hProv, CALG_RC4, 0, &hKey2); @@ -320,7 +320,7 @@ result = pCryptHashSessionKey(hHash, hKey, 0); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
- result = pCryptImportKey(hProv, &temp, 1, (HCRYPTKEY)NULL, 0, &hKey2); + result = pCryptImportKey(hProv, &temp, 1, 0, 0, &hKey2); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError());
if (pCryptSignHashW) @@ -560,59 +560,77 @@ LocalFree(provider); }
-static BOOL FindProvTypesRegVals(DWORD dwIndex, DWORD *pdwProvType, LPSTR *pszTypeName, +static BOOL FindProvTypesRegVals(DWORD *pdwIndex, DWORD *pdwProvType, LPSTR *pszTypeName, DWORD *pcbTypeName, DWORD *pdwTypeCount) { HKEY hKey; HKEY hSubKey; PSTR ch; - + LPSTR szName; + DWORD cbName; + BOOL ret = FALSE; + if (RegOpenKey(HKEY_LOCAL_MACHINE, "Software\Microsoft\Cryptography\Defaults\Provider Types", &hKey)) return FALSE; - - if (RegQueryInfoKey(hKey, NULL, NULL, NULL, pdwTypeCount, pcbTypeName, NULL, + + if (RegQueryInfoKey(hKey, NULL, NULL, NULL, pdwTypeCount, &cbName, 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, (LPBYTE)*pszTypeName, pcbTypeName)) - return FALSE; - + goto cleanup; + cbName++; + + if (!(szName = LocalAlloc(LMEM_ZEROINIT, cbName))) + goto cleanup; + + while (!RegEnumKeyEx(hKey, *pdwIndex, szName, &cbName, NULL, NULL, NULL, NULL)) + { + cbName++; + ch = szName + strlen(szName); + /* Convert "Type 000" to 0, etc/ */ + *pdwProvType = *(--ch) - '0'; + *pdwProvType += (*(--ch) - '0') * 10; + *pdwProvType += (*(--ch) - '0') * 100; + + if (RegOpenKey(hKey, szName, &hSubKey)) + break; + + if (!RegQueryValueEx(hSubKey, "TypeName", NULL, NULL, NULL, pcbTypeName)) + { + if (!(*pszTypeName = LocalAlloc(LMEM_ZEROINIT, *pcbTypeName))) + break; + + if (!RegQueryValueEx(hSubKey, "TypeName", NULL, NULL, (LPBYTE)*pszTypeName, pcbTypeName)) + { + ret = TRUE; + break; + } + + LocalFree(*pszTypeName); + } + + RegCloseKey(hSubKey); + + (*pdwIndex)++; + } + + if (!ret) + LocalFree(*pszTypeName); RegCloseKey(hSubKey); + LocalFree(szName); + +cleanup: RegCloseKey(hKey); - - return TRUE; + + return ret; }
static void test_enum_provider_types(void) { /* expected values */ - DWORD dwProvType; + DWORD dwProvType = 0; LPSTR pszTypeName = NULL; DWORD cbTypeName; DWORD dwTypeCount; - + /* actual values */ DWORD index = 0; DWORD provType; @@ -622,45 +640,47 @@ DWORD result; DWORD notNull = 5; DWORD notZeroFlags = 5; - + if(!pCryptEnumProviderTypesA) { - skip("CryptEnumProviderTypesA is not available\n"); - return; - } - - if (!FindProvTypesRegVals(index, &dwProvType, &pszTypeName, &cbTypeName, &dwTypeCount)) - { - skip("Could not find provider types in registry\n"); - return; - } - + skip("CryptEnumProviderTypesA is not available\n"); + return; + } + + if (!FindProvTypesRegVals(&index, &dwProvType, &pszTypeName, &cbTypeName, &dwTypeCount)) + { + skip("Could not find provider types in registry\n"); + return; + } + /* check pdwReserved for NULL */ result = pCryptEnumProviderTypesA(index, ¬Null, 0, &provType, typeName, &typeNameSize); - ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "expected %i, got %d\n", - ERROR_INVALID_PARAMETER, GetLastError()); - + ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", + GetLastError()); + /* check dwFlags == zero */ result = pCryptEnumProviderTypesA(index, NULL, notZeroFlags, &provType, typeName, &typeNameSize); - ok(!result && GetLastError()==NTE_BAD_FLAGS, "expected %i, got %d\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; + ok(!result && GetLastError()==NTE_BAD_FLAGS, "expected ERROR_INVALID_PARAMETER, got %d\n", + GetLastError());
/* 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); - + * result = TRUE, GetLastError() == 0xdeadbeef */ + if (0) + { + /* alloc provider type to half the size required + * cbTypeName holds the size required */ + typeNameSize = cbTypeName / 2; + if (!(typeName = ((LPSTR)LocalAlloc(LMEM_ZEROINIT, typeNameSize)))) + goto cleanup; + + SetLastError(0xdeadbeef); + result = pCryptEnumProviderTypesA(index, NULL, 0, &provType, typeName, &typeNameSize); + ok(!result && GetLastError()==ERROR_MORE_DATA, "expected 0/ERROR_MORE_DATA, got %d/%d\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 */ @@ -669,30 +689,31 @@ ; typeCount--; ok(typeCount==dwTypeCount, "expected %d, got %d\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 %d\n", - ERROR_NO_MORE_ITEMS, GetLastError()); - + ok(!result && GetLastError()==ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", + GetLastError());
/* check expected versus actual values returned */ result = pCryptEnumProviderTypesA(index, NULL, 0, &provType, NULL, &typeNameSize); ok(result && typeNameSize==cbTypeName, "expected %d, got %d\n", cbTypeName, typeNameSize); if (!(typeName = ((LPSTR)LocalAlloc(LMEM_ZEROINIT, typeNameSize)))) - return; - + goto cleanup; + typeNameSize = 0xdeadbeef; result = pCryptEnumProviderTypesA(index, NULL, 0, &provType, typeName, &typeNameSize); ok(result, "expected TRUE, got %d\n", result); ok(provType==dwProvType, "expected %d, got %d\n", dwProvType, provType); if (pszTypeName) - ok(!strcmp(pszTypeName, typeName), "expected %s, got %s\n", pszTypeName, typeName); + ok(!strcmp(pszTypeName, typeName), "expected %s, got %s\n", pszTypeName, typeName); ok(typeNameSize==cbTypeName, "expected %d, got %d\n", cbTypeName, typeNameSize); - + LocalFree(typeName); +cleanup: + LocalFree(pszTypeName); }
static BOOL FindDfltProvRegVals(DWORD dwProvType, DWORD dwFlags, LPSTR *pszProvName, DWORD *pcbProvName)
Modified: trunk/rostests/winetests/advapi32/registry.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/registr... ============================================================================== --- trunk/rostests/winetests/advapi32/registry.c [iso-8859-1] (original) +++ trunk/rostests/winetests/advapi32/registry.c [iso-8859-1] Tue Dec 9 13:26:45 2008 @@ -199,13 +199,14 @@ assert (!RegCreateKeyA( HKEY_CURRENT_USER, "Software\Wine\Test", &hkey_main )); }
-static void test_hkey_main_Value_A(LPCSTR name, LPCSTR string, +#define lok ok_(__FILE__, line) +#define test_hkey_main_Value_A(name, string, full_byte_len) _test_hkey_main_Value_A(__LINE__, name, string, full_byte_len) +static void _test_hkey_main_Value_A(int line, LPCSTR name, LPCSTR string, DWORD full_byte_len) { DWORD ret, type, cbData; DWORD str_byte_len; - LPSTR value; - static const char nA[]={'N', 0}; + BYTE* value;
type=0xdeadbeef; cbData=0xdeadbeef; @@ -215,43 +216,44 @@ SetLastError(0xdeadbeef); ret = RegQueryValueExA(hkey_main, name, NULL, &type, NULL, &cbData); GLE = GetLastError(); - ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%d\n", ret, GLE); + lok(ret == ERROR_SUCCESS, "RegQueryValueExA/1 failed: %d, GLE=%d\n", ret, GLE); /* It is wrong for the Ansi version to not be implemented */ ok(GLE == 0xdeadbeef, "RegQueryValueExA set GLE = %u\n", GLE); if(GLE == ERROR_CALL_NOT_IMPLEMENTED) return;
str_byte_len = (string ? lstrlenA(string) : 0) + 1; - ok(type == REG_SZ, "RegQueryValueExA returned type %d\n", type); - ok(cbData == full_byte_len || cbData == str_byte_len /* Win9x */, + lok(type == REG_SZ, "RegQueryValueExA/1 returned type %d\n", type); + lok(cbData == full_byte_len || cbData == str_byte_len /* Win9x */, "cbData=%d instead of %d or %d\n", cbData, full_byte_len, str_byte_len);
- value = HeapAlloc(GetProcessHeap(), 0, (cbData+2)*sizeof(*value)); - strcpy(value, nA); + value = HeapAlloc(GetProcessHeap(), 0, cbData+1); + memset(value, 0xbd, cbData+1); type=0xdeadbeef; - ret = RegQueryValueExA(hkey_main, name, NULL, &type, (BYTE*)value, &cbData); + ret = RegQueryValueExA(hkey_main, name, NULL, &type, value, &cbData); GLE = GetLastError(); - ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%d\n", ret, GLE); + lok(ret == ERROR_SUCCESS, "RegQueryValueExA/2 failed: %d, GLE=%d\n", ret, GLE); if (!string) { /* When cbData == 0, RegQueryValueExA() should not modify the buffer */ - ok(strcmp(value, nA) == 0 || (cbData == 1 && *value == '\0') /* Win9x */, - "RegQueryValueExA failed: '%s' != '%s'\n", value, string); + lok(*value == 0xbd || (cbData == 1 && *value == '\0') /* Win9x */, + "RegQueryValueExA overflowed: cbData=%u *value=%02x\n", cbData, *value); } else { - ok(memcmp(value, string, cbData) == 0, "RegQueryValueExA failed: %s/%d != %s/%d\n", - wine_debugstr_an(value, cbData), cbData, + lok(memcmp(value, string, cbData) == 0, "RegQueryValueExA/2 failed: %s/%d != %s/%d\n", + wine_debugstr_an((char*)value, cbData), cbData, wine_debugstr_an(string, full_byte_len), full_byte_len); + lok(*(value+cbData) == 0xbd, "RegQueryValueExA/2 overflowed at offset %u: %02x != bd\n", cbData, *(value+cbData)); } HeapFree(GetProcessHeap(), 0, value); }
-static void test_hkey_main_Value_W(LPCWSTR name, LPCWSTR string, +#define test_hkey_main_Value_W(name, string, full_byte_len) _test_hkey_main_Value_W(__LINE__, name, string, full_byte_len) +static void _test_hkey_main_Value_W(int line, LPCWSTR name, LPCWSTR string, DWORD full_byte_len) { DWORD ret, type, cbData; - LPWSTR value; - static const WCHAR nW[]={'N', 0}; + BYTE* value;
type=0xdeadbeef; cbData=0xdeadbeef; @@ -261,31 +263,33 @@ SetLastError(0xdeadbeef); ret = RegQueryValueExW(hkey_main, name, NULL, &type, NULL, &cbData); GLE = GetLastError(); - ok(ret == ERROR_SUCCESS, "RegQueryValueExW failed: %d, GLE=%d\n", ret, GLE); + lok(ret == ERROR_SUCCESS, "RegQueryValueExW/1 failed: %d, GLE=%d\n", ret, GLE); if(GLE == ERROR_CALL_NOT_IMPLEMENTED) { win_skip("RegQueryValueExW() is not implemented\n"); return; }
- ok(type == REG_SZ, "RegQueryValueExW returned type %d\n", type); - ok(cbData == full_byte_len, + lok(type == REG_SZ, "RegQueryValueExW/1 returned type %d\n", type); + lok(cbData == full_byte_len, "cbData=%d instead of %d\n", cbData, full_byte_len);
- value = HeapAlloc(GetProcessHeap(), 0, (cbData+2)*sizeof(*value)); - lstrcpyW(value, nW); + /* Give enough space to overflow by one WCHAR */ + value = HeapAlloc(GetProcessHeap(), 0, cbData+2); + memset(value, 0xbd, cbData+2); type=0xdeadbeef; - ret = RegQueryValueExW(hkey_main, name, NULL, &type, (BYTE*)value, &cbData); + ret = RegQueryValueExW(hkey_main, name, NULL, &type, value, &cbData); GLE = GetLastError(); - ok(ret == ERROR_SUCCESS, "RegQueryValueExW failed: %d, GLE=%d\n", ret, GLE); - if (!string) - { - /* When cbData == 0, RegQueryValueExW() should not modify the buffer */ - string=nW; - } - ok(memcmp(value, string, cbData) == 0, "RegQueryValueExW failed: %s/%d != %s/%d\n", - wine_debugstr_wn(value, cbData / sizeof(WCHAR)), cbData, - wine_debugstr_wn(string, full_byte_len / sizeof(WCHAR)), full_byte_len); + lok(ret == ERROR_SUCCESS, "RegQueryValueExW/2 failed: %d, GLE=%d\n", ret, GLE); + if (string) + { + lok(memcmp(value, string, cbData) == 0, "RegQueryValueExW failed: %s/%d != %s/%d\n", + wine_debugstr_wn((WCHAR*)value, cbData / sizeof(WCHAR)), cbData, + wine_debugstr_wn(string, full_byte_len / sizeof(WCHAR)), full_byte_len); + } + /* This implies that when cbData == 0, RegQueryValueExW() should not modify the buffer */ + lok(*(value+cbData) == 0xbd, "RegQueryValueExW/2 overflowed at %u: %02x != bd\n", cbData, *(value+cbData)); + lok(*(value+cbData+1) == 0xbd, "RegQueryValueExW/2 overflowed at %u+1: %02x != bd\n", cbData, *(value+cbData+1)); HeapFree(GetProcessHeap(), 0, value); }
@@ -957,6 +961,14 @@ ret == ERROR_FILE_NOT_FOUND /* Win9x,ME */ , "expected ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %d\n", ret);
+ hkResult = NULL; + ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, "\clsid", 0, KEY_QUERY_VALUE, &hkResult); + ok(ret == ERROR_SUCCESS || /* 2k/XP */ + ret == ERROR_BAD_PATHNAME || /* NT */ + ret == ERROR_FILE_NOT_FOUND /* Win9x,ME */ + , "expected ERROR_SUCCESS, ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %d\n", ret); + RegCloseKey(hkResult); + /* WOW64 flags */ hkResult = NULL; ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WOW64_32KEY, &hkResult); @@ -1304,6 +1316,87 @@ ok(size == sizeof(expected), "Got wrong size: %d\n", size);
cleanup: + RegDeleteKeyA(subkey, ""); + RegCloseKey(subkey); +} + +static void test_string_termination(void) +{ + HKEY subkey; + LSTATUS ret; + static const char string[] = "FullString"; + char name[11]; + BYTE buffer[11]; + DWORD insize, outsize, nsize; + + ret = RegCreateKeyA(hkey_main, "string_termination", &subkey); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + + /* Off-by-one RegSetValueExA -> adds a trailing '\0'! */ + insize=sizeof(string)-1; + ret = RegSetValueExA(subkey, "stringtest", 0, REG_SZ, (BYTE*)string, insize); + ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", ret); + outsize=insize; + ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize); + ok(ret == ERROR_MORE_DATA, "RegQueryValueExA returned: %d\n", ret); + + /* Off-by-two RegSetValueExA -> no trailing '\0', except on Win9x */ + insize=sizeof(string)-2; + ret = RegSetValueExA(subkey, "stringtest", 0, REG_SZ, (BYTE*)string, insize); + ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", ret); + outsize=0; + ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, NULL, &outsize); + ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", ret); + ok(outsize == insize || broken(outsize == sizeof(string)) /* Win9x */, + "wrong size %u != %u\n", outsize, insize); + + if (outsize == insize) + { + /* RegQueryValueExA may return a string with no trailing '\0' */ + outsize=insize; + memset(buffer, 0xbd, sizeof(buffer)); + ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize); + ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", ret); + ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize); + ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n", + wine_debugstr_an((char*)buffer, outsize), outsize, string); + ok(buffer[insize] == 0xbd, "buffer overflow at %u %02x\n", insize, buffer[insize]); + + /* RegQueryValueExA adds a trailing '\0' if there is room */ + outsize=insize+1; + memset(buffer, 0xbd, sizeof(buffer)); + ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize); + ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", ret); + ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize); + ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n", + wine_debugstr_an((char*)buffer, outsize), outsize, string); + ok(buffer[insize] == 0, "buffer overflow at %u %02x\n", insize, buffer[insize]); + + /* RegEnumValueA may return a string with no trailing '\0' */ + outsize=insize; + memset(buffer, 0xbd, sizeof(buffer)); + nsize=sizeof(name); + ret = RegEnumValueA(subkey, 0, name, &nsize, NULL, NULL, buffer, &outsize); + ok(ret == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", ret); + ok(strcmp(name, "stringtest") == 0, "wrong name: %s\n", name); + ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize); + ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n", + wine_debugstr_an((char*)buffer, outsize), outsize, string); + ok(buffer[insize] == 0xbd, "buffer overflow at %u %02x\n", insize, buffer[insize]); + + /* RegEnumValueA adds a trailing '\0' if there is room */ + outsize=insize+1; + memset(buffer, 0xbd, sizeof(buffer)); + nsize=sizeof(name); + ret = RegEnumValueA(subkey, 0, name, &nsize, NULL, NULL, buffer, &outsize); + ok(ret == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", ret); + ok(strcmp(name, "stringtest") == 0, "wrong name: %s\n", name); + ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize); + ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n", + wine_debugstr_an((char*)buffer, outsize), outsize, string); + ok(buffer[insize] == 0, "buffer overflow at %u %02x\n", insize, buffer[insize]); + } + RegDeleteKeyA(subkey, ""); RegCloseKey(subkey); } @@ -1398,6 +1491,7 @@ test_reg_close_key(); test_reg_delete_key(); test_reg_query_value(); + test_string_termination();
/* SaveKey/LoadKey require the SE_BACKUP_NAME privilege to be set */ if (set_privileges(SE_BACKUP_NAME, TRUE) &&
Modified: trunk/rostests/winetests/advapi32/security.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/securit... ============================================================================== --- trunk/rostests/winetests/advapi32/security.c [iso-8859-1] (original) +++ trunk/rostests/winetests/advapi32/security.c [iso-8859-1] Tue Dec 9 13:26:45 2008 @@ -81,10 +81,14 @@ typedef BOOL (WINAPI *fnConvertStringSidToSidA)( LPCSTR str, PSID pSid ); static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorA)(LPCSTR, DWORD, PSECURITY_DESCRIPTOR*, PULONG ); +static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorW)(LPCWSTR, DWORD, + PSECURITY_DESCRIPTOR*, PULONG ); static BOOL (WINAPI *pConvertSecurityDescriptorToStringSecurityDescriptorA)(PSECURITY_DESCRIPTOR, DWORD, SECURITY_INFORMATION, LPSTR *, PULONG ); typedef BOOL (WINAPI *fnGetFileSecurityA)(LPCSTR, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD); +typedef BOOL (WINAPI *fnSetFileSecurityA)(LPCSTR, SECURITY_INFORMATION, + PSECURITY_DESCRIPTOR); static DWORD (WINAPI *pGetNamedSecurityInfoA)(LPSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION, PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*); @@ -117,6 +121,7 @@ fnConvertSidToStringSidA pConvertSidToStringSidA; fnConvertStringSidToSidA pConvertStringSidToSidA; fnGetFileSecurityA pGetFileSecurityA; +fnSetFileSecurityA pSetFileSecurityA; fnRtlAdjustPrivilege pRtlAdjustPrivilege; fnCreateWellKnownSid pCreateWellKnownSid; fnDuplicateTokenEx pDuplicateTokenEx; @@ -144,8 +149,12 @@ pAddAuditAccessAceEx = (void *)GetProcAddress(hmod, "AddAuditAccessAceEx"); pConvertStringSecurityDescriptorToSecurityDescriptorA = (void *)GetProcAddress(hmod, "ConvertStringSecurityDescriptorToSecurityDescriptorA" ); + pConvertStringSecurityDescriptorToSecurityDescriptorW = + (void *)GetProcAddress(hmod, "ConvertStringSecurityDescriptorToSecurityDescriptorW" ); pConvertSecurityDescriptorToStringSecurityDescriptorA = (void *)GetProcAddress(hmod, "ConvertSecurityDescriptorToStringSecurityDescriptorA" ); + pGetFileSecurityA = (fnGetFileSecurityA)GetProcAddress(hmod, "GetFileSecurityA" ); + pSetFileSecurityA = (fnSetFileSecurityA)GetProcAddress(hmod, "SetFileSecurityA" ); pCreateWellKnownSid = (fnCreateWellKnownSid)GetProcAddress( hmod, "CreateWellKnownSid" ); pGetNamedSecurityInfoA = (void *)GetProcAddress(hmod, "GetNamedSecurityInfoA"); pMakeSelfRelativeSD = (void *)GetProcAddress(hmod, "MakeSelfRelativeSD"); @@ -495,7 +504,7 @@ #define SE_DEBUG_PRIVILEGE 20L #define SE_AUDIT_PRIVILEGE 21L #define SE_SYSTEM_ENVIRONMENT_PRIVILEGE 22L -#define SE_CHANGE_NOTIFY_PRIVILLEGE 23L +#define SE_CHANGE_NOTIFY_PRIVILEGE 23L #define SE_REMOTE_SHUTDOWN_PRIVILEGE 24L #define SE_UNDOCK_PRIVILEGE 25L #define SE_SYNC_AGENT_PRIVILEGE 26L @@ -570,7 +579,7 @@ "SeCreateTokenPrivilege (got %d, expected %d)\n", cchName, (int)strlen("SeCreateTokenPrivilege")); /* check known values */ - for (i = SE_MIN_WELL_KNOWN_PRIVILEGE; i < SE_MAX_WELL_KNOWN_PRIVILEGE; i++) + for (i = SE_MIN_WELL_KNOWN_PRIVILEGE; i <= SE_MAX_WELL_KNOWN_PRIVILEGE; i++) { luid.LowPart = i; cchName = sizeof(buf); @@ -625,7 +634,7 @@ { "SeDebugPrivilege", SE_DEBUG_PRIVILEGE }, { "SeAuditPrivilege", SE_AUDIT_PRIVILEGE }, { "SeSystemEnvironmentPrivilege", SE_SYSTEM_ENVIRONMENT_PRIVILEGE }, - { "SeChangeNotifyPrivilege", SE_CHANGE_NOTIFY_PRIVILLEGE }, + { "SeChangeNotifyPrivilege", SE_CHANGE_NOTIFY_PRIVILEGE }, { "SeRemoteShutdownPrivilege", SE_REMOTE_SHUTDOWN_PRIVILEGE }, { "SeUndockPrivilege", SE_UNDOCK_PRIVILEGE }, { "SeSyncAgentPrivilege", SE_SYNC_AGENT_PRIVILEGE }, @@ -690,31 +699,128 @@
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 %d\n", GetLastError()); + char wintmpdir [MAX_PATH]; + char path [MAX_PATH]; + char file [MAX_PATH]; + BOOL rc; + HANDLE fh; + DWORD sdSize; + DWORD retSize; + BYTE *sd; + SECURITY_INFORMATION const request = OWNER_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | DACL_SECURITY_INFORMATION; + + if (!pGetFileSecurityA) { + win_skip ("GetFileSecurity is not available\n"); + return; + } + + if (!pSetFileSecurityA) { + win_skip ("SetFileSecurity is not available\n"); + return; + } + + if (!GetTempPathA (sizeof (wintmpdir), wintmpdir)) { + win_skip ("GetTempPathA failed\n"); + return; + } + + /* Create a temporary directory and in it a temporary file */ + strcat (strcpy (path, wintmpdir), "rary"); + SetLastError(0xdeadbeef); + rc = CreateDirectoryA (path, NULL); + ok (rc || GetLastError() == ERROR_ALREADY_EXISTS, "CreateDirectoryA " + "failed for '%s' with %d\n", path, GetLastError()); + + strcat (strcpy (file, path), "\ess"); + SetLastError(0xdeadbeef); + fh = CreateFileA (file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); + ok (fh != INVALID_HANDLE_VALUE, "CreateFileA " + "failed for '%s' with %d\n", file, GetLastError()); + CloseHandle (fh); + + /* For the temporary file ... */ + + /* Get size needed */ + retSize = 0; + SetLastError(0xdeadbeef); + rc = pGetFileSecurityA (file, request, NULL, 0, &retSize); + if (!rc && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) { + win_skip("GetFileSecurityA is not implemented\n"); + goto cleanup; + } + ok (!rc, "GetFileSecurityA " + "was expected to fail for '%s'\n", file); + ok (GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetFileSecurityA " + "returned %d; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError()); + ok (retSize > sizeof (SECURITY_DESCRIPTOR), "GetFileSecurityA returned size %d\n", retSize); + + sdSize = retSize; + sd = HeapAlloc (GetProcessHeap (), 0, sdSize); + + /* Get security descriptor for real */ + retSize = -1; + SetLastError(0xdeadbeef); + rc = pGetFileSecurityA (file, request, sd, sdSize, &retSize); + ok (rc, "GetFileSecurityA " + "was not expected to fail '%s': %d\n", file, GetLastError()); + ok (retSize == sdSize || + broken(retSize == 0), /* NT4 */ + "GetFileSecurityA returned size %d; expected %d\n", retSize, sdSize); + + /* Use it to set security descriptor */ + SetLastError(0xdeadbeef); + rc = pSetFileSecurityA (file, request, sd); + ok (rc, "SetFileSecurityA " + "was not expected to fail '%s': %d\n", file, GetLastError()); + + HeapFree (GetProcessHeap (), 0, sd); + + /* Repeat for the temporary directory ... */ + + /* Get size needed */ + retSize = 0; + SetLastError(0xdeadbeef); + rc = pGetFileSecurityA (path, request, NULL, 0, &retSize); + ok (!rc, "GetFileSecurityA " + "was expected to fail for '%s'\n", path); + ok (GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetFileSecurityA " + "returned %d; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError()); + ok (retSize > sizeof (SECURITY_DESCRIPTOR), "GetFileSecurityA returned size %d\n", retSize); + + sdSize = retSize; + sd = HeapAlloc (GetProcessHeap (), 0, sdSize); + + /* Get security descriptor for real */ + retSize = -1; + SetLastError(0xdeadbeef); + rc = pGetFileSecurityA (path, request, sd, sdSize, &retSize); + ok (rc, "GetFileSecurityA " + "was not expected to fail '%s': %d\n", path, GetLastError()); + ok (retSize == sdSize || + broken(retSize == 0), /* NT4 */ + "GetFileSecurityA returned size %d; expected %d\n", retSize, sdSize); + + /* Use it to set security descriptor */ + SetLastError(0xdeadbeef); + rc = pSetFileSecurityA (path, request, sd); + ok (rc, "SetFileSecurityA " + "was not expected to fail '%s': %d\n", path, GetLastError()); + HeapFree (GetProcessHeap (), 0, sd); + + /* Old test */ + strcpy (wintmpdir, "\Should not exist"); + SetLastError(0xdeadbeef); + rc = pGetFileSecurityA (wintmpdir, OWNER_SECURITY_INFORMATION, NULL, 0, &sdSize); + ok (!rc, "GetFileSecurityA should fail for not existing directories/files\n"); + ok (GetLastError() == ERROR_FILE_NOT_FOUND, + "last error ERROR_FILE_NOT_FOUND expected, got %d\n", GetLastError()); + +cleanup: + /* Remove temporary file and directory */ + DeleteFileA(file); + RemoveDirectoryA(path); }
static void test_AccessCheck(void) @@ -1309,6 +1415,14 @@ real_dom_sizeW = MAX_PATH; ret = LookupAccountSidW(NULL, pUsersSid, accountW, &real_acc_sizeW, domainW, &real_dom_sizeW, &use); ok(ret, "LookupAccountSidW() Expected TRUE, got FALSE\n"); + + /* try an invalid system name */ + real_acc_sizeA = MAX_PATH; + real_dom_sizeA = MAX_PATH; + ret = LookupAccountSidA("deepthought", pUsersSid, accountA, &real_acc_sizeA, domainA, &real_dom_sizeA, &use); + ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n"); + ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* Vista */, + "LookupAccountSidA() Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %u\n", GetLastError());
/* native windows crashes if domainW or accountW is NULL */
@@ -1550,10 +1664,10 @@ { ok(!lstrcmp(account, user_name), "Expected %s, got %s\n", user_name, account); ok(!lstrcmp(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain); - ok(domain_size == domain_save - 1, "Expected %d, got %d\n", domain_save - 1, domain_size); - ok(lstrlen(domain) == domain_size, "Expected %d\n", lstrlen(domain)); - ok(sid_use == SidTypeUser, "Expected SidTypeUser, got %d\n", sid_use); - } + } + ok(domain_size == domain_save - 1, "Expected %d, got %d\n", domain_save - 1, domain_size); + ok(lstrlen(domain) == domain_size, "Expected %d, got %d\n", lstrlen(domain), domain_size); + ok(sid_use == SidTypeUser, "Expected SidTypeUser (%d), got %d\n", SidTypeUser, sid_use); domain_size = domain_save; sid_size = sid_save;
@@ -1568,12 +1682,10 @@ ok(ret, "Failed to lookup account name\n"); ok(sid_size != 0, "sid_size was zero\n"); ok(!lstrcmp(account, "Everyone"), "Expected Everyone, got %s\n", account); - todo_wine ok(!lstrcmp(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain); ok(domain_size == 0, "Expected 0, got %d\n", domain_size); - todo_wine ok(lstrlen(domain) == domain_size, "Expected %d, got %d\n", lstrlen(domain), domain_size); - ok(sid_use == SidTypeWellKnownGroup, "Expected SidTypeUser, got %d\n", sid_use); + ok(sid_use == SidTypeWellKnownGroup, "Expected SidTypeWellKnownGroup (%d), got %d\n", SidTypeWellKnownGroup, sid_use); domain_size = domain_save; }
@@ -1616,28 +1728,33 @@ sid_use = 0xcafebabe; SetLastError(0xdeadbeef); ret = LookupAccountNameA(NULL, NULL, NULL, &sid_size, NULL, &domain_size, &sid_use); - ok(!ret, "Expected 0, got %d\n", ret); - ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, - "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); - ok(sid_size != 0, "Expected non-zero sid size\n"); - ok(domain_size != 0, "Expected non-zero domain size\n"); - ok(sid_use == 0xcafebabe, "Expected 0xcafebabe, got %d\n", sid_use); - - psid = HeapAlloc(GetProcessHeap(), 0, sid_size); - domain = HeapAlloc(GetProcessHeap(), 0, domain_size); - - /* try NULL account name */ - ret = LookupAccountNameA(NULL, NULL, psid, &sid_size, domain, &domain_size, &sid_use); - get_sid_info(psid, &account, &sid_dom); - ok(ret, "Failed to lookup account name\n"); - todo_wine - { + if (!ret && GetLastError() != ERROR_NONE_MAPPED) + { + ok(!ret, "Expected 0, got %d\n", ret); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); + ok(sid_size != 0, "Expected non-zero sid size\n"); + ok(domain_size != 0, "Expected non-zero domain size\n"); + ok(sid_use == 0xcafebabe, "Expected 0xcafebabe, got %d\n", sid_use); + + psid = HeapAlloc(GetProcessHeap(), 0, sid_size); + domain = HeapAlloc(GetProcessHeap(), 0, domain_size); + + /* try NULL account name */ + ret = LookupAccountNameA(NULL, NULL, psid, &sid_size, domain, &domain_size, &sid_use); + get_sid_info(psid, &account, &sid_dom); + ok(ret, "Failed to lookup account name\n"); /* Using a fixed string will not work on different locales */ ok(!lstrcmp(account, domain), "Got %s for account and %s for domain, these should be the same\n", account, domain); - ok(sid_use == SidTypeDomain, "Expected SidTypeDomain, got %d\n", SidTypeDomain); - } + ok(sid_use == SidTypeDomain, "Expected SidTypeDomain (%d), got %d\n", SidTypeDomain, sid_use); + + HeapFree(GetProcessHeap(), 0, psid); + HeapFree(GetProcessHeap(), 0, domain); + } + else + win_skip("NULL account name doesn't work on NT4\n");
/* try an invalid account name */ SetLastError(0xdeadbeef); @@ -1645,17 +1762,22 @@ domain_size = 0; ret = LookupAccountNameA(NULL, "oogabooga", NULL, &sid_size, NULL, &domain_size, &sid_use); ok(!ret, "Expected 0, got %d\n", ret); - todo_wine - { - ok(GetLastError() == ERROR_NONE_MAPPED || - broken(GetLastError() == ERROR_TRUSTED_RELATIONSHIP_FAILURE), - "Expected ERROR_NONE_MAPPED, got %d\n", GetLastError()); - ok(sid_size == 0, "Expected 0, got %d\n", sid_size); - ok(domain_size == 0, "Expected 0, got %d\n", domain_size); - } - - HeapFree(GetProcessHeap(), 0, psid); - HeapFree(GetProcessHeap(), 0, domain); + ok(GetLastError() == ERROR_NONE_MAPPED || + broken(GetLastError() == ERROR_TRUSTED_RELATIONSHIP_FAILURE), + "Expected ERROR_NONE_MAPPED, got %d\n", GetLastError()); + ok(sid_size == 0, "Expected 0, got %d\n", sid_size); + ok(domain_size == 0, "Expected 0, got %d\n", domain_size); + + /* try an invalid system name */ + SetLastError(0xdeadbeef); + sid_size = 0; + domain_size = 0; + ret = LookupAccountNameA("deepthought", NULL, NULL, &sid_size, NULL, &domain_size, &sid_use); + ok(!ret, "Expected 0, got %d\n", ret); + ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* Vista */, + "Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %d\n", GetLastError()); + ok(sid_size == 0, "Expected 0, got %d\n", sid_size); + ok(domain_size == 0, "Expected 0, got %d\n", domain_size); }
static void test_security_descriptor(void) @@ -1962,7 +2084,7 @@ ret = GetTokenInformation(Token, TokenUser, NULL, 0, &Size); error = GetLastError(); ok(!ret && error == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenUser) should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", error); - User = (TOKEN_USER *)HeapAlloc(GetProcessHeap(), 0, Size); + User = HeapAlloc(GetProcessHeap(), 0, Size); ret = GetTokenInformation(Token, TokenUser, User, Size, &Size); ok(ret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError()); HeapFree(GetProcessHeap(), 0, User); @@ -1971,11 +2093,11 @@ ret = GetTokenInformation(Token, TokenPrivileges, NULL, 0, &Size); error = GetLastError(); ok(!ret && error == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", error); - Privileges = (TOKEN_PRIVILEGES *)HeapAlloc(GetProcessHeap(), 0, Size); + Privileges = HeapAlloc(GetProcessHeap(), 0, Size); ret = GetTokenInformation(Token, TokenPrivileges, Privileges, Size, &Size); ok(ret, "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
- PrivilegeSet = (PRIVILEGE_SET *)HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(PRIVILEGE_SET, Privilege[Privileges->PrivilegeCount])); + PrivilegeSet = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(PRIVILEGE_SET, Privilege[Privileges->PrivilegeCount])); PrivilegeSet->PrivilegeCount = Privileges->PrivilegeCount; memcpy(PrivilegeSet->Privilege, Privileges->Privileges, PrivilegeSet->PrivilegeCount * sizeof(PrivilegeSet->Privilege[0])); PrivilegeSet->Control = PRIVILEGE_SET_ALL_NECESSARY; @@ -2031,7 +2153,7 @@
if (!pSetEntriesInAclW) { - skip("SetEntriesInAclW is not available\n"); + win_skip("SetEntriesInAclW is not available\n"); return; }
@@ -2039,17 +2161,20 @@ res = pSetEntriesInAclW(0, NULL, NULL, &NewAcl); if(res == ERROR_CALL_NOT_IMPLEMENTED) { - skip("SetEntriesInAclW is not implemented\n"); + win_skip("SetEntriesInAclW is not implemented\n"); return; } ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res); - ok(NewAcl == NULL, "NewAcl=%p, expected NULL\n", NewAcl); + ok(NewAcl == NULL || + broken(NewAcl != NULL), /* NT4 */ + "NewAcl=%p, expected NULL\n", NewAcl); + LocalFree(NewAcl);
OldAcl = HeapAlloc(GetProcessHeap(), 0, 256); res = InitializeAcl(OldAcl, 256, ACL_REVISION); if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { - skip("ACLs not implemented - skipping tests\n"); + win_skip("ACLs not implemented - skipping tests\n"); HeapFree(GetProcessHeap(), 0, OldAcl); return; } @@ -2093,16 +2218,22 @@
ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_BAD_FORM; res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl); - ok(res == ERROR_INVALID_PARAMETER, "SetEntriesInAclW failed: %u\n", res); - ok(NewAcl == NULL, "returned acl wasn't NULL: %p\n", NewAcl); - LocalFree(NewAcl); + ok(res == ERROR_INVALID_PARAMETER || + broken(res == ERROR_NOT_SUPPORTED), /* NT4 */ + "SetEntriesInAclW failed: %u\n", res); + ok(NewAcl == NULL || + broken(NewAcl != NULL), /* NT4 */ + "returned acl wasn't NULL: %p\n", NewAcl);
ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_USER; ExplicitAccess.Trustee.MultipleTrusteeOperation = TRUSTEE_IS_IMPERSONATE; res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl); - ok(res == ERROR_INVALID_PARAMETER, "SetEntriesInAclW failed: %u\n", res); - ok(NewAcl == NULL, "returned acl wasn't NULL: %p\n", NewAcl); - LocalFree(NewAcl); + ok(res == ERROR_INVALID_PARAMETER || + broken(res == ERROR_NOT_SUPPORTED), /* NT4 */ + "SetEntriesInAclW failed: %u\n", res); + ok(NewAcl == NULL || + broken(NewAcl != NULL), /* NT4 */ + "returned acl wasn't NULL: %p\n", NewAcl);
ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; ExplicitAccess.grfAccessMode = SET_ACCESS; @@ -2175,6 +2306,7 @@ { BOOL ret; PSECURITY_DESCRIPTOR pSD; + static const WCHAR Blank[] = { 0 };
if (!pConvertStringSecurityDescriptorToSecurityDescriptorA) { @@ -2255,10 +2387,50 @@ SetLastError(0xdeadbeef); ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( "D:(A;;ROB;;;WD)", SDDL_REVISION_1, &pSD, NULL); - todo_wine ok(!ret && GetLastError() == ERROR_INVALID_ACL, "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_ACL instead of %d\n", GetLastError()); + + /* test behaviour with NULL parameters */ + SetLastError(0xdeadbeef); + ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( + NULL, 0xdeadbeef, &pSD, NULL); + todo_wine + ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, + "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n", + GetLastError()); + + SetLastError(0xdeadbeef); + ret = pConvertStringSecurityDescriptorToSecurityDescriptorW( + NULL, 0xdeadbeef, &pSD, NULL); + ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, + "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n", + GetLastError()); + + SetLastError(0xdeadbeef); + ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( + "D:(A;;ROB;;;WD)", 0xdeadbeef, NULL, NULL); + ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, + "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n", + GetLastError()); + + SetLastError(0xdeadbeef); + ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( + "D:(A;;ROB;;;WD)", SDDL_REVISION_1, NULL, NULL); + ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, + "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n", + GetLastError()); + + /* test behaviour with empty strings */ + SetLastError(0xdeadbeef); + ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( + "", SDDL_REVISION_1, &pSD, NULL); + ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = pConvertStringSecurityDescriptorToSecurityDescriptorW( + Blank, SDDL_REVISION_1, &pSD, NULL); + ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
/* test ACE string SID */ SetLastError(0xdeadbeef); @@ -2386,11 +2558,100 @@ } }
+static void test_SetSecurityDescriptorControl (PSECURITY_DESCRIPTOR sec) +{ + SECURITY_DESCRIPTOR_CONTROL ref; + SECURITY_DESCRIPTOR_CONTROL test; + + SECURITY_DESCRIPTOR_CONTROL const mutable + = SE_DACL_AUTO_INHERIT_REQ | SE_SACL_AUTO_INHERIT_REQ + | SE_DACL_AUTO_INHERITED | SE_SACL_AUTO_INHERITED + | SE_DACL_PROTECTED | SE_SACL_PROTECTED + | 0x00000040 | 0x00000080 /* not defined in winnt.h */ + ; + SECURITY_DESCRIPTOR_CONTROL const immutable + = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED + | SE_DACL_PRESENT | SE_DACL_DEFAULTED + | SE_SACL_PRESENT | SE_SACL_DEFAULTED + | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE + ; + + int bit; + DWORD dwRevision; + LPCSTR fmt = "Expected error %s, got %u\n"; + + GetSecurityDescriptorControl (sec, &ref, &dwRevision); + + /* The mutable bits are mutable regardless of the truth of + SE_DACL_PRESENT and/or SE_SACL_PRESENT */ + + /* Check call barfs if any bit-of-interest is immutable */ + for (bit = 0; bit < 16; ++bit) + { + SECURITY_DESCRIPTOR_CONTROL const bitOfInterest = 1 << bit; + SECURITY_DESCRIPTOR_CONTROL setOrClear = ref & bitOfInterest; + + SECURITY_DESCRIPTOR_CONTROL ctrl; + + DWORD dwExpect = (bitOfInterest & immutable) + ? ERROR_INVALID_PARAMETER : 0xbebecaca; + LPCSTR strExpect = (bitOfInterest & immutable) + ? "ERROR_INVALID_PARAMETER" : "0xbebecaca"; + + ctrl = (bitOfInterest & mutable) ? ref + bitOfInterest : ref; + setOrClear ^= bitOfInterest; + SetLastError (0xbebecaca); + pSetSecurityDescriptorControl (sec, bitOfInterest, setOrClear); + ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ()); + GetSecurityDescriptorControl(sec, &test, &dwRevision); + expect_eq(test, ctrl, int, "%x"); + + ctrl = ref; + setOrClear ^= bitOfInterest; + SetLastError (0xbebecaca); + pSetSecurityDescriptorControl (sec, bitOfInterest, setOrClear); + ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ()); + GetSecurityDescriptorControl (sec, &test, &dwRevision); + expect_eq(test, ref, int, "%x"); + } + + /* Check call barfs if any bit-to-set is immutable + even when not a bit-of-interest */ + for (bit = 0; bit < 16; ++bit) + { + SECURITY_DESCRIPTOR_CONTROL const bitsOfInterest = mutable; + SECURITY_DESCRIPTOR_CONTROL setOrClear = ref & bitsOfInterest; + + SECURITY_DESCRIPTOR_CONTROL ctrl; + + DWORD dwExpect = ((1 << bit) & immutable) + ? ERROR_INVALID_PARAMETER : 0xbebecaca; + LPCSTR strExpect = ((1 << bit) & immutable) + ? "ERROR_INVALID_PARAMETER" : "0xbebecaca"; + + ctrl = ((1 << bit) & immutable) ? test : ref | mutable; + setOrClear ^= bitsOfInterest; + SetLastError (0xbebecaca); + pSetSecurityDescriptorControl (sec, bitsOfInterest, setOrClear | (1 << bit)); + ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ()); + GetSecurityDescriptorControl(sec, &test, &dwRevision); + expect_eq(test, ctrl, int, "%x"); + + ctrl = ((1 << bit) & immutable) ? test : ref | (1 << bit); + setOrClear ^= bitsOfInterest; + SetLastError (0xbebecaca); + pSetSecurityDescriptorControl (sec, bitsOfInterest, setOrClear | (1 << bit)); + ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ()); + GetSecurityDescriptorControl(sec, &test, &dwRevision); + expect_eq(test, ctrl, int, "%x"); + } +} + static void test_PrivateObjectSecurity(void) { SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION; SECURITY_DESCRIPTOR_CONTROL ctrl; - PSECURITY_DESCRIPTOR sec = NULL; + PSECURITY_DESCRIPTOR sec; DWORD dwDescSize; DWORD dwRevision; DWORD retSize; @@ -2407,13 +2668,33 @@ ok(pConvertStringSecurityDescriptorToSecurityDescriptorA( "O:SY" "G:S-1-5-21-93476-23408-4576" + "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)" + "(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)" + "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", + SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n"); + + test_SetSecurityDescriptorControl(sec); + + LocalFree(sec); + + ok(pConvertStringSecurityDescriptorToSecurityDescriptorA( + "O:SY" + "G:S-1-5-21-93476-23408-4576", + SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n"); + + test_SetSecurityDescriptorControl(sec); + + LocalFree(sec); + + ok(pConvertStringSecurityDescriptorToSecurityDescriptorA( + "O:SY" + "G:S-1-5-21-93476-23408-4576" "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)" "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n"); buf = HeapAlloc(GetProcessHeap(), 0, dwDescSize); - DbgPrint("Received %p\n", sec); pSetSecurityDescriptorControl(sec, SE_DACL_PROTECTED, SE_DACL_PROTECTED); GetSecurityDescriptorControl(sec, &ctrl, &dwRevision); - todo_wine expect_eq(ctrl, 0x9014, int, "%x"); + expect_eq(ctrl, 0x9014, int, "%x");
ok(GetPrivateObjectSecurity(sec, GROUP_SECURITY_INFORMATION, buf, dwDescSize, &retSize), "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError()); @@ -2488,11 +2769,17 @@ ret = IsValidAcl(pAcl); ok(ret, "IsValidAcl failed with error %d\n", GetLastError());
+ SetLastError(0xdeadbeef); ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION4); - ok(ret, "InitializeAcl(ACL_REVISION4) failed with error %d\n", GetLastError()); - - ret = IsValidAcl(pAcl); - ok(ret, "IsValidAcl failed with error %d\n", GetLastError()); + if (GetLastError() != ERROR_INVALID_PARAMETER) + { + ok(ret, "InitializeAcl(ACL_REVISION4) failed with error %d\n", GetLastError()); + + ret = IsValidAcl(pAcl); + ok(ret, "IsValidAcl failed with error %d\n", GetLastError()); + } + else + win_skip("ACL_REVISION4 is not implemented on NT4\n");
SetLastError(0xdeadbeef); ret = InitializeAcl(pAcl, sizeof(buffer), -1); @@ -2539,6 +2826,13 @@ ok(IsValidAcl(dacl), "GetSecurityInfo\n");
LocalFree(sd); + + if (!pCreateWellKnownSid) + { + win_skip("NULL parameter test would crash on NT4\n"); + CloseHandle(obj); + return; + }
/* If we don't ask for the security descriptor, Windows will still give us the other stuff, leaving us no way to free it. */
Modified: trunk/rostests/winetests/advapi32/service.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/service... ============================================================================== --- trunk/rostests/winetests/advapi32/service.c [iso-8859-1] (original) +++ trunk/rostests/winetests/advapi32/service.c [iso-8859-1] Tue Dec 9 13:26:45 2008 @@ -564,7 +564,7 @@ displaysize = tempsizeW / 2; ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize); ok(!ret, "Expected failure\n"); - ok(displaysize = tempsizeW, "Expected the needed buffersize\n"); + ok(displaysize == tempsizeW, "Expected the needed buffersize\n"); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
@@ -573,7 +573,7 @@ displaysize = tempsizeW; ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize); ok(!ret, "Expected failure\n"); - ok(displaysize = tempsizeW, "Expected the needed buffersize\n"); + ok(displaysize == tempsizeW, "Expected the needed buffersize\n"); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
@@ -649,7 +649,7 @@
/* Delete the service */ ret = DeleteService(svc_handle); - ok(ret, "Expected success\n"); + ok(ret, "Expected success (err=%d)\n", GetLastError());
CloseServiceHandle(svc_handle); CloseServiceHandle(scm_handle); @@ -882,7 +882,7 @@ /* Only info level is correct. It looks like the buffer/size is checked second */ SetLastError(0xdeadbeef); ret = pQueryServiceStatusEx(NULL, 0, NULL, 0, &needed); - /* NT4 checks the handle first */ + /* NT4 and Wine check the handle first */ if (GetLastError() != ERROR_INVALID_HANDLE) { ok(!ret, "Expected failure\n"); @@ -893,7 +893,7 @@ }
/* Pass a correct buffer and buffersize but a NULL handle */ - statusproc = HeapAlloc(GetProcessHeap(), 0, needed); + statusproc = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS)); bufsize = needed; SetLastError(0xdeadbeef); ret = pQueryServiceStatusEx(NULL, 0, (BYTE*)statusproc, bufsize, &needed); @@ -1985,7 +1985,7 @@
/* Check if we can close the handle to the Service Control Manager */ ret = CloseServiceHandle(scm_handle); - ok(ret, "Expected success\n"); + ok(ret, "Expected success (err=%d)\n", GetLastError());
/* Get a new handle to the Service Control Manager */ scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL); @@ -1997,7 +1997,7 @@
/* Delete the service */ ret = DeleteService(svc_handle4); - ok(ret, "Expected success\n"); + ok(ret, "Expected success (err=%d)\n", GetLastError());
/* We cannot create the same service again as it's still marked as 'being deleted'. * The reason is that we still have 4 open handles to this service even though we @@ -2023,13 +2023,13 @@
/* Close all the handles to the service and try again */ ret = CloseServiceHandle(svc_handle4); - ok(ret, "Expected success\n"); + ok(ret, "Expected success (err=%d)\n", GetLastError()); ret = CloseServiceHandle(svc_handle3); - ok(ret, "Expected success\n"); + ok(ret, "Expected success (err=%d)\n", GetLastError()); ret = CloseServiceHandle(svc_handle2); - ok(ret, "Expected success\n"); + ok(ret, "Expected success (err=%d)\n", GetLastError()); ret = CloseServiceHandle(svc_handle1); - ok(ret, "Expected success\n"); + ok(ret, "Expected success (err=%d)\n", GetLastError());
/* Wait a while. Doing a CreateService too soon will result again * in an ERROR_SERVICE_MARKED_FOR_DELETE error. @@ -2044,7 +2044,7 @@
/* Delete the service */ ret = DeleteService(svc_handle5); - ok(ret, "Expected success\n"); + ok(ret, "Expected success (err=%d)\n", GetLastError());
/* Wait a while. Just in case one of the following tests does a CreateService again */ Sleep(1000);