Commit 331b99cf authored by Erich Hoover's avatar Erich Hoover Committed by Alexandre Julliard

advapi32: Support service objects in GetSecurityInfo.

parent c8e71e9a
......@@ -21,6 +21,7 @@
#define __WINE_ADVAPI32MISC_H
#include "ntsecapi.h"
#include "winsvc.h"
const char * debugstr_sid(PSID sid) DECLSPEC_HIDDEN;
BOOL ADVAPI_IsLocalComputer(LPCWSTR ServerName) DECLSPEC_HIDDEN;
......@@ -28,6 +29,7 @@ BOOL ADVAPI_GetComputerSid(PSID sid) DECLSPEC_HIDDEN;
BOOL lookup_local_wellknown_name(const LSA_UNICODE_STRING*, PSID, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE, BOOL*) DECLSPEC_HIDDEN;
BOOL lookup_local_user_name(const LSA_UNICODE_STRING*, PSID, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE, BOOL*) DECLSPEC_HIDDEN;
WCHAR *SERV_dup(const char *str);
WCHAR *SERV_dup(const char *str) DECLSPEC_HIDDEN;
NTSTATUS SERV_QueryServiceObjectSecurity(SC_HANDLE, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD) DECLSPEC_HIDDEN;
#endif /* __WINE_ADVAPI32MISC_H */
......@@ -3046,7 +3046,26 @@ DWORD WINAPI GetSecurityInfo(
ULONG n1, n2;
BOOL present, defaulted;
status = NtQuerySecurityObject(hObject, SecurityInfo, NULL, 0, &n1);
/* A NULL descriptor is allowed if any one of the other pointers is not NULL */
if (!(ppsidOwner||ppsidGroup||ppDacl||ppSacl||ppSecurityDescriptor)) return ERROR_INVALID_PARAMETER;
/* If no descriptor, we have to check that there's a pointer for the requested information */
if( !ppSecurityDescriptor && (
((SecurityInfo & OWNER_SECURITY_INFORMATION) && !ppsidOwner)
|| ((SecurityInfo & GROUP_SECURITY_INFORMATION) && !ppsidGroup)
|| ((SecurityInfo & DACL_SECURITY_INFORMATION) && !ppDacl)
|| ((SecurityInfo & SACL_SECURITY_INFORMATION) && !ppSacl) ))
return ERROR_INVALID_PARAMETER;
switch (ObjectType)
{
case SE_SERVICE:
status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, NULL, 0, &n1);
break;
default:
status = NtQuerySecurityObject(hObject, SecurityInfo, NULL, 0, &n1);
break;
}
if (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_SUCCESS)
return RtlNtStatusToDosError(status);
......@@ -3054,7 +3073,15 @@ DWORD WINAPI GetSecurityInfo(
if (!sd)
return ERROR_NOT_ENOUGH_MEMORY;
status = NtQuerySecurityObject(hObject, SecurityInfo, sd, n1, &n2);
switch (ObjectType)
{
case SE_SERVICE:
status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, sd, n1, &n2);
break;
default:
status = NtQuerySecurityObject(hObject, SecurityInfo, sd, n1, &n2);
break;
}
if (status != STATUS_SUCCESS)
{
LocalFree(sd);
......
......@@ -28,6 +28,8 @@
#include <time.h>
#include <assert.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winsvc.h"
......@@ -2147,17 +2149,14 @@ BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
return err == ERROR_SUCCESS;
}
/******************************************************************************
* QueryServiceObjectSecurity [ADVAPI32.@]
*/
BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
NTSTATUS SERV_QueryServiceObjectSecurity(SC_HANDLE hService,
SECURITY_INFORMATION dwSecurityInformation,
PSECURITY_DESCRIPTOR lpSecurityDescriptor,
DWORD cbBufSize, LPDWORD pcbBytesNeeded)
{
SECURITY_DESCRIPTOR descriptor;
NTSTATUS status;
DWORD size;
BOOL succ;
ACL acl;
FIXME("%p %d %p %u %p - semi-stub\n", hService, dwSecurityInformation,
......@@ -2172,9 +2171,27 @@ BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
SetSecurityDescriptorDacl(&descriptor, TRUE, &acl, TRUE);
size = cbBufSize;
succ = MakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
status = RtlMakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
*pcbBytesNeeded = size;
return succ;
return status;
}
/******************************************************************************
* QueryServiceObjectSecurity [ADVAPI32.@]
*/
BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
SECURITY_INFORMATION dwSecurityInformation,
PSECURITY_DESCRIPTOR lpSecurityDescriptor,
DWORD cbBufSize, LPDWORD pcbBytesNeeded)
{
NTSTATUS status = SERV_QueryServiceObjectSecurity(hService, dwSecurityInformation, lpSecurityDescriptor,
cbBufSize, pcbBytesNeeded);
if (status != STATUS_SUCCESS)
{
SetLastError(RtlNtStatusToDosError(status));
return FALSE;
}
return TRUE;
}
/******************************************************************************
......
......@@ -48,6 +48,8 @@ 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 BOOL (WINAPI *pQueryServiceObjectSecurity)(SC_HANDLE, SECURITY_INFORMATION,
PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
static void init_function_pointers(void)
{
......@@ -60,6 +62,7 @@ static void init_function_pointers(void)
pQueryServiceConfig2A= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2A");
pQueryServiceConfig2W= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2W");
pQueryServiceStatusEx= (void*)GetProcAddress(hadvapi32, "QueryServiceStatusEx");
pQueryServiceObjectSecurity = (void*)GetProcAddress(hadvapi32, "QueryServiceObjectSecurity");
}
static void test_open_scm(void)
......@@ -1756,7 +1759,7 @@ static void test_close(void)
static void test_sequence(void)
{
SC_HANDLE scm_handle, svc_handle;
BOOL ret;
BOOL ret, is_nt4;
QUERY_SERVICE_CONFIGA *config;
DWORD given, needed;
static const CHAR servicename [] = "Winetest";
......@@ -1780,6 +1783,9 @@ static void test_sequence(void)
ok(scm_handle != NULL, "Could not get a handle to the manager: %d\n", GetLastError());
if (!scm_handle) return;
svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
is_nt4=(svc_handle == NULL && GetLastError() == ERROR_INVALID_PARAMETER);
CloseServiceHandle(svc_handle);
/* Create a dummy service */
SetLastError(0xdeadbeef);
......@@ -1817,8 +1823,44 @@ static void test_sequence(void)
PSID sidOwner, sidGroup;
PACL dacl, sacl;
PSECURITY_DESCRIPTOR pSD;
HRESULT retval = pGetSecurityInfo(svc_handle,SE_SERVICE,DACL_SECURITY_INFORMATION,&sidOwner,&sidGroup,&dacl,&sacl,&pSD);
todo_wine ok(ERROR_SUCCESS == retval, "Expected GetSecurityInfo to succeed: result %d\n",retval);
DWORD error, n1, n2;
HRESULT retval;
BOOL bret;
/* Test using GetSecurityInfo to obtain security information */
retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, &sidOwner,
&sidGroup, &dacl, &sacl, &pSD);
LocalFree(pSD);
ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval);
retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
NULL, NULL, NULL, &pSD);
LocalFree(pSD);
ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval);
if (!is_nt4)
{
retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
NULL, &dacl, NULL, NULL);
ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval);
SetLastError(0xdeadbeef);
retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
NULL, NULL, NULL, NULL);
error = GetLastError();
ok(retval == ERROR_INVALID_PARAMETER, "Expected GetSecurityInfo to fail: result %d\n", retval);
ok(error == 0xdeadbeef, "Unexpected last error %d\n", error);
}
else
win_skip("A NULL security descriptor in GetSecurityInfo results in an exception on NT4.\n");
/* Test using QueryServiceObjectSecurity to obtain security information */
SetLastError(0xdeadbeef);
bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, pSD, 0, &n1);
error = GetLastError();
ok(!bret, "Expected QueryServiceObjectSecurity to fail: result %d\n", bret);
ok(error == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", error);
pSD = LocalAlloc(0, n1);
bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, pSD, n1, &n2);
ok(bret, "Expected QueryServiceObjectSecurity to succeed: result %d\n", bret);
LocalFree(pSD);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment