mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 02:05:50 +00:00
sync advapi32_winetest to wine 1.1.4
svn path=/trunk/; revision=36247
This commit is contained in:
parent
2435f146c3
commit
2d4aadb83f
7 changed files with 1027 additions and 53 deletions
|
@ -97,8 +97,12 @@ static void test_CredWriteA(void)
|
||||||
|
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = pCredWriteA(&new_cred, 0);
|
ret = pCredWriteA(&new_cred, 0);
|
||||||
ok(!ret && ( GetLastError() == ERROR_BAD_USERNAME || GetLastError() == ERROR_NO_SUCH_LOGON_SESSION /* Vista */ ),
|
ok(!ret, "CredWrite with username without domain should have failed\n");
|
||||||
"CredWrite with username without domain should return ERROR_BAD_USERNAME or ERROR_NO_SUCH_LOGON_SESSION not %d\n", GetLastError());
|
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;
|
new_cred.UserName = NULL;
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
|
@ -175,10 +179,12 @@ static void test_generic(void)
|
||||||
{
|
{
|
||||||
if (!strcmp(creds[i]->TargetName, TEST_TARGET_NAME))
|
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(!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);
|
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(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);
|
ok(!strcmp(creds[i]->UserName, "winetest"), "expected creds[%d]->UserName \"winetest\" but got \"%s\"\n", i, creds[i]->UserName);
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
|
@ -216,6 +222,12 @@ static void test_domain_password(DWORD cred_type)
|
||||||
new_cred.TargetAlias = NULL;
|
new_cred.TargetAlias = NULL;
|
||||||
new_cred.UserName = (char *)"test\\winetest";
|
new_cred.UserName = (char *)"test\\winetest";
|
||||||
ret = pCredWriteA(&new_cred, 0);
|
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());
|
ok(ret, "CredWriteA failed with error %d\n", GetLastError());
|
||||||
|
|
||||||
ret = pCredEnumerateA(NULL, 0, &count, &creds);
|
ret = pCredEnumerateA(NULL, 0, &count, &creds);
|
||||||
|
|
|
@ -903,7 +903,7 @@ static void test_machine_guid(void)
|
||||||
/* Create and release a provider */
|
/* Create and release a provider */
|
||||||
ret = pCryptAcquireContextA(&hCryptProv, szKeySet, NULL, PROV_RSA_FULL, 0);
|
ret = pCryptAcquireContextA(&hCryptProv, szKeySet, NULL, PROV_RSA_FULL, 0);
|
||||||
ok(ret, "CryptAcquireContextA failed: %08x\n", GetLastError());
|
ok(ret, "CryptAcquireContextA failed: %08x\n", GetLastError());
|
||||||
CryptReleaseContext(hCryptProv, 0);
|
pCryptReleaseContext(hCryptProv, 0);
|
||||||
|
|
||||||
if (restoreGuid)
|
if (restoreGuid)
|
||||||
RegSetValueExA(key, "MachineGuid", 0, REG_SZ, (const BYTE *)originalGuid,
|
RegSetValueExA(key, "MachineGuid", 0, REG_SZ, (const BYTE *)originalGuid,
|
||||||
|
|
|
@ -348,18 +348,24 @@ static void test_SystemFunction005(void)
|
||||||
out.Length = 0;
|
out.Length = 0;
|
||||||
out.MaximumLength = 0;
|
out.MaximumLength = 0;
|
||||||
r = pSystemFunction005(&out, &key, &res);
|
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(res.Length == in.Length, "Length wrong\n");
|
||||||
ok(!memcmp(res.Buffer, in.Buffer, in.Length), "data wrong\n");
|
ok(!memcmp(res.Buffer, in.Buffer, in.Length), "data wrong\n");
|
||||||
|
|
||||||
res.MaximumLength = 0;
|
res.MaximumLength = 0;
|
||||||
r = pSystemFunction005(&out, &key, &res);
|
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;
|
key.Length = 1;
|
||||||
r = pSystemFunction005(&out, &key, &res);
|
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;
|
key.Length = 0;
|
||||||
r = pSystemFunction005(&out, &key, &res);
|
r = pSystemFunction005(&out, &key, &res);
|
||||||
|
|
|
@ -30,10 +30,11 @@
|
||||||
#include "sddl.h"
|
#include "sddl.h"
|
||||||
#include "winnls.h"
|
#include "winnls.h"
|
||||||
#include "objbase.h"
|
#include "objbase.h"
|
||||||
#define INITGUID
|
#include "initguid.h"
|
||||||
#include "guiddef.h"
|
|
||||||
#include "wine/test.h"
|
#include "wine/test.h"
|
||||||
|
|
||||||
|
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
|
||||||
|
|
||||||
static HMODULE hadvapi32;
|
static HMODULE hadvapi32;
|
||||||
static NTSTATUS (WINAPI *pLsaClose)(LSA_HANDLE);
|
static NTSTATUS (WINAPI *pLsaClose)(LSA_HANDLE);
|
||||||
static NTSTATUS (WINAPI *pLsaFreeMemory)(PVOID);
|
static NTSTATUS (WINAPI *pLsaFreeMemory)(PVOID);
|
||||||
|
@ -95,7 +96,6 @@ static void test_lsa(void)
|
||||||
status = pLsaQueryInformationPolicy(handle, PolicyPrimaryDomainInformation, (PVOID*)&primary_domain_info);
|
status = pLsaQueryInformationPolicy(handle, PolicyPrimaryDomainInformation, (PVOID*)&primary_domain_info);
|
||||||
ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy(PolicyPrimaryDomainInformation) failed, returned 0x%08x\n", status);
|
ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy(PolicyPrimaryDomainInformation) failed, returned 0x%08x\n", status);
|
||||||
if (status == STATUS_SUCCESS) {
|
if (status == STATUS_SUCCESS) {
|
||||||
ok(primary_domain_info->Sid==0,"Sid should be NULL on the local computer\n");
|
|
||||||
if (primary_domain_info->Sid) {
|
if (primary_domain_info->Sid) {
|
||||||
LPSTR strsid;
|
LPSTR strsid;
|
||||||
if (pConvertSidToStringSidA(primary_domain_info->Sid, &strsid))
|
if (pConvertSidToStringSidA(primary_domain_info->Sid, &strsid))
|
||||||
|
@ -115,6 +115,8 @@ static void test_lsa(void)
|
||||||
else
|
else
|
||||||
trace("invalid sid\n");
|
trace("invalid sid\n");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
trace("Running on a standalone system.\n");
|
||||||
pLsaFreeMemory((LPVOID)primary_domain_info);
|
pLsaFreeMemory((LPVOID)primary_domain_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,8 +131,6 @@ static void test_lsa(void)
|
||||||
ok(status == STATUS_SUCCESS || status == STATUS_INVALID_PARAMETER,
|
ok(status == STATUS_SUCCESS || status == STATUS_INVALID_PARAMETER,
|
||||||
"LsaQueryInformationPolicy(PolicyDnsDomainInformation) failed, returned 0x%08x\n", status);
|
"LsaQueryInformationPolicy(PolicyDnsDomainInformation) failed, returned 0x%08x\n", status);
|
||||||
if (status == STATUS_SUCCESS) {
|
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)) {
|
if (dns_domain_info->Sid || !IsEqualGUID(&dns_domain_info->DomainGuid, &GUID_NULL)) {
|
||||||
LPSTR strsid = NULL;
|
LPSTR strsid = NULL;
|
||||||
LPSTR name = NULL;
|
LPSTR name = NULL;
|
||||||
|
@ -169,6 +169,8 @@ static void test_lsa(void)
|
||||||
LocalFree( guidstr );
|
LocalFree( guidstr );
|
||||||
LocalFree( strsid );
|
LocalFree( strsid );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
trace("Running on a standalone system.\n");
|
||||||
pLsaFreeMemory((LPVOID)dns_domain_info);
|
pLsaFreeMemory((LPVOID)dns_domain_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -159,9 +159,8 @@ static const char *wine_debugstr_wn( const WCHAR *str, int n )
|
||||||
|
|
||||||
|
|
||||||
#define ADVAPI32_GET_PROC(func) \
|
#define ADVAPI32_GET_PROC(func) \
|
||||||
p ## func = (void*)GetProcAddress(hadvapi32, #func); \
|
p ## func = (void*)GetProcAddress(hadvapi32, #func);
|
||||||
if(!p ## func) \
|
|
||||||
trace("GetProcAddress(%s) failed\n", #func);
|
|
||||||
|
|
||||||
static void InitFunctionPtrs(void)
|
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);
|
ret = RegQueryValueExW(hkey_main, name, NULL, &type, NULL, &cbData);
|
||||||
GLE = GetLastError();
|
GLE = GetLastError();
|
||||||
ok(ret == ERROR_SUCCESS, "RegQueryValueExW failed: %d, GLE=%d\n", ret, GLE);
|
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(type == REG_SZ, "RegQueryValueExW returned type %d\n", type);
|
||||||
ok(cbData == full_byte_len,
|
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_A(NULL, substring2A, sizeof(substring2A));
|
||||||
test_hkey_main_Value_W(NULL, substring2W, sizeof(substring2W));
|
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));
|
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));
|
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));
|
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).
|
/* Test RegSetValueExA with a 'zero-byte' string (as Office 2003 does).
|
||||||
* Surprisingly enough we're supposed to get zero bytes out of it.
|
* 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");
|
"RegSetValueExA failed\n");
|
||||||
ok(!RegSetValueExA(hkey_main,"TP1_SZ",0,REG_SZ, (const BYTE *)sTestpath1, strlen(sTestpath1)+1),
|
ok(!RegSetValueExA(hkey_main,"TP1_SZ",0,REG_SZ, (const BYTE *)sTestpath1, strlen(sTestpath1)+1),
|
||||||
"RegSetValueExA failed\n");
|
"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");
|
"RegSetValueExA failed\n");
|
||||||
ok(!RegSetValueExA(hkey_main,"TP2_EXP_SZ",0,REG_EXPAND_SZ, (const BYTE *)sTestpath2, strlen(sTestpath2)+1),
|
ok(!RegSetValueExA(hkey_main,"TP2_EXP_SZ",0,REG_EXPAND_SZ, (const BYTE *)sTestpath2, strlen(sTestpath2)+1),
|
||||||
"RegSetValueExA failed\n");
|
"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) );
|
res = RegSetValueExW( test_key, testW, 0, REG_SZ, (const BYTE *)foobarW, 7*sizeof(WCHAR) );
|
||||||
if (res==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
|
if (res==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
|
||||||
{
|
{
|
||||||
skip("RegSetValueExW is not implemented\n");
|
win_skip("RegSetValueExW is not implemented\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
ok( res == 0, "RegSetValueExW failed error %d\n", res );
|
ok( res == 0, "RegSetValueExW failed error %d\n", res );
|
||||||
|
@ -675,7 +686,7 @@ static void test_get_value(void)
|
||||||
|
|
||||||
if(!pRegGetValueA)
|
if(!pRegGetValueA)
|
||||||
{
|
{
|
||||||
skip("RegGetValue not available on this platform\n");
|
win_skip("RegGetValue not available on this platform\n");
|
||||||
return;
|
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);
|
ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ, &type, NULL, &size);
|
||||||
ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
|
ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
|
||||||
/* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
|
/* 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);
|
"strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
|
||||||
ok(type == REG_SZ, "type=%d\n", type);
|
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);
|
ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size);
|
||||||
ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
|
ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
|
||||||
/* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath1 length + 1 here. */
|
/* 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);
|
"strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded), lstrlenA(sTestpath1), size);
|
||||||
ok(type == REG_SZ, "type=%d\n", type);
|
ok(type == REG_SZ, "type=%d\n", type);
|
||||||
ok(!strcmp(expanded, buf), "expanded=\"%s\" buf=\"%s\"\n", expanded, buf);
|
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);
|
ret = pRegGetValueA(hkey_main, NULL, "TP2_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size);
|
||||||
ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
|
ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
|
||||||
/* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath2 length + 1 here. */
|
/* 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);
|
"strlen(expanded2)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded2), lstrlenA(sTestpath2), size);
|
||||||
ok(type == REG_SZ, "type=%d\n", type);
|
ok(type == REG_SZ, "type=%d\n", type);
|
||||||
ok(!strcmp(expanded2, buf), "expanded2=\"%s\" buf=\"%s\"\n", expanded2, buf);
|
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);
|
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);
|
ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
|
||||||
/* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
|
/* 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);
|
"strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
|
||||||
|
|
||||||
/* Query REG_EXPAND_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (type mismatch) */
|
/* 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) */
|
/* 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);
|
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);
|
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)
|
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 */
|
ok(ret == ERROR_BAD_PATHNAME || /* NT/2k/XP */
|
||||||
ret == ERROR_FILE_NOT_FOUND /* Win9x,ME */
|
ret == ERROR_FILE_NOT_FOUND /* Win9x,ME */
|
||||||
, "expected ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %d\n", ret);
|
, "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)
|
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);
|
ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
|
||||||
RegDeleteKey(hkey1, NULL);
|
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)
|
static void test_reg_close_key(void)
|
||||||
|
@ -1124,7 +1171,7 @@ static void test_regconnectregistry( void)
|
||||||
schnd = OpenSCManagerA( compName, NULL, GENERIC_READ);
|
schnd = OpenSCManagerA( compName, NULL, GENERIC_READ);
|
||||||
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||||
{
|
{
|
||||||
skip("OpenSCManagerA is not implemented\n");
|
win_skip("OpenSCManagerA is not implemented\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1157,7 +1204,9 @@ static void test_reg_query_value(void)
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
size = MAX_PATH;
|
size = MAX_PATH;
|
||||||
ret = RegQueryValueA((HKEY)0xcafebabe, "subkey", val, &size);
|
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);
|
"Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
|
||||||
ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
|
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);
|
ret = RegQueryValueW(subkey, NULL, valW, &size);
|
||||||
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||||
{
|
{
|
||||||
skip("RegQueryValueW is not implemented\n");
|
win_skip("RegQueryValueW is not implemented\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
|
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;
|
LONG size, ret;
|
||||||
|
|
||||||
if(!pRegDeleteTreeA) {
|
if(!pRegDeleteTreeA) {
|
||||||
skip("Skipping RegDeleteTreeA tests, function not present\n");
|
win_skip("Skipping RegDeleteTreeA tests, function not present\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,8 @@ static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,U
|
||||||
static DWORD (WINAPI *pSetEntriesInAclW)(ULONG, PEXPLICIT_ACCESSW, PACL, PACL*);
|
static DWORD (WINAPI *pSetEntriesInAclW)(ULONG, PEXPLICIT_ACCESSW, PACL, PACL*);
|
||||||
static BOOL (WINAPI *pSetSecurityDescriptorControl)(PSECURITY_DESCRIPTOR, SECURITY_DESCRIPTOR_CONTROL,
|
static BOOL (WINAPI *pSetSecurityDescriptorControl)(PSECURITY_DESCRIPTOR, SECURITY_DESCRIPTOR_CONTROL,
|
||||||
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 HMODULE hmod;
|
||||||
static int myARGC;
|
static int myARGC;
|
||||||
|
@ -149,6 +151,7 @@ static void init(void)
|
||||||
pMakeSelfRelativeSD = (void *)GetProcAddress(hmod, "MakeSelfRelativeSD");
|
pMakeSelfRelativeSD = (void *)GetProcAddress(hmod, "MakeSelfRelativeSD");
|
||||||
pSetEntriesInAclW = (void *)GetProcAddress(hmod, "SetEntriesInAclW");
|
pSetEntriesInAclW = (void *)GetProcAddress(hmod, "SetEntriesInAclW");
|
||||||
pSetSecurityDescriptorControl = (void *)GetProcAddress(hmod, "SetSecurityDescriptorControl");
|
pSetSecurityDescriptorControl = (void *)GetProcAddress(hmod, "SetSecurityDescriptorControl");
|
||||||
|
pGetSecurityInfo = (void *)GetProcAddress(hmod, "GetSecurityInfo");
|
||||||
|
|
||||||
myARGC = winetest_get_mainargs( &myARGV );
|
myARGC = winetest_get_mainargs( &myARGV );
|
||||||
}
|
}
|
||||||
|
@ -586,8 +589,9 @@ static void test_lookupPrivilegeName(void)
|
||||||
luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
|
luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
|
||||||
cchName = sizeof(buf);
|
cchName = sizeof(buf);
|
||||||
ret = pLookupPrivilegeNameA("b0gu5.Nam3", &luid, buf, &cchName);
|
ret = pLookupPrivilegeNameA("b0gu5.Nam3", &luid, buf, &cchName);
|
||||||
ok( !ret && GetLastError() == RPC_S_SERVER_UNAVAILABLE,
|
ok( !ret && (GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
|
||||||
"LookupPrivilegeNameA didn't fail with RPC_S_SERVER_UNAVAILABLE: %d\n",
|
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());
|
GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,8 +648,9 @@ static void test_lookupPrivilegeValue(void)
|
||||||
|
|
||||||
/* check a bogus system name */
|
/* check a bogus system name */
|
||||||
ret = pLookupPrivilegeValueA("b0gu5.Nam3", "SeCreateTokenPrivilege", &luid);
|
ret = pLookupPrivilegeValueA("b0gu5.Nam3", "SeCreateTokenPrivilege", &luid);
|
||||||
ok( !ret && GetLastError() == RPC_S_SERVER_UNAVAILABLE,
|
ok( !ret && (GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
|
||||||
"LookupPrivilegeValueA didn't fail with RPC_S_SERVER_UNAVAILABLE: %d\n",
|
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());
|
GetLastError());
|
||||||
/* check a NULL string */
|
/* check a NULL string */
|
||||||
ret = pLookupPrivilegeValueA(NULL, 0, &luid);
|
ret = pLookupPrivilegeValueA(NULL, 0, &luid);
|
||||||
|
@ -1642,7 +1647,8 @@ static void test_LookupAccountName(void)
|
||||||
ok(!ret, "Expected 0, got %d\n", ret);
|
ok(!ret, "Expected 0, got %d\n", ret);
|
||||||
todo_wine
|
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());
|
"Expected ERROR_NONE_MAPPED, got %d\n", GetLastError());
|
||||||
ok(sid_size == 0, "Expected 0, got %d\n", sid_size);
|
ok(sid_size == 0, "Expected 0, got %d\n", sid_size);
|
||||||
ok(domain_size == 0, "Expected 0, got %d\n", domain_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__)
|
#define TEST_GRANTED_ACCESS(a,b) test_granted_access(a,b,0,__LINE__)
|
||||||
static void test_granted_access(HANDLE handle, ACCESS_MASK access, int 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;
|
OBJECT_BASIC_INFORMATION obj_info;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
@ -1714,8 +1722,13 @@ static void test_granted_access(HANDLE handle, ACCESS_MASK access, int line)
|
||||||
status = pNtQueryObject( handle, ObjectBasicInformation, &obj_info,
|
status = pNtQueryObject( handle, ObjectBasicInformation, &obj_info,
|
||||||
sizeof(obj_info), NULL );
|
sizeof(obj_info), NULL );
|
||||||
ok_(__FILE__, line)(!status, "NtQueryObject with err: %08x\n", status);
|
ok_(__FILE__, line)(!status, "NtQueryObject with err: %08x\n", status);
|
||||||
ok_(__FILE__, line)(obj_info.GrantedAccess == access, "Granted access should "
|
if (alt)
|
||||||
"be 0x%08x, instead of 0x%08x\n", access, obj_info.GrantedAccess);
|
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) \
|
#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 */
|
/* 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 ),
|
ok(CreateProcessA( NULL, buffer, &psa, NULL, FALSE, 0, NULL, NULL, &startup, &info ),
|
||||||
"CreateProcess with err:%d\n", GetLastError());
|
"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 );
|
winetest_wait_child_process( info.hProcess );
|
||||||
|
|
||||||
CloseHandle( info.hProcess );
|
CloseHandle( info.hProcess );
|
||||||
|
@ -1876,7 +1890,8 @@ static void test_process_security_child(void)
|
||||||
ok(DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
|
ok(DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
|
||||||
&handle, 0, TRUE, DUPLICATE_SAME_ACCESS ),
|
&handle, 0, TRUE, DUPLICATE_SAME_ACCESS ),
|
||||||
"duplicating handle err:%d\n", GetLastError());
|
"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 );
|
CloseHandle( handle );
|
||||||
|
|
||||||
|
@ -1884,7 +1899,8 @@ static void test_process_security_child(void)
|
||||||
ok(DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
|
ok(DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
|
||||||
&handle, PROCESS_ALL_ACCESS, TRUE, 0 ),
|
&handle, PROCESS_ALL_ACCESS, TRUE, 0 ),
|
||||||
"duplicating handle err:%d\n", GetLastError());
|
"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(),
|
ok(DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
|
||||||
&handle1, PROCESS_VM_READ, TRUE, 0 ),
|
&handle1, PROCESS_VM_READ, TRUE, 0 ),
|
||||||
"duplicating handle err:%d\n", GetLastError());
|
"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());
|
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)
|
START_TEST(security)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
@ -2510,4 +2581,5 @@ START_TEST(security)
|
||||||
test_ConvertSecurityDescriptorToString();
|
test_ConvertSecurityDescriptorToString();
|
||||||
test_PrivateObjectSecurity();
|
test_PrivateObjectSecurity();
|
||||||
test_acls();
|
test_acls();
|
||||||
|
test_GetSecurityInfo();
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,26 @@
|
||||||
|
|
||||||
static const CHAR spooler[] = "Spooler"; /* Should be available on all platforms */
|
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)
|
static void test_open_scm(void)
|
||||||
{
|
{
|
||||||
SC_HANDLE scm_handle;
|
SC_HANDLE scm_handle;
|
||||||
|
@ -66,7 +86,8 @@ static void test_open_scm(void)
|
||||||
scm_handle = OpenSCManagerA("DOESNOTEXIST", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT);
|
scm_handle = OpenSCManagerA("DOESNOTEXIST", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT);
|
||||||
ok(!scm_handle, "Expected failure\n");
|
ok(!scm_handle, "Expected failure\n");
|
||||||
todo_wine
|
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 */
|
CloseServiceHandle(scm_handle); /* Just in case */
|
||||||
|
|
||||||
/* Proper call with an empty hostname */
|
/* Proper call with an empty hostname */
|
||||||
|
@ -145,7 +166,17 @@ static void test_open_svc(void)
|
||||||
GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
|
GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
|
||||||
/* Get the displayname */
|
/* Get the displayname */
|
||||||
GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
|
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);
|
svc_handle = OpenServiceA(scm_handle, displayname, GENERIC_READ);
|
||||||
ok(!svc_handle, "Expected failure\n");
|
ok(!svc_handle, "Expected failure\n");
|
||||||
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
|
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);
|
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)
|
static void test_close(void)
|
||||||
{
|
{
|
||||||
SC_HANDLE handle;
|
SC_HANDLE handle;
|
||||||
|
@ -947,13 +1782,7 @@ static void test_queryconfig2(void)
|
||||||
static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
|
static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
|
||||||
static const CHAR password [] = "";
|
static const CHAR password [] = "";
|
||||||
static const CHAR description [] = "Description";
|
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)
|
if(!pQueryServiceConfig2A)
|
||||||
{
|
{
|
||||||
skip("function QueryServiceConfig2A not present\n");
|
skip("function QueryServiceConfig2A not present\n");
|
||||||
|
@ -1239,12 +2068,16 @@ START_TEST(service)
|
||||||
}
|
}
|
||||||
CloseServiceHandle(scm_handle);
|
CloseServiceHandle(scm_handle);
|
||||||
|
|
||||||
|
init_function_pointers();
|
||||||
|
|
||||||
/* First some parameter checking */
|
/* First some parameter checking */
|
||||||
test_open_scm();
|
test_open_scm();
|
||||||
test_open_svc();
|
test_open_svc();
|
||||||
test_create_delete_svc();
|
test_create_delete_svc();
|
||||||
test_get_displayname();
|
test_get_displayname();
|
||||||
test_get_servicekeyname();
|
test_get_servicekeyname();
|
||||||
|
test_query_svc();
|
||||||
|
test_enum_svc();
|
||||||
test_close();
|
test_close();
|
||||||
/* Test the creation, querying and deletion of a service */
|
/* Test the creation, querying and deletion of a service */
|
||||||
test_sequence();
|
test_sequence();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue