advapi/service: Check servicetype and starttype.
This commit is contained in:
parent
d470e688c4
commit
f09359cda4
|
@ -1344,6 +1344,39 @@ CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ServiceType can only be one value (except for SERVICE_INTERACTIVE_PROCESS which can be used
|
||||||
|
* together with SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS when the service
|
||||||
|
* runs under the LocalSystem account)
|
||||||
|
*/
|
||||||
|
switch (dwServiceType)
|
||||||
|
{
|
||||||
|
case SERVICE_KERNEL_DRIVER:
|
||||||
|
case SERVICE_FILE_SYSTEM_DRIVER:
|
||||||
|
case SERVICE_WIN32_OWN_PROCESS:
|
||||||
|
case SERVICE_WIN32_SHARE_PROCESS:
|
||||||
|
/* No problem */
|
||||||
|
break;
|
||||||
|
case SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS:
|
||||||
|
case SERVICE_WIN32_SHARE_PROCESS | SERVICE_INTERACTIVE_PROCESS:
|
||||||
|
/* FIXME : Do we need a more thorough check? */
|
||||||
|
if (lpServiceStartName)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* StartType can only be a single value (if several values are mixed the result is probably not what was intended) */
|
||||||
|
if (dwStartType > SERVICE_DISABLED)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
r = RegCreateKeyExW(hscm->hkey, lpServiceName, 0, NULL,
|
r = RegCreateKeyExW(hscm->hkey, lpServiceName, 0, NULL,
|
||||||
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dp);
|
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dp);
|
||||||
if (r!=ERROR_SUCCESS)
|
if (r!=ERROR_SUCCESS)
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "winerror.h"
|
#include "winerror.h"
|
||||||
#include "winsvc.h"
|
#include "winsvc.h"
|
||||||
|
#include "lmcons.h"
|
||||||
|
|
||||||
#include "wine/test.h"
|
#include "wine/test.h"
|
||||||
|
|
||||||
|
@ -135,9 +136,19 @@ static void test_open_svc(void)
|
||||||
static void test_create_delete_svc(void)
|
static void test_create_delete_svc(void)
|
||||||
{
|
{
|
||||||
SC_HANDLE scm_handle, svc_handle1;
|
SC_HANDLE scm_handle, svc_handle1;
|
||||||
|
CHAR username[UNLEN + 1];
|
||||||
|
DWORD user_size = UNLEN + 1;
|
||||||
|
CHAR account[UNLEN + 3];
|
||||||
static const CHAR servicename [] = "Winetest";
|
static const CHAR servicename [] = "Winetest";
|
||||||
static const CHAR pathname [] = "we_dont_care.exe";
|
static const CHAR pathname [] = "we_dont_care.exe";
|
||||||
static const CHAR empty [] = "";
|
static const CHAR empty [] = "";
|
||||||
|
static const CHAR spooler [] = "Spooler";
|
||||||
|
static const CHAR password [] = "secret";
|
||||||
|
|
||||||
|
/* Get the username and turn it into an account to be used in some tests */
|
||||||
|
GetUserNameA(username, &user_size);
|
||||||
|
lstrcpy(account, ".\\");
|
||||||
|
lstrcat(account, username);
|
||||||
|
|
||||||
/* All NULL */
|
/* All NULL */
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
|
@ -198,6 +209,8 @@ static void test_create_delete_svc(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: It looks like account (ServiceStartName) and (maybe) password are checked at this place */
|
||||||
|
|
||||||
/* Empty strings for servicename and binary name are checked */
|
/* Empty strings for servicename and binary name are checked */
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
|
svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
@ -220,6 +233,57 @@ static void test_create_delete_svc(void)
|
||||||
ok(!svc_handle1, "Expected failure\n");
|
ok(!svc_handle1, "Expected failure\n");
|
||||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||||
|
|
||||||
|
/* Windows checks if the 'service type', 'access type' and the combination of them are valid, so let's test that */
|
||||||
|
|
||||||
|
/* Illegal (service-type, which is used as a mask can't have a mix. Except the one with SERVICE_INTERACTIVE_PROCESS which is tested below) */
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS,
|
||||||
|
SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
ok(!svc_handle1, "Expected failure\n");
|
||||||
|
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||||
|
|
||||||
|
/* Illegal (SERVICE_INTERACTIVE_PROCESS is only allowed with SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS) */
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_FILE_SYSTEM_DRIVER | SERVICE_INTERACTIVE_PROCESS,
|
||||||
|
SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
ok(!svc_handle1, "Expected failure\n");
|
||||||
|
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||||
|
|
||||||
|
/* Illegal (this combination is only allowed when the LocalSystem account (ServiceStartName) is used)
|
||||||
|
* Not having a correct account would have resulted in an ERROR_INVALID_SERVICE_ACCOUNT.
|
||||||
|
*/
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
|
||||||
|
SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, account, password);
|
||||||
|
ok(!svc_handle1, "Expected failure\n");
|
||||||
|
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||||
|
|
||||||
|
/* Illegal (start-type is not a mask and should only be one of the possibilities)
|
||||||
|
* Remark : 'OR'-ing them could result in a valid possibility (but doesn't make sense as it's most likely not the wanted start-type)
|
||||||
|
*/
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START | SERVICE_DISABLED,
|
||||||
|
0, pathname, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
ok(!svc_handle1, "Expected failure\n");
|
||||||
|
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||||
|
|
||||||
|
/* TODO: Add check for illegal combination of service-type and start-type */
|
||||||
|
|
||||||
|
/* TODO: Add check for displayname, it must be unique (or NULL/empty) */
|
||||||
|
|
||||||
|
/* The service already exists (check first, just in case) */
|
||||||
|
svc_handle1 = OpenServiceA(scm_handle, spooler, GENERIC_READ);
|
||||||
|
if (svc_handle1)
|
||||||
|
{
|
||||||
|
CloseServiceHandle(svc_handle1);
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
svc_handle1 = CreateServiceA(scm_handle, spooler, NULL, 0, SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
ok(!svc_handle1, "Expected failure\n");
|
||||||
|
ok(GetLastError() == ERROR_SERVICE_EXISTS, "Expected ERROR_SERVICE_EXISTS, got %d\n", GetLastError());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
skip("Spooler service doesn't exist\n");
|
||||||
|
|
||||||
CloseServiceHandle(scm_handle);
|
CloseServiceHandle(scm_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue