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)
{
if (*(LPWSTR)lpPassword != 0)
{
- /* FIXME: Decrypt the password */
+ /* 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);
/* Write the password */
dwError = ScmSetServicePassword(lpService->szServiceName,
- (LPCWSTR)lpPassword);
+ lpClearTextPassword);
if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmSetServicePassword failed (Error %lu)\n", dwError);
goto done;
+ }
}
else
{
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;
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;
}
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 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 < sizeof(WCHAR))
- {
- *lpcchBuffer = sizeof(WCHAR);
- 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 < sizeof(WCHAR))
- {
- *lpcchBuffer = sizeof(WCHAR);
- 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;
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 = sizeof(CHAR);
- 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 = sizeof(CHAR);
- 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;
+ }
}
/* Function 46 */
DWORD
WINAPI
-RQueryServiceTagInfo(
- handle_t BindingHandle) /* FIXME */
+RI_ScQueryServiceTagInfo(
+ SC_RPC_HANDLE hSCManager,
+ TAG_INFO_LEVEL dwInfoLevel,
+ PTAG_INFO_NAME_FROM_TAG_IN_PARAMS * lpInParams,
+ PTAG_INFO_NAME_FROM_TAG_OUT_PARAMS * lpOutParams)
{
- UNIMPLEMENTED;
- return ERROR_CALL_NOT_IMPLEMENTED;
+ PMANAGER_HANDLE hManager;
+
+ /* Validate handle */
+ hManager = ScmGetServiceManagerFromHandle(hSCManager);
+ if (hManager == NULL)
+ {
+ return ERROR_INVALID_HANDLE;
+ }
+
+ /* FIXME: should check whether client is local */
+
+ /* Check access rights */
+ if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
+ SC_MANAGER_ENUMERATE_SERVICE))
+ {
+ return ERROR_ACCESS_DENIED;
+ }
+
+ /* Check parameters */
+ if (lpInParams == NULL || lpOutParams == NULL)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ /* Check info level */
+ if (dwInfoLevel != TagInfoLevelNameFromTag)
+ {
+ return ERROR_RETRY;
+ }
+
+ /* Call internal helper */
+ return ScmGetServiceNameFromTag(*lpInParams, lpOutParams);
}