-/* $Id: scm.c,v 1.19 2003/08/07 04:03:22 royce Exp $
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/advapi32/service/scm.c
* PURPOSE: Service control manager functions
* PROGRAMMER: Emanuele Aliberti
+ * Eric Kohl
* UPDATE HISTORY:
* 19990413 EA created
* 19990515 EA
/* INCLUDES ******************************************************************/
-#define NTOS_MODE_USER
-#include <ntos.h>
-#include <windows.h>
-#include <wchar.h>
-#include <tchar.h>
+#include <advapi32.h>
+#include "svcctl_c.h"
-#define DBG
+#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
+handle_t BindingHandle = NULL;
+
+static VOID
+HandleBind(VOID)
+{
+ LPWSTR pszStringBinding;
+ RPC_STATUS status;
+
+ if (BindingHandle != NULL)
+ return;
+
+ status = RpcStringBindingComposeW(NULL,
+ L"ncacn_np",
+ NULL,
+ L"\\pipe\\ntsvcs",
+ NULL,
+ &pszStringBinding);
+ if (status)
+ {
+ DPRINT1("RpcStringBindingCompose returned 0x%x\n", status);
+ return;
+ }
+
+ /* Set the binding handle that will be used to bind to the server. */
+ status = RpcBindingFromStringBindingW(pszStringBinding,
+ &BindingHandle);
+ if (status)
+ {
+ DPRINT1("RpcBindingFromStringBinding returned 0x%x\n", status);
+ }
+
+ status = RpcStringFreeW(&pszStringBinding);
+ if (status)
+ {
+ DPRINT1("RpcStringFree returned 0x%x\n", status);
+ }
+}
+
+
+#if 0
+static VOID
+HandleUnbind(VOID)
+{
+ RPC_STATUS status;
+
+ if (BindingHandle == NULL)
+ return;
+
+ status = RpcBindingFree(&BindingHandle);
+ if (status)
+ {
+ DPRINT1("RpcBindingFree returned 0x%x\n", status);
+ }
+}
+#endif
+
+
/**********************************************************************
* ChangeServiceConfigA
*
LPCSTR lpPassword,
LPCSTR lpDisplayName)
{
+ DPRINT1("ChangeServiceConfigA is unimplemented\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/**********************************************************************
* ChangeServiceConfigW
*
- * @unimplemented
+ * @implemented
*/
-BOOL
-STDCALL
-ChangeServiceConfigW(
- SC_HANDLE hService,
- DWORD dwServiceType,
- DWORD dwStartType,
- DWORD dwErrorControl,
- LPCWSTR lpBinaryPathName,
- LPCWSTR lpLoadOrderGroup,
- LPDWORD lpdwTagId,
- LPCWSTR lpDependencies,
- LPCWSTR lpServiceStartName,
- LPCWSTR lpPassword,
- LPCWSTR lpDisplayName)
+BOOL STDCALL
+ChangeServiceConfigW(SC_HANDLE hService,
+ DWORD dwServiceType,
+ DWORD dwStartType,
+ DWORD dwErrorControl,
+ LPCWSTR lpBinaryPathName,
+ LPCWSTR lpLoadOrderGroup,
+ LPDWORD lpdwTagId,
+ LPCWSTR lpDependencies,
+ LPCWSTR lpServiceStartName,
+ LPCWSTR lpPassword,
+ LPCWSTR lpDisplayName)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ DWORD dwError;
+ DWORD dwDependenciesLength = 0;
+ DWORD dwLength;
+ LPWSTR lpStr;
+
+ DPRINT("ChangeServiceConfigW() called\n");
+
+ /* Calculate the Dependencies length*/
+ if (lpDependencies != NULL)
+ {
+ lpStr = (LPWSTR)lpDependencies;
+ while (*lpStr)
+ {
+ dwLength = wcslen(lpStr) + 1;
+ dwDependenciesLength += dwLength;
+ lpStr = lpStr + dwLength;
+ }
+ dwDependenciesLength++;
+ }
+
+ /* FIXME: Encrypt the password */
+
+ HandleBind();
+
+ /* Call to services.exe using RPC */
+ dwError = ScmrChangeServiceConfigW(BindingHandle,
+ (unsigned int)hService,
+ dwServiceType,
+ dwStartType,
+ dwErrorControl,
+ (LPWSTR)lpBinaryPathName,
+ (LPWSTR)lpLoadOrderGroup,
+ lpdwTagId,
+ (LPWSTR)lpDependencies,
+ dwDependenciesLength,
+ (LPWSTR)lpServiceStartName,
+ NULL, /* FIXME: lpPassword */
+ 0, /* FIXME: dwPasswordLength */
+ (LPWSTR)lpDisplayName);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmrChangeServiceConfigW() failed (Error %lu)\n", dwError);
+ SetLastError(dwError);
+ return FALSE;
+ }
+
+ return TRUE;
}
*
* @implemented
*/
-BOOL
-STDCALL
+BOOL STDCALL
CloseServiceHandle(SC_HANDLE hSCObject)
{
- HANDLE hPipe;
- DPRINT("CloseServiceHandle() - called.\n");
-// SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ DWORD dwError;
- if (!CloseHandle(hPipe)) {
- SetLastError(ERROR_INVALID_HANDLE);
+ DPRINT("CloseServiceHandle() called\n");
+
+ HandleBind();
+
+ /* Call to services.exe using RPC */
+ dwError = ScmrCloseServiceHandle(BindingHandle,
+ (unsigned int)hSCObject);
+ if (dwError)
+ {
+ DPRINT1("ScmrCloseServiceHandle() failed (Error %lu)\n", dwError);
+ SetLastError(dwError);
return FALSE;
}
+
+ DPRINT("CloseServiceHandle() done\n");
+
return TRUE;
}
*
* @unimplemented
*/
-BOOL
-STDCALL
-ControlService(SC_HANDLE hService,
- DWORD dwControl,
+BOOL STDCALL
+ControlService(SC_HANDLE hService,
+ DWORD dwControl,
LPSERVICE_STATUS lpServiceStatus)
{
+ DWORD dwError;
+
+ DPRINT("ControlService(%x, %x, %p)\n",
+ hService, dwControl, lpServiceStatus);
+
+ HandleBind();
+
+ /* Call to services.exe using RPC */
+ dwError = ScmrControlService(BindingHandle,
+ (unsigned int)hService,
+ dwControl,
+ lpServiceStatus);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmrControlService() failed (Error %lu)\n", dwError);
+ SetLastError(dwError);
+ return FALSE;
+ }
+
+ DPRINT("ControlService() done\n");
+
+ return TRUE;
+}
+
+
+/**********************************************************************
+ * ControlServiceEx
+ *
+ * @unimplemented
+ */
+BOOL STDCALL
+ControlServiceEx(IN SC_HANDLE hService,
+ IN DWORD dwControl,
+ IN DWORD dwInfoLevel,
+ IN OUT PVOID pControlParams)
+{
+ DPRINT1("ControlServiceEx(0x%p, 0x%x, 0x%x, 0x%p) UNIMPLEMENTED!\n",
+ hService, dwControl, dwInfoLevel, pControlParams);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
+
/**********************************************************************
* CreateServiceA
*
- * @unimplemented
+ * @implemented
*/
SC_HANDLE
STDCALL
LPCSTR lpServiceStartName,
LPCSTR lpPassword)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return NULL;
+ SC_HANDLE RetVal = NULL;
+ LPWSTR lpServiceNameW = NULL;
+ LPWSTR lpDisplayNameW = NULL;
+ LPWSTR lpBinaryPathNameW = NULL;
+ LPWSTR lpLoadOrderGroupW = NULL;
+ LPWSTR lpDependenciesW = NULL;
+ LPWSTR lpServiceStartNameW = NULL;
+ LPWSTR lpPasswordW = NULL;
+
+ int len = MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, NULL, 0);
+ lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!lpServiceNameW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, lpServiceNameW, len);
+
+ len = MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, NULL, 0);
+ lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!lpDisplayNameW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, lpDisplayNameW, len);
+
+ len = MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, NULL, 0);
+ lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!lpBinaryPathNameW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, lpBinaryPathNameW, len);
+
+ len = MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, NULL, 0);
+ lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!lpLoadOrderGroupW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, lpLoadOrderGroupW, len);
+
+ len = MultiByteToWideChar(CP_ACP, 0, lpDependencies, -1, NULL, 0);
+ lpDependenciesW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!lpDependenciesW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, lpDependencies, -1, lpDependenciesW, len);
+
+ len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0);
+ lpServiceStartName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!lpServiceStartNameW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, lpServiceStartNameW, len);
+
+ len = MultiByteToWideChar(CP_ACP, 0, lpPassword, -1, NULL, 0);
+ lpPasswordW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!lpPasswordW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, lpPassword, -1, lpPasswordW, len);
+
+ RetVal = CreateServiceW(hSCManager,
+ lpServiceNameW,
+ lpDisplayNameW,
+ dwDesiredAccess,
+ dwServiceType,
+ dwStartType,
+ dwErrorControl,
+ lpBinaryPathNameW,
+ lpLoadOrderGroupW,
+ lpdwTagId,
+ lpDependenciesW,
+ lpServiceStartNameW,
+ lpPasswordW);
+
+
+cleanup:
+ if (!lpServiceNameW) HeapFree(GetProcessHeap(), 0, lpServiceNameW);
+ if (!lpDisplayNameW) HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
+ if (!lpBinaryPathNameW) HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW);
+ if (!lpLoadOrderGroupW) HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
+ if (!lpDependenciesW) HeapFree(GetProcessHeap(), 0, lpDependenciesW);
+ if (!lpServiceStartNameW) HeapFree(GetProcessHeap(), 0, lpServiceStartNameW);
+ if (!lpPasswordW) HeapFree(GetProcessHeap(), 0, lpPasswordW);
+
+ return RetVal;
}
/**********************************************************************
* CreateServiceW
*
- * @unimplemented
+ * @implemented
*/
-SC_HANDLE
-STDCALL
-CreateServiceW(
- SC_HANDLE hSCManager,
- LPCWSTR lpServiceName,
- LPCWSTR lpDisplayName,
- DWORD dwDesiredAccess,
- DWORD dwServiceType,
- DWORD dwStartType,
- DWORD dwErrorControl,
- LPCWSTR lpBinaryPathName,
- LPCWSTR lpLoadOrderGroup,
- LPDWORD lpdwTagId,
- LPCWSTR lpDependencies,
- LPCWSTR lpServiceStartName,
- LPCWSTR lpPassword)
+SC_HANDLE STDCALL
+CreateServiceW(SC_HANDLE hSCManager,
+ LPCWSTR lpServiceName,
+ LPCWSTR lpDisplayName,
+ DWORD dwDesiredAccess,
+ DWORD dwServiceType,
+ DWORD dwStartType,
+ DWORD dwErrorControl,
+ LPCWSTR lpBinaryPathName,
+ LPCWSTR lpLoadOrderGroup,
+ LPDWORD lpdwTagId,
+ LPCWSTR lpDependencies,
+ LPCWSTR lpServiceStartName,
+ LPCWSTR lpPassword)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return NULL;
+ SC_HANDLE hService = NULL;
+ DWORD dwError;
+ DWORD dwDependenciesLength = 0;
+ DWORD dwLength;
+ LPWSTR lpStr;
+
+ DPRINT1("CreateServiceW() called\n");
+
+ /* Calculate the Dependencies length*/
+ if (lpDependencies != NULL)
+ {
+ lpStr = (LPWSTR)lpDependencies;
+ while (*lpStr)
+ {
+ dwLength = wcslen(lpStr) + 1;
+ dwDependenciesLength += dwLength;
+ lpStr = lpStr + dwLength;
+ }
+ dwDependenciesLength++;
+ }
+
+ /* FIXME: Encrypt the password */
+
+ HandleBind();
+
+ /* Call to services.exe using RPC */
+ dwError = ScmrCreateServiceW(BindingHandle,
+ (unsigned int)hSCManager,
+ (LPWSTR)lpServiceName,
+ (LPWSTR)lpDisplayName,
+ dwDesiredAccess,
+ dwServiceType,
+ dwStartType,
+ dwErrorControl,
+ (LPWSTR)lpBinaryPathName,
+ (LPWSTR)lpLoadOrderGroup,
+ lpdwTagId,
+ (LPWSTR)lpDependencies,
+ dwDependenciesLength,
+ (LPWSTR)lpServiceStartName,
+ NULL, /* FIXME: lpPassword */
+ 0, /* FIXME: dwPasswordLength */
+ (unsigned int *)&hService);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmrCreateServiceW() failed (Error %lu)\n", dwError);
+ SetLastError(dwError);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ return hService;
}
/**********************************************************************
* DeleteService
*
- * @unimplemented
+ * @implemented
*/
-BOOL
-STDCALL
+BOOL STDCALL
DeleteService(SC_HANDLE hService)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ DWORD dwError;
+
+ DPRINT("DeleteService(%x)\n", hService);
+
+ HandleBind();
+
+ /* Call to services.exe using RPC */
+ dwError = ScmrDeleteService(BindingHandle,
+ (unsigned int)hService);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmrDeleteService() failed (Error %lu)\n", dwError);
+ SetLastError(dwError);
+ return FALSE;
+ }
+
+ return TRUE;
}
LPDWORD pcbBytesNeeded,
LPDWORD lpServicesReturned)
{
+ DPRINT1("EnumDependentServicesA is unimplemented\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
LPDWORD pcbBytesNeeded,
LPDWORD lpServicesReturned)
{
+ DPRINT1("EnumDependentServicesW is unimplemented\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
DWORD Unknown7,
DWORD Unknown8)
{
+ DPRINT1("EnumServiceGroupW is unimplemented\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
LPDWORD lpServicesReturned,
LPDWORD lpResumeHandle)
{
+ DPRINT1("EnumServicesStatusA is unimplemented\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
LPDWORD lpResumeHandle,
LPCSTR pszGroupName)
{
+ DPRINT1("EnumServicesStatusExA is unimplemented\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
LPDWORD lpResumeHandle,
LPCWSTR pszGroupName)
{
+ DPRINT1("EnumServicesStatusExW is unimplemented\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
LPDWORD lpServicesReturned,
LPDWORD lpResumeHandle)
{
+ DPRINT1("EnumServicesStatusW is unimplemented\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
LPSTR lpDisplayName,
LPDWORD lpcchBuffer)
{
+ DPRINT1("GetServiceDisplayNameA is unimplemented\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/**********************************************************************
* GetServiceDisplayNameW
*
- * @unimplemented
+ * @implemented
*/
-BOOL
-STDCALL
-GetServiceDisplayNameW(
- SC_HANDLE hSCManager,
- LPCWSTR lpServiceName,
- LPWSTR lpDisplayName,
- LPDWORD lpcchBuffer)
+BOOL STDCALL
+GetServiceDisplayNameW(SC_HANDLE hSCManager,
+ LPCWSTR lpServiceName,
+ LPWSTR lpDisplayName,
+ LPDWORD lpcchBuffer)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ DWORD dwError;
+
+ DPRINT("GetServiceDisplayNameW() called\n");
+
+ HandleBind();
+
+ dwError = ScmrGetServiceDisplayNameW(BindingHandle,
+ (unsigned int)hSCManager,
+ (LPWSTR)lpServiceName,
+ lpDisplayName,
+ lpcchBuffer);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmrGetServiceDisplayNameW() failed (Error %lu)\n", dwError);
+ SetLastError(dwError);
+ return FALSE;
+ }
+
+ (*lpcchBuffer)--;
+
+ return TRUE;
}
LPSTR lpServiceName,
LPDWORD lpcchBuffer)
{
+ DPRINT1("GetServiceKeyNameA is unimplemented\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/**********************************************************************
* GetServiceKeyNameW
*
- * @unimplemented
+ * @implemented
*/
-BOOL
-STDCALL
-GetServiceKeyNameW(
- SC_HANDLE hSCManager,
- LPCWSTR lpDisplayName,
- LPWSTR lpServiceName,
- LPDWORD lpcchBuffer)
+BOOL STDCALL
+GetServiceKeyNameW(SC_HANDLE hSCManager,
+ LPCWSTR lpDisplayName,
+ LPWSTR lpServiceName,
+ LPDWORD lpcchBuffer)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ DWORD dwError;
+
+ DPRINT("GetServiceKeyNameW() called\n");
+
+ HandleBind();
+
+ dwError = ScmrGetServiceKeyNameW(BindingHandle,
+ (unsigned int)hSCManager,
+ (LPWSTR)lpDisplayName,
+ lpServiceName,
+ lpcchBuffer);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmrGetServiceKeyNameW() failed (Error %lu)\n", dwError);
+ SetLastError(dwError);
+ return FALSE;
+ }
+
+ (*lpcchBuffer)--;
+
+ return TRUE;
}
+
/**********************************************************************
* LockServiceDatabase
*
- * @unimplemented
+ * @implemented
*/
-SC_LOCK
-STDCALL
-LockServiceDatabase(SC_HANDLE hSCManager)
+SC_LOCK STDCALL
+LockServiceDatabase(SC_HANDLE hSCManager)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return NULL;
+ SC_LOCK hLock;
+ DWORD dwError;
+
+ DPRINT("LockServiceDatabase(%x)\n", hSCManager);
+
+ HandleBind();
+
+ /* Call to services.exe using RPC */
+ dwError = ScmrLockServiceDatabase(BindingHandle,
+ (unsigned int)hSCManager,
+ (unsigned int *)&hLock);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmrLockServiceDatabase() failed (Error %lu)\n", dwError);
+ SetLastError(dwError);
+ return NULL;
+ }
+
+ DPRINT("hLock = %p\n", hLock);
+
+ return hLock;
+}
+
+
+static VOID
+WaitForSCManager(VOID)
+{
+ HANDLE hEvent;
+
+ DPRINT("WaitForSCManager() called\n");
+
+ /* Try to open the existing event */
+ hEvent = OpenEventW(SYNCHRONIZE,
+ FALSE,
+ L"SvcctrlStartEvent_A3725DX");
+ if (hEvent == NULL)
+ {
+ if (GetLastError() != ERROR_FILE_NOT_FOUND)
+ return;
+
+ /* Try to create a new event */
+ hEvent = CreateEventW(NULL,
+ TRUE,
+ FALSE,
+ L"SvcctrlStartEvent_A3725DX");
+ if (hEvent == NULL)
+ {
+ /* Try to open the existing event again */
+ hEvent = OpenEventW(SYNCHRONIZE,
+ FALSE,
+ L"SvcctrlStartEvent_A3725DX");
+ if (hEvent == NULL)
+ return;
+ }
+ }
+
+ /* Wait for 3 minutes */
+ WaitForSingleObject(hEvent, 180000);
+ CloseHandle(hEvent);
+
+ DPRINT("ScmWaitForSCManager() done\n");
}
/**********************************************************************
* OpenSCManagerA
*
- * @unplemented
+ * @implemented
*/
SC_HANDLE STDCALL
OpenSCManagerA(LPCSTR lpMachineName,
- LPCSTR lpDatabaseName,
- DWORD dwDesiredAccess)
+ LPCSTR lpDatabaseName,
+ DWORD dwDesiredAccess)
{
- SC_HANDLE Handle;
- UNICODE_STRING MachineNameW;
- UNICODE_STRING DatabaseNameW;
- ANSI_STRING MachineNameA;
- ANSI_STRING DatabaseNameA;
+ SC_HANDLE hScm = NULL;
+ DWORD dwError;
- DPRINT("OpenSCManagerA(%x, %x, %d)\n", lpMachineName, lpDatabaseName, dwDesiredAccess);
+ DPRINT("OpenSCManagerA(%s, %s, %lx)\n",
+ lpMachineName, lpDatabaseName, dwDesiredAccess);
- RtlInitAnsiString(&MachineNameA, (LPSTR)lpMachineName);
- RtlAnsiStringToUnicodeString(&MachineNameW, &MachineNameA, TRUE);
- RtlInitAnsiString(&DatabaseNameA, (LPSTR)lpDatabaseName);
- RtlAnsiStringToUnicodeString(&DatabaseNameW, &DatabaseNameA, TRUE);
+ WaitForSCManager();
+
+ HandleBind();
+
+ /* Call to services.exe using RPC */
+ dwError = ScmrOpenSCManagerA(BindingHandle,
+ (LPSTR)lpMachineName,
+ (LPSTR)lpDatabaseName,
+ dwDesiredAccess,
+ (unsigned int*)&hScm);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmrOpenSCManagerA() failed (Error %lu)\n", dwError);
+ SetLastError(dwError);
+ return NULL;
+ }
- Handle = OpenSCManagerW(lpMachineName ? MachineNameW.Buffer : NULL,
- lpDatabaseName ? DatabaseNameW.Buffer : NULL,
- dwDesiredAccess);
+ DPRINT("hScm = %p\n", hScm);
- RtlFreeHeap(GetProcessHeap(), 0, MachineNameW.Buffer);
- RtlFreeHeap(GetProcessHeap(), 0, DatabaseNameW.Buffer);
- return Handle;
+ return hScm;
}
/**********************************************************************
* OpenSCManagerW
*
- * @unimplemented
+ * @implemented
*/
-SC_HANDLE STDCALL OpenSCManagerW(LPCWSTR lpMachineName,
- LPCWSTR lpDatabaseName,
- DWORD dwDesiredAccess)
+SC_HANDLE STDCALL
+OpenSCManagerW(LPCWSTR lpMachineName,
+ LPCWSTR lpDatabaseName,
+ DWORD dwDesiredAccess)
{
- HANDLE hPipe;
- DWORD dwMode;
- DWORD dwWait;
- BOOL fSuccess;
- HANDLE hStartEvent;
- LPWSTR lpszPipeName = L"\\\\.\\pipe\\Ntsvcs";
+ SC_HANDLE hScm = NULL;
+ DWORD dwError;
- DPRINT("OpenSCManagerW(%x, %x, %d)\n", lpMachineName, lpDatabaseName, dwDesiredAccess);
+ DPRINT("OpenSCManagerW(%S, %S, %lx)\n",
+ lpMachineName, lpDatabaseName, dwDesiredAccess);
- if (lpMachineName == NULL || wcslen(lpMachineName) == 0)
- {
- if (lpDatabaseName != NULL && wcscmp(lpDatabaseName, SERVICES_ACTIVE_DATABASEW) != 0)
- {
- DPRINT("OpenSCManagerW() - Invalid parameters.\n");
- return NULL;
- }
-
- DPRINT("OpenSCManagerW() - OpenEvent(\"SvcctrlStartEvent_A3725DX\")\n");
-
- // Only connect to scm when event "SvcctrlStartEvent_A3725DX" is signaled
- hStartEvent = OpenEventW(SYNCHRONIZE, FALSE, L"SvcctrlStartEvent_A3725DX");
- if (hStartEvent == NULL)
- {
- SetLastError(ERROR_DATABASE_DOES_NOT_EXIST);
- DPRINT("OpenSCManagerW() - Failed to Open Event \"SvcctrlStartEvent_A3725DX\".\n");
- return NULL;
- }
-
- DPRINT("OpenSCManagerW() - Waiting forever on event handle: %x\n", hStartEvent);
-
-#if 1
- dwWait = WaitForSingleObject(hStartEvent, INFINITE);
- if (dwWait == WAIT_FAILED)
- {
- DPRINT("OpenSCManagerW() - Wait For Start Event failed.\n");
- SetLastError(ERROR_ACCESS_DENIED);
- return NULL;
- }
-#else
- {
- DWORD Count;
-
- /* wait for event creation (by SCM) for max. 20 seconds */
- for (Count = 0; Count < 20; Count++)
- {
- dwWait = WaitForSingleObject(hStartEvent, 1000);
- if (dwWait == WAIT_FAILED)
- {
- DPRINT("OpenSCManagerW() - Wait For Start Event failed.\n");
- Sleep(1000);
- }
- else
- {
- break;
- }
- }
-
- if (dwWait == WAIT_FAILED)
- {
- DbgPrint("WL: Failed to wait on event \"SvcctrlStartEvent_A3725DX\"\n");
- }
-
- }
-#endif
+ WaitForSCManager();
- DPRINT("OpenSCManagerW() - Closing handle to event...\n");
-
- CloseHandle(hStartEvent);
-
- // Try to open a named pipe; wait for it, if necessary
- while (1)
- {
- DWORD dwLastError;
- DPRINT("OpenSCManagerW() - attempting to open named pipe to SCM.\n");
- hPipe = CreateFileW(lpszPipeName, // pipe name
- dwDesiredAccess,
- 0, // no sharing
- NULL, // no security attributes
- OPEN_EXISTING, // opens existing pipe
- 0, // default attributes
- NULL); // no template file
-
- DPRINT("OpenSCManagerW() - handle to named pipe: %x\n", hPipe);
- // Break if the pipe handle is valid
- if (hPipe != INVALID_HANDLE_VALUE)
- {
- break;
- }
-
- // Exit if an error other than ERROR_PIPE_BUSY occurs
- dwLastError = GetLastError();
- if (dwLastError != ERROR_PIPE_BUSY)
- {
- DPRINT("OpenSCManagerW() - returning at 4, dwLastError %d\n", dwLastError);
- return NULL;
- }
-
- // All pipe instances are busy, so wait for 20 seconds
- if (!WaitNamedPipeW(lpszPipeName, 20000))
- {
- DPRINT("OpenSCManagerW() - Failed on WaitNamedPipeW(...).\n");
- return NULL;
- }
- }
-
- // The pipe connected; change to message-read mode
- dwMode = PIPE_READMODE_MESSAGE;
- fSuccess = SetNamedPipeHandleState(
- hPipe, // pipe handle
- &dwMode, // new pipe mode
- NULL, // don't set maximum bytes
- NULL); // don't set maximum time
- if (!fSuccess)
- {
- CloseHandle(hPipe);
- DPRINT("OpenSCManagerW() - Failed on SetNamedPipeHandleState(...).\n");
- return NULL;
- }
-#if 0
- // Send a message to the pipe server
- lpvMessage = (argc > 1) ? argv[1] : "default message";
-
- fSuccess = WriteFile(
- hPipe, // pipe handle
- lpvMessage, // message
- strlen(lpvMessage) + 1, // message length
- &cbWritten, // bytes written
- NULL); // not overlapped
- if (!fSuccess)
- {
- CloseHandle(hPipe);
- DPRINT("OpenSCManagerW() - Failed to write to pipe.\n");
- return NULL;
- }
-
- do
- {
- DPRINT("OpenSCManagerW() - in I/O loop to SCM...\n");
- // Read from the pipe
- fSuccess = ReadFile(
- hPipe, // pipe handle
- chBuf, // buffer to receive reply
- 512, // size of buffer
- &cbRead, // number of bytes read
- NULL); // not overlapped
-
- if (!fSuccess && GetLastError() != ERROR_MORE_DATA)
- {
- break;
- }
-
- // Reply from the pipe is written to STDOUT.
- if (!WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), chBuf, cbRead, &cbWritten, NULL))
- {
- break;
- }
- } while(!fSuccess); // repeat loop if ERROR_MORE_DATA
-
- DPRINT("OpenSCManagerW() - I/O loop completed.\n");
- //CloseHandle(hPipe);
-#endif
- DPRINT("OpenSCManagerW() - success, returning handle to pipe %x\n", hPipe);
- return hPipe;
- }
- else
+ HandleBind();
+
+ /* Call to services.exe using RPC */
+ dwError = ScmrOpenSCManagerW(BindingHandle,
+ (LPWSTR)lpMachineName,
+ (LPWSTR)lpDatabaseName,
+ dwDesiredAccess,
+ (unsigned int*)&hScm);
+ if (dwError != ERROR_SUCCESS)
{
- /* FIXME: Connect to remote SCM */
- DPRINT("OpenSCManagerW() - FIXME: Connect to remote SCM not implemented.\n");
- return NULL;
+ DPRINT1("ScmrOpenSCManagerW() failed (Error %lu)\n", dwError);
+ SetLastError(dwError);
+ return NULL;
}
+
+ DPRINT("hScm = %p\n", hScm);
+
+ return hScm;
}
/**********************************************************************
* OpenServiceA
*
- * @unimplemented
+ * @implemented
*/
SC_HANDLE STDCALL
OpenServiceA(SC_HANDLE hSCManager,
- LPCSTR lpServiceName,
- DWORD dwDesiredAccess)
+ LPCSTR lpServiceName,
+ DWORD dwDesiredAccess)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return NULL;
+ SC_HANDLE hService = NULL;
+ DWORD dwError;
+
+ DPRINT("OpenServiceA(%p, %s, %lx)\n",
+ hSCManager, lpServiceName, dwDesiredAccess);
+
+ HandleBind();
+
+ /* Call to services.exe using RPC */
+ dwError = ScmrOpenServiceA(BindingHandle,
+ (unsigned int)hSCManager,
+ (LPSTR)lpServiceName,
+ dwDesiredAccess,
+ (unsigned int*)&hService);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmrOpenServiceA() failed (Error %lu)\n", dwError);
+ SetLastError(dwError);
+ return NULL;
+ }
+
+ DPRINT("hService = %p\n", hService);
+
+ return hService;
}
/**********************************************************************
* OpenServiceW
*
- * @unimplemented
+ * @implemented
*/
-SC_HANDLE
-STDCALL
-OpenServiceW(
- SC_HANDLE hSCManager,
- LPCWSTR lpServiceName,
- DWORD dwDesiredAccess
- )
+SC_HANDLE STDCALL
+OpenServiceW(SC_HANDLE hSCManager,
+ LPCWSTR lpServiceName,
+ DWORD dwDesiredAccess)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return NULL;
+ SC_HANDLE hService = NULL;
+ DWORD dwError;
+
+ DPRINT("OpenServiceW(%p, %S, %lx)\n",
+ hSCManager, lpServiceName, dwDesiredAccess);
+
+ HandleBind();
+
+ /* Call to services.exe using RPC */
+ dwError = ScmrOpenServiceW(BindingHandle,
+ (unsigned int)hSCManager,
+ (LPWSTR)lpServiceName,
+ dwDesiredAccess,
+ (unsigned int*)&hService);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmrOpenServiceW() failed (Error %lu)\n", dwError);
+ SetLastError(dwError);
+ return NULL;
+ }
+
+ DPRINT("hService = %p\n", hService);
+
+ return hService;
}
DWORD cbBufSize,
LPDWORD pcbBytesNeeded)
{
+ DPRINT1("QueryServiceConfigA is unimplemented\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
DWORD cbBufSize,
LPDWORD pcbBytesNeeded)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ DPRINT1("QueryServiceConfigW is unimplemented\n");
+ if (lpServiceConfig && cbBufSize >= sizeof(QUERY_SERVICE_CONFIGW))
+ {
+ memset(lpServiceConfig, 0, *pcbBytesNeeded);
+ return TRUE;
+ }
+ else
+ {
+ *pcbBytesNeeded = sizeof(QUERY_SERVICE_CONFIGW);
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
}
DWORD cbBufSize,
LPDWORD pcbBytesNeeded)
{
+ DPRINT1("QueryServiceLockStatusA is unimplemented\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
DWORD cbBufSize,
LPDWORD pcbBytesNeeded)
{
+ DPRINT1("QueryServiceLockStatusW is unimplemented\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
DWORD cbBufSize,
LPDWORD pcbBytesNeeded)
{
+ DPRINT1("QueryServiceObjectSecurity is unimplemented\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/**********************************************************************
* QueryServiceStatus
*
- * @unimplemented
+ * @implemented
*/
-BOOL
-STDCALL
-QueryServiceStatus(
- SC_HANDLE hService,
- LPSERVICE_STATUS lpServiceStatus)
+BOOL STDCALL
+QueryServiceStatus(SC_HANDLE hService,
+ LPSERVICE_STATUS lpServiceStatus)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ DWORD dwError;
+
+ DPRINT("QueryServiceStatus(%p, %p)\n",
+ hService, lpServiceStatus);
+
+ HandleBind();
+
+ /* Call to services.exe using RPC */
+ dwError = ScmrQueryServiceStatus(BindingHandle,
+ (unsigned int)hService,
+ lpServiceStatus);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmrQueryServiceStatus() failed (Error %lu)\n", dwError);
+ SetLastError(dwError);
+ return FALSE;
+ }
+
+ return TRUE;
}
DWORD cbBufSize,
LPDWORD pcbBytesNeeded)
{
+ DPRINT1("QueryServiceStatusEx is unimplemented\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
DWORD dwNumServiceArgs,
LPCSTR *lpServiceArgVectors)
{
+ DPRINT1("StartServiceA is unimplemented\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
-
-
/**********************************************************************
* StartServiceW
*
DWORD dwNumServiceArgs,
LPCWSTR *lpServiceArgVectors)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ DPRINT1("StartServiceW is unimplemented, but returns success...\n");
+ //SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ //return FALSE;
+ return TRUE;
}
/**********************************************************************
* UnlockServiceDatabase
*
- * @unimplemented
+ * @implemented
*/
-BOOL
-STDCALL
-UnlockServiceDatabase(SC_LOCK ScLock)
+BOOL STDCALL
+UnlockServiceDatabase(SC_LOCK ScLock)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ DWORD dwError;
+
+ DPRINT("UnlockServiceDatabase(%x)\n", ScLock);
+
+ HandleBind();
+
+ /* Call to services.exe using RPC */
+ dwError = ScmrUnlockServiceDatabase(BindingHandle,
+ (unsigned int)ScLock);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmrUnlockServiceDatabase() failed (Error %lu)\n", dwError);
+ SetLastError(dwError);
+ return FALSE;
+ }
+
+ return TRUE;
}
+/**********************************************************************
+ * NotifyBootConfigStatus
+ *
+ * @implemented
+ */
+BOOL STDCALL
+NotifyBootConfigStatus(BOOL BootAcceptable)
+{
+ DWORD dwError;
+
+ DPRINT1("NotifyBootConfigStatus()\n");
+
+ HandleBind();
+
+ /* Call to services.exe using RPC */
+ dwError = ScmrNotifyBootConfigStatus(BindingHandle,
+ BootAcceptable);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("NotifyBootConfigStatus() failed (Error %lu)\n", dwError);
+ SetLastError(dwError);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
+{
+ return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
+}
+
+
+void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
+{
+ HeapFree(GetProcessHeap(), 0, ptr);
+}
+
/* EOF */