Better handling of some service functions resulting from exploration of InstMsiW.exe under win2k version.
-aric
Index: include/winsvc.h =================================================================== RCS file: /home/wine/wine/include/winsvc.h,v retrieving revision 1.13 diff -u -w -r1.13 winsvc.h --- include/winsvc.h 2 Dec 2003 03:48:53 -0000 1.13 +++ include/winsvc.h 12 Dec 2003 19:35:18 -0000 @@ -178,6 +178,46 @@ LPWSTR lpDisplayName; } QUERY_SERVICE_CONFIGW, *LPQUERY_SERVICE_CONFIGW; +/* defines and structures for ChangeServiceConfig2 */ +#define SERVICE_CONFIG_DESCRIPTION 1 +#define SERVICE_CONFIG_FAILURE_ACTIONS 2 + +typedef struct _SERVICE_DESCRIPTIONA { + LPSTR lpDescription; +} SERVICE_DESCRIPTIONA,*LPSERVICE_DESCRIPTIONA; + +typedef struct _SERVICE_DESCRIPTIONW { + LPWSTR lpDescription; +} SERVICE_DESCRIPTIONW,*LPSERVICE_DESCRIPTIONW; + +typedef enum _SC_ACTION_TYPE { + SC_ACTION_NONE = 0, + SC_ACTION_RESTART = 1, + SC_ACTION_REBOOT = 2, + SC_ACTION_RUN_COMMAND = 3 +} SC_ACTION_TYPE; + +typedef struct _SC_ACTION { + SC_ACTION_TYPE Type; + DWORD Delay; +} SC_ACTION,*LPSC_ACTION; + +typedef struct _SERVICE_FAILURE_ACTIONSA { + DWORD dwResetPeriod; + LPSTR lpRebootMsg; + LPSTR lpCommand; + DWORD cActions; + SC_ACTION * lpsaActions; +} SERVICE_FAILURE_ACTIONSA,*LPSERVICE_FAILURE_ACTIONSA; + +typedef struct _SERVICE_FAILURE_ACTIONSW { + DWORD dwResetPeriod; + LPWSTR lpRebootMsg; + LPWSTR lpCommand; + DWORD cActions; + SC_ACTION * lpsaActions; +} SERVICE_FAILURE_ACTIONSW,*LPSERVICE_FAILURE_ACTIONSW; + /* Service control handler function prototype */ typedef VOID (WINAPI *LPHANDLER_FUNCTION)(DWORD); Index: dlls/advapi32/service.c =================================================================== RCS file: /home/wine/wine/dlls/advapi32/service.c,v retrieving revision 1.41 diff -u -w -r1.41 service.c --- dlls/advapi32/service.c 11 Dec 2003 04:26:20 -0000 1.41 +++ dlls/advapi32/service.c 12 Dec 2003 19:35:19 -0000 @@ -40,6 +40,10 @@ static const WCHAR _ServiceStartDataW[] = {'A','D','V','A','P','I','_','S', 'e','r','v','i','c','e','S','t', 'a','r','t','D','a','t','a',0}; +const WCHAR szServiceManagerKey[] = { '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 }; + /****************************************************************************** * EnumServicesStatusA [ADVAPI32.@] @@ -273,9 +277,6 @@ OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName, DWORD dwDesiredAccess ) { - 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; @@ -291,7 +292,7 @@ r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg); if (r==ERROR_SUCCESS) { - r = RegOpenKeyExW(hReg, szKey, 0, dwDesiredAccess, &hKey ); + r = RegOpenKeyExW(hReg, szServiceManagerKey,0, dwDesiredAccess, &hKey ); RegCloseKey( hReg ); } @@ -435,10 +436,15 @@ FIXME("%p %s %s\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName)); + /* + * We cannot use dwDesiredAccess because it is not the same as the reg + * access + */ r = RegCreateKeyExW(hSCManager, lpServiceName, 0, NULL, - REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp); + REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dp); if (r!=ERROR_SUCCESS) return 0; + if (dp != REG_CREATED_NEW_KEY) return 0; @@ -601,7 +607,64 @@ BOOL WINAPI DeleteService( SC_HANDLE hService ) { + WCHAR valname[MAX_PATH+1]; + INT index = 0; + LONG rc; + DWORD value = 0x1; + DWORD size; + HKEY hKey; + + const WCHAR szDeleted[] = {'D','e','l','e','t','e','d',0}; + FIXME("(%p): stub\n",hService); + + size = MAX_PATH+1; + /* Clean out the values */ + rc = RegEnumValueW(hService, index, valname,&size,0,0,0,0); + while (rc == ERROR_SUCCESS) + { + RegDeleteValueW(hService,valname); + index++; + size = MAX_PATH+1; + rc = RegEnumValueW(hService, index, valname, &size,0,0,0,0); + } + + /* tag for deletion */ + RegSetValueExW(hService, szDeleted, 0, REG_DWORD, (LPVOID)&value, + sizeof (DWORD) ); + + RegCloseKey(hService); + + /* find and delete the key */ + rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szServiceManagerKey,0, + KEY_ALL_ACCESS, &hKey ); + index = 0; + size = MAX_PATH+1; + rc = RegEnumKeyExW(hKey,0, valname, &size, 0, 0, 0, 0); + while (rc == ERROR_SUCCESS) + { + HKEY checking; + rc = RegOpenKeyExW(hKey,valname,0,KEY_ALL_ACCESS,&checking); + if (rc == ERROR_SUCCESS) + { + DWORD deleted = 0; + DWORD size = sizeof(DWORD); + rc = RegQueryValueExW(checking, szDeleted , NULL, NULL, + (LPVOID)&deleted, &size); + if (deleted) + { + RegDeleteValueW(checking,szDeleted); + RegDeleteKeyW(hKey,valname); + } + else + index ++; + RegCloseKey(checking); + } + size = MAX_PATH+1; + rc = RegEnumKeyExW(hKey, index, valname, &size, 0, 0, 0, 0); + } + RegCloseKey(hKey); + return TRUE; } @@ -978,3 +1041,41 @@ debugstr_a(lpPassword), debugstr_a(lpDisplayName) ); return TRUE; } + +/****************************************************************************** + * ChangeServiceConfig2A [ADVAPI32.@] + */ +BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel, + LPVOID lpInfo) +{ + FIXME("STUB: %p %ld %p\n",hService, dwInfoLevel, lpInfo); + return TRUE; +} + +/****************************************************************************** + * ChangeServiceConfig2W [ADVAPI32.@] + */ +BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel, + LPVOID lpInfo) +{ + if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) + { + const WCHAR szDescription[] = { + 'D','e','s','c','r','i','p','t','i','o','n',0}; + LPSERVICE_DESCRIPTIONW sd = (LPSERVICE_DESCRIPTIONW)lpInfo; + if (sd->lpDescription) + { + TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription)); + if (sd->lpDescription[0] == 0) + RegDeleteValueW(hService,szDescription); + else + RegSetValueExW(hService, szDescription, 0, REG_SZ, + (LPVOID)sd->lpDescription, + sizeof(WCHAR)*(strlenW(sd->lpDescription)+1)); + } + } + else + FIXME("STUB: %p %ld %p\n",hService, dwInfoLevel, lpInfo); + return TRUE; +} +