Paul Vriens : advapi/service: Check servicetype and starttype.
Alexandre Julliard
julliard at wine.codeweavers.com
Fri Jul 13 08:30:13 CDT 2007
Module: wine
Branch: master
Commit: f09359cda40c21455396797486be85d2b74de300
URL: http://source.winehq.org/git/wine.git/?a=commit;h=f09359cda40c21455396797486be85d2b74de300
Author: Paul Vriens <paul.vriens.wine at gmail.com>
Date: Thu Jul 12 21:34:21 2007 +0200
advapi/service: Check servicetype and starttype.
---
dlls/advapi32/service.c | 33 +++++++++++++++++++++
dlls/advapi32/tests/service.c | 64 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 97 insertions(+), 0 deletions(-)
diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c
index f087d75..93f96a8 100644
--- a/dlls/advapi32/service.c
+++ b/dlls/advapi32/service.c
@@ -1344,6 +1344,39 @@ CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
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,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dp);
if (r!=ERROR_SUCCESS)
diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c
index d383fee..dc5087a 100644
--- a/dlls/advapi32/tests/service.c
+++ b/dlls/advapi32/tests/service.c
@@ -24,6 +24,7 @@
#include "winbase.h"
#include "winerror.h"
#include "winsvc.h"
+#include "lmcons.h"
#include "wine/test.h"
@@ -135,9 +136,19 @@ static void test_open_svc(void)
static void test_create_delete_svc(void)
{
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 pathname [] = "we_dont_care.exe";
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 */
SetLastError(0xdeadbeef);
@@ -198,6 +209,8 @@ static void test_create_delete_svc(void)
return;
}
+ /* TODO: It looks like account (ServiceStartName) and (maybe) password are checked at this place */
+
/* Empty strings for servicename and binary name are checked */
SetLastError(0xdeadbeef);
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(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);
}
More information about the wine-cvs
mailing list