sync advapi32_winetest to wine 1.1.4

svn path=/trunk/; revision=36247
This commit is contained in:
Christoph von Wittich 2008-09-14 18:24:25 +00:00
parent 2435f146c3
commit 2d4aadb83f
7 changed files with 1027 additions and 53 deletions

View file

@ -97,8 +97,12 @@ static void test_CredWriteA(void)
SetLastError(0xdeadbeef);
ret = pCredWriteA(&new_cred, 0);
ok(!ret && ( 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());
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());
new_cred.UserName = NULL;
SetLastError(0xdeadbeef);
@ -175,10 +179,12 @@ static void test_generic(void)
{
if (!strcmp(creds[i]->TargetName, TEST_TARGET_NAME))
{
ok(creds[i]->Type == CRED_TYPE_GENERIC, "expected creds[%d]->Type CRED_TYPE_GENERIC but got %d\n", i, creds[i]->Type);
ok(creds[i]->Type == CRED_TYPE_GENERIC ||
creds[i]->Type == CRED_TYPE_DOMAIN_PASSWORD, /* Vista */
"expected creds[%d]->Type CRED_TYPE_GENERIC or CRED_TYPE_DOMAIN_PASSWORD but got %d\n", i, creds[i]->Type);
ok(!creds[i]->Flags, "expected creds[%d]->Flags 0 but got 0x%x\n", i, creds[i]->Flags);
ok(!strcmp(creds[i]->Comment, "Comment"), "expected creds[%d]->Comment \"Comment\" but got \"%s\"\n", i, creds[i]->Comment);
check_blob(__LINE__, CRED_TYPE_GENERIC, creds[i]);
check_blob(__LINE__, creds[i]->Type, creds[i]);
ok(creds[i]->Persist, "expected creds[%d]->Persist CRED_PERSIST_ENTERPRISE but got %d\n", i, creds[i]->Persist);
ok(!strcmp(creds[i]->UserName, "winetest"), "expected creds[%d]->UserName \"winetest\" but got \"%s\"\n", i, creds[i]->UserName);
found = TRUE;
@ -216,6 +222,12 @@ static void test_domain_password(DWORD cred_type)
new_cred.TargetAlias = NULL;
new_cred.UserName = (char *)"test\\winetest";
ret = pCredWriteA(&new_cred, 0);
if (!ret && GetLastError() == ERROR_NO_SUCH_LOGON_SESSION)
{
skip("CRED_TYPE_DOMAIN_PASSWORD credentials are not supported "
"or are disabled. Skipping\n");
return;
}
ok(ret, "CredWriteA failed with error %d\n", GetLastError());
ret = pCredEnumerateA(NULL, 0, &count, &creds);

View file

@ -903,7 +903,7 @@ static void test_machine_guid(void)
/* Create and release a provider */
ret = pCryptAcquireContextA(&hCryptProv, szKeySet, NULL, PROV_RSA_FULL, 0);
ok(ret, "CryptAcquireContextA failed: %08x\n", GetLastError());
CryptReleaseContext(hCryptProv, 0);
pCryptReleaseContext(hCryptProv, 0);
if (restoreGuid)
RegSetValueExA(key, "MachineGuid", 0, REG_SZ, (const BYTE *)originalGuid,

View file

@ -348,18 +348,24 @@ static void test_SystemFunction005(void)
out.Length = 0;
out.MaximumLength = 0;
r = pSystemFunction005(&out, &key, &res);
ok(r == STATUS_SUCCESS, "function failed\n");
ok(r == STATUS_SUCCESS ||
r == STATUS_INVALID_PARAMETER_1, /* Vista */
"Expected STATUS_SUCCESS or STATUS_INVALID_PARAMETER_1, got %08x\n", r);
ok(res.Length == in.Length, "Length wrong\n");
ok(!memcmp(res.Buffer, in.Buffer, in.Length), "data wrong\n");
res.MaximumLength = 0;
r = pSystemFunction005(&out, &key, &res);
ok(r == STATUS_BUFFER_TOO_SMALL, "function failed\n");
ok(r == STATUS_BUFFER_TOO_SMALL ||
r == STATUS_INVALID_PARAMETER_1, /* Vista */
"Expected STATUS_BUFFER_TOO_SMALL or STATUS_INVALID_PARAMETER_1, got %08x\n", r);
key.Length = 1;
r = pSystemFunction005(&out, &key, &res);
ok(r == STATUS_UNKNOWN_REVISION, "function failed\n");
ok(r == STATUS_UNKNOWN_REVISION ||
r == STATUS_INVALID_PARAMETER_1, /* Vista */
"Expected STATUS_UNKNOWN_REVISION or STATUS_INVALID_PARAMETER_1, got %08x\n", r);
key.Length = 0;
r = pSystemFunction005(&out, &key, &res);

View file

@ -30,10 +30,11 @@
#include "sddl.h"
#include "winnls.h"
#include "objbase.h"
#define INITGUID
#include "guiddef.h"
#include "initguid.h"
#include "wine/test.h"
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
static HMODULE hadvapi32;
static NTSTATUS (WINAPI *pLsaClose)(LSA_HANDLE);
static NTSTATUS (WINAPI *pLsaFreeMemory)(PVOID);
@ -95,7 +96,6 @@ static void test_lsa(void)
status = pLsaQueryInformationPolicy(handle, PolicyPrimaryDomainInformation, (PVOID*)&primary_domain_info);
ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy(PolicyPrimaryDomainInformation) failed, returned 0x%08x\n", status);
if (status == STATUS_SUCCESS) {
ok(primary_domain_info->Sid==0,"Sid should be NULL on the local computer\n");
if (primary_domain_info->Sid) {
LPSTR strsid;
if (pConvertSidToStringSidA(primary_domain_info->Sid, &strsid))
@ -115,6 +115,8 @@ static void test_lsa(void)
else
trace("invalid sid\n");
}
else
trace("Running on a standalone system.\n");
pLsaFreeMemory((LPVOID)primary_domain_info);
}
@ -129,8 +131,6 @@ static void test_lsa(void)
ok(status == STATUS_SUCCESS || status == STATUS_INVALID_PARAMETER,
"LsaQueryInformationPolicy(PolicyDnsDomainInformation) failed, returned 0x%08x\n", status);
if (status == STATUS_SUCCESS) {
ok(IsEqualGUID(&dns_domain_info->DomainGuid, &GUID_NULL), "DomainGUID should be GUID_NULL on local computer\n");
ok(dns_domain_info->Sid==0,"Sid should be NULL on the local computer\n");
if (dns_domain_info->Sid || !IsEqualGUID(&dns_domain_info->DomainGuid, &GUID_NULL)) {
LPSTR strsid = NULL;
LPSTR name = NULL;
@ -169,6 +169,8 @@ static void test_lsa(void)
LocalFree( guidstr );
LocalFree( strsid );
}
else
trace("Running on a standalone system.\n");
pLsaFreeMemory((LPVOID)dns_domain_info);
}

View file

@ -159,9 +159,8 @@ static const char *wine_debugstr_wn( const WCHAR *str, int n )
#define ADVAPI32_GET_PROC(func) \
p ## func = (void*)GetProcAddress(hadvapi32, #func); \
if(!p ## func) \
trace("GetProcAddress(%s) failed\n", #func);
p ## func = (void*)GetProcAddress(hadvapi32, #func);
static void InitFunctionPtrs(void)
{
@ -263,7 +262,11 @@ static void test_hkey_main_Value_W(LPCWSTR name, LPCWSTR string,
ret = RegQueryValueExW(hkey_main, name, NULL, &type, NULL, &cbData);
GLE = GetLastError();
ok(ret == ERROR_SUCCESS, "RegQueryValueExW failed: %d, GLE=%d\n", ret, GLE);
if(GLE == ERROR_CALL_NOT_IMPLEMENTED) return;
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,
@ -328,13 +331,21 @@ static void test_set_value(void)
test_hkey_main_Value_A(NULL, substring2A, sizeof(substring2A));
test_hkey_main_Value_W(NULL, substring2W, sizeof(substring2W));
/* only REG_SZ is supported */
/* only REG_SZ is supported on NT*/
ret = RegSetValueA(hkey_main, NULL, REG_BINARY, string2A, sizeof(string2A));
ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueA should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
/* NT: ERROR_INVALID_PARAMETER, 9x: ERROR_SUCCESS */
ok(ret == ERROR_INVALID_PARAMETER || broken(ret == ERROR_SUCCESS),
"got %d (expected ERROR_INVALID_PARAMETER or ERROR_SUCCESS)\n", ret);
ret = RegSetValueA(hkey_main, NULL, REG_EXPAND_SZ, string2A, sizeof(string2A));
ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueA should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
/* NT: ERROR_INVALID_PARAMETER, 9x: ERROR_SUCCESS */
ok(ret == ERROR_INVALID_PARAMETER || broken(ret == ERROR_SUCCESS),
"got %d (expected ERROR_INVALID_PARAMETER or ERROR_SUCCESS)\n", ret);
ret = RegSetValueA(hkey_main, NULL, REG_MULTI_SZ, string2A, sizeof(string2A));
ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueA should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
/* NT: ERROR_INVALID_PARAMETER, 9x: ERROR_SUCCESS */
ok(ret == ERROR_INVALID_PARAMETER || broken(ret == ERROR_SUCCESS),
"got %d (expected ERROR_INVALID_PARAMETER or ERROR_SUCCESS)\n", ret);
/* Test RegSetValueExA with a 'zero-byte' string (as Office 2003 does).
* Surprisingly enough we're supposed to get zero bytes out of it.
@ -433,7 +444,7 @@ static void create_test_entries(void)
"RegSetValueExA failed\n");
ok(!RegSetValueExA(hkey_main,"TP1_SZ",0,REG_SZ, (const BYTE *)sTestpath1, strlen(sTestpath1)+1),
"RegSetValueExA failed\n");
ok(!RegSetValueExA(hkey_main,"TP1_ZB_SZ",0,REG_SZ, NULL, 0),
ok(!RegSetValueExA(hkey_main,"TP1_ZB_SZ",0,REG_SZ, (const BYTE *)"", 0),
"RegSetValueExA failed\n");
ok(!RegSetValueExA(hkey_main,"TP2_EXP_SZ",0,REG_EXPAND_SZ, (const BYTE *)sTestpath2, strlen(sTestpath2)+1),
"RegSetValueExA failed\n");
@ -556,7 +567,7 @@ static void test_enum_value(void)
res = RegSetValueExW( test_key, testW, 0, REG_SZ, (const BYTE *)foobarW, 7*sizeof(WCHAR) );
if (res==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
{
skip("RegSetValueExW is not implemented\n");
win_skip("RegSetValueExW is not implemented\n");
goto cleanup;
}
ok( res == 0, "RegSetValueExW failed error %d\n", res );
@ -675,7 +686,7 @@ static void test_get_value(void)
if(!pRegGetValueA)
{
skip("RegGetValue not available on this platform\n");
win_skip("RegGetValue not available on this platform\n");
return;
}
@ -775,7 +786,7 @@ static void test_get_value(void)
ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ, &type, NULL, &size);
ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
/* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
ok(size == strlen(sTestpath1)+1 || size == strlen(sTestpath1)+2,
ok(size == strlen(sTestpath1)+1 || broken(size == strlen(sTestpath1)+2),
"strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
ok(type == REG_SZ, "type=%d\n", type);
@ -816,7 +827,7 @@ static void test_get_value(void)
ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size);
ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
/* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath1 length + 1 here. */
ok((size == strlen(expanded)+1) || (size == strlen(sTestpath1)+1),
ok(size == strlen(expanded)+1 || broken(size == strlen(sTestpath1)+1),
"strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded), lstrlenA(sTestpath1), size);
ok(type == REG_SZ, "type=%d\n", type);
ok(!strcmp(expanded, buf), "expanded=\"%s\" buf=\"%s\"\n", expanded, buf);
@ -826,7 +837,7 @@ static void test_get_value(void)
ret = pRegGetValueA(hkey_main, NULL, "TP2_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size);
ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
/* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath2 length + 1 here. */
ok((size == strlen(expanded2)+1) || (size == strlen(sTestpath2)+1),
ok(size == strlen(expanded2)+1 || broken(size == strlen(sTestpath2)+1),
"strlen(expanded2)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded2), lstrlenA(sTestpath2), size);
ok(type == REG_SZ, "type=%d\n", type);
ok(!strcmp(expanded2, buf), "expanded2=\"%s\" buf=\"%s\"\n", expanded2, buf);
@ -844,7 +855,7 @@ static void test_get_value(void)
ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND, NULL, NULL, &size);
ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
/* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
ok(size == strlen(sTestpath1)+1 || size == strlen(sTestpath1)+2,
ok(size == strlen(sTestpath1)+1 || broken(size == strlen(sTestpath1)+2),
"strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
/* Query REG_EXPAND_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (type mismatch) */
@ -854,6 +865,16 @@ static void test_get_value(void)
/* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ (not allowed without RRF_NOEXPAND) */
ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ, NULL, NULL, NULL);
ok(ret == ERROR_INVALID_PARAMETER, "ret=%d\n", ret);
/* Query REG_EXPAND_SZ using RRF_RT_ANY */
buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_ANY, &type, buf, &size);
ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
/* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath1 length + 1 here. */
ok(size == strlen(expanded)+1 || broken(size == strlen(sTestpath1)+1),
"strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded), lstrlenA(sTestpath1), size);
ok(type == REG_SZ, "type=%d\n", type);
ok(!strcmp(expanded, buf), "expanded=\"%s\" buf=\"%s\"\n", expanded, buf);
}
static void test_reg_open_key(void)
@ -935,6 +956,19 @@ static void test_reg_open_key(void)
ok(ret == ERROR_BAD_PATHNAME || /* NT/2k/XP */
ret == ERROR_FILE_NOT_FOUND /* Win9x,ME */
, "expected ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %d\n", ret);
/* WOW64 flags */
hkResult = NULL;
ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WOW64_32KEY, &hkResult);
ok((ret == ERROR_SUCCESS && hkResult != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */),
"RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret);
RegCloseKey(hkResult);
hkResult = NULL;
ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WOW64_64KEY, &hkResult);
ok((ret == ERROR_SUCCESS && hkResult != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */),
"RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret);
RegCloseKey(hkResult);
}
static void test_reg_create_key(void)
@ -960,6 +994,19 @@ static void test_reg_create_key(void)
ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
RegDeleteKey(hkey1, NULL);
}
/* WOW64 flags - open an existing key */
hkey1 = NULL;
ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, KEY_READ|KEY_WOW64_32KEY, NULL, &hkey1, NULL);
ok((ret == ERROR_SUCCESS && hkey1 != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */),
"RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret);
RegCloseKey(hkey1);
hkey1 = NULL;
ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, KEY_READ|KEY_WOW64_64KEY, NULL, &hkey1, NULL);
ok((ret == ERROR_SUCCESS && hkey1 != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */),
"RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret);
RegCloseKey(hkey1);
}
static void test_reg_close_key(void)
@ -1124,7 +1171,7 @@ static void test_regconnectregistry( void)
schnd = OpenSCManagerA( compName, NULL, GENERIC_READ);
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
skip("OpenSCManagerA is not implemented\n");
win_skip("OpenSCManagerA is not implemented\n");
return;
}
@ -1157,7 +1204,9 @@ static void test_reg_query_value(void)
SetLastError(0xdeadbeef);
size = MAX_PATH;
ret = RegQueryValueA((HKEY)0xcafebabe, "subkey", val, &size);
ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 98 returns BADKEY */
ok(ret == ERROR_INVALID_HANDLE ||
ret == ERROR_BADKEY || /* Windows 98 returns BADKEY */
ret == ERROR_ACCESS_DENIED, /* non-admin winxp */
"Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
@ -1218,7 +1267,7 @@ static void test_reg_query_value(void)
ret = RegQueryValueW(subkey, NULL, valW, &size);
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
skip("RegQueryValueW is not implemented\n");
win_skip("RegQueryValueW is not implemented\n");
goto cleanup;
}
ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
@ -1266,7 +1315,7 @@ static void test_reg_delete_tree(void)
LONG size, ret;
if(!pRegDeleteTreeA) {
skip("Skipping RegDeleteTreeA tests, function not present\n");
win_skip("Skipping RegDeleteTreeA tests, function not present\n");
return;
}

View file

@ -101,6 +101,8 @@ static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,U
static DWORD (WINAPI *pSetEntriesInAclW)(ULONG, PEXPLICIT_ACCESSW, PACL, PACL*);
static BOOL (WINAPI *pSetSecurityDescriptorControl)(PSECURITY_DESCRIPTOR, SECURITY_DESCRIPTOR_CONTROL,
SECURITY_DESCRIPTOR_CONTROL);
static DWORD (WINAPI *pGetSecurityInfo)(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*);
static HMODULE hmod;
static int myARGC;
@ -149,6 +151,7 @@ static void init(void)
pMakeSelfRelativeSD = (void *)GetProcAddress(hmod, "MakeSelfRelativeSD");
pSetEntriesInAclW = (void *)GetProcAddress(hmod, "SetEntriesInAclW");
pSetSecurityDescriptorControl = (void *)GetProcAddress(hmod, "SetSecurityDescriptorControl");
pGetSecurityInfo = (void *)GetProcAddress(hmod, "GetSecurityInfo");
myARGC = winetest_get_mainargs( &myARGV );
}
@ -586,8 +589,9 @@ static void test_lookupPrivilegeName(void)
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: %d\n",
ok( !ret && (GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
GetLastError() == RPC_S_INVALID_NET_ADDR) /* w2k8 */,
"LookupPrivilegeNameA didn't fail with RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR: %d\n",
GetLastError());
}
@ -644,8 +648,9 @@ static void test_lookupPrivilegeValue(void)
/* 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: %d\n",
ok( !ret && (GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
GetLastError() == RPC_S_INVALID_NET_ADDR) /* w2k8 */,
"LookupPrivilegeValueA didn't fail with RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR: %d\n",
GetLastError());
/* check a NULL string */
ret = pLookupPrivilegeValueA(NULL, 0, &luid);
@ -1642,7 +1647,8 @@ static void test_LookupAccountName(void)
ok(!ret, "Expected 0, got %d\n", ret);
todo_wine
{
ok(GetLastError() == ERROR_NONE_MAPPED,
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);
@ -1699,8 +1705,10 @@ static void test_security_descriptor(void)
}
}
#define TEST_GRANTED_ACCESS(a,b) test_granted_access(a,b,__LINE__)
static void test_granted_access(HANDLE handle, ACCESS_MASK access, int line)
#define TEST_GRANTED_ACCESS(a,b) test_granted_access(a,b,0,__LINE__)
#define TEST_GRANTED_ACCESS2(a,b,c) test_granted_access(a,b,c,__LINE__)
static void test_granted_access(HANDLE handle, ACCESS_MASK access,
ACCESS_MASK alt, int line)
{
OBJECT_BASIC_INFORMATION obj_info;
NTSTATUS status;
@ -1714,8 +1722,13 @@ static void test_granted_access(HANDLE handle, ACCESS_MASK access, int line)
status = pNtQueryObject( handle, ObjectBasicInformation, &obj_info,
sizeof(obj_info), NULL );
ok_(__FILE__, line)(!status, "NtQueryObject with err: %08x\n", status);
ok_(__FILE__, line)(obj_info.GrantedAccess == access, "Granted access should "
"be 0x%08x, instead of 0x%08x\n", access, obj_info.GrantedAccess);
if (alt)
ok_(__FILE__, line)(obj_info.GrantedAccess == access ||
obj_info.GrantedAccess == alt, "Granted access should be 0x%08x "
"or 0x%08x, instead of 0x%08x\n", access, alt, obj_info.GrantedAccess);
else
ok_(__FILE__, line)(obj_info.GrantedAccess == access, "Granted access should "
"be 0x%08x, instead of 0x%08x\n", access, obj_info.GrantedAccess);
}
#define CHECK_SET_SECURITY(o,i,e) \
@ -1827,7 +1840,8 @@ static void test_process_security(void)
/* Doesn't matter what ACL say we should get full access for ourselves */
ok(CreateProcessA( NULL, buffer, &psa, NULL, FALSE, 0, NULL, NULL, &startup, &info ),
"CreateProcess with err:%d\n", GetLastError());
TEST_GRANTED_ACCESS( info.hProcess, PROCESS_ALL_ACCESS );
TEST_GRANTED_ACCESS2( info.hProcess, PROCESS_ALL_ACCESS,
STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
winetest_wait_child_process( info.hProcess );
CloseHandle( info.hProcess );
@ -1876,7 +1890,8 @@ static void test_process_security_child(void)
ok(DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
&handle, 0, TRUE, DUPLICATE_SAME_ACCESS ),
"duplicating handle err:%d\n", GetLastError());
TEST_GRANTED_ACCESS( handle, PROCESS_ALL_ACCESS );
TEST_GRANTED_ACCESS2( handle, PROCESS_ALL_ACCESS,
STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
CloseHandle( handle );
@ -1884,7 +1899,8 @@ static void test_process_security_child(void)
ok(DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
&handle, PROCESS_ALL_ACCESS, TRUE, 0 ),
"duplicating handle err:%d\n", GetLastError());
TEST_GRANTED_ACCESS( handle, PROCESS_ALL_ACCESS );
TEST_GRANTED_ACCESS2( handle, PROCESS_ALL_ACCESS,
PROCESS_ALL_ACCESS | PROCESS_QUERY_LIMITED_INFORMATION );
ok(DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
&handle1, PROCESS_VM_READ, TRUE, 0 ),
"duplicating handle err:%d\n", GetLastError());
@ -2482,6 +2498,61 @@ static void test_acls(void)
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl(-1) failed with error %d\n", GetLastError());
}
static void test_GetSecurityInfo(void)
{
HANDLE obj;
PSECURITY_DESCRIPTOR sd;
PSID owner, group;
PACL dacl;
DWORD ret;
if (!pGetSecurityInfo)
{
win_skip("GetSecurityInfo is not available\n");
return;
}
/* Create something. Files have lots of associated security info. */
obj = CreateFile(myARGV[0], GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (obj == INVALID_HANDLE_VALUE)
{
skip("Couldn't create an object for GetSecurityInfo test\n");
return;
}
ret = pGetSecurityInfo(obj, SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
&owner, &group, &dacl, NULL, &sd);
if (ret == ERROR_CALL_NOT_IMPLEMENTED)
{
win_skip("GetSecurityInfo is not implemented\n");
CloseHandle(obj);
return;
}
ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret);
ok(sd != NULL, "GetSecurityInfo\n");
ok(owner != NULL, "GetSecurityInfo\n");
ok(group != NULL, "GetSecurityInfo\n");
ok(dacl != NULL, "GetSecurityInfo\n");
ok(IsValidAcl(dacl), "GetSecurityInfo\n");
LocalFree(sd);
/* If we don't ask for the security descriptor, Windows will still give us
the other stuff, leaving us no way to free it. */
ret = pGetSecurityInfo(obj, SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
&owner, &group, &dacl, NULL, NULL);
ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret);
ok(owner != NULL, "GetSecurityInfo\n");
ok(group != NULL, "GetSecurityInfo\n");
ok(dacl != NULL, "GetSecurityInfo\n");
ok(IsValidAcl(dacl), "GetSecurityInfo\n");
CloseHandle(obj);
}
START_TEST(security)
{
init();
@ -2510,4 +2581,5 @@ START_TEST(security)
test_ConvertSecurityDescriptorToString();
test_PrivateObjectSecurity();
test_acls();
test_GetSecurityInfo();
}

View file

@ -33,6 +33,26 @@
static const CHAR spooler[] = "Spooler"; /* Should be available on all platforms */
static BOOL (WINAPI *pChangeServiceConfig2A)(SC_HANDLE,DWORD,LPVOID);
static BOOL (WINAPI *pEnumServicesStatusExA)(SC_HANDLE, SC_ENUM_TYPE, DWORD,
DWORD, LPBYTE, DWORD, LPDWORD,
LPDWORD, LPDWORD, LPCSTR);
static BOOL (WINAPI *pQueryServiceConfig2A)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
static BOOL (WINAPI *pQueryServiceConfig2W)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
static BOOL (WINAPI *pQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE,
DWORD, LPDWORD);
static void init_function_pointers(void)
{
HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
pChangeServiceConfig2A = (void*)GetProcAddress(hadvapi32, "ChangeServiceConfig2A");
pEnumServicesStatusExA= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExA");
pQueryServiceConfig2A= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2A");
pQueryServiceConfig2W= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2W");
pQueryServiceStatusEx= (void*)GetProcAddress(hadvapi32, "QueryServiceStatusEx");
}
static void test_open_scm(void)
{
SC_HANDLE scm_handle;
@ -66,7 +86,8 @@ static void test_open_scm(void)
scm_handle = OpenSCManagerA("DOESNOTEXIST", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT);
ok(!scm_handle, "Expected failure\n");
todo_wine
ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE, "Expected RPC_S_SERVER_UNAVAILABLE, got %d\n", GetLastError());
ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* w2k8 */,
"Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %d\n", GetLastError());
CloseServiceHandle(scm_handle); /* Just in case */
/* Proper call with an empty hostname */
@ -145,7 +166,17 @@ static void test_open_svc(void)
GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
/* Get the displayname */
GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
/* Try to open the service with this displayname */
/* Try to open the service with this displayname, unless the displayname equals
* the servicename as that would defeat the purpose of this test.
*/
if (!lstrcmpi(spooler, displayname))
{
skip("displayname equals servicename\n");
CloseServiceHandle(scm_handle);
return;
}
SetLastError(0xdeadbeef);
svc_handle = OpenServiceA(scm_handle, displayname, GENERIC_READ);
ok(!svc_handle, "Expected failure\n");
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
@ -773,6 +804,810 @@ static void test_get_servicekeyname(void)
CloseServiceHandle(scm_handle);
}
static void test_query_svc(void)
{
SC_HANDLE scm_handle, svc_handle;
BOOL ret;
SERVICE_STATUS status;
SERVICE_STATUS_PROCESS *statusproc;
DWORD bufsize, needed;
/* All NULL or wrong */
SetLastError(0xdeadbeef);
ret = QueryServiceStatus(NULL, NULL);
ok(!ret, "Expected failure\n");
ok(GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
/* Check if 'Spooler' exists.
* Open with not enough rights to query the status.
*/
svc_handle = OpenServiceA(scm_handle, spooler, STANDARD_RIGHTS_READ);
if (!svc_handle)
{
skip("Spooler service doesn't exist\n");
CloseServiceHandle(scm_handle);
return;
}
SetLastError(0xdeadbeef);
ret = QueryServiceStatus(svc_handle, NULL);
ok(!ret, "Expected failure\n");
todo_wine
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
"Unexpected last error %d\n", GetLastError());
SetLastError(0xdeadbeef);
ret = QueryServiceStatus(svc_handle, &status);
ok(!ret, "Expected failure\n");
ok(GetLastError() == ERROR_ACCESS_DENIED,
"Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
/* Open the service with just enough rights.
* (Verified with 'SERVICE_ALL_ACCESS &~ SERVICE_QUERY_STATUS')
*/
CloseServiceHandle(svc_handle);
svc_handle = OpenServiceA(scm_handle, spooler, SERVICE_QUERY_STATUS);
SetLastError(0xdeadbeef);
ret = QueryServiceStatus(svc_handle, &status);
ok(ret, "Expected success\n");
ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
GetLastError() == 0xdeadbeef /* NT4, XP and Vista */ ||
GetLastError() == ERROR_IO_PENDING /* W2K */,
"Unexpected last error %d\n", GetLastError());
CloseServiceHandle(svc_handle);
/* More or less the same tests for QueryServiceStatusEx */
/* Open service with not enough rights to query the status */
svc_handle = OpenServiceA(scm_handle, spooler, STANDARD_RIGHTS_READ);
/* All NULL or wrong, this proves that info level is checked first */
SetLastError(0xdeadbeef);
ret = pQueryServiceStatusEx(NULL, 1, NULL, 0, NULL);
ok(!ret, "Expected failure\n");
todo_wine
ok(GetLastError() == ERROR_INVALID_LEVEL,
"Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError());
/* Passing a NULL parameter for the needed buffer size
* will crash on anything but NT4.
*/
/* 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 */
if (GetLastError() != ERROR_INVALID_HANDLE)
{
ok(!ret, "Expected failure\n");
ok(needed == sizeof(SERVICE_STATUS_PROCESS),
"Needed buffersize is wrong : %d\n", needed);
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
"Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
}
/* Pass a correct buffer and buffersize but a NULL handle */
statusproc = HeapAlloc(GetProcessHeap(), 0, needed);
bufsize = needed;
SetLastError(0xdeadbeef);
ret = pQueryServiceStatusEx(NULL, 0, (BYTE*)statusproc, bufsize, &needed);
ok(!ret, "Expected failure\n");
ok(GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
HeapFree(GetProcessHeap(), 0, statusproc);
/* Correct handle and info level */
SetLastError(0xdeadbeef);
ret = pQueryServiceStatusEx(svc_handle, 0, NULL, 0, &needed);
/* NT4 doesn't return the needed size */
if (GetLastError() != ERROR_INVALID_PARAMETER)
{
ok(!ret, "Expected failure\n");
todo_wine
{
ok(needed == sizeof(SERVICE_STATUS_PROCESS),
"Needed buffersize is wrong : %d\n", needed);
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
"Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
}
}
/* All parameters are OK but we don't have enough rights */
statusproc = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS));
bufsize = sizeof(SERVICE_STATUS_PROCESS);
SetLastError(0xdeadbeef);
ret = pQueryServiceStatusEx(svc_handle, 0, (BYTE*)statusproc, bufsize, &needed);
ok(!ret, "Expected failure\n");
ok(GetLastError() == ERROR_ACCESS_DENIED,
"Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
HeapFree(GetProcessHeap(), 0, statusproc);
/* Open the service with just enough rights. */
CloseServiceHandle(svc_handle);
svc_handle = OpenServiceA(scm_handle, spooler, SERVICE_QUERY_STATUS);
/* Everything should be fine now. */
statusproc = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS));
bufsize = sizeof(SERVICE_STATUS_PROCESS);
SetLastError(0xdeadbeef);
ret = pQueryServiceStatusEx(svc_handle, 0, (BYTE*)statusproc, bufsize, &needed);
ok(ret, "Expected success\n");
ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
GetLastError() == 0xdeadbeef /* NT4, XP and Vista */ ||
GetLastError() == ERROR_IO_PENDING /* W2K */,
"Unexpected last error %d\n", GetLastError());
if (statusproc->dwCurrentState == SERVICE_RUNNING)
ok(statusproc->dwProcessId != 0,
"Expect a process id for this running service\n");
else
ok(statusproc->dwProcessId == 0,
"Expect no process id for this stopped service\n");
HeapFree(GetProcessHeap(), 0, statusproc);
CloseServiceHandle(svc_handle);
CloseServiceHandle(scm_handle);
}
static void test_enum_svc(void)
{
SC_HANDLE scm_handle;
BOOL ret;
DWORD bufsize, needed, returned, resume;
DWORD tempneeded, tempreturned;
DWORD servicecountactive, servicecountinactive;
ENUM_SERVICE_STATUS *services;
ENUM_SERVICE_STATUS_PROCESS *exservices;
INT i;
/* All NULL or wrong */
SetLastError(0xdeadbeef);
ret = EnumServicesStatusA(NULL, 1, 0, NULL, 0, NULL, NULL, NULL);
ok(!ret, "Expected failure\n");
todo_wine
ok(GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
/* Open the service control manager with not enough rights at first */
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
/* Valid handle but rest is still NULL or wrong */
SetLastError(0xdeadbeef);
ret = EnumServicesStatusA(scm_handle, 1, 0, NULL, 0, NULL, NULL, NULL);
ok(!ret, "Expected failure\n");
todo_wine
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
"Unexpected last error %d\n", GetLastError());
/* Don't specify the two required pointers */
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, NULL, &returned, NULL);
ok(!ret, "Expected failure\n");
ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
todo_wine
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
"Unexpected last error %d\n", GetLastError());
/* Don't specify the two required pointers */
needed = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, &needed, NULL, NULL);
ok(!ret, "Expected failure\n");
ok(needed == 0xdeadbeef, "Expected no change to the needed buffer variable\n");
todo_wine
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
"Unexpected last error %d\n", GetLastError());
/* No valid servicetype and servicestate */
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, &needed, &returned, NULL);
ok(!ret, "Expected failure\n");
todo_wine
{
ok(needed == 0, "Expected needed buffer size to be set to 0, got %d\n", needed);
ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
}
/* No valid servicetype and servicestate */
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, 0, NULL, 0, &needed, &returned, NULL);
ok(!ret, "Expected failure\n");
todo_wine
{
ok(needed == 0, "Expected needed buffer size to be set to 0, got %d\n", needed);
ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
}
/* No valid servicetype and servicestate */
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = EnumServicesStatusA(scm_handle, 0, SERVICE_STATE_ALL, NULL, 0,
&needed, &returned, NULL);
ok(!ret, "Expected failure\n");
todo_wine
{
ok(needed == 0, "Expected needed buffer size to be set to 0, got %d\n", needed);
ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
}
/* All parameters are correct but our access rights are wrong */
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0,
&needed, &returned, NULL);
ok(!ret, "Expected failure\n");
todo_wine
{
ok(needed == 0, "Expected needed buffer size to be set to 0, got %d\n", needed);
ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned);
}
ok(GetLastError() == ERROR_ACCESS_DENIED,
"Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
/* Open the service control manager with the needed rights */
CloseServiceHandle(scm_handle);
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
/* All parameters are correct. Request the needed buffer size */
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0,
&needed, &returned, NULL);
ok(!ret, "Expected failure\n");
todo_wine
{
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n");
ok(returned == 0, "Expected no service returned, got %d\n", returned);
ok(GetLastError() == ERROR_MORE_DATA,
"Expected ERROR_MORE_DATA, got %d\n", GetLastError());
}
/* Store the needed bytes */
tempneeded = needed;
/* Allocate the correct needed bytes */
services = HeapAlloc(GetProcessHeap(), 0, needed);
bufsize = needed;
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
services, bufsize, &needed, &returned, NULL);
todo_wine
{
ok(ret, "Expected success\n");
ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
ok(returned != 0xdeadbeef && returned > 0, "Expected some returned services\n");
ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
GetLastError() == 0xdeadbeef /* NT4, XP and Vista */ ||
GetLastError() == ERROR_IO_PENDING /* W2K */,
"Unexpected last error %d\n", GetLastError());
}
HeapFree(GetProcessHeap(), 0, services);
/* Store the number of returned services */
tempreturned = returned;
/* Allocate less than the needed bytes and don't specify a resume handle */
services = HeapAlloc(GetProcessHeap(), 0, tempneeded - 1);
bufsize = tempneeded - 1;
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
services, bufsize, &needed, &returned, NULL);
ok(!ret, "Expected failure\n");
todo_wine
{
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n");
ok(returned == (tempreturned - 1), "Expected one service less to be returned\n");
ok(GetLastError() == ERROR_MORE_DATA,
"Expected ERROR_MORE_DATA, got %d\n", GetLastError());
}
HeapFree(GetProcessHeap(), 0, services);
/* Allocate less than the needed bytes, this time with a correct resume handle */
services = HeapAlloc(GetProcessHeap(), 0, tempneeded - 1);
bufsize = tempneeded - 1;
needed = 0xdeadbeef;
returned = 0xdeadbeef;
resume = 0;
SetLastError(0xdeadbeef);
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
services, bufsize, &needed, &returned, &resume);
ok(!ret, "Expected failure\n");
todo_wine
{
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n");
ok(returned == (tempreturned - 1), "Expected one service less to be returned\n");
ok(resume, "Expected a resume handle\n");
ok(GetLastError() == ERROR_MORE_DATA,
"Expected ERROR_MORE_DATA, got %d\n", GetLastError());
}
HeapFree(GetProcessHeap(), 0, services);
/* Fetch that last service but pass a bigger buffer size */
services = HeapAlloc(GetProcessHeap(), 0, tempneeded);
bufsize = tempneeded;
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
services, bufsize, &needed, &returned, &resume);
todo_wine
{
ok(ret, "Expected success\n");
ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
ok(returned == 1, "Expected only 1 service to be returned\n");
ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
GetLastError() == 0xdeadbeef /* NT4, XP and Vista */ ||
GetLastError() == ERROR_IO_PENDING /* W2K */,
"Unexpected last error %d\n", GetLastError());
}
ok(resume == 0, "Expected the resume handle to be 0\n");
HeapFree(GetProcessHeap(), 0, services);
/* See if things add up */
/* Vista only shows the drivers with a state of SERVICE_RUNNING as active
* and doesn't count the others as inactive. This means that Vista could
* show a total that is greater than the sum of active and inactive
* drivers.
* The number of active and inactive drivers is greatly influenced by the
* time when tests are run, immediately after boot or later for example.
*
* Both reasons make calculations for drivers not so useful
*/
/* Get the number of active win32 services */
EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, NULL, 0,
&needed, &returned, NULL);
services = HeapAlloc(GetProcessHeap(), 0, needed);
EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, services,
needed, &needed, &returned, NULL);
HeapFree(GetProcessHeap(), 0, services);
servicecountactive = returned;
/* Get the number of inactive win32 services */
EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, NULL, 0,
&needed, &returned, NULL);
services = HeapAlloc(GetProcessHeap(), 0, needed);
EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, services,
needed, &needed, &returned, NULL);
HeapFree(GetProcessHeap(), 0, services);
servicecountinactive = returned;
/* Get the number of win32 services */
EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0,
&needed, &returned, NULL);
services = HeapAlloc(GetProcessHeap(), 0, needed);
EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services,
needed, &needed, &returned, NULL);
HeapFree(GetProcessHeap(), 0, services);
/* Check if total is the same as active and inactive win32 services */
todo_wine
ok(returned == (servicecountactive + servicecountinactive),
"Something wrong in the calculation\n");
/* Get all drivers and services
*
* Fetch the status of the last call as failing could make the following tests crash
* on Wine (we don't return anything yet).
*/
EnumServicesStatusA(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL,
NULL, 0, &needed, &returned, NULL);
services = HeapAlloc(GetProcessHeap(), 0, needed);
ret = EnumServicesStatusA(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL,
services, needed, &needed, &returned, NULL);
/* Loop through all those returned drivers and services */
for (i = 0; ret && i < returned; i++)
{
SERVICE_STATUS status = services[i].ServiceStatus;
/* lpServiceName and lpDisplayName should always be filled */
ok(lstrlenA(services[i].lpServiceName) > 0, "Expected a service name\n");
ok(lstrlenA(services[i].lpDisplayName) > 0, "Expected a display name\n");
/* Decrement the counters to see if the functions calls return the same
* numbers as the contents of these structures.
*/
if (status.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS))
{
if (status.dwCurrentState == SERVICE_RUNNING)
servicecountactive--;
else
servicecountinactive--;
}
}
HeapFree(GetProcessHeap(), 0, services);
todo_wine
{
ok(servicecountactive == 0, "Active services mismatch\n");
ok(servicecountinactive == 0, "Inactive services mismatch\n");
}
CloseServiceHandle(scm_handle);
/* More or less the same for EnumServicesStatusExA */
/* All NULL or wrong */
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(NULL, 1, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
ok(!ret, "Expected failure\n");
todo_wine
ok(GetLastError() == ERROR_INVALID_LEVEL,
"Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError());
/* All NULL or wrong, just the info level is correct */
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
ok(!ret, "Expected failure\n");
todo_wine
ok(GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
/* Open the service control manager with not enough rights at first */
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
/* Valid handle and info level but rest is still NULL or wrong */
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
ok(!ret, "Expected failure\n");
todo_wine
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
"Unexpected last error %d\n", GetLastError());
/* Don't specify the two required pointers */
needed = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, NULL, NULL, NULL);
ok(!ret, "Expected failure\n");
ok(needed == 0xdeadbeef, "Expected no change to the needed buffer variable\n");
todo_wine
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
"Unexpected last error %d\n", GetLastError());
/* Don't specify the two required pointers */
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, NULL, &returned, NULL, NULL);
ok(!ret, "Expected failure\n");
todo_wine
{
ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
"Unexpected last error %d\n", GetLastError());
}
/* No valid servicetype and servicestate */
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, &returned, NULL, NULL);
ok(!ret, "Expected failure\n");
ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
todo_wine
{
ok(needed == 0, "Expected needed buffer size to be set to 0, got %d\n", needed);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
}
/* No valid servicestate */
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, 0, NULL, 0,
&needed, &returned, NULL, NULL);
ok(!ret, "Expected failure\n");
ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
todo_wine
{
ok(needed == 0, "Expected needed buffer size to be set to 0, got %d\n", needed);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
}
/* No valid servicetype */
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(scm_handle, 0, 0, SERVICE_STATE_ALL, NULL, 0,
&needed, &returned, NULL, NULL);
ok(!ret, "Expected failure\n");
ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
todo_wine
{
ok(needed == 0, "Expected needed buffer size to be set to 0, got %d\n", needed);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
}
/* No valid servicetype and servicestate and unknown service group */
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed,
&returned, NULL, "deadbeef_group");
ok(!ret, "Expected failure\n");
ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
todo_wine
{
ok(needed == 0, "Expected needed buffer size to be set to 0, got %d\n", needed);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
}
/* All parameters are correct but our access rights are wrong */
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
NULL, 0, &needed, &returned, NULL, NULL);
ok(!ret, "Expected failure\n");
todo_wine
ok(needed == 0, "Expected needed buffer size to be set to 0, got %d\n", needed);
ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
ok(GetLastError() == ERROR_ACCESS_DENIED,
"Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
/* All parameters are correct, access rights are wrong but the
* group name won't be checked yet.
*/
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
NULL, 0, &needed, &returned, NULL, "deadbeef_group");
ok(!ret, "Expected failure\n");
todo_wine
ok(needed == 0, "Expected needed buffer size to be set to 0, got %d\n", needed);
ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
ok(GetLastError() == ERROR_ACCESS_DENIED,
"Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
/* Open the service control manager with the needed rights */
CloseServiceHandle(scm_handle);
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
/* All parameters are correct and the group will be checked */
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
NULL, 0, &needed, &returned, NULL, "deadbeef_group");
ok(!ret, "Expected failure\n");
ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
todo_wine
{
ok(needed == 0, "Expected needed buffer size to be set to 0, got %d\n", needed);
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
}
/* TODO: Create a test that makes sure we enumerate all services that don't
* belong to a group. (specifying "").
*/
/* All parameters are correct. Request the needed buffer size */
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
NULL, 0, &needed, &returned, NULL, NULL);
ok(!ret, "Expected failure\n");
ok(returned == 0, "Expected no service returned, got %d\n", returned);
todo_wine
{
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
ok(GetLastError() == ERROR_MORE_DATA,
"Expected ERROR_MORE_DATA, got %d\n", GetLastError());
}
/* Store the needed bytes */
tempneeded = needed;
/* Allocate the correct needed bytes */
exservices = HeapAlloc(GetProcessHeap(), 0, needed);
bufsize = needed;
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
(BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL);
todo_wine
{
ok(ret, "Expected success\n");
ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
ok(returned == tempreturned, "Expected the same number of service from this function\n");
ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
GetLastError() == 0xdeadbeef /* NT4, XP and Vista */ ||
GetLastError() == ERROR_IO_PENDING /* W2K */,
"Unexpected last error %d\n", GetLastError());
}
HeapFree(GetProcessHeap(), 0, exservices);
/* Store the number of returned services */
tempreturned = returned;
/* Allocate less than the needed bytes and don't specify a resume handle */
exservices = HeapAlloc(GetProcessHeap(), 0, tempneeded - 1);
bufsize = tempneeded - 1;
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
(BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL);
ok(!ret, "Expected failure\n");
todo_wine
{
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
ok(returned == (tempreturned - 1), "Expected one service less to be returned\n");
ok(GetLastError() == ERROR_MORE_DATA,
"Expected ERROR_MORE_DATA, got %d\n", GetLastError());
}
HeapFree(GetProcessHeap(), 0, exservices);
/* Allocate less than the needed bytes, this time with a correct resume handle */
exservices = HeapAlloc(GetProcessHeap(), 0, tempneeded - 1);
bufsize = tempneeded - 1;
needed = 0xdeadbeef;
returned = 0xdeadbeef;
resume = 0;
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
(BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL);
ok(!ret, "Expected failure\n");
todo_wine
{
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
ok(returned == (tempreturned - 1), "Expected one service less to be returned\n");
ok(resume, "Expected a resume handle\n");
ok(GetLastError() == ERROR_MORE_DATA,
"Expected ERROR_MORE_DATA, got %d\n", GetLastError());
}
HeapFree(GetProcessHeap(), 0, exservices);
/* Fetch that last service but pass a bigger buffer size */
exservices = HeapAlloc(GetProcessHeap(), 0, tempneeded);
bufsize = tempneeded;
needed = 0xdeadbeef;
returned = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
(BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL);
todo_wine
{
ok(ret, "Expected success\n");
ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
ok(returned == 1, "Expected only 1 service to be returned\n");
ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
GetLastError() == 0xdeadbeef /* NT4, XP and Vista */ ||
GetLastError() == ERROR_IO_PENDING /* W2K */,
"Unexpected last error %d\n", GetLastError());
}
ok(resume == 0, "Expected the resume handle to be 0\n");
HeapFree(GetProcessHeap(), 0, exservices);
/* See if things add up */
/* Get the number of active win32 services */
pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE,
NULL, 0, &needed, &returned, NULL, NULL);
exservices = HeapAlloc(GetProcessHeap(), 0, needed);
pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE,
(BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
HeapFree(GetProcessHeap(), 0, exservices);
servicecountactive = returned;
/* Get the number of inactive win32 services */
pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE,
NULL, 0, &needed, &returned, NULL, NULL);
exservices = HeapAlloc(GetProcessHeap(), 0, needed);
pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE,
(BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
HeapFree(GetProcessHeap(), 0, exservices);
servicecountinactive = returned;
/* Get the number of win32 services */
pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
NULL, 0, &needed, &returned, NULL, NULL);
exservices = HeapAlloc(GetProcessHeap(), 0, needed);
pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
(BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
HeapFree(GetProcessHeap(), 0, exservices);
/* Check if total is the same as active and inactive win32 services */
ok(returned == (servicecountactive + servicecountinactive),
"Something wrong in the calculation\n");
/* Get all drivers and services */
pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER,
SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL, NULL);
exservices = HeapAlloc(GetProcessHeap(), 0, needed);
pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER,
SERVICE_STATE_ALL, (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
/* Loop through all those returned drivers and services */
for (i = 0; i < returned; i++)
{
SERVICE_STATUS_PROCESS status = exservices[i].ServiceStatusProcess;
/* lpServiceName and lpDisplayName should always be filled */
ok(lstrlenA(exservices[i].lpServiceName) > 0, "Expected a service name\n");
ok(lstrlenA(exservices[i].lpDisplayName) > 0, "Expected a display name\n");
/* Decrement the counters to see if the functions calls return the
* same numbers as the contents of these structures.
* Check some process id specifics.
*/
if (status.dwServiceType & (SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER))
{
/* We shouldn't have a process id for drivers */
ok(status.dwProcessId == 0,
"This driver shouldn't have an associated process id\n");
}
if (status.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS))
{
if (status.dwCurrentState == SERVICE_RUNNING)
{
/* We expect a process id for every running service */
ok(status.dwProcessId > 0, "Expected a process id for this running service (%s)\n",
exservices[i].lpServiceName);
servicecountactive--;
}
else
{
/* We shouldn't have a process id for inactive services */
ok(status.dwProcessId == 0, "This service shouldn't have an associated process id\n");
servicecountinactive--;
}
}
}
HeapFree(GetProcessHeap(), 0, exservices);
ok(servicecountactive == 0, "Active services mismatch\n");
ok(servicecountinactive == 0, "Inactive services mismatch\n");
CloseServiceHandle(scm_handle);
}
static void test_close(void)
{
SC_HANDLE handle;
@ -947,13 +1782,7 @@ static void test_queryconfig2(void)
static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
static const CHAR password [] = "";
static const CHAR description [] = "Description";
HMODULE dllhandle = GetModuleHandleA("advapi32.dll");
BOOL (WINAPI *pChangeServiceConfig2A)(SC_HANDLE,DWORD,LPVOID)
= (void*)GetProcAddress(dllhandle, "ChangeServiceConfig2A");
BOOL (WINAPI *pQueryServiceConfig2A)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD)
= (void*)GetProcAddress(dllhandle, "QueryServiceConfig2A");
BOOL (WINAPI *pQueryServiceConfig2W)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD)
= (void*)GetProcAddress(dllhandle, "QueryServiceConfig2W");
if(!pQueryServiceConfig2A)
{
skip("function QueryServiceConfig2A not present\n");
@ -1239,12 +2068,16 @@ START_TEST(service)
}
CloseServiceHandle(scm_handle);
init_function_pointers();
/* First some parameter checking */
test_open_scm();
test_open_svc();
test_create_delete_svc();
test_get_displayname();
test_get_servicekeyname();
test_query_svc();
test_enum_svc();
test_close();
/* Test the creation, querying and deletion of a service */
test_sequence();