advapi32: Reimplemented QueryServiceConfig2W in services.exe.

oldstable
Alexandre Julliard 2009-01-19 20:18:24 +01:00
parent 8e16e78710
commit b608a43df7
3 changed files with 81 additions and 40 deletions

View File

@ -292,6 +292,7 @@ static DWORD map_exception_code(DWORD exception_code)
switch (exception_code) switch (exception_code)
{ {
case RPC_X_NULL_REF_POINTER: case RPC_X_NULL_REF_POINTER:
return ERROR_INVALID_ADDRESS;
case RPC_X_ENUM_VALUE_OUT_OF_RANGE: case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
case RPC_X_BYTE_COUNT_TOO_SMALL: case RPC_X_BYTE_COUNT_TOO_SMALL:
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
@ -1654,9 +1655,7 @@ cleanup:
BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer, BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
DWORD size, LPDWORD needed) DWORD size, LPDWORD needed)
{ {
DWORD sz, type; DWORD err;
HKEY hKey;
LONG r;
struct sc_service *hsvc; struct sc_service *hsvc;
if(dwLevel != SERVICE_CONFIG_DESCRIPTION) { if(dwLevel != SERVICE_CONFIG_DESCRIPTION) {
@ -1670,7 +1669,8 @@ BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffe
SetLastError(ERROR_INVALID_LEVEL); SetLastError(ERROR_INVALID_LEVEL);
return FALSE; return FALSE;
} }
if(!needed || (!buffer && size)) {
if(!buffer && size) {
SetLastError(ERROR_INVALID_ADDRESS); SetLastError(ERROR_INVALID_ADDRESS);
return FALSE; return FALSE;
} }
@ -1683,36 +1683,36 @@ BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffe
SetLastError(ERROR_INVALID_HANDLE); SetLastError(ERROR_INVALID_HANDLE);
return FALSE; return FALSE;
} }
hKey = hsvc->hkey;
switch(dwLevel) { __TRY
case SERVICE_CONFIG_DESCRIPTION: { {
static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0}; err = svcctl_QueryServiceConfig2W(hsvc->hdr.server_handle, dwLevel, buffer, size, needed);
LPSERVICE_DESCRIPTIONW config = (LPSERVICE_DESCRIPTIONW) buffer; }
LPBYTE strbuf = NULL; __EXCEPT(rpc_filter)
*needed = sizeof (SERVICE_DESCRIPTIONW); {
sz = size - *needed; err = map_exception_code(GetExceptionCode());
if(config && (*needed <= size)) }
strbuf = (LPBYTE) (config + 1); __ENDTRY
r = RegQueryValueExW( hKey, szDescription, 0, &type, strbuf, &sz );
if((r == ERROR_SUCCESS) && ( type != REG_SZ)) { if (err != ERROR_SUCCESS)
FIXME("SERVICE_CONFIG_DESCRIPTION: don't know how to handle type %d\n", type); {
SetLastError( err );
return FALSE; return FALSE;
} }
*needed += sz;
if(config) { switch (dwLevel)
if(r == ERROR_SUCCESS) {
config->lpDescription = (LPWSTR) (config + 1); case SERVICE_CONFIG_DESCRIPTION:
else if (buffer)
config->lpDescription = NULL; {
} SERVICE_DESCRIPTIONW *descr = (SERVICE_DESCRIPTIONW *)buffer;
} if (descr->lpDescription) /* make it an absolute pointer */
descr->lpDescription = (WCHAR *)(buffer + (ULONG_PTR)descr->lpDescription);
break; break;
} }
if(*needed > size) }
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (*needed <= size); return TRUE;
} }
/****************************************************************************** /******************************************************************************

View File

@ -296,8 +296,14 @@ typedef [switch_type(DWORD)] union
/* Not compatible with Windows function 0x26 */ /* Not compatible with Windows function 0x26 */
DWORD svcctl_QueryServiceConfig2A(/* FIXME */); DWORD svcctl_QueryServiceConfig2A(/* FIXME */);
/* Not compatible with Windows function 0x27 */ /* Untested with Windows function 0x27 */
DWORD svcctl_QueryServiceConfig2W(/* FIXME */); DWORD svcctl_QueryServiceConfig2W(
[in] SC_RPC_HANDLE hService,
[in] DWORD InfoLevel,
[out,size_is(cbBufSize)] BYTE lpBuffer[],
[in] DWORD cbBufSize,
[out] LPDWORD pcbBytesNeeded
);
/* Untested with Windows function 0x28 */ /* Untested with Windows function 0x28 */
DWORD svcctl_QueryServiceStatusEx( DWORD svcctl_QueryServiceStatusEx(

View File

@ -646,6 +646,48 @@ DWORD svcctl_ChangeServiceConfig2W( SC_RPC_HANDLE hService, DWORD level, SERVICE
return err; return err;
} }
DWORD svcctl_QueryServiceConfig2W( SC_RPC_HANDLE hService, DWORD level,
BYTE *buffer, DWORD size, LPDWORD needed )
{
struct sc_service_handle *service;
DWORD err;
if ((err = validate_service_handle(hService, SERVICE_QUERY_STATUS, &service)) != 0)
return err;
switch (level)
{
case SERVICE_CONFIG_DESCRIPTION:
{
SERVICE_DESCRIPTIONW *descr = (SERVICE_DESCRIPTIONW *)buffer;
service_lock_shared(service->service_entry);
*needed = sizeof(*descr);
if (service->service_entry->description)
*needed += (strlenW(service->service_entry->description) + 1) * sizeof(WCHAR);
if (size >= *needed)
{
if (service->service_entry->description)
{
/* store a buffer offset instead of a pointer */
descr->lpDescription = (WCHAR *)((BYTE *)(descr + 1) - buffer);
strcpyW( (WCHAR *)(descr + 1), service->service_entry->description );
}
else descr->lpDescription = NULL;
}
else err = ERROR_INSUFFICIENT_BUFFER;
service_unlock(service->service_entry);
}
break;
default:
WINE_FIXME("level %u not implemented\n", level);
err = ERROR_INVALID_LEVEL;
break;
}
return err;
}
DWORD svcctl_QueryServiceStatusEx( DWORD svcctl_QueryServiceStatusEx(
SC_RPC_HANDLE hService, SC_RPC_HANDLE hService,
SC_STATUS_TYPE InfoLevel, SC_STATUS_TYPE InfoLevel,
@ -1141,13 +1183,6 @@ DWORD svcctl_QueryServiceConfig2A(
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
} }
DWORD svcctl_QueryServiceConfig2W(
void)
{
WINE_FIXME("\n");
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD RPC_Init(void) DWORD RPC_Init(void)
{ {