forked from Mirrors/wine-wine
services: Move GetServiceDisplayName to services.exe and implement GetServiceKeyName.
parent
76d4eeebff
commit
010dcb168b
|
@ -2135,8 +2135,44 @@ EnumServicesStatusExW(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServ
|
|||
BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
|
||||
LPSTR lpServiceName, LPDWORD lpcchBuffer )
|
||||
{
|
||||
FIXME("%p %s %p %p\n", hSCManager, debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
|
||||
return FALSE;
|
||||
LPWSTR lpDisplayNameW, lpServiceNameW;
|
||||
DWORD sizeW;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
TRACE("%p %s %p %p\n", hSCManager,
|
||||
debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
|
||||
|
||||
lpDisplayNameW = SERV_dup(lpDisplayName);
|
||||
if (lpServiceName)
|
||||
lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
|
||||
else
|
||||
lpServiceNameW = NULL;
|
||||
|
||||
sizeW = *lpcchBuffer;
|
||||
if (!GetServiceKeyNameW(hSCManager, lpDisplayNameW, lpServiceNameW, &sizeW))
|
||||
{
|
||||
if (*lpcchBuffer && lpServiceName)
|
||||
lpServiceName[0] = 0;
|
||||
*lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, (sizeW + 1), lpServiceName,
|
||||
*lpcchBuffer, NULL, NULL ))
|
||||
{
|
||||
if (*lpcchBuffer && lpServiceName)
|
||||
lpServiceName[0] = 0;
|
||||
*lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, -1, NULL, 0, NULL, NULL);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
|
||||
ret = TRUE;
|
||||
|
||||
cleanup:
|
||||
HeapFree(GetProcessHeap(), 0, lpServiceNameW);
|
||||
HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -2145,8 +2181,31 @@ BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
|
|||
BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
|
||||
LPWSTR lpServiceName, LPDWORD lpcchBuffer )
|
||||
{
|
||||
FIXME("%p %s %p %p\n", hSCManager, debugstr_w(lpDisplayName), lpServiceName, lpcchBuffer);
|
||||
return FALSE;
|
||||
struct sc_manager *hscm;
|
||||
DWORD err;
|
||||
|
||||
TRACE("%p %s %p %p\n", hSCManager,
|
||||
debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
|
||||
|
||||
hscm = sc_handle_get_handle_data(hSCManager, SC_HTYPE_MANAGER);
|
||||
if (!hscm)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!lpDisplayName)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_ADDRESS);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
err = svcctl_GetServiceKeyNameW(hscm->hdr.server_handle,
|
||||
lpDisplayName, lpServiceName, lpServiceName ? *lpcchBuffer : 0, lpcchBuffer);
|
||||
|
||||
if (err)
|
||||
SetLastError(err);
|
||||
return err == ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -2195,6 +2254,8 @@ BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
|
|||
sizeW = *lpcchBuffer;
|
||||
if (!GetServiceDisplayNameW(hSCManager, lpServiceNameW, lpDisplayNameW, &sizeW))
|
||||
{
|
||||
if (*lpcchBuffer && lpDisplayName)
|
||||
lpDisplayName[0] = 0;
|
||||
*lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -2202,6 +2263,8 @@ BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
|
|||
if (!WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName,
|
||||
*lpcchBuffer, NULL, NULL ))
|
||||
{
|
||||
if (*lpcchBuffer && lpDisplayName)
|
||||
lpDisplayName[0] = 0;
|
||||
*lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, NULL, 0, NULL, NULL);
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -2223,8 +2286,7 @@ BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
|
|||
LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
|
||||
{
|
||||
struct sc_manager *hscm;
|
||||
DWORD type, size;
|
||||
LONG ret;
|
||||
DWORD err;
|
||||
|
||||
TRACE("%p %s %p %p\n", hSCManager,
|
||||
debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
|
||||
|
@ -2242,56 +2304,12 @@ BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
size = *lpcchBuffer * sizeof(WCHAR);
|
||||
ret = RegGetValueW(hscm->hkey, lpServiceName, szDisplayName, RRF_RT_REG_SZ, &type, lpDisplayName, &size);
|
||||
if (!ret && !lpDisplayName && size)
|
||||
ret = ERROR_MORE_DATA;
|
||||
err = svcctl_GetServiceDisplayNameW(hscm->hdr.server_handle,
|
||||
lpServiceName, lpDisplayName, lpDisplayName ? *lpcchBuffer : 0, lpcchBuffer);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
if (lpDisplayName && *lpcchBuffer) *lpDisplayName = 0;
|
||||
|
||||
if (ret == ERROR_MORE_DATA)
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
*lpcchBuffer = (size / sizeof(WCHAR)) - 1;
|
||||
}
|
||||
else if (ret == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
HKEY hkey;
|
||||
|
||||
if (!RegOpenKeyW(hscm->hkey, lpServiceName, &hkey))
|
||||
{
|
||||
UINT len = lstrlenW(lpServiceName);
|
||||
BOOL r = FALSE;
|
||||
|
||||
if ((*lpcchBuffer <= len) || (!lpDisplayName && *lpcchBuffer))
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
else if (lpDisplayName && *lpcchBuffer)
|
||||
{
|
||||
/* No displayname, but the service exists and the buffer
|
||||
* is big enough. We should return the servicename.
|
||||
*/
|
||||
lstrcpyW(lpDisplayName, lpServiceName);
|
||||
r = TRUE;
|
||||
}
|
||||
|
||||
*lpcchBuffer = len;
|
||||
RegCloseKey(hkey);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
|
||||
}
|
||||
else
|
||||
SetLastError(ret);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Always return the correct needed size on success */
|
||||
*lpcchBuffer = (size / sizeof(WCHAR)) - 1;
|
||||
|
||||
return TRUE;
|
||||
if (err)
|
||||
SetLastError(err);
|
||||
return err == ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "winerror.h"
|
||||
#include "winreg.h"
|
||||
#include "winsvc.h"
|
||||
#include "winnls.h"
|
||||
#include "lmcons.h"
|
||||
|
||||
#include "wine/test.h"
|
||||
|
@ -614,45 +615,77 @@ static void test_get_servicekeyname(void)
|
|||
SC_HANDLE scm_handle, svc_handle;
|
||||
CHAR servicename[4096];
|
||||
CHAR displayname[4096];
|
||||
WCHAR servicenameW[4096];
|
||||
WCHAR displaynameW[4096];
|
||||
DWORD servicesize, displaysize, tempsize;
|
||||
BOOL ret;
|
||||
static const CHAR deadbeef[] = "Deadbeef";
|
||||
static const WCHAR deadbeefW[] = {'D','e','a','d','b','e','e','f',0};
|
||||
|
||||
/* Having NULL for the size of the buffer will crash on W2K3 */
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetServiceKeyNameA(NULL, NULL, NULL, &servicesize);
|
||||
ok(!ret, "Expected failure\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE,
|
||||
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
|
||||
|
||||
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
|
||||
|
||||
servicesize = 200;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetServiceKeyNameA(scm_handle, NULL, NULL, &servicesize);
|
||||
ok(!ret, "Expected failure\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
|
||||
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
|
||||
"Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
|
||||
|
||||
/* Valid handle and buffer but no displayname */
|
||||
servicesize = 200;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetServiceKeyNameA(scm_handle, NULL, servicename, &servicesize);
|
||||
ok(!ret, "Expected failure\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
|
||||
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
|
||||
"Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
todo_wine ok(servicesize == 200, "Service size expected 1, got %d\n", servicesize);
|
||||
|
||||
/* Test for nonexistent displayname */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetServiceKeyNameA(scm_handle, deadbeef, NULL, &servicesize);
|
||||
ok(!ret, "Expected failure\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
|
||||
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
|
||||
todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
|
||||
|
||||
servicesize = 15;
|
||||
strcpy(servicename, "ABC");
|
||||
ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
|
||||
ok(!ret, "Expected failure\n");
|
||||
todo_wine ok(servicesize == 15, "Service size expected 15, got %d\n", servicesize);
|
||||
ok(servicename[0] == 0, "Service name not empty\n");
|
||||
|
||||
servicesize = 15;
|
||||
servicenameW[0] = 'A';
|
||||
ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
|
||||
ok(!ret, "Expected failure\n");
|
||||
todo_wine ok(servicesize == 15, "Service size expected 15, got %d\n", servicesize);
|
||||
ok(servicenameW[0] == 0, "Service name not empty\n");
|
||||
|
||||
servicesize = 0;
|
||||
strcpy(servicename, "ABC");
|
||||
ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
|
||||
ok(!ret, "Expected failure\n");
|
||||
todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
|
||||
ok(servicename[0] == 'A', "Service name changed\n");
|
||||
|
||||
servicesize = 0;
|
||||
servicenameW[0] = 'A';
|
||||
ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
|
||||
ok(!ret, "Expected failure\n");
|
||||
todo_wine ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize);
|
||||
ok(servicenameW[0] == 'A', "Service name changed\n");
|
||||
|
||||
/* Check if 'Spooler' exists */
|
||||
svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_READ);
|
||||
|
@ -673,7 +706,6 @@ static void test_get_servicekeyname(void)
|
|||
servicesize = 0;
|
||||
ret = GetServiceKeyNameA(scm_handle, displayname, NULL, &servicesize);
|
||||
ok(!ret, "Expected failure\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
"Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
|
||||
|
||||
|
@ -682,7 +714,6 @@ static void test_get_servicekeyname(void)
|
|||
tempsize = servicesize;
|
||||
servicesize *= 2;
|
||||
ret = GetServiceKeyNameA(scm_handle, displayname, servicename, &servicesize);
|
||||
todo_wine
|
||||
ok(ret, "Expected success\n");
|
||||
ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
|
||||
GetLastError() == ERROR_IO_PENDING /* W2K */ ||
|
||||
|
@ -693,8 +724,35 @@ static void test_get_servicekeyname(void)
|
|||
ok(lstrlen(servicename) == tempsize/2,
|
||||
"Expected the buffer to be twice the length of the string\n") ;
|
||||
ok(!lstrcmpi(servicename, spooler), "Expected %s, got %s\n", spooler, servicename);
|
||||
ok(servicesize == (tempsize * 2),
|
||||
"Expected servicesize not to change if buffer not insufficient\n") ;
|
||||
}
|
||||
|
||||
MultiByteToWideChar(CP_ACP, 0, displayname, -1, displaynameW, sizeof(displaynameW)/2);
|
||||
SetLastError(0xdeadbeef);
|
||||
servicesize *= 2;
|
||||
ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize);
|
||||
ok(ret, "Expected success\n");
|
||||
ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ ||
|
||||
GetLastError() == ERROR_IO_PENDING /* W2K */ ||
|
||||
GetLastError() == 0xdeadbeef /* NT4, XP, Vista */,
|
||||
"Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
ok(lstrlen(servicename) == tempsize/2,
|
||||
"Expected the buffer to be twice the length of the string\n") ;
|
||||
ok(servicesize == lstrlenW(servicenameW),
|
||||
"Expected servicesize not to change if buffer not insufficient\n") ;
|
||||
}
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
servicesize = 3;
|
||||
ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize);
|
||||
ok(!ret, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
"Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
|
||||
ok(servicenameW[0] == 0, "Buffer not empty\n");
|
||||
|
||||
CloseServiceHandle(scm_handle);
|
||||
}
|
||||
|
||||
|
|
|
@ -127,4 +127,19 @@ cpp_quote("#endif")
|
|||
[in] SC_RPC_HANDLE hService,
|
||||
[out] QUERY_SERVICE_CONFIGW *config);
|
||||
|
||||
/* Compatible with Windows function 0x14 */
|
||||
DWORD svcctl_GetServiceDisplayNameW(
|
||||
[in] SC_RPC_HANDLE hSCManager,
|
||||
[in] LPCWSTR lpServiceName,
|
||||
[out,size_is(cchBufSize)] WCHAR lpBuffer[],
|
||||
[in] DWORD cchBufSize,
|
||||
[out] DWORD *cchLength);
|
||||
|
||||
/* Compatible with Windows function 0x15 */
|
||||
DWORD svcctl_GetServiceKeyNameW(
|
||||
[in] SC_RPC_HANDLE hSCManager,
|
||||
[in] LPCWSTR lpServiceDisplayName,
|
||||
[out,size_is(cchBufSize)] WCHAR lpBuffer[],
|
||||
[in] DWORD cchBufSize,
|
||||
[out] DWORD *cchLength);
|
||||
}
|
||||
|
|
|
@ -183,6 +183,93 @@ static void SC_RPC_HANDLE_destroy(SC_RPC_HANDLE handle)
|
|||
}
|
||||
}
|
||||
|
||||
DWORD svcctl_GetServiceDisplayNameW(
|
||||
SC_RPC_HANDLE hSCManager,
|
||||
LPCWSTR lpServiceName,
|
||||
WCHAR *lpBuffer,
|
||||
DWORD cchBufSize,
|
||||
DWORD *cchLength)
|
||||
{
|
||||
struct sc_manager *manager;
|
||||
struct service_entry *entry;
|
||||
DWORD err;
|
||||
|
||||
WINE_TRACE("(%s, %d)\n", wine_dbgstr_w(lpServiceName), cchBufSize);
|
||||
|
||||
if ((err = validate_scm_handle(hSCManager, 0, &manager)) != ERROR_SUCCESS)
|
||||
return err;
|
||||
|
||||
lock_services();
|
||||
|
||||
entry = find_service(lpServiceName);
|
||||
if (entry != NULL)
|
||||
{
|
||||
LPCWSTR name = get_display_name(entry);
|
||||
*cchLength = strlenW(name);
|
||||
if (*cchLength < cchBufSize)
|
||||
{
|
||||
err = ERROR_SUCCESS;
|
||||
lstrcpyW(lpBuffer, name);
|
||||
}
|
||||
else
|
||||
err = ERROR_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
else
|
||||
{
|
||||
*cchLength = 1;
|
||||
err = ERROR_SERVICE_DOES_NOT_EXIST;
|
||||
}
|
||||
|
||||
if (err != ERROR_SUCCESS && cchBufSize > 0)
|
||||
lpBuffer[0] = 0;
|
||||
unlock_services();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
DWORD svcctl_GetServiceKeyNameW(
|
||||
SC_RPC_HANDLE hSCManager,
|
||||
LPCWSTR lpServiceDisplayName,
|
||||
WCHAR *lpBuffer,
|
||||
DWORD cchBufSize,
|
||||
DWORD *cchLength)
|
||||
{
|
||||
struct service_entry *entry;
|
||||
struct sc_manager *manager;
|
||||
DWORD err;
|
||||
|
||||
WINE_TRACE("(%s, %d)\n", wine_dbgstr_w(lpServiceDisplayName), cchBufSize);
|
||||
|
||||
if ((err = validate_scm_handle(hSCManager, 0, &manager)) != ERROR_SUCCESS)
|
||||
return err;
|
||||
|
||||
lock_services();
|
||||
|
||||
entry = find_service_by_displayname(lpServiceDisplayName);
|
||||
if (entry != NULL)
|
||||
{
|
||||
*cchLength = strlenW(entry->name);
|
||||
if (*cchLength < cchBufSize)
|
||||
{
|
||||
err = ERROR_SUCCESS;
|
||||
lstrcpyW(lpBuffer, entry->name);
|
||||
}
|
||||
else
|
||||
err = ERROR_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
else
|
||||
{
|
||||
*cchLength = 1;
|
||||
err = ERROR_SERVICE_DOES_NOT_EXIST;
|
||||
}
|
||||
|
||||
if (err != ERROR_SUCCESS && cchBufSize > 0)
|
||||
lpBuffer[0] = 0;
|
||||
unlock_services();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static DWORD create_handle_for_service(struct service_entry *entry, DWORD dwDesiredAccess, SC_RPC_HANDLE *phService)
|
||||
{
|
||||
struct sc_service *service;
|
||||
|
|
Loading…
Reference in New Issue