Author: cwittich
Date: Sun Sep 14 13:24:25 2008
New Revision: 36247
URL:
http://svn.reactos.org/svn/reactos?rev=36247&view=rev
Log:
sync advapi32_winetest to wine 1.1.4
Modified:
trunk/rostests/winetests/advapi32/cred.c
trunk/rostests/winetests/advapi32/crypt.c
trunk/rostests/winetests/advapi32/crypt_lmhash.c
trunk/rostests/winetests/advapi32/lsa.c
trunk/rostests/winetests/advapi32/registry.c
trunk/rostests/winetests/advapi32/security.c
trunk/rostests/winetests/advapi32/service.c
Modified: trunk/rostests/winetests/advapi32/cred.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/cred.c…
==============================================================================
--- trunk/rostests/winetests/advapi32/cred.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/advapi32/cred.c [iso-8859-1] Sun Sep 14 13:24:25 2008
@@ -97,8 +97,12 @@
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 @@
{
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 @@
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);
Modified: trunk/rostests/winetests/advapi32/crypt.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/crypt.…
==============================================================================
--- trunk/rostests/winetests/advapi32/crypt.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/advapi32/crypt.c [iso-8859-1] Sun Sep 14 13:24:25 2008
@@ -903,7 +903,7 @@
/* 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,
Modified: trunk/rostests/winetests/advapi32/crypt_lmhash.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/crypt_…
==============================================================================
--- trunk/rostests/winetests/advapi32/crypt_lmhash.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/advapi32/crypt_lmhash.c [iso-8859-1] Sun Sep 14 13:24:25
2008
@@ -348,18 +348,24 @@
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);
Modified: trunk/rostests/winetests/advapi32/lsa.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/lsa.c?…
==============================================================================
--- trunk/rostests/winetests/advapi32/lsa.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/advapi32/lsa.c [iso-8859-1] Sun Sep 14 13:24:25 2008
@@ -30,9 +30,10 @@
#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);
@@ -95,7 +96,6 @@
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 @@
else
trace("invalid sid\n");
}
+ else
+ trace("Running on a standalone system.\n");
pLsaFreeMemory((LPVOID)primary_domain_info);
}
@@ -129,8 +131,6 @@
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 @@
LocalFree( guidstr );
LocalFree( strsid );
}
+ else
+ trace("Running on a standalone system.\n");
pLsaFreeMemory((LPVOID)dns_domain_info);
}
Modified: trunk/rostests/winetests/advapi32/registry.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/regist…
==============================================================================
--- trunk/rostests/winetests/advapi32/registry.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/advapi32/registry.c [iso-8859-1] Sun Sep 14 13:24:25 2008
@@ -159,9 +159,8 @@
#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 @@
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 @@
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 @@
"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 @@
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 @@
if(!pRegGetValueA)
{
- skip("RegGetValue not available on this platform\n");
+ win_skip("RegGetValue not available on this platform\n");
return;
}
@@ -775,7 +786,7 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
LONG size, ret;
if(!pRegDeleteTreeA) {
- skip("Skipping RegDeleteTreeA tests, function not present\n");
+ win_skip("Skipping RegDeleteTreeA tests, function not present\n");
return;
}
Modified: trunk/rostests/winetests/advapi32/security.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/securi…
==============================================================================
--- trunk/rostests/winetests/advapi32/security.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/advapi32/security.c [iso-8859-1] Sun Sep 14 13:24:25 2008
@@ -101,6 +101,8 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
}
}
-#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 @@
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 @@
/* 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 @@
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 @@
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());
@@ -2480,6 +2496,61 @@
SetLastError(0xdeadbeef);
ret = InitializeAcl(pAcl, sizeof(buffer), -1);
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)
@@ -2510,4 +2581,5 @@
test_ConvertSecurityDescriptorToString();
test_PrivateObjectSecurity();
test_acls();
-}
+ test_GetSecurityInfo();
+}
Modified: trunk/rostests/winetests/advapi32/service.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/servic…
==============================================================================
--- trunk/rostests/winetests/advapi32/service.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/advapi32/service.c [iso-8859-1] Sun Sep 14 13:24:25 2008
@@ -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 @@
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 @@
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 @@
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 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 @@
}
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();