Alexandre Julliard : advapi32: Reimplemented QueryServiceConfig2W in services.exe.
Alexandre Julliard
julliard at winehq.org
Tue Jan 20 08:27:25 CST 2009
Module: wine
Branch: master
Commit: b608a43df7429794fed77ae80804f08226497891
URL: http://source.winehq.org/git/wine.git/?a=commit;h=b608a43df7429794fed77ae80804f08226497891
Author: Alexandre Julliard <julliard at winehq.org>
Date: Mon Jan 19 20:18:24 2009 +0100
advapi32: Reimplemented QueryServiceConfig2W in services.exe.
---
dlls/advapi32/service.c | 60 +++++++++++++++++++++++-----------------------
include/wine/svcctl.idl | 10 ++++++-
programs/services/rpc.c | 49 ++++++++++++++++++++++++++++++++-----
3 files changed, 80 insertions(+), 39 deletions(-)
diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c
index cf58e2c..dd056b2 100644
--- a/dlls/advapi32/service.c
+++ b/dlls/advapi32/service.c
@@ -292,6 +292,7 @@ static DWORD map_exception_code(DWORD exception_code)
switch (exception_code)
{
case RPC_X_NULL_REF_POINTER:
+ return ERROR_INVALID_ADDRESS;
case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
case RPC_X_BYTE_COUNT_TOO_SMALL:
return ERROR_INVALID_PARAMETER;
@@ -1654,9 +1655,7 @@ cleanup:
BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
DWORD size, LPDWORD needed)
{
- DWORD sz, type;
- HKEY hKey;
- LONG r;
+ DWORD err;
struct sc_service *hsvc;
if(dwLevel != SERVICE_CONFIG_DESCRIPTION) {
@@ -1670,7 +1669,8 @@ BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffe
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
- if(!needed || (!buffer && size)) {
+
+ if(!buffer && size) {
SetLastError(ERROR_INVALID_ADDRESS);
return FALSE;
}
@@ -1683,36 +1683,36 @@ BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffe
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
- hKey = hsvc->hkey;
- switch(dwLevel) {
- case SERVICE_CONFIG_DESCRIPTION: {
- static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
- LPSERVICE_DESCRIPTIONW config = (LPSERVICE_DESCRIPTIONW) buffer;
- LPBYTE strbuf = NULL;
- *needed = sizeof (SERVICE_DESCRIPTIONW);
- sz = size - *needed;
- if(config && (*needed <= size))
- strbuf = (LPBYTE) (config + 1);
- r = RegQueryValueExW( hKey, szDescription, 0, &type, strbuf, &sz );
- if((r == ERROR_SUCCESS) && ( type != REG_SZ)) {
- FIXME("SERVICE_CONFIG_DESCRIPTION: don't know how to handle type %d\n", type);
- return FALSE;
- }
- *needed += sz;
- if(config) {
- if(r == ERROR_SUCCESS)
- config->lpDescription = (LPWSTR) (config + 1);
- else
- config->lpDescription = NULL;
- }
+ __TRY
+ {
+ err = svcctl_QueryServiceConfig2W(hsvc->hdr.server_handle, dwLevel, buffer, size, needed);
+ }
+ __EXCEPT(rpc_filter)
+ {
+ err = map_exception_code(GetExceptionCode());
+ }
+ __ENDTRY
+
+ if (err != ERROR_SUCCESS)
+ {
+ SetLastError( err );
+ return FALSE;
+ }
+
+ switch (dwLevel)
+ {
+ case SERVICE_CONFIG_DESCRIPTION:
+ if (buffer)
+ {
+ 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;
}
/******************************************************************************
diff --git a/include/wine/svcctl.idl b/include/wine/svcctl.idl
index 66abd30..d04da08 100644
--- a/include/wine/svcctl.idl
+++ b/include/wine/svcctl.idl
@@ -296,8 +296,14 @@ typedef [switch_type(DWORD)] union
/* Not compatible with Windows function 0x26 */
DWORD svcctl_QueryServiceConfig2A(/* FIXME */);
- /* Not compatible with Windows function 0x27 */
- DWORD svcctl_QueryServiceConfig2W(/* FIXME */);
+ /* Untested with Windows function 0x27 */
+ 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 */
DWORD svcctl_QueryServiceStatusEx(
diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index 830ed9c..b6014aa 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -646,6 +646,48 @@ DWORD svcctl_ChangeServiceConfig2W( SC_RPC_HANDLE hService, DWORD level, SERVICE
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(
SC_RPC_HANDLE hService,
SC_STATUS_TYPE InfoLevel,
@@ -1141,13 +1183,6 @@ DWORD svcctl_QueryServiceConfig2A(
return ERROR_CALL_NOT_IMPLEMENTED;
}
-DWORD svcctl_QueryServiceConfig2W(
- void)
-{
- WINE_FIXME("\n");
- return ERROR_CALL_NOT_IMPLEMENTED;
-}
-
DWORD RPC_Init(void)
{
More information about the wine-cvs
mailing list