You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
700 lines
21 KiB
700 lines
21 KiB
// mpsmpssv.cpp
|
|
//
|
|
// This is the main file containing the entry points.
|
|
|
|
#include "NTServApp.h"
|
|
#include "PMSPservice.h"
|
|
#include <nserror.h>
|
|
#include "svchost.h"
|
|
#include <Sddl.h>
|
|
#include <aclapi.h>
|
|
#include <crtdbg.h>
|
|
#include <wmsstd.h>
|
|
|
|
HRESULT AddToSvcHostGroup();
|
|
BOOL UnregisterOldServer( SC_HANDLE hSCM );
|
|
STDAPI DllUnregisterServer(void);
|
|
|
|
#define SVCHOST_SUBKEY "netsvcs"
|
|
#define SVCHOST_SUBKEYW L"netsvcs"
|
|
|
|
//#define DEBUG_STOP { _asm { int 3 }; }
|
|
#define DEBUG_STOP
|
|
|
|
HMODULE g_hDll = NULL;
|
|
|
|
BOOL APIENTRY DllMain( HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
|
|
{
|
|
switch (ul_reason_for_call)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
g_hDll = (HMODULE)hModule;
|
|
InitializeCriticalSection (&g_csLock);
|
|
DisableThreadLibraryCalls (hModule);
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
DeleteCriticalSection (&g_csLock);
|
|
break;
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
case DLL_THREAD_DETACH:
|
|
_ASSERTE(0);
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
// Main entry point to start service
|
|
void ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
|
|
{
|
|
// We grab the lock so that any attempt to stop the service while
|
|
// the object is being constructed or registered will be pended.
|
|
EnterCriticalSection (&g_csLock);
|
|
|
|
_ASSERTE(g_pService == NULL);
|
|
|
|
DEBUG_STOP
|
|
CNTService::DebugMsg("Entering CNTService::ServiceMain()");
|
|
|
|
DWORD dwLastError;
|
|
|
|
// Allocate this on the heap rather than the stack so that
|
|
// we have a chance to call its destructor if the service
|
|
// terminates ungracefully.
|
|
CPMSPService* pService = new CPMSPService(dwLastError);
|
|
|
|
if (pService == NULL)
|
|
{
|
|
LeaveCriticalSection (&g_csLock);
|
|
dwLastError = ERROR_NOT_ENOUGH_MEMORY;
|
|
// @@@@: What message do we log here
|
|
// CNTService::LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_CTRLHANDLERNOTINSTALLED);
|
|
CNTService::DebugMsg("Leaving CNTService::ServiceMain() CPMSPService constructor failed - last error %u", dwLastError);
|
|
return;
|
|
}
|
|
|
|
CPMSPService& service = *pService;
|
|
|
|
if (dwLastError != ERROR_SUCCESS)
|
|
{
|
|
LeaveCriticalSection (&g_csLock);
|
|
// @@@@: What message do we log here
|
|
// CNTService::LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_CTRLHANDLERNOTINSTALLED);
|
|
CNTService::DebugMsg("Leaving CNTService::ServiceMain() CPMSPService constructor failed - last error %u", dwLastError);
|
|
delete pService;
|
|
return;
|
|
}
|
|
|
|
// Register the control request handler
|
|
service.m_hServiceStatus = RegisterServiceCtrlHandler( SERVICE_NAME,
|
|
CNTService::Handler );
|
|
if (service.m_hServiceStatus == NULL)
|
|
{
|
|
LeaveCriticalSection (&g_csLock);
|
|
CNTService::LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_CTRLHANDLERNOTINSTALLED);
|
|
CNTService::DebugMsg("Leaving CNTService::ServiceMain() RegisterServiceCtrlHandler failed");
|
|
delete pService;
|
|
return;
|
|
}
|
|
|
|
service.SetStatus(SERVICE_START_PENDING);
|
|
|
|
// Start the initialisation
|
|
__try
|
|
{
|
|
g_pService = &service; // The Handler method will need to get a hold of this object
|
|
LeaveCriticalSection (&g_csLock);
|
|
|
|
if (service.Initialize()) {
|
|
|
|
// Do the real work.
|
|
// When the Run function returns, the service has stopped.
|
|
service.m_bIsRunning = TRUE;
|
|
service.Run();
|
|
}
|
|
}
|
|
__finally
|
|
{
|
|
// Tell the service manager we are stopped and reset g_pService.
|
|
// Note that we hold the crit sect while calling SetStatus so that
|
|
// we have the final say on the status reported to the SCM.
|
|
|
|
// Note: If the thread dies (e.g., av's), we clean up, but svchost
|
|
// does not, so it is not possible to re-start the service. Consider
|
|
// adding our own exception handler.
|
|
|
|
EnterCriticalSection (&g_csLock);
|
|
service.SetStatus(SERVICE_STOPPED);
|
|
g_pService = NULL;
|
|
LeaveCriticalSection (&g_csLock);
|
|
CNTService::DebugMsg("Leaving CNTService::ServiceMain()");
|
|
delete pService;
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT ModifySD(SC_HANDLE hService)
|
|
{
|
|
PACL pDacl = NULL;
|
|
PACL pNewDacl = NULL;
|
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
|
DWORD Err = ERROR_SUCCESS;
|
|
PSID pAuthenUserSid = NULL;
|
|
|
|
|
|
__try
|
|
{
|
|
//
|
|
// Get DACL for the service object.
|
|
//
|
|
Err = GetSecurityInfo(hService, SE_SERVICE, DACL_SECURITY_INFORMATION,
|
|
NULL, NULL, &pDacl, NULL, &pSD
|
|
);
|
|
|
|
if(Err != ERROR_SUCCESS)
|
|
{
|
|
__leave;
|
|
}
|
|
|
|
SID_IDENTIFIER_AUTHORITY Auth = SECURITY_NT_AUTHORITY;
|
|
if(0 == AllocateAndInitializeSid(&Auth, 1, SECURITY_INTERACTIVE_RID,
|
|
0, 0, 0, 0, 0, 0, 0, &pAuthenUserSid)
|
|
)
|
|
{
|
|
Err = GetLastError();
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Initialize an EXPLICIT_ACCESS structure for the new ACE. The new ACE allows
|
|
// authenticated users to start/stop our service.
|
|
//
|
|
EXPLICIT_ACCESS ExpAccess;
|
|
ZeroMemory(&ExpAccess, sizeof(EXPLICIT_ACCESS));
|
|
ExpAccess.grfAccessPermissions = SERVICE_START; // | SERVICE_STOP ;
|
|
ExpAccess.grfAccessMode = GRANT_ACCESS;
|
|
ExpAccess.grfInheritance = NO_INHERITANCE;
|
|
ExpAccess.Trustee.pMultipleTrustee = NULL;
|
|
ExpAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
|
|
ExpAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
|
|
ExpAccess.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
|
|
ExpAccess.Trustee.ptstrName = (LPTSTR)pAuthenUserSid;
|
|
|
|
//Create new DACL
|
|
Err = SetEntriesInAcl(1, &ExpAccess, pDacl, &pNewDacl) ;
|
|
if(ERROR_SUCCESS == Err)
|
|
{
|
|
// Update the security descriptor on the service
|
|
Err = SetSecurityInfo(hService, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL, NULL,
|
|
pNewDacl, NULL);
|
|
}
|
|
|
|
|
|
}
|
|
__finally
|
|
{
|
|
|
|
if(pSD)
|
|
{
|
|
LocalFree(pSD);
|
|
}
|
|
|
|
if(pAuthenUserSid){
|
|
FreeSid(pAuthenUserSid);
|
|
}
|
|
|
|
if(pNewDacl)
|
|
{
|
|
LocalFree(pNewDacl);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
return HRESULT_FROM_WIN32(Err);
|
|
}
|
|
|
|
// Install and start service
|
|
STDAPI DllRegisterServer(void)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
SC_HANDLE hSCM = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
TCHAR pszDisplayName[256];
|
|
char szKey[256];
|
|
HKEY hKey = NULL;
|
|
|
|
DEBUG_STOP;
|
|
|
|
// Already installed?
|
|
if( CNTService::IsInstalled() )
|
|
{
|
|
hr = DllUnregisterServer();
|
|
if( !SUCCEEDED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
if( g_hDll == NULL )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Open the Service Control Manager
|
|
hSCM = ::OpenSCManager( NULL, // local machine
|
|
NULL, // ServicesActive database
|
|
SC_MANAGER_ALL_ACCESS); // full access
|
|
if (!hSCM)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// On Win2k we have this service running as separate process which should
|
|
// be uninstalled.
|
|
//
|
|
UnregisterOldServer( hSCM );
|
|
|
|
|
|
// Get the path of this dll
|
|
char szFilePath[MAX_PATH];
|
|
if (::GetModuleFileName( g_hDll, szFilePath, ARRAYSIZE(szFilePath)) == 0)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Error;
|
|
}
|
|
|
|
// Create the service
|
|
if (FormatMessage( FORMAT_MESSAGE_FROM_HMODULE, g_hDll, EVMSG_DISPLAYNAME,
|
|
0, pszDisplayName, ARRAYSIZE(pszDisplayName), NULL ) == 0)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Error;
|
|
}
|
|
hService = ::CreateService( hSCM,
|
|
SERVICE_NAME,
|
|
pszDisplayName,
|
|
SERVICE_ALL_ACCESS,
|
|
SERVICE_WIN32_SHARE_PROCESS,
|
|
SERVICE_DEMAND_START,
|
|
SERVICE_ERROR_NORMAL,
|
|
"%SystemRoot%\\System32\\svchost.exe -k " SVCHOST_SUBKEY,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if (!hService)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// Modify the security descriptor on the created service so that
|
|
// Authenticated Users can start/stop services. By default only admins can start/stop
|
|
// services
|
|
//
|
|
|
|
hr = ModifySD(hService);
|
|
if(!SUCCEEDED(hr))
|
|
{
|
|
goto Error;
|
|
}
|
|
|
|
// Set description of service, method only avalible for OS >= Win2K so we
|
|
// need to load the dll, method in runtime.
|
|
{
|
|
typedef BOOL (WINAPI *funCSC2)(SC_HANDLE, DWORD, LPVOID );
|
|
funCSC2 pChangeServiceConfig2 = NULL;
|
|
HINSTANCE hDll = NULL;
|
|
|
|
hDll = ::LoadLibraryExA( "advapi32.dll", NULL, 0 );
|
|
if( hDll != NULL )
|
|
{
|
|
pChangeServiceConfig2 = (funCSC2)GetProcAddress( hDll, "ChangeServiceConfig2W");
|
|
|
|
if( pChangeServiceConfig2 )
|
|
{
|
|
WCHAR pszDescription[1024];
|
|
int iCharsLoaded = 0;
|
|
|
|
SERVICE_DESCRIPTIONW sd;
|
|
iCharsLoaded = FormatMessageW( FORMAT_MESSAGE_FROM_HMODULE, g_hDll, EVMSG_DESCRIPTION,
|
|
0, pszDescription, sizeof(pszDescription)/sizeof(pszDescription[0]), NULL );
|
|
if( iCharsLoaded )
|
|
{
|
|
sd.lpDescription = pszDescription;
|
|
pChangeServiceConfig2( hService,
|
|
SERVICE_CONFIG_DESCRIPTION,
|
|
&sd);
|
|
}
|
|
}
|
|
FreeLibrary( hDll );
|
|
}
|
|
}
|
|
|
|
// Add parameters subkey
|
|
{
|
|
strcpy(szKey, "SYSTEM\\CurrentControlSet\\Services\\");
|
|
strcat(szKey, SERVICE_NAME);
|
|
strcat(szKey, "\\Parameters");
|
|
hr = ::RegCreateKey(HKEY_LOCAL_MACHINE, szKey, &hKey);
|
|
if( hr != ERROR_SUCCESS)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
goto Error;
|
|
}
|
|
|
|
// Add the Event ID message-file name to the 'EventMessageFile' subkey.
|
|
hr = ::RegSetValueEx(hKey,
|
|
"ServiceDll",
|
|
0,
|
|
REG_EXPAND_SZ,
|
|
(CONST BYTE*)szFilePath,
|
|
strlen(szFilePath) + 1);
|
|
if( hr != ERROR_SUCCESS)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
::RegCloseKey(hKey);
|
|
goto Error;
|
|
}
|
|
::RegCloseKey(hKey);
|
|
}
|
|
|
|
|
|
hr = AddToSvcHostGroup();
|
|
if( FAILED(hr) ) goto Error;
|
|
|
|
// make registry entries to support logging messages
|
|
// Add the source name as a subkey under the Application
|
|
// key in the EventLog service portion of the registry.
|
|
{
|
|
strcpy(szKey, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\");
|
|
strcat(szKey, SERVICE_NAME);
|
|
hr = ::RegCreateKey(HKEY_LOCAL_MACHINE, szKey, &hKey);
|
|
if( hr != ERROR_SUCCESS)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
goto Error;
|
|
}
|
|
|
|
// Add the Event ID message-file name to the 'EventMessageFile' subkey.
|
|
hr = ::RegSetValueEx(hKey,
|
|
"EventMessageFile",
|
|
0,
|
|
REG_EXPAND_SZ,
|
|
(CONST BYTE*)szFilePath,
|
|
strlen(szFilePath) + 1);
|
|
if( hr != ERROR_SUCCESS)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
::RegCloseKey(hKey);
|
|
goto Error;
|
|
}
|
|
|
|
// Set the supported types flags.
|
|
DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
|
|
hr = ::RegSetValueEx(hKey,
|
|
"TypesSupported",
|
|
0,
|
|
REG_DWORD,
|
|
(CONST BYTE*)&dwData,
|
|
sizeof(DWORD));
|
|
if( hr != ERROR_SUCCESS)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
::RegCloseKey(hKey);
|
|
goto Error;
|
|
}
|
|
::RegCloseKey(hKey);
|
|
}
|
|
|
|
#if 0
|
|
// Start service
|
|
{
|
|
SERVICE_STATUS ServiceStatus;
|
|
|
|
if( !QueryServiceStatus( hService, &ServiceStatus ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Error;
|
|
}
|
|
|
|
if( ServiceStatus.dwCurrentState != SERVICE_RUNNING )
|
|
{
|
|
// start the service
|
|
BOOL bStarted;
|
|
bStarted = StartService(hService, 0, NULL);
|
|
if( !bStarted )
|
|
{
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
// The service can not be started if it just was added to the svchost group.
|
|
// The svchost needs to be restarted first.
|
|
// (The svchost only reads it's service array at startup)
|
|
if( hr == HRESULT_FROM_WIN32(ERROR_SERVICE_NOT_IN_EXE) )
|
|
{
|
|
// This error code will be handled by the installer
|
|
hr = NS_S_REBOOT_REQUIRED; // 0x000D2AF9L
|
|
}
|
|
goto Error;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
CNTService::LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_INSTALLED, SERVICE_NAME);
|
|
hr = S_OK;
|
|
|
|
Error:
|
|
if( hService ) ::CloseServiceHandle(hService);
|
|
if( hSCM ) ::CloseServiceHandle(hSCM);
|
|
|
|
//
|
|
// Check: should we return here NS_S_REBOOT_REQUIRED, if the service is installed.
|
|
return hr;
|
|
}
|
|
|
|
// Stop and Uninstall service
|
|
STDAPI DllUnregisterServer(void)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
char szKey[256];
|
|
HKEY hKey = NULL;
|
|
SC_HANDLE hSCM = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
|
|
DEBUG_STOP
|
|
|
|
// Not installed ?
|
|
if( !CNTService::IsInstalled() )
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
// Open the Service Control Manager
|
|
hSCM = ::OpenSCManager( NULL, // local machine
|
|
NULL, // ServicesActive database
|
|
SC_MANAGER_ALL_ACCESS); // full access
|
|
if (!hSCM)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Error;
|
|
}
|
|
|
|
hService = ::OpenService( hSCM,
|
|
SERVICE_NAME,
|
|
SERVICE_ALL_ACCESS);
|
|
|
|
// Remove service
|
|
if (hService)
|
|
{
|
|
// Stop service
|
|
{
|
|
SERVICE_STATUS ServiceStatus;
|
|
|
|
if( !QueryServiceStatus( hService, &ServiceStatus ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Error;
|
|
}
|
|
|
|
if( ServiceStatus.dwCurrentState != SERVICE_STOPPED )
|
|
{
|
|
// start the service
|
|
SERVICE_STATUS ss;
|
|
BOOL bStopped;
|
|
|
|
bStopped = ControlService( hService,
|
|
SERVICE_CONTROL_STOP,
|
|
&ss);
|
|
if( !bStopped )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Error;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (::DeleteService(hService))
|
|
{
|
|
CNTService::LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_REMOVED, SERVICE_NAME);
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
CNTService::LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_NOTREMOVED, SERVICE_NAME);
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
// Do not delete eventlog related registry keys unless the service has been deleted
|
|
goto Error;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Error;
|
|
}
|
|
|
|
// Delete EventLog entry in registry
|
|
strcpy(szKey, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\");
|
|
strcat(szKey, SERVICE_NAME);
|
|
RegDeleteKey( HKEY_LOCAL_MACHINE, szKey );
|
|
|
|
Error:
|
|
if(hSCM) ::CloseServiceHandle(hSCM);
|
|
if(hService) ::CloseServiceHandle(hService);
|
|
|
|
return hr;
|
|
}
|
|
|
|
// Add entry to the right svchost group, (netsvcs)
|
|
HRESULT AddToSvcHostGroup()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwOrgSize;
|
|
DWORD dwDestSize;
|
|
long lResult;
|
|
DWORD dwStrIndex;
|
|
DWORD dwType;
|
|
HKEY hKey = NULL;
|
|
WCHAR* pwszStringOrg = NULL;
|
|
WCHAR* pwszStringDest = NULL;
|
|
|
|
DEBUG_STOP
|
|
|
|
lResult = RegCreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost", &hKey);
|
|
if( lResult != ERROR_SUCCESS )
|
|
{
|
|
hr = E_FAIL;
|
|
goto Error;
|
|
}
|
|
lResult = RegQueryValueExW( hKey,
|
|
SVCHOST_SUBKEYW, // subkey name
|
|
NULL,
|
|
&dwType,
|
|
NULL, // string buffer
|
|
&dwOrgSize ); // size of returned string
|
|
if( lResult != ERROR_SUCCESS )
|
|
{
|
|
hr = E_FAIL;
|
|
goto Error;
|
|
}
|
|
if (dwType != REG_SZ && dwType != REG_MULTI_SZ && dwType != REG_EXPAND_SZ)
|
|
{
|
|
hr = E_FAIL;
|
|
goto Error;
|
|
}
|
|
|
|
dwDestSize = dwOrgSize + (wcslen( SERVICE_NAMEW ) +1)*sizeof(WCHAR);
|
|
pwszStringOrg = (WCHAR*)new BYTE[dwOrgSize];
|
|
pwszStringDest = (WCHAR*)new BYTE[dwDestSize];
|
|
|
|
if( pwszStringOrg == NULL || pwszStringDest == NULL )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Error;
|
|
}
|
|
lResult = RegQueryValueExW( hKey,
|
|
SVCHOST_SUBKEYW, // subkey name
|
|
NULL,
|
|
&dwType,
|
|
(BYTE*)pwszStringOrg, // string buffer
|
|
&dwOrgSize ); // size of returned string
|
|
if( lResult != ERROR_SUCCESS )
|
|
{
|
|
hr = E_FAIL;
|
|
goto Error;
|
|
}
|
|
if (dwType != REG_SZ && dwType != REG_MULTI_SZ && dwType != REG_EXPAND_SZ)
|
|
{
|
|
hr = E_FAIL;
|
|
goto Error;
|
|
}
|
|
|
|
// Copy the org string to the dest, check to see if our string is already there
|
|
memset( pwszStringDest, 0, dwDestSize );
|
|
for( dwStrIndex = 0;
|
|
(dwStrIndex*sizeof(WCHAR) < dwOrgSize) && ((pwszStringOrg)[dwStrIndex] != '\0');
|
|
dwStrIndex += wcslen( &((WCHAR*)pwszStringOrg)[dwStrIndex] ) +1 )
|
|
{
|
|
// Check this string in the [array] of strings
|
|
if( wcscmp( &((WCHAR*)pwszStringOrg)[dwStrIndex], SERVICE_NAMEW ) == 0 )
|
|
{
|
|
hr = S_OK; // String already added
|
|
goto Error;
|
|
}
|
|
wcscpy( &pwszStringDest[dwStrIndex], &pwszStringOrg[dwStrIndex] );
|
|
}
|
|
|
|
|
|
// Add this new string to the array of strings. Terminate the array with two '\0' chars
|
|
wcscpy( &pwszStringDest[dwStrIndex], SERVICE_NAMEW );
|
|
dwStrIndex += wcslen( SERVICE_NAMEW ) + 1;
|
|
|
|
dwDestSize = (dwStrIndex +1)* sizeof(WCHAR); // Add space for terminating extra '\0'
|
|
|
|
lResult = RegSetValueExW(hKey,
|
|
SVCHOST_SUBKEYW, // subkey name
|
|
NULL,
|
|
dwType,
|
|
(BYTE*)pwszStringDest, // string buffer
|
|
dwDestSize ); // size of returned string
|
|
|
|
Error:
|
|
if( pwszStringOrg ) delete [] pwszStringOrg;
|
|
if( pwszStringDest ) delete [] pwszStringDest;
|
|
if( hKey ) RegCloseKey(hKey);
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Stop and Uninstall the old .exe service
|
|
BOOL UnregisterOldServer( SC_HANDLE hSCM )
|
|
{
|
|
char szKey[256];
|
|
BOOL bRet = TRUE;
|
|
SC_HANDLE hServiceOld;
|
|
SERVICE_STATUS ss;
|
|
|
|
if( !hSCM ) return FALSE;
|
|
|
|
hServiceOld = OpenService( hSCM,
|
|
SERVICE_OLD_NAME,
|
|
SERVICE_ALL_ACCESS);
|
|
|
|
// Could not find the old service
|
|
if( !hServiceOld )
|
|
{
|
|
bRet = FALSE;
|
|
goto Error;
|
|
}
|
|
|
|
// stop the service
|
|
bRet = ControlService(hServiceOld,
|
|
SERVICE_CONTROL_STOP,
|
|
&ss);
|
|
|
|
// Delete the service
|
|
if ( !::DeleteService(hServiceOld))
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
|
|
// Delete old EventLog entry in registry
|
|
strcpy(szKey, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\");
|
|
strcat(szKey, SERVICE_OLD_NAME);
|
|
RegDeleteKey( HKEY_LOCAL_MACHINE, szKey );
|
|
|
|
Error:
|
|
if(hServiceOld) CloseServiceHandle(hServiceOld);
|
|
return bRet;
|
|
}
|