SERVICE_EXECUTE,
SERVICE_ALL_ACCESS};
+DWORD g_dwServiceBits = 0;
/* FUNCTIONS ***************************************************************/
/* Get buffer size needed for expanding env strings */
BufferSize = ExpandEnvironmentStringsW(L"%SystemRoot%\\", &Dest, 1);
-
if (BufferSize <= 1)
{
DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
&pcbBytesNeeded,
&dwServicesReturned);
- /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service */
+ /* If pcbBytesNeeded returned a value then there are services running that are dependent on this service */
if (pcbBytesNeeded)
{
DPRINT("Deletion failed due to running dependencies.\n");
if (dwSecurityInformation == 0 ||
dwSecurityInformation & ~(OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION))
+ {
return ERROR_INVALID_PARAMETER;
+ }
if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR)lpSecurityDescriptor))
return ERROR_INVALID_PARAMETER;
if ((dwSecurityInformation & OWNER_SECURITY_INFORMATION) &&
(((PISECURITY_DESCRIPTOR)lpSecurityDescriptor)->Owner == NULL))
+ {
return ERROR_INVALID_PARAMETER;
+ }
if ((dwSecurityInformation & GROUP_SECURITY_INFORMATION) &&
(((PISECURITY_DESCRIPTOR)lpSecurityDescriptor)->Group == NULL))
+ {
return ERROR_INVALID_PARAMETER;
+ }
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
DesiredAccess))
int bUpdateImmediately,
wchar_t *lpString)
{
- UNIMPLEMENTED;
- return ERROR_CALL_NOT_IMPLEMENTED;
+ PSERVICE pService;
+
+ DPRINT("RI_ScSetServiceBitsW(%p %lx %d %d %S)\n",
+ hServiceStatus, dwServiceBits, bSetBitsOn,
+ bUpdateImmediately, lpString);
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ if (lpString != NULL)
+ return ERROR_INVALID_PARAMETER;
+
+ if (hServiceStatus == 0)
+ {
+ DPRINT("hServiceStatus == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ // FIXME: Validate the status handle
+ pService = (PSERVICE)hServiceStatus;
+
+ if (bSetBitsOn)
+ {
+ DPRINT("Old service bits: %08lx\n", pService->dwServiceBits);
+ DPRINT("Old global service bits: %08lx\n", g_dwServiceBits);
+ pService->dwServiceBits |= dwServiceBits;
+ g_dwServiceBits |= dwServiceBits;
+ DPRINT("New service bits: %08lx\n", pService->dwServiceBits);
+ DPRINT("New global service bits: %08lx\n", g_dwServiceBits);
+ }
+ else
+ {
+ DPRINT("Old service bits: %08lx\n", pService->dwServiceBits);
+ DPRINT("Old global service bits: %08lx\n", g_dwServiceBits);
+ pService->dwServiceBits &= ~dwServiceBits;
+ g_dwServiceBits &= ~dwServiceBits;
+ DPRINT("New service bits: %08lx\n", pService->dwServiceBits);
+ DPRINT("New global service bits: %08lx\n", g_dwServiceBits);
+ }
+
+ return ERROR_SUCCESS;
}
HKEY hServiceKey = NULL;
LPWSTR lpDisplayNameW = NULL;
LPWSTR lpImagePathW = NULL;
+ LPWSTR lpClearTextPassword = NULL;
DPRINT("RChangeServiceConfigW() called\n");
DPRINT("dwServiceType = 0x%lx\n", dwServiceType);
DPRINT("dwErrorControl = %lu\n", dwErrorControl);
DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
+ DPRINT("lpServiceStartName = %S\n", lpServiceStartName);
+ DPRINT("lpPassword = %p\n", lpPassword);
+ DPRINT("dwPwSite = %lu\n", dwPwSize);
DPRINT("lpDisplayName = %S\n", lpDisplayName);
if (ScmShutdown)
(dwServiceType != SERVICE_FILE_SYSTEM_DRIVER) &&
((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_OWN_PROCESS) &&
((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_SHARE_PROCESS))
- return ERROR_INVALID_PARAMETER;
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
/* Check for invalid start type value */
if ((dwStartType != SERVICE_NO_CHANGE) &&
(dwStartType != SERVICE_AUTO_START) &&
(dwStartType != SERVICE_DEMAND_START) &&
(dwStartType != SERVICE_DISABLED))
+ {
return ERROR_INVALID_PARAMETER;
+ }
/* Only drivers can be boot start or system start services */
if ((dwStartType == SERVICE_BOOT_START) ||
(dwErrorControl != SERVICE_ERROR_NORMAL) &&
(dwErrorControl != SERVICE_ERROR_SEVERE) &&
(dwErrorControl != SERVICE_ERROR_CRITICAL))
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if (lpdwTagId && (!lpLoadOrderGroup || !*lpLoadOrderGroup))
+ {
return ERROR_INVALID_PARAMETER;
+ }
lpService = hSvc->ServiceEntry;
if (lpService == NULL)
goto done;
/* Write service data to the registry */
+
/* Set the display name */
if (lpDisplayName != NULL && *lpDisplayName != 0)
{
goto done;
}
- if (lpPassword != NULL)
+ /* Start name and password are only used by Win32 services */
+ if (lpService->Status.dwServiceType & SERVICE_WIN32)
{
- if (wcslen((LPWSTR)lpPassword) != 0)
+ /* Write service start name */
+ if (lpServiceStartName != NULL && *lpServiceStartName != 0)
{
- /* FIXME: Decrypt the password */
-
- /* Write the password */
- dwError = ScmSetServicePassword(lpService->szServiceName,
- (LPCWSTR)lpPassword);
+ dwError = RegSetValueExW(hServiceKey,
+ L"ObjectName",
+ 0,
+ REG_SZ,
+ (LPBYTE)lpServiceStartName,
+ (DWORD)((wcslen(lpServiceStartName) + 1) * sizeof(WCHAR)));
if (dwError != ERROR_SUCCESS)
goto done;
}
- else
+
+ if (lpPassword != NULL)
{
- /* Delete the password */
- dwError = ScmSetServicePassword(lpService->szServiceName,
- NULL);
- if (dwError == ERROR_FILE_NOT_FOUND)
- dwError = ERROR_SUCCESS;
+ if (*(LPWSTR)lpPassword != 0)
+ {
+ /* Decrypt the password */
+ dwError = ScmDecryptPassword(lpPassword,
+ dwPwSize,
+ &lpClearTextPassword);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmDecryptPassword failed (Error %lu)\n", dwError);
+ goto done;
+ }
+ DPRINT1("Clear text password: %S\n", lpClearTextPassword);
- if (dwError != ERROR_SUCCESS)
- goto done;
+ /* Write the password */
+ dwError = ScmSetServicePassword(lpService->szServiceName,
+ lpClearTextPassword);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmSetServicePassword failed (Error %lu)\n", dwError);
+ goto done;
+ }
+ }
+ else
+ {
+ /* Delete the password */
+ dwError = ScmSetServicePassword(lpService->szServiceName,
+ NULL);
+ if (dwError == ERROR_FILE_NOT_FOUND)
+ dwError = ERROR_SUCCESS;
+
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmSetServicePassword failed (Error %lu)\n", dwError);
+ goto done;
+ }
+ }
}
}
done:
+ if (lpClearTextPassword != NULL)
+ {
+ /* Wipe and release the password buffer */
+ SecureZeroMemory(lpClearTextPassword,
+ (wcslen(lpClearTextPassword) + 1) * sizeof(WCHAR));
+ HeapFree(GetProcessHeap(), 0, lpClearTextPassword);
+ }
+
if (hServiceKey != NULL)
RegCloseKey(hServiceKey);
PSERVICE lpService = NULL;
SC_HANDLE hServiceHandle = NULL;
LPWSTR lpImagePath = NULL;
+ LPWSTR lpClearTextPassword = NULL;
HKEY hServiceKey = NULL;
LPWSTR lpObjectName;
return ERROR_ACCESS_DENIED;
}
- if (wcslen(lpServiceName) == 0)
- {
+ if (*lpServiceName == 0)
return ERROR_INVALID_NAME;
- }
- if (wcslen(lpBinaryPathName) == 0)
- {
+ if (*lpBinaryPathName == 0)
return ERROR_INVALID_PARAMETER;
- }
/* Check for invalid service type value */
if ((dwServiceType != SERVICE_KERNEL_DRIVER) &&
(dwServiceType != SERVICE_FILE_SYSTEM_DRIVER) &&
((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_OWN_PROCESS) &&
((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_SHARE_PROCESS))
- return ERROR_INVALID_PARAMETER;
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
/* Check for invalid start type value */
if ((dwStartType != SERVICE_BOOT_START) &&
(dwStartType != SERVICE_AUTO_START) &&
(dwStartType != SERVICE_DEMAND_START) &&
(dwStartType != SERVICE_DISABLED))
+ {
return ERROR_INVALID_PARAMETER;
+ }
/* Only drivers can be boot start or system start services */
if ((dwStartType == SERVICE_BOOT_START) ||
{
if ((dwServiceType != SERVICE_KERNEL_DRIVER) &&
(dwServiceType != SERVICE_FILE_SYSTEM_DRIVER))
+ {
return ERROR_INVALID_PARAMETER;
+ }
}
/* Check for invalid error control value */
(dwErrorControl != SERVICE_ERROR_NORMAL) &&
(dwErrorControl != SERVICE_ERROR_SEVERE) &&
(dwErrorControl != SERVICE_ERROR_CRITICAL))
+ {
return ERROR_INVALID_PARAMETER;
+ }
if ((dwServiceType == (SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS)) &&
(lpServiceStartName))
if (lpService->bDeleted)
return ERROR_SERVICE_MARKED_FOR_DELETE;
- /* Return Error exist */
+ /* Return service-exists error */
return ERROR_SERVICE_EXISTS;
}
if (dwError != ERROR_SUCCESS)
goto done;
- if (lpPassword != NULL && wcslen((LPWSTR)lpPassword) != 0)
+ if (lpPassword != NULL && *(LPWSTR)lpPassword != 0)
{
- /* FIXME: Decrypt the password */
+ /* Decrypt the password */
+ dwError = ScmDecryptPassword(lpPassword,
+ dwPwSize,
+ &lpClearTextPassword);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
/* Write the password */
dwError = ScmSetServicePassword(lpServiceName,
- (LPCWSTR)lpPassword);
+ lpClearTextPassword);
if (dwError != ERROR_SUCCESS)
goto done;
}
-DPRINT1("\n");
/* Write the security descriptor */
dwError = ScmWriteSecurityDescriptor(hServiceKey,
lpService->pSecurityDescriptor);
if (hServiceKey != NULL)
RegCloseKey(hServiceKey);
+ if (lpClearTextPassword != NULL)
+ {
+ /* Wipe and release the password buffer */
+ SecureZeroMemory(lpClearTextPassword,
+ (wcslen(lpClearTextPassword) + 1) * sizeof(WCHAR));
+ HeapFree(GetProcessHeap(), 0, lpClearTextPassword);
+ }
+
if (dwError == ERROR_SUCCESS)
{
DPRINT("hService %p\n", hServiceHandle);
lpService = ScmGetServiceEntryByName(lpServiceName);
if (lpService == NULL)
{
- DPRINT("Could not find a service!\n");
+ DPRINT("Could not find the service!\n");
dwError = ERROR_SERVICE_DOES_NOT_EXIST;
goto Done;
}
LPWSTR lpDependencies = NULL;
DWORD dwDependenciesLength = 0;
DWORD dwRequiredSize;
- WCHAR lpEmptyString[] = {0,0};
LPWSTR lpStr;
DPRINT("RQueryServiceConfigW() called\n");
}
else
{
- wcscpy(lpStr, lpEmptyString);
+ *lpStr = 0;
}
lpServiceConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
}
else
{
- wcscpy(lpStr, lpEmptyString);
+ *lpStr = 0;
}
lpServiceConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
}
else
{
- wcscpy(lpStr, lpEmptyString);
+ *lpStr = 0;
}
lpServiceConfig->lpDependencies = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
}
else
{
- wcscpy(lpStr, lpEmptyString);
+ *lpStr = 0;
}
lpServiceConfig->lpServiceStartName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
}
else
{
- wcscpy(lpStr, lpEmptyString);
+ *lpStr = 0;
}
lpServiceConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
LPWSTR lpDisplayName,
DWORD *lpcchBuffer)
{
-// PMANAGER_HANDLE hManager;
+ // PMANAGER_HANDLE hManager;
PSERVICE lpService;
+ LPCWSTR lpSvcDisplayName;
DWORD dwLength;
DWORD dwError;
DPRINT("lpDisplayName: %p\n", lpDisplayName);
DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
-// hManager = (PMANAGER_HANDLE)hSCManager;
-// if (hManager->Handle.Tag != MANAGER_TAG)
-// {
-// DPRINT("Invalid manager handle!\n");
-// return ERROR_INVALID_HANDLE;
-// }
+#if 0
+ hManager = (PMANAGER_HANDLE)hSCManager;
+ if (hManager->Handle.Tag != MANAGER_TAG)
+ {
+ DPRINT("Invalid manager handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+#endif
/* Get service database entry */
lpService = ScmGetServiceEntryByName(lpServiceName);
if (lpService == NULL)
{
- DPRINT("Could not find a service!\n");
-
- /* If the service could not be found and lpcchBuffer is less than 2, windows
- puts null in lpDisplayName and puts 2 in lpcchBuffer */
- if (*lpcchBuffer < 2)
- {
- *lpcchBuffer = 2;
- if (lpDisplayName != NULL)
- {
- *lpDisplayName = 0;
- }
- }
-
+ DPRINT("Could not find the service!\n");
return ERROR_SERVICE_DOES_NOT_EXIST;
}
- if (!lpService->lpDisplayName)
+ if (lpService->lpDisplayName)
+ lpSvcDisplayName = lpService->lpDisplayName;
+ else
+ lpSvcDisplayName = lpService->lpServiceName;
+
+ dwLength = (DWORD)wcslen(lpSvcDisplayName);
+
+ if (*lpcchBuffer > dwLength)
{
- dwLength = (DWORD)wcslen(lpService->lpServiceName);
+ if (lpDisplayName != NULL)
+ wcscpy(lpDisplayName, lpSvcDisplayName);
- if (lpDisplayName != NULL &&
- *lpcchBuffer > dwLength)
- {
- wcscpy(lpDisplayName, lpService->lpServiceName);
- }
+ dwError = ERROR_SUCCESS;
}
else
{
- dwLength = (DWORD)wcslen(lpService->lpDisplayName);
-
- if (lpDisplayName != NULL &&
- *lpcchBuffer > dwLength)
- {
- wcscpy(lpDisplayName, lpService->lpDisplayName);
- }
+ dwError = ERROR_INSUFFICIENT_BUFFER;
}
- dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
-
*lpcchBuffer = dwLength;
return dwError;
LPWSTR lpServiceName,
DWORD *lpcchBuffer)
{
-// PMANAGER_HANDLE hManager;
+ // PMANAGER_HANDLE hManager;
PSERVICE lpService;
DWORD dwLength;
DWORD dwError;
DPRINT("lpServiceName: %p\n", lpServiceName);
DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
-// hManager = (PMANAGER_HANDLE)hSCManager;
-// if (hManager->Handle.Tag != MANAGER_TAG)
-// {
-// DPRINT("Invalid manager handle!\n");
-// return ERROR_INVALID_HANDLE;
-// }
+#if 0
+ hManager = (PMANAGER_HANDLE)hSCManager;
+ if (hManager->Handle.Tag != MANAGER_TAG)
+ {
+ DPRINT("Invalid manager handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+#endif
/* Get service database entry */
lpService = ScmGetServiceEntryByDisplayName(lpDisplayName);
if (lpService == NULL)
{
- DPRINT("Could not find a service!\n");
-
- /* If the service could not be found and lpcchBuffer is less than 2, windows
- puts null in lpDisplayName and puts 2 in lpcchBuffer */
- if (*lpcchBuffer < 2)
- {
- *lpcchBuffer = 2;
- if (lpServiceName != NULL)
- {
- *lpServiceName = 0;
- }
- }
-
+ DPRINT("Could not find the service!\n");
return ERROR_SERVICE_DOES_NOT_EXIST;
}
dwLength = (DWORD)wcslen(lpService->lpServiceName);
- if (lpServiceName != NULL &&
- *lpcchBuffer > dwLength)
+ if (*lpcchBuffer > dwLength)
{
- wcscpy(lpServiceName, lpService->lpServiceName);
- *lpcchBuffer = dwLength;
- return ERROR_SUCCESS;
- }
+ if (lpServiceName != NULL)
+ wcscpy(lpServiceName, lpService->lpServiceName);
- dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
+ dwError = ERROR_SUCCESS;
+ }
+ else
+ {
+ dwError = ERROR_INSUFFICIENT_BUFFER;
+ }
*lpcchBuffer = dwLength;
int bUpdateImmediately,
char *lpString)
{
- UNIMPLEMENTED;
- return ERROR_CALL_NOT_IMPLEMENTED;
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ if (lpString != NULL)
+ return ERROR_INVALID_PARAMETER;
+
+ return RI_ScSetServiceBitsW(hServiceStatus,
+ dwServiceBits,
+ bSetBitsOn,
+ bUpdateImmediately,
+ NULL);
}
LPSTR lpDisplayName)
{
DWORD dwError = ERROR_SUCCESS;
- PSERVICE_HANDLE hSvc;
- PSERVICE lpService = NULL;
- HKEY hServiceKey = NULL;
- LPWSTR lpDisplayNameW = NULL;
LPWSTR lpBinaryPathNameW = NULL;
- LPWSTR lpCanonicalImagePathW = NULL;
LPWSTR lpLoadOrderGroupW = NULL;
LPWSTR lpDependenciesW = NULL;
+ LPWSTR lpServiceStartNameW = NULL;
+ LPWSTR lpDisplayNameW = NULL;
+ DWORD dwDependenciesLength = 0;
+ SIZE_T cchLength;
+ int len;
+ LPCSTR lpStr;
- DPRINT("RChangeServiceConfigA() called\n");
- DPRINT("dwServiceType = %lu\n", dwServiceType);
- DPRINT("dwStartType = %lu\n", dwStartType);
- DPRINT("dwErrorControl = %lu\n", dwErrorControl);
- DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName);
- DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup);
- DPRINT("lpDisplayName = %s\n", lpDisplayName);
-
- if (ScmShutdown)
- return ERROR_SHUTDOWN_IN_PROGRESS;
-
- hSvc = ScmGetServiceFromHandle(hService);
- if (hSvc == NULL)
+ if (lpBinaryPathName)
{
- DPRINT1("Invalid service handle!\n");
- return ERROR_INVALID_HANDLE;
+ len = MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, NULL, 0);
+ lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
+ if (!lpBinaryPathNameW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, len);
}
- if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
- SERVICE_CHANGE_CONFIG))
+ if (lpLoadOrderGroup)
{
- DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
- return ERROR_ACCESS_DENIED;
+ len = MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, NULL, 0);
+ lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
+ if (!lpLoadOrderGroupW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, lpLoadOrderGroupW, len);
}
- lpService = hSvc->ServiceEntry;
- if (lpService == NULL)
+ if (lpDependencies)
{
- DPRINT("lpService == NULL!\n");
- return ERROR_INVALID_HANDLE;
- }
+ lpStr = (LPCSTR)lpDependencies;
+ while (*lpStr)
+ {
+ cchLength = strlen(lpStr) + 1;
+ dwDependenciesLength += (DWORD)cchLength;
+ lpStr = lpStr + cchLength;
+ }
+ dwDependenciesLength++;
- /* Lock the service database exclusively */
- ScmLockDatabaseExclusive();
+ lpDependenciesW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDependenciesLength * sizeof(WCHAR));
+ if (!lpDependenciesW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lpDependencies, dwDependenciesLength, lpDependenciesW, dwDependenciesLength);
+ }
- if (lpService->bDeleted)
+ if (lpServiceStartName)
{
- DPRINT("The service has already been marked for delete!\n");
- dwError = ERROR_SERVICE_MARKED_FOR_DELETE;
- goto done;
+ len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0);
+ lpServiceStartNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
+ if (!lpServiceStartNameW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, lpServiceStartNameW, len);
}
- /* Open the service key */
- dwError = ScmOpenServiceKey(lpService->szServiceName,
- KEY_SET_VALUE,
- &hServiceKey);
- if (dwError != ERROR_SUCCESS)
- goto done;
-
- /* Write service data to the registry */
-
- if (lpDisplayName != NULL && *lpDisplayName != 0)
+ if (lpDisplayName)
{
- /* Set the display name */
- lpDisplayNameW = HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- (strlen(lpDisplayName) + 1) * sizeof(WCHAR));
- if (lpDisplayNameW == NULL)
+ len = MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, NULL, 0);
+ lpDisplayNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
+ if (!lpDisplayNameW)
{
- dwError = ERROR_NOT_ENOUGH_MEMORY;
- goto done;
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
}
+ MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, lpDisplayNameW, len);
+ }
- MultiByteToWideChar(CP_ACP,
- 0,
- lpDisplayName,
- -1,
- lpDisplayNameW,
- (int)(strlen(lpDisplayName) + 1));
-
- RegSetValueExW(hServiceKey,
- L"DisplayName",
- 0,
- REG_SZ,
- (LPBYTE)lpDisplayNameW,
- (DWORD)((wcslen(lpDisplayNameW) + 1) * sizeof(WCHAR)));
-
- /* Update lpService->lpDisplayName */
- if (lpService->lpDisplayName)
- HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
-
- lpService->lpDisplayName = lpDisplayNameW;
- }
-
- if (dwServiceType != SERVICE_NO_CHANGE)
- {
- /* Set the service type */
- dwError = RegSetValueExW(hServiceKey,
- L"Type",
- 0,
- REG_DWORD,
- (LPBYTE)&dwServiceType,
- sizeof(DWORD));
- if (dwError != ERROR_SUCCESS)
- goto done;
-
- lpService->Status.dwServiceType = dwServiceType;
- }
-
- if (dwStartType != SERVICE_NO_CHANGE)
- {
- /* Set the start value */
- dwError = RegSetValueExW(hServiceKey,
- L"Start",
- 0,
- REG_DWORD,
- (LPBYTE)&dwStartType,
- sizeof(DWORD));
- if (dwError != ERROR_SUCCESS)
- goto done;
-
- lpService->dwStartType = dwStartType;
- }
-
- if (dwErrorControl != SERVICE_NO_CHANGE)
- {
- /* Set the error control value */
- dwError = RegSetValueExW(hServiceKey,
- L"ErrorControl",
- 0,
- REG_DWORD,
- (LPBYTE)&dwErrorControl,
- sizeof(DWORD));
- if (dwError != ERROR_SUCCESS)
- goto done;
-
- lpService->dwErrorControl = dwErrorControl;
- }
-
- if (lpBinaryPathName != NULL && *lpBinaryPathName != 0)
- {
- /* Set the image path */
- lpBinaryPathNameW = HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- (strlen(lpBinaryPathName) + 1) * sizeof(WCHAR));
- if (lpBinaryPathNameW == NULL)
- {
- dwError = ERROR_NOT_ENOUGH_MEMORY;
- goto done;
- }
-
- MultiByteToWideChar(CP_ACP,
- 0,
- lpBinaryPathName,
- -1,
- lpBinaryPathNameW,
- (int)(strlen(lpBinaryPathName) + 1));
-
- if (lpService->Status.dwServiceType & SERVICE_DRIVER)
- {
- dwError = ScmCanonDriverImagePath(lpService->dwStartType,
- lpBinaryPathNameW,
- &lpCanonicalImagePathW);
-
- HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW);
-
- if (dwError != ERROR_SUCCESS)
- goto done;
-
- lpBinaryPathNameW = lpCanonicalImagePathW;
- }
-
- dwError = RegSetValueExW(hServiceKey,
- L"ImagePath",
- 0,
- REG_EXPAND_SZ,
- (LPBYTE)lpBinaryPathNameW,
- (DWORD)((wcslen(lpBinaryPathNameW) + 1) * sizeof(WCHAR)));
+ dwError = RChangeServiceConfigW(hService,
+ dwServiceType,
+ dwStartType,
+ dwErrorControl,
+ lpBinaryPathNameW,
+ lpLoadOrderGroupW,
+ lpdwTagId,
+ (LPBYTE)lpDependenciesW,
+ dwDependenciesLength,
+ lpServiceStartNameW,
+ lpPassword,
+ dwPwSize,
+ lpDisplayNameW);
+cleanup:
+ if (lpBinaryPathNameW != NULL)
HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW);
- if (dwError != ERROR_SUCCESS)
- goto done;
- }
-
- /* Set the group name */
- if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
- {
- lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- (strlen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
- if (lpLoadOrderGroupW == NULL)
- {
- dwError = ERROR_NOT_ENOUGH_MEMORY;
- goto done;
- }
-
- MultiByteToWideChar(CP_ACP,
- 0,
- lpLoadOrderGroup,
- -1,
- lpLoadOrderGroupW,
- (int)(strlen(lpLoadOrderGroup) + 1));
-
- dwError = RegSetValueExW(hServiceKey,
- L"Group",
- 0,
- REG_SZ,
- (LPBYTE)lpLoadOrderGroupW,
- (DWORD)((wcslen(lpLoadOrderGroupW) + 1) * sizeof(WCHAR)));
- if (dwError != ERROR_SUCCESS)
- {
- HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
- goto done;
- }
-
- dwError = ScmSetServiceGroup(lpService,
- lpLoadOrderGroupW);
-
+ if (lpLoadOrderGroupW != NULL)
HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
- if (dwError != ERROR_SUCCESS)
- goto done;
- }
-
- if (lpdwTagId != NULL)
- {
- dwError = ScmAssignNewTag(lpService);
- if (dwError != ERROR_SUCCESS)
- goto done;
-
- dwError = RegSetValueExW(hServiceKey,
- L"Tag",
- 0,
- REG_DWORD,
- (LPBYTE)&lpService->dwTag,
- sizeof(DWORD));
- if (dwError != ERROR_SUCCESS)
- goto done;
-
- *lpdwTagId = lpService->dwTag;
- }
-
- /* Write dependencies */
- if (lpDependencies != NULL && *lpDependencies != 0)
- {
- lpDependenciesW = HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- (strlen((LPSTR)lpDependencies) + 1) * sizeof(WCHAR));
- if (lpDependenciesW == NULL)
- {
- dwError = ERROR_NOT_ENOUGH_MEMORY;
- goto done;
- }
-
- MultiByteToWideChar(CP_ACP,
- 0,
- (LPSTR)lpDependencies,
- dwDependSize,
- lpDependenciesW,
- (int)(strlen((LPSTR)lpDependencies) + 1));
-
- dwError = ScmWriteDependencies(hServiceKey,
- (LPWSTR)lpDependenciesW,
- dwDependSize);
-
+ if (lpDependenciesW != NULL)
HeapFree(GetProcessHeap(), 0, lpDependenciesW);
- if (dwError != ERROR_SUCCESS)
- goto done;
- }
-
- if (lpPassword != NULL)
- {
- if (wcslen((LPWSTR)lpPassword) != 0)
- {
- /* FIXME: Decrypt the password */
-
- /* Write the password */
- dwError = ScmSetServicePassword(lpService->szServiceName,
- (LPCWSTR)lpPassword);
- if (dwError != ERROR_SUCCESS)
- goto done;
- }
- else
- {
- /* Delete the password */
- dwError = ScmSetServicePassword(lpService->szServiceName,
- NULL);
- if (dwError == ERROR_FILE_NOT_FOUND)
- dwError = ERROR_SUCCESS;
-
- if (dwError != ERROR_SUCCESS)
- goto done;
- }
- }
-
-done:
- /* Unlock the service database */
- ScmUnlockDatabase();
-
- if (hServiceKey != NULL)
- RegCloseKey(hServiceKey);
+ if (lpServiceStartNameW != NULL)
+ HeapFree(GetProcessHeap(), 0, lpServiceStartNameW);
- DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError);
+ if (lpDisplayNameW != NULL)
+ HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
return dwError;
}
LPWSTR lpDependencies = NULL;
DWORD dwDependenciesLength = 0;
DWORD dwRequiredSize;
- CHAR lpEmptyString[]={0,0};
LPSTR lpStr;
DPRINT("RQueryServiceConfigA() called\n");
if (lpImagePath != NULL)
dwRequiredSize += (DWORD)(wcslen(lpImagePath) + 1);
else
- dwRequiredSize += 2;
+ dwRequiredSize += 2 * sizeof(CHAR);
if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL))
dwRequiredSize += (DWORD)(wcslen(lpService->lpGroup->lpGroupName) + 1);
else
- dwRequiredSize += 2;
+ dwRequiredSize += 2 * sizeof(CHAR);
/* Add Dependencies length */
if (lpDependencies != NULL)
dwRequiredSize += dwDependenciesLength;
else
- dwRequiredSize += 2;
+ dwRequiredSize += 2 * sizeof(CHAR);
if (lpServiceStartName != NULL)
dwRequiredSize += (DWORD)(wcslen(lpServiceStartName) + 1);
else
- dwRequiredSize += 2;
+ dwRequiredSize += 2 * sizeof(CHAR);
if (lpService->lpDisplayName != NULL)
dwRequiredSize += (DWORD)(wcslen(lpService->lpDisplayName) + 1);
else
- dwRequiredSize += 2;
+ dwRequiredSize += 2 * sizeof(CHAR);
if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize)
{
}
else
{
- strcpy(lpStr, lpEmptyString);
+ *lpStr = 0;
}
lpServiceConfig->lpBinaryPathName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
}
else
{
- strcpy(lpStr, lpEmptyString);
+ *lpStr = 0;
}
lpServiceConfig->lpLoadOrderGroup = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
}
else
{
- strcpy(lpStr, lpEmptyString);
+ *lpStr = 0;
}
lpServiceConfig->lpDependencies = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
}
else
{
- strcpy(lpStr, lpEmptyString);
+ *lpStr = 0;
}
lpServiceConfig->lpServiceStartName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
}
else
{
- strcpy(lpStr, lpEmptyString);
+ *lpStr = 0;
}
lpServiceConfig->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig);
LPSTR lpDisplayName,
LPBOUNDED_DWORD_4K lpcchBuffer)
{
-// PMANAGER_HANDLE hManager;
+ // PMANAGER_HANDLE hManager;
PSERVICE lpService = NULL;
- DWORD dwLength;
- DWORD dwError;
+ LPCWSTR lpSvcDisplayName;
LPWSTR lpServiceNameW;
+ DWORD dwLength;
DPRINT("RGetServiceDisplayNameA() called\n");
DPRINT("hSCManager = %p\n", hSCManager);
DPRINT("lpDisplayName: %p\n", lpDisplayName);
DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
-// hManager = (PMANAGER_HANDLE)hSCManager;
-// if (hManager->Handle.Tag != MANAGER_TAG)
-// {
-// DPRINT("Invalid manager handle!\n");
-// return ERROR_INVALID_HANDLE;
-// }
+#if 0
+ hManager = (PMANAGER_HANDLE)hSCManager;
+ if (hManager->Handle.Tag != MANAGER_TAG)
+ {
+ DPRINT("Invalid manager handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+#endif
+ /* Get service database entry */
if (lpServiceName != NULL)
{
dwLength = (DWORD)(strlen(lpServiceName) + 1);
if (lpService == NULL)
{
- DPRINT("Could not find a service!\n");
-
- /* If the service could not be found and lpcchBuffer is 0, windows
- puts null in lpDisplayName and puts 1 in lpcchBuffer */
- if (*lpcchBuffer == 0)
- {
- *lpcchBuffer = 1;
- if (lpDisplayName != NULL)
- {
- *lpDisplayName = 0;
- }
- }
+ DPRINT("Could not find the service!\n");
return ERROR_SERVICE_DOES_NOT_EXIST;
}
- if (!lpService->lpDisplayName)
+ if (lpService->lpDisplayName)
+ lpSvcDisplayName = lpService->lpDisplayName;
+ else
+ lpSvcDisplayName = lpService->lpServiceName;
+
+ /*
+ * NOTE: On Windows the comparison on *lpcchBuffer is made against
+ * the number of (wide) characters of the UNICODE display name, and
+ * not against the number of bytes needed to store the ANSI string.
+ */
+ dwLength = (DWORD)wcslen(lpSvcDisplayName);
+
+ if (*lpcchBuffer > dwLength)
{
- dwLength = (DWORD)wcslen(lpService->lpServiceName);
if (lpDisplayName != NULL &&
- *lpcchBuffer > dwLength)
- {
WideCharToMultiByte(CP_ACP,
0,
- lpService->lpServiceName,
- (int)wcslen(lpService->lpServiceName),
+ lpSvcDisplayName,
+ -1,
lpDisplayName,
- dwLength + 1,
+ (int)*lpcchBuffer,
NULL,
- NULL);
- return ERROR_SUCCESS;
+ NULL) == 0)
+ {
+ /*
+ * But then, if *lpcchBuffer was greater than the number of
+ * (wide) characters of the UNICODE display name, yet smaller
+ * than the number of bytes needed due to the possible presence
+ * of DBCS characters, the *exact* number of bytes is returned
+ * (without the NULL terminator).
+ */
+ dwLength = (DWORD)WideCharToMultiByte(CP_ACP,
+ 0,
+ lpSvcDisplayName,
+ (int)dwLength,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ *lpDisplayName = 0;
+ *lpcchBuffer = dwLength;
+ return ERROR_INSUFFICIENT_BUFFER;
}
+
+ /*
+ * NOTE: On Windows, RGetServiceDisplayNameA() does not update
+ * *lpcchBuffer on success, contrary to RGetServiceDisplayNameW().
+ */
+ return ERROR_SUCCESS;
}
else
{
- dwLength = (DWORD)wcslen(lpService->lpDisplayName);
- if (lpDisplayName != NULL &&
- *lpcchBuffer > dwLength)
- {
- WideCharToMultiByte(CP_ACP,
- 0,
- lpService->lpDisplayName,
- (int)wcslen(lpService->lpDisplayName),
- lpDisplayName,
- dwLength + 1,
- NULL,
- NULL);
- return ERROR_SUCCESS;
- }
+ /*
+ * NOTE: On Windows, if *lpcchBuffer is smaller than the number of
+ * (wide) characters of the UNICODE display name, only an upper
+ * estimation is returned by doubling the string length, to account
+ * for the presence of any possible DBCS characters.
+ */
+ *lpcchBuffer = dwLength * sizeof(WCHAR);
+ return ERROR_INSUFFICIENT_BUFFER;
}
-
- dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
-
- *lpcchBuffer = dwLength * 2;
-
- return dwError;
}
LPSTR lpServiceName,
LPBOUNDED_DWORD_4K lpcchBuffer)
{
+ // PMANAGER_HANDLE hManager;
PSERVICE lpService;
- DWORD dwLength;
- DWORD dwError;
LPWSTR lpDisplayNameW;
+ DWORD dwLength;
DPRINT("RGetServiceKeyNameA() called\n");
DPRINT("hSCManager = %p\n", hSCManager);
DPRINT("lpServiceName: %p\n", lpServiceName);
DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
+#if 0
+ hManager = (PMANAGER_HANDLE)hSCManager;
+ if (hManager->Handle.Tag != MANAGER_TAG)
+ {
+ DPRINT("Invalid manager handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+#endif
+
+ /* Get service database entry */
+
dwLength = (DWORD)(strlen(lpDisplayName) + 1);
lpDisplayNameW = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
if (lpService == NULL)
{
DPRINT("Could not find the service!\n");
-
- /* If the service could not be found and lpcchBuffer is 0,
- put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
- if (*lpcchBuffer == 0)
- {
- *lpcchBuffer = 1;
- if (lpServiceName != NULL)
- {
- *lpServiceName = 0;
- }
- }
-
return ERROR_SERVICE_DOES_NOT_EXIST;
}
+ /*
+ * NOTE: On Windows the comparison on *lpcchBuffer is made against
+ * the number of (wide) characters of the UNICODE service name, and
+ * not against the number of bytes needed to store the ANSI string.
+ */
dwLength = (DWORD)wcslen(lpService->lpServiceName);
- if (lpServiceName != NULL &&
- *lpcchBuffer > dwLength)
+
+ if (*lpcchBuffer > dwLength)
{
- WideCharToMultiByte(CP_ACP,
- 0,
- lpService->lpServiceName,
- (int)wcslen(lpService->lpServiceName),
- lpServiceName,
- dwLength + 1,
- NULL,
- NULL);
+ if (lpServiceName != NULL &&
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpService->lpServiceName,
+ -1,
+ lpServiceName,
+ (int)*lpcchBuffer,
+ NULL,
+ NULL) == 0)
+ {
+ /*
+ * But then, if *lpcchBuffer was greater than the number of
+ * (wide) characters of the UNICODE service name, yet smaller
+ * than the number of bytes needed due to the possible presence
+ * of DBCS characters, the *exact* number of bytes is returned
+ * (without the NULL terminator).
+ */
+ dwLength = (DWORD)WideCharToMultiByte(CP_ACP,
+ 0,
+ lpService->lpServiceName,
+ (int)dwLength,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ *lpServiceName = 0;
+ *lpcchBuffer = dwLength;
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ /*
+ * NOTE: On Windows, RGetServiceKeyNameA() does not update
+ * *lpcchBuffer on success, contrary to RGetServiceKeyNameW().
+ */
return ERROR_SUCCESS;
}
-
- dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
-
- *lpcchBuffer = dwLength * 2;
-
- return dwError;
+ else
+ {
+ /*
+ * NOTE: On Windows, if *lpcchBuffer is smaller than the number of
+ * (wide) characters of the UNICODE service name, only an upper
+ * estimation is returned by doubling the string length, to account
+ * for the presence of any possible DBCS characters.
+ */
+ *lpcchBuffer = dwLength * sizeof(WCHAR);
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
}
SC_RPC_HANDLE hService,
SC_RPC_CONFIG_INFOA Info)
{
- SC_RPC_CONFIG_INFOW InfoW;
+ SC_RPC_CONFIG_INFOW InfoW = { 0 };
DWORD dwRet, dwLength;
PVOID ptr = NULL;
DPRINT("RChangeServiceConfig2A() called\n");
DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
+ if ((Info.dwInfoLevel < SERVICE_CONFIG_DESCRIPTION) ||
+ (Info.dwInfoLevel > SERVICE_CONFIG_FAILURE_ACTIONS))
+ {
+ return ERROR_INVALID_LEVEL;
+ }
+
InfoW.dwInfoLevel = Info.dwInfoLevel;
if (InfoW.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
NULL,
&dwType,
NULL,
- &dwRequiredSize);
+ &dwRequiredSize);
if (dwError != ERROR_SUCCESS &&
dwError != ERROR_MORE_DATA &&
dwError != ERROR_FILE_NOT_FOUND)
+ {
return dwError;
+ }
dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSW), dwRequiredSize)
: sizeof(SERVICE_FAILURE_ACTIONSW);
if (ScmShutdown)
return ERROR_SHUTDOWN_IN_PROGRESS;
+ if ((Info.dwInfoLevel < SERVICE_CONFIG_DESCRIPTION) ||
+ (Info.dwInfoLevel > SERVICE_CONFIG_FAILURE_ACTIONS))
+ {
+ return ERROR_INVALID_LEVEL;
+ }
+
hSvc = ScmGetServiceFromHandle(hService);
if (hSvc == NULL)
{
if (ScmShutdown)
return ERROR_SHUTDOWN_IN_PROGRESS;
+ if ((dwInfoLevel < SERVICE_CONFIG_DESCRIPTION) ||
+ (dwInfoLevel > SERVICE_CONFIG_FAILURE_ACTIONS))
+ {
+ return ERROR_INVALID_LEVEL;
+ }
+
hSvc = ScmGetServiceFromHandle(hService);
if (hSvc == NULL)
{
if (dwError != ERROR_SUCCESS &&
dwError != ERROR_MORE_DATA &&
dwError != ERROR_FILE_NOT_FOUND)
+ {
goto done;
+ }
dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSA), dwRequiredSize)
: sizeof(SERVICE_FAILURE_ACTIONSA);
if (ScmShutdown)
return ERROR_SHUTDOWN_IN_PROGRESS;
+ if ((dwInfoLevel < SERVICE_CONFIG_DESCRIPTION) ||
+ (dwInfoLevel > SERVICE_CONFIG_FAILURE_ACTIONS))
+ {
+ return ERROR_INVALID_LEVEL;
+ }
+
hSvc = ScmGetServiceFromHandle(hService);
if (hSvc == NULL)
{
if (dwError != ERROR_SUCCESS &&
dwError != ERROR_MORE_DATA &&
dwError != ERROR_FILE_NOT_FOUND)
+ {
goto done;
+ }
dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSW), dwRequiredSize)
: sizeof(SERVICE_FAILURE_ACTIONSW);
else
lpStatus->dwProcessId = lpService->lpImage->dwProcessId;
- lpStatus->dwServiceFlags = 0; /* FIXME */
+ lpStatus->dwServiceFlags = 0; /* FIXME */
/* Unlock the service database */
ScmUnlockDatabase();