ChangeLog: * Fix OpenSCManagerW. Stub implemenations for ChangeServiceConfigA/W Implement CreateServiceW and call it from CreateServiceA Partial implementation of QueryServiceConfigW
Index: include/winsvc.h =================================================================== RCS file: /home/wine/wine/include/winsvc.h,v retrieving revision 1.12 diff -u -r1.12 winsvc.h --- include/winsvc.h 5 Sep 2003 23:15:44 -0000 1.12 +++ include/winsvc.h 1 Dec 2003 12:57:29 -0000 @@ -154,6 +154,30 @@ DECL_WINELIB_TYPE_AW(ENUM_SERVICE_STATUS) DECL_WINELIB_TYPE_AW(LPENUM_SERVICE_STATUS) +typedef struct _QUERY_SERVICE_CONFIGA { + DWORD dwServiceType; + DWORD dwStartType; + DWORD dwErrorControl; + LPSTR lpBinaryPathName; + LPSTR lpLoadOrderGroup; + DWORD dwTagId; + LPSTR lpDependencies; + LPSTR lpServiceStartName; + LPSTR lpDisplayName; +} QUERY_SERVICE_CONFIGA, *LPQUERY_SERVICE_CONFIGA; + +typedef struct _QUERY_SERVICE_CONFIGW { + DWORD dwServiceType; + DWORD dwStartType; + DWORD dwErrorControl; + LPWSTR lpBinaryPathName; + LPWSTR lpLoadOrderGroup; + DWORD dwTagId; + LPWSTR lpDependencies; + LPWSTR lpServiceStartName; + LPWSTR lpDisplayName; +} QUERY_SERVICE_CONFIGW, *LPQUERY_SERVICE_CONFIGW; + /* Service control handler function prototype */ typedef VOID (WINAPI *LPHANDLER_FUNCTION)(DWORD); @@ -191,6 +215,10 @@ #define StartServiceCtrlDispatcher WINELIB_NAME_AW(StartServiceCtrlDispatcher) BOOL WINAPI QueryServiceStatus(SC_HANDLE,LPSERVICE_STATUS); BOOL WINAPI QueryServiceStatusEx(SC_HANDLE,SC_STATUS_TYPE,LPBYTE,DWORD,LPDWORD); +BOOL WINAPI QueryServiceConfigA(SC_HANDLE,LPQUERY_SERVICE_CONFIGA,DWORD,LPDWORD); +BOOL WINAPI QueryServiceConfigW(SC_HANDLE,LPQUERY_SERVICE_CONFIGW,DWORD,LPDWORD); +#define QueryServiceConfig WINELIB_NAME_AW(QueryServiceConfig) + #ifdef __cplusplus } /* extern "C" */ #endif /* defined(__cplusplus) */ Index: dlls/advapi32/advapi32.spec =================================================================== RCS file: /home/wine/wine/dlls/advapi32/advapi32.spec,v retrieving revision 1.43 diff -u -r1.43 advapi32.spec --- dlls/advapi32/advapi32.spec 11 Nov 2003 22:03:24 -0000 1.43 +++ dlls/advapi32/advapi32.spec 1 Dec 2003 12:57:29 -0000 @@ -20,8 +20,8 @@ @ stdcall BackupEventLogW (long wstr) @ stdcall BuildTrusteeWithSidA(ptr ptr) @ stdcall BuildTrusteeWithSidW(ptr ptr) -@ stub ChangeServiceConfigA -@ stub ChangeServiceConfigW +@ stdcall ChangeServiceConfigA(long long long long wstr str ptr str str str str) +@ stdcall ChangeServiceConfigW(long long long long wstr wstr ptr wstr wstr wstr wstr) @ stdcall ClearEventLogA (long str) @ stdcall ClearEventLogW (long wstr) @ stdcall CloseEventLog (long) @@ -182,8 +182,8 @@ @ stdcall PrivilegeCheck(ptr ptr ptr) @ stub PrivilegedServiceAuditAlarmA @ stub PrivilegedServiceAuditAlarmW -@ stub QueryServiceConfigA -@ stub QueryServiceConfigW +@ stdcall QueryServiceConfigA(long ptr long ptr) +@ stdcall QueryServiceConfigW(long ptr long ptr) @ stub QueryServiceLockStatusA @ stub QueryServiceLockStatusW @ stub QueryServiceObjectSecurity Index: dlls/advapi32/service.c =================================================================== RCS file: /home/wine/wine/dlls/advapi32/service.c,v retrieving revision 1.39 diff -u -r1.39 service.c --- dlls/advapi32/service.c 10 Oct 2003 00:05:49 -0000 1.39 +++ dlls/advapi32/service.c 1 Dec 2003 12:57:30 -0000 @@ -273,7 +273,10 @@ OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName, DWORD dwDesiredAccess ) { - HKEY hKey; + const WCHAR szKey[] = { 'S','y','s','t','e','m','\\', + 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', + 'S','e','r','v','i','c','e','s','\\',0 }; + HKEY hReg, hKey = NULL; LONG r; TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName), @@ -285,11 +288,14 @@ * docs, but what if it isn't? */ - r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey); - if (r!=ERROR_SUCCESS) - return 0; + r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg); + if (r==ERROR_SUCCESS) + { + r = RegOpenKeyExW(hReg, szKey, 0, dwDesiredAccess, &hKey ); + RegCloseKey( hReg ); + } - TRACE("returning %p\n",hKey); + TRACE("returning %p\n", hKey); return hKey; } @@ -387,21 +393,14 @@ OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName, DWORD dwDesiredAccess) { - const char *str = "System\\CurrentControlSet\\Services\\"; - WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */ HKEY hKey; long r; TRACE("(%p,%p,%ld)\n",hSCManager, lpServiceName, dwDesiredAccess); - MultiByteToWideChar( CP_ACP, 0, str, -1, lpServiceKey, sizeof(lpServiceKey)/sizeof(WCHAR) ); - strcatW(lpServiceKey,lpServiceName); - - TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey)); - /* FIXME: dwDesiredAccess may need some processing */ - r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey ); + r = RegOpenKeyExW(hSCManager, lpServiceName, 0, dwDesiredAccess, &hKey ); if (r!=ERROR_SUCCESS) return 0; @@ -422,30 +421,21 @@ LPCWSTR lpDependencies, LPCWSTR lpServiceStartName, LPCWSTR lpPassword ) { - FIXME("(%p,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName)); - return 0; -} - - -/****************************************************************************** - * CreateServiceA [ADVAPI32.@] - */ -SC_HANDLE WINAPI -CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName, - LPCSTR lpDisplayName, DWORD dwDesiredAccess, - DWORD dwServiceType, DWORD dwStartType, - DWORD dwErrorControl, LPCSTR lpBinaryPathName, - LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, - LPCSTR lpDependencies, LPCSTR lpServiceStartName, - LPCSTR lpPassword ) -{ HKEY hKey; LONG r; DWORD dp; + const WCHAR szDisplayName[] = { 'D','i','s','p','l','a','y','N','a','m','e', 0 }; + const WCHAR szType[] = {'T','y','p','e',0}; + const WCHAR szStart[] = {'S','t','a','r','t',0}; + const WCHAR szError[] = {'E','r','r','o','r','C','o','n','t','r','o','l', 0}; + const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0}; + const WCHAR szGroup[] = {'G','r','o','u','p',0}; + const WCHAR szDependencies[] = { 'D','e','p','e','n','d','e','n','c','i','e','s',0}; - TRACE("(%p,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName)); + FIXME("%p %s %s\n", hSCManager, + debugstr_w(lpServiceName), debugstr_w(lpDisplayName)); - r = RegCreateKeyExA(hSCManager, lpServiceName, 0, NULL, + r = RegCreateKeyExW(hSCManager, lpServiceName, 0, NULL, REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp); if (r!=ERROR_SUCCESS) return 0; @@ -454,57 +444,52 @@ if(lpDisplayName) { - r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, strlen(lpDisplayName) ); + r = RegSetValueExW(hKey, szDisplayName, 0, REG_SZ, (LPBYTE)lpDisplayName, + (strlenW(lpDisplayName)+1)*sizeof(WCHAR) ); if (r!=ERROR_SUCCESS) return 0; } - r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) ); + r = RegSetValueExW(hKey, szType, 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) ); if (r!=ERROR_SUCCESS) return 0; - r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) ); + r = RegSetValueExW(hKey, szStart, 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) ); if (r!=ERROR_SUCCESS) return 0; - r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD, + r = RegSetValueExW(hKey, szError, 0, REG_DWORD, (LPVOID)&dwErrorControl, sizeof (DWORD) ); if (r!=ERROR_SUCCESS) return 0; if(lpBinaryPathName) { - r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ, - lpBinaryPathName,strlen(lpBinaryPathName)+1 ); + r = RegSetValueExW(hKey, szImagePath, 0, REG_SZ, (LPBYTE)lpBinaryPathName, + (strlenW(lpBinaryPathName)+1)*sizeof(WCHAR) ); if (r!=ERROR_SUCCESS) return 0; } if(lpLoadOrderGroup) { - r = RegSetValueExA(hKey, "Group", 0, REG_SZ, - lpLoadOrderGroup, strlen(lpLoadOrderGroup)+1 ); + r = RegSetValueExW(hKey, szGroup, 0, REG_SZ, (LPBYTE)lpLoadOrderGroup, + (strlenW(lpLoadOrderGroup)+1)*sizeof(WCHAR) ); if (r!=ERROR_SUCCESS) return 0; } - r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD, - (LPVOID)&dwErrorControl, sizeof (DWORD) ); - if (r!=ERROR_SUCCESS) - return 0; - if(lpDependencies) { DWORD len = 0; /* determine the length of a double null terminated multi string */ do { - len += (strlen(&lpDependencies[len])+1); + len += (strlenW(&lpDependencies[len])+1); } while (lpDependencies[len++]); - /* FIXME: this should be unicode */ - r = RegSetValueExA(hKey, "Dependencies", 0, REG_MULTI_SZ, - lpDependencies, len ); + r = RegSetValueExW(hKey, szDependencies, 0, REG_MULTI_SZ, + (LPBYTE)lpDependencies, len ); if (r!=ERROR_SUCCESS) return 0; } @@ -523,6 +508,85 @@ } +static inline LPWSTR SERV_dup( LPCSTR str ) +{ + UINT len; + LPWSTR wstr; + + if( !str ) + return NULL; + len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); + wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len ); + return wstr; +} + +static inline LPWSTR SERV_dupmulti( LPCSTR str ) +{ + UINT len = 0, n = 0; + LPWSTR wstr; + + do { + len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 ); + n += (strlen( &str[n] ) + 1); + } while (str[n]); + len++; + n++; + + wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len ); + return wstr; +} + +static inline VOID SERV_free( LPWSTR wstr ) +{ + HeapFree( GetProcessHeap(), 0, wstr ); +} + +/****************************************************************************** + * CreateServiceA [ADVAPI32.@] + */ +SC_HANDLE WINAPI +CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName, + LPCSTR lpDisplayName, DWORD dwDesiredAccess, + DWORD dwServiceType, DWORD dwStartType, + DWORD dwErrorControl, LPCSTR lpBinaryPathName, + LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, + LPCSTR lpDependencies, LPCSTR lpServiceStartName, + LPCSTR lpPassword ) +{ + LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW, + lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW; + SC_HANDLE r; + + TRACE("%p %s %s\n", hSCManager, + debugstr_a(lpServiceName), debugstr_a(lpDisplayName)); + + lpServiceNameW = SERV_dup( lpServiceName ); + lpDisplayNameW = SERV_dup( lpDisplayName ); + lpBinaryPathNameW = SERV_dup( lpBinaryPathName ); + lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup ); + lpDependenciesW = SERV_dupmulti( lpDependencies ); + lpServiceStartNameW = SERV_dup( lpServiceStartName ); + lpPasswordW = SERV_dup( lpPassword ); + + r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW, + dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, + lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId, + lpDependenciesW, lpServiceStartNameW, lpPasswordW ); + + SERV_free( lpServiceNameW ); + SERV_free( lpDisplayNameW ); + SERV_free( lpBinaryPathNameW ); + SERV_free( lpLoadOrderGroupW ); + SERV_free( lpDependenciesW ); + SERV_free( lpServiceStartNameW ); + SERV_free( lpPasswordW ); + + return r; +} + + /****************************************************************************** * DeleteService [ADVAPI32.@] * @@ -748,3 +812,168 @@ SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } + +/****************************************************************************** + * QueryServiceConfigA [ADVAPI32.@] + */ +BOOL WINAPI +QueryServiceConfigA( SC_HANDLE hService, + LPQUERY_SERVICE_CONFIGA lpServiceConfig, + DWORD cbBufSize, LPDWORD pcbBytesNeeded) +{ + FIXME("%p %p %ld %p\n", hService, lpServiceConfig, + cbBufSize, pcbBytesNeeded); + return FALSE; +} + +/****************************************************************************** + * QueryServiceConfigW [ADVAPI32.@] + */ +BOOL WINAPI +QueryServiceConfigW( SC_HANDLE hService, + LPQUERY_SERVICE_CONFIGW lpServiceConfig, + DWORD cbBufSize, LPDWORD pcbBytesNeeded) +{ + const WCHAR szDisplayName[] = { + 'D','i','s','p','l','a','y','N','a','m','e', 0 }; + const WCHAR szType[] = {'T','y','p','e',0}; + const WCHAR szStart[] = {'S','t','a','r','t',0}; + const WCHAR szError[] = { + 'E','r','r','o','r','C','o','n','t','r','o','l', 0}; + const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0}; + const WCHAR szGroup[] = {'G','r','o','u','p',0}; + const WCHAR szDependencies[] = { + 'D','e','p','e','n','d','e','n','c','i','e','s',0}; + LONG r; + DWORD type, val, sz, total, n; + LPBYTE p; + + TRACE("%p %p %ld %p\n", hService, lpServiceConfig, + cbBufSize, pcbBytesNeeded); + + /* calculate the size required first */ + total = sizeof (QUERY_SERVICE_CONFIGW); + + sz = 0; + r = RegQueryValueExW( hService, szImagePath, 0, &type, NULL, &sz ); + if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) ) + total += sz; + + sz = 0; + r = RegQueryValueExW( hService, szGroup, 0, &type, NULL, &sz ); + if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) ) + total += sz; + + sz = 0; + r = RegQueryValueExW( hService, szDependencies, 0, &type, NULL, &sz ); + if( ( r == ERROR_SUCCESS ) && ( type == REG_MULTI_SZ ) ) + total += sz; + + sz = 0; + r = RegQueryValueExW( hService, szStart, 0, &type, NULL, &sz ); + if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) ) + total += sz; + + sz = 0; + r = RegQueryValueExW( hService, szDisplayName, 0, &type, NULL, &sz ); + if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) ) + total += sz; + + /* if there's not enough memory, return an error */ + if( total > *pcbBytesNeeded ) + { + *pcbBytesNeeded = total; + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + + *pcbBytesNeeded = total; + ZeroMemory( lpServiceConfig, total ); + + sz = sizeof val; + r = RegQueryValueExW( hService, szType, 0, &type, (LPBYTE)&val, &sz ); + if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) ) + lpServiceConfig->dwServiceType = val; + + sz = sizeof val; + r = RegQueryValueExW( hService, szStart, 0, &type, (LPBYTE)&val, &sz ); + if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) ) + lpServiceConfig->dwStartType = val; + + sz = sizeof val; + r = RegQueryValueExW( hService, szError, 0, &type, (LPBYTE)&val, &sz ); + if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) ) + lpServiceConfig->dwErrorControl = val; + + /* now do the strings */ + p = (LPBYTE) &lpServiceConfig[1]; + n = total - sizeof (QUERY_SERVICE_CONFIGW); + + sz = n; + r = RegQueryValueExW( hService, szImagePath, 0, &type, p, &sz ); + if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) ) + { + lpServiceConfig->lpBinaryPathName = (LPWSTR) p; + p += sz; + n -= sz; + } + + sz = n; + r = RegQueryValueExW( hService, szGroup, 0, &type, p, &sz ); + if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) ) + { + lpServiceConfig->lpLoadOrderGroup = (LPWSTR) p; + p += sz; + n -= sz; + } + + sz = n; + r = RegQueryValueExW( hService, szDependencies, 0, &type, p, &sz ); + if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) ) + { + lpServiceConfig->lpDependencies = (LPWSTR) p; + p += sz; + n -= sz; + } + + if( n < 0 ) + ERR("Buffer overflow!\n"); + + TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) ); + TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) ); + + return TRUE; +} + +/****************************************************************************** + * ChangeServiceConfigW [ADVAPI32.@] + */ +BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType, + DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName, + LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies, + LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName) +{ + FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n", + hService, dwServiceType, dwStartType, dwErrorControl, + debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup), + lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName), + debugstr_w(lpPassword), debugstr_w(lpDisplayName) ); + return TRUE; +} + +/****************************************************************************** + * ChangeServiceConfigA [ADVAPI32.@] + */ +BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType, + DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName, + LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies, + LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName) +{ + FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n", + hService, dwServiceType, dwStartType, dwErrorControl, + debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup), + lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName), + debugstr_a(lpPassword), debugstr_a(lpDisplayName) ); + return TRUE; +} +