|
|
////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1997-2001 Microsoft Corporation, All rights reserved
//
// Module: regcode.cpp
//
// Implements the Service registration routines
//
// History:
//
// ivanbrug 17-09-2000 CreateF
//
//
//
////////////////////////////////////////////////////////////////////////
#include "precomp.h"
#include <winmgmt.h>
#include <strings.h> // for LoadString
#include <malloc.h>
#include <winntsec.h>
#include <autoptr.h>
#include <strutils.h>
#define SVCHOST_HOME TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\SvcHost")
#define SERVICE_PATH TEXT("System\\CurrentControlSet\\Services\\")
#define DLL_PATH TEXT("%SystemRoot%\\system32\\wbem\\WMIsvc.dll")
#define ENTRY_POINT TEXT("ServiceMain")
#define COM_APPID TEXT("Software\\classes\\AppID\\{8BC3F05E-D86B-11D0-A075-00C04FB68820}")
//= Windows Management Instrumentation
//LocalService = WinMgmt
#define COM_APPID_NAME TEXT("Software\\classes\\AppID\\winmgmt")
//AppID = {8BC3F05E-D86B-11D0-A075-00C04FB68820}
#define SERVICE_CLSID TEXT("{8BC3F05E-D86B-11D0-A075-00C04FB68820}")
#define SERVICE_NAME_GROUP_ALONE TEXT("winmgmt")
#define SERVICE_NAME_GROUP TEXT("netsvcs")
#define SERVICE_NAME_GROUP_TOGETHER TEXT("netsvcs")
// see winmgmt.h
//#define SERVICE_NAME TEXT("winmgmt")
#define VALUE_AUTH TEXT("AuthenticationCapabilities")
#define VALUE_COINIT TEXT("CoInitializeSecurityParam")
#define VALUE_AUTZN TEXT("AuthenticationLevel")
#define VALUE_IMPER TEXT("ImpersonationLevel")
#define ACCOUNT_NAME TEXT("LocalService") // unused, for now
#define DISPLAY_CLSID TEXT("Windows Management and Instrumentation")
#define DISPLAY_BACKUP_CLSID TEXT("Windows Management Instrumentation Backup and Recovery")
//
// for the Description string
//
#define MAX_BUFF 2048
//
// this is the rundll32 interface
// usage is
// C:\>rundll32 %windir%\system32\wbem\wmisvc.dll,MoveToAlone X
// where X is the AuthenticationLevel
//
//////////////////////////////////////////////////////////////////
void CALLBACK MoveToAlone(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) //RPC_C_AUTHN_LEVEL_CONNECT
{ BOOL bRet = TRUE; LONG lRet;
DWORD dwLevel = RPC_C_AUTHN_LEVEL_CONNECT; if (lpszCmdLine) { dwLevel = atoi(lpszCmdLine); if (0 == dwLevel) // in case of error
{ dwLevel = RPC_C_AUTHN_LEVEL_CONNECT; } }
if (bRet) { // create the new group key under svchost
HKEY hKey; lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SVCHOST_HOME, 0, KEY_ALL_ACCESS, &hKey); if (ERROR_SUCCESS == lRet) { OnDelete<HKEY,LONG(*)(HKEY),RegCloseKey> cm(hKey); // add the group
LONG lRet2; DWORD dwCurrSize = 0; DWORD dwType; lRet2 = RegQueryValueEx(hKey,SERVICE_NAME_GROUP_ALONE,0,&dwType,NULL,&dwCurrSize); if (ERROR_SUCCESS == lRet2) { // the key is there, append to the multistring
BYTE * pMulti = new BYTE[(dwCurrSize+sizeof(SERVICE_NAME)+4)]; wmilib::auto_buffer<BYTE> rm_(pMulti); if (pMulti) { lRet2 = RegQueryValueEx(hKey,SERVICE_NAME_GROUP_ALONE,0,&dwType,pMulti,&dwCurrSize); if (ERROR_SUCCESS == lRet2 && REG_MULTI_SZ == dwType) { TCHAR * pInsertPoint = (TCHAR *)(pMulti+dwCurrSize-sizeof(TCHAR)); // verify the multisz
TCHAR *pEnd = (TCHAR *)pMulti; BOOL bIsThere = FALSE;
while (*pEnd) { if (0 == wbem_wcsicmp(pEnd,SERVICE_NAME)) { bIsThere = TRUE; } while (*pEnd){ pEnd++; } pEnd++; // past the zero who terminates the string
} if (!bIsThere) { if ((ULONG_PTR)pEnd == (ULONG_PTR)pInsertPoint) { wcsncpy(pEnd,SERVICE_NAME TEXT("\0"),sizeof(SERVICE_NAME)/sizeof(TCHAR)+1); DWORD dwNowSize = dwCurrSize+sizeof(SERVICE_NAME); if (ERROR_SUCCESS == RegSetValueEx(hKey,SERVICE_NAME_GROUP_ALONE,0,REG_MULTI_SZ,pMulti,dwNowSize)) bRet = TRUE; else bRet = FALSE; } else { bRet = FALSE; } } } } } else if (ERROR_FILE_NOT_FOUND == lRet2) { BYTE * pMulti = (BYTE *)SERVICE_NAME_GROUP_ALONE TEXT("\0"); LONG lResInner = RegSetValueEx(hKey,SERVICE_NAME_GROUP_ALONE,0,REG_MULTI_SZ,pMulti,sizeof(SERVICE_NAME_GROUP)+sizeof(TEXT(""))); bRet = (ERROR_SUCCESS == lResInner)?TRUE:FALSE; } else { bRet = FALSE; }
// create the key with the COM init Param
if (bRet) { HKEY hKey2; DWORD dwDisposistion; lRet = RegCreateKeyEx(hKey, SERVICE_NAME_GROUP_ALONE, 0,NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey2, &dwDisposistion); if (ERROR_SUCCESS == lRet) { OnDelete<HKEY,LONG(*)(HKEY),RegCloseKey> cm2(hKey2); // any value non NULL will work
DWORD dwVal = 1; RegSetValueEx(hKey2,VALUE_COINIT,0,REG_DWORD,(BYTE *)&dwVal,sizeof(DWORD)); // from packet to connect
dwVal = dwLevel; //RPC_C_AUTHN_LEVEL_CONNECT;
RegSetValueEx(hKey2,VALUE_AUTZN,0,REG_DWORD,(BYTE *)&dwVal,sizeof(DWORD));
dwVal = RPC_C_IMP_LEVEL_IDENTIFY; RegSetValueEx(hKey2,VALUE_IMPER,0,REG_DWORD,(BYTE *)&dwVal,sizeof(DWORD));
dwVal = EOAC_DISABLE_AAA | EOAC_NO_CUSTOM_MARSHAL | EOAC_STATIC_CLOAKING ; RegSetValueEx(hKey2,VALUE_AUTH,0,REG_DWORD,(BYTE *)&dwVal,sizeof(DWORD));
bRet = TRUE; } else { bRet = FALSE; } } } else { // no svchost key
bRet = FALSE; } }
if (bRet) { SC_HANDLE scHandle = OpenSCManager(NULL,SERVICES_ACTIVE_DATABASE,SC_MANAGER_ALL_ACCESS); if (scHandle) { OnDelete<SC_HANDLE,BOOL(*)(SC_HANDLE),CloseServiceHandle> cm1(scHandle); SC_HANDLE scService = OpenService(scHandle,SERVICE_NAME,SERVICE_ALL_ACCESS); if (scService) { OnDelete<SC_HANDLE,BOOL(*)(SC_HANDLE),CloseServiceHandle> cm2(scService); DWORD dwNeeded = 0; bRet = QueryServiceConfig(scService,NULL,0,&dwNeeded); if (!bRet && (ERROR_INSUFFICIENT_BUFFER == GetLastError())) { BYTE * pByte = new BYTE[dwNeeded]; wmilib::auto_buffer<BYTE> rm_(pByte); QUERY_SERVICE_CONFIG* pConfig = (QUERY_SERVICE_CONFIG *)pByte; if (pConfig) { bRet = QueryServiceConfig(scService,pConfig,dwNeeded,&dwNeeded); if (bRet) { TCHAR BinPath[MAX_PATH]; StringCchPrintf(BinPath,MAX_PATH,TEXT("%%systemroot%%\\system32\\svchost.exe -k %s"),SERVICE_NAME_GROUP_ALONE);
bRet = ChangeServiceConfig(scService, pConfig->dwServiceType, pConfig->dwStartType, pConfig->dwErrorControl, BinPath, pConfig->lpLoadOrderGroup, NULL, //&pConfig->dwTagId,
pConfig->lpDependencies, pConfig->lpServiceStartName, NULL, pConfig->lpDisplayName); if (!bRet) { DBG_PRINTFA((pBuff,"ChangeServiceConfig %d\n",GetLastError())); } } } else { bRet = FALSE; } } else { bRet = FALSE; } } else { // the service was not there or other error
DBG_PRINTFA((pBuff,"MoveToStandalone OpenService %d\n",GetLastError())); bRet = FALSE; } } else { DBG_PRINTFA((pBuff,"MoveToStandalone OpenSCManager %d\n",GetLastError())); bRet = FALSE; } }
if (bRet) { //
// remove the winmgmt string from the multi-sz of netsvcs
//
HKEY hKey; lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SVCHOST_HOME, 0, KEY_ALL_ACCESS, &hKey); if (ERROR_SUCCESS == lRet) { OnDelete<HKEY,LONG(*)(HKEY),RegCloseKey> cm3(hKey); // add the group
LONG lRet2; DWORD dwCurrSize = 0; DWORD dwType; lRet2 = RegQueryValueEx(hKey,SERVICE_NAME_GROUP_TOGETHER,0,&dwType,NULL,&dwCurrSize); if (ERROR_SUCCESS == lRet2) { // the key is there, append to the multistring
BYTE * pMulti = new BYTE[dwCurrSize+4]; wmilib::auto_buffer<BYTE> rm1_(pMulti); BYTE * pMultiNew = new BYTE[dwCurrSize+4]; wmilib::auto_buffer<BYTE> rm2_(pMultiNew); TCHAR * pMultiNewCopy = (TCHAR *)pMultiNew;
if (pMulti && pMultiNew) { lRet2 = RegQueryValueEx(hKey,SERVICE_NAME_GROUP_TOGETHER,0,&dwType,pMulti,&dwCurrSize); if (ERROR_SUCCESS == lRet2 && REG_MULTI_SZ == dwType) { // verify the multisz
TCHAR *pEnd = (TCHAR *)pMulti; BOOL bIsThere = FALSE;
while (*pEnd) { if (0 == wbem_wcsicmp(pEnd,SERVICE_NAME)) { bIsThere = TRUE; while (*pEnd){ pEnd++; } pEnd++; // past the zero who terminates the string
} else // copy
{ while (*pEnd){ *pMultiNewCopy++ = *pEnd++; } pEnd++; // past the zero who terminates the string
*pMultiNewCopy++ = 0; } } *pMultiNewCopy++ = 0; // put the double terminator
if (bIsThere) { DWORD dwNowSize = dwCurrSize-sizeof(SERVICE_NAME); RegSetValueEx(hKey,SERVICE_NAME_GROUP_TOGETHER,0,REG_MULTI_SZ,pMultiNew,dwNowSize); } } else { bRet = FALSE; } } else { bRet = FALSE; } } else { //
// the netsvcs multi sz MUST be there !!!!
//
bRet = TRUE; }
} else { bRet = FALSE; } }
return; }
//
//
// this is the rundll32 interface
//
//
//////////////////////////////////////////////////////////////////
void CALLBACK MoveToShared(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) //RPC_C_AUTHN_LEVEL_CONNECT
{ //
BOOL bRet = TRUE; LONG lRet;
DWORD dwLevel = RPC_C_PROTECT_LEVEL_PKT; if (lpszCmdLine) { dwLevel = atoi(lpszCmdLine); if (0 == dwLevel) // in case of error
{ dwLevel = RPC_C_PROTECT_LEVEL_PKT; } }
// create the new group key under svchost
if (bRet) { HKEY hKey; lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SVCHOST_HOME, 0, KEY_ALL_ACCESS, &hKey); if (ERROR_SUCCESS == lRet) { OnDelete<HKEY,LONG(*)(HKEY),RegCloseKey> cm(hKey); // add the group
LONG lRet2; DWORD dwCurrSize = 0; DWORD dwType; lRet2 = RegQueryValueEx(hKey,SERVICE_NAME_GROUP_TOGETHER,0,&dwType,NULL,&dwCurrSize); if (ERROR_SUCCESS == lRet2) { // the key is there, append to the multistring
BYTE * pMulti = new BYTE[(dwCurrSize+sizeof(SERVICE_NAME)+4)]; wmilib::auto_buffer<BYTE> rm_(pMulti); if (pMulti) { lRet2 = RegQueryValueEx(hKey,SERVICE_NAME_GROUP_TOGETHER,0,&dwType,pMulti,&dwCurrSize); if (ERROR_SUCCESS == lRet2 && REG_MULTI_SZ == dwType) { TCHAR * pInsertPoint = (TCHAR *)(pMulti+dwCurrSize-sizeof(TCHAR)); // verify the multisz
TCHAR *pEnd = (TCHAR *)pMulti; BOOL bIsThere = FALSE;
while (*pEnd) { if (0 == wbem_wcsicmp(pEnd,SERVICE_NAME)) { bIsThere = TRUE; } while (*pEnd){ pEnd++; } pEnd++; // past the zero who terminates the string
} if (!bIsThere) { if ((ULONG_PTR)pEnd == (ULONG_PTR)pInsertPoint) { wcsncpy(pEnd,SERVICE_NAME TEXT("\0"),sizeof(SERVICE_NAME)/sizeof(TCHAR)+1); DWORD dwNowSize = dwCurrSize+sizeof(SERVICE_NAME); RegSetValueEx(hKey,SERVICE_NAME_GROUP_TOGETHER,0,REG_MULTI_SZ,pMulti,dwNowSize); } else { bRet = FALSE; DBG_PRINTFA((pBuff,"Malformed REG_MULTI_SZ under %S\n",SERVICE_NAME_GROUP_TOGETHER)); } } } else { // invalid type in reg_multi_sz
bRet = FALSE; } } else { bRet = FALSE; } } else if (ERROR_FILE_NOT_FOUND == lRet2) { BYTE * pMulti = (BYTE *)SERVICE_NAME_GROUP_TOGETHER TEXT("\0"); RegSetValueEx(hKey,SERVICE_NAME_GROUP_TOGETHER,0,REG_MULTI_SZ,pMulti,sizeof(SERVICE_NAME_GROUP)+sizeof(TEXT(""))); } else { bRet = FALSE; }
HKEY hKey2; DWORD dwDisposistion; lRet = RegCreateKeyEx(hKey, SERVICE_NAME_GROUP_TOGETHER, 0,NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey2, &dwDisposistion); if (ERROR_SUCCESS == lRet) { OnDelete<HKEY,LONG(*)(HKEY),RegCloseKey> cm2(hKey2); // any value non NULL will work
DWORD dwVal = 1; RegSetValueEx(hKey2,VALUE_COINIT,0,REG_DWORD,(BYTE *)&dwVal,sizeof(DWORD)); // from packet to connect
dwVal = dwLevel; //RPC_C_AUTHN_LEVEL_CONNECT;
RegSetValueEx(hKey2,VALUE_AUTZN,0,REG_DWORD,(BYTE *)&dwVal,sizeof(DWORD));
dwVal = RPC_C_IMP_LEVEL_IDENTIFY; RegSetValueEx(hKey2,VALUE_IMPER,0,REG_DWORD,(BYTE *)&dwVal,sizeof(DWORD));
dwVal = EOAC_DISABLE_AAA | EOAC_NO_CUSTOM_MARSHAL | EOAC_STATIC_CLOAKING ; RegSetValueEx(hKey2,VALUE_AUTH,0,REG_DWORD,(BYTE *)&dwVal,sizeof(DWORD)); bRet = TRUE; } else { DBG_PRINTFA((pBuff,"Could not create %S\n",SERVICE_NAME_GROUP_TOGETHER)); bRet = FALSE; } } else { bRet = FALSE; } }
//
// changes the SCM database
//
if (bRet) { SC_HANDLE scHandle = OpenSCManager(NULL,SERVICES_ACTIVE_DATABASE,SC_MANAGER_ALL_ACCESS);
if (scHandle) { OnDelete<SC_HANDLE,BOOL(*)(SC_HANDLE),CloseServiceHandle> cm1(scHandle);
SC_HANDLE scService = OpenService(scHandle,SERVICE_NAME,SERVICE_ALL_ACCESS); if (scService) { OnDelete<SC_HANDLE,BOOL(*)(SC_HANDLE),CloseServiceHandle> cm2(scService);
DWORD dwNeeded = 0; bRet = QueryServiceConfig(scService,NULL,0,&dwNeeded); if (!bRet && (ERROR_INSUFFICIENT_BUFFER == GetLastError())) { BYTE * pByte = new BYTE[dwNeeded]; wmilib::auto_buffer<BYTE> rm1_(pByte); QUERY_SERVICE_CONFIG* pConfig = (QUERY_SERVICE_CONFIG *)pByte; if (pConfig) { bRet = QueryServiceConfig(scService,pConfig,dwNeeded,&dwNeeded); if (bRet) { TCHAR BinPath[MAX_PATH]; StringCchPrintf(BinPath,MAX_PATH,TEXT("%%systemroot%%\\system32\\svchost.exe -k %s"),SERVICE_NAME_GROUP_TOGETHER);
bRet = ChangeServiceConfig(scService, pConfig->dwServiceType, pConfig->dwStartType, pConfig->dwErrorControl, BinPath, pConfig->lpLoadOrderGroup, NULL, //&pConfig->dwTagId,
pConfig->lpDependencies, pConfig->lpServiceStartName, NULL, pConfig->lpDisplayName); if (!bRet) { DBG_PRINTFA((pBuff,"ChangeServiceConfig %d\n",GetLastError())); } } } else { bRet = FALSE; } } else { bRet = FALSE; } } else { // the service was not there or other error
DBG_PRINTFA((pBuff,"MoveToShared OpenService %d\n",GetLastError())); bRet = FALSE; } } else { DBG_PRINTFA((pBuff,"MoveToShared OpenSCManager %d\n",GetLastError())); bRet = FALSE; } }
if (bRet) { //
// remove the winmgmt string from the multi-sz of winmgmt
//
HKEY hKey; lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SVCHOST_HOME, 0, KEY_ALL_ACCESS, &hKey); if (ERROR_SUCCESS == lRet) { OnDelete<HKEY,LONG(*)(HKEY),RegCloseKey> cm3(hKey); // add the group
LONG lRet2; DWORD dwCurrSize; DWORD dwType; lRet2 = RegQueryValueEx(hKey,SERVICE_NAME_GROUP_ALONE,0,&dwType,NULL,&dwCurrSize); if (ERROR_SUCCESS == lRet2) { // the key is there, append to the multistring
BYTE * pMulti = new BYTE[dwCurrSize+4]; wmilib::auto_buffer<BYTE> rm2_(pMulti); BYTE * pMultiNew = new BYTE[dwCurrSize+4]; wmilib::auto_buffer<BYTE> rm3_(pMultiNew); TCHAR * pMultiNewCopy = (TCHAR *)pMultiNew;
if (pMulti && pMultiNew) { lRet2 = RegQueryValueEx(hKey,SERVICE_NAME_GROUP_ALONE,0,&dwType,pMulti,&dwCurrSize); if (ERROR_SUCCESS == lRet2 && REG_MULTI_SZ == dwType) { // verify the multisz
TCHAR *pEnd = (TCHAR *)pMulti; BOOL bIsThere = FALSE;
while (*pEnd) { if (0 == wbem_wcsicmp(pEnd,SERVICE_NAME)) { bIsThere = TRUE; while (*pEnd){ pEnd++; } pEnd++; // past the zero who terminates the string
} else // copy
{ while (*pEnd){ *pMultiNewCopy++ = *pEnd++; } pEnd++; // past the zero who terminates the string
*pMultiNewCopy++ = 0; } } *pMultiNewCopy++ = 0; // put the double terminator
if (bIsThere) { DWORD dwNowSize = dwCurrSize-sizeof(SERVICE_NAME); RegSetValueEx(hKey,SERVICE_NAME_GROUP_ALONE,0,REG_MULTI_SZ,pMultiNew,dwNowSize); } } else { bRet = FALSE; } } else { bRet = FALSE; } } else { //
// the winmgmt multi sz MUST can be NOT there
//
bRet = TRUE; } } else { bRet = FALSE; } }
}
//***************************************************************************
//
// void InitializeLaunchPermissions()
//
// DESCRIPTION:
//
// Sets the DCOM Launch permissions.
//
//***************************************************************************
void InitializeLaunchPermissions() {
Registry reg(__TEXT("SOFTWARE\\CLASSES\\APPID\\{8bc3f05e-d86b-11d0-a075-00c04fb68820}")); if(reg.GetLastError() != 0) return;
// If there already is a SD, then dont overwrite
BYTE * pData = NULL; DWORD dwDataSize = 0;
int iRet = reg.GetBinary(__TEXT("LaunchPermission"), &pData, &dwDataSize); if(iRet == 0) { delete [] pData; return; // it's already there
} PSID pEveryoneSid; SID_IDENTIFIER_AUTHORITY id_World = SECURITY_WORLD_SID_AUTHORITY;
if(!AllocateAndInitializeSid( &id_World, 1, SECURITY_WORLD_RID, 0,0,0,0,0,0,0, &pEveryoneSid)) return; OnDelete<PSID,PVOID(*)(PSID),FreeSid> freeSid1(pEveryoneSid);
SID_IDENTIFIER_AUTHORITY id_NT = SECURITY_NT_AUTHORITY; PSID pAdministratorsSid = NULL; if (!AllocateAndInitializeSid(&id_NT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdministratorsSid)) return; OnDelete<PSID,PVOID(*)(PSID),FreeSid> freeSid2(pAdministratorsSid); // Create the class sids for everyone and administrators
CNtSid SidEveryone(pEveryoneSid); CNtSid SidAdmins(pAdministratorsSid); if(SidEveryone.GetStatus() != 0 || SidAdmins.GetStatus() != 0) return;
// Create a single ACE, and add it to the ACL
CNtAcl DestAcl; CNtAce Users(1, ACCESS_ALLOWED_ACE_TYPE, 0, SidEveryone); if(Users.GetStatus() != 0) return; DestAcl.AddAce(&Users); if(DestAcl.GetStatus() != 0) return;
// Set the descresionary acl, and the owner and group sids
// Create a sd with a single entry for launch permissions.
CNtSecurityDescriptor LaunchPermSD; LaunchPermSD.SetDacl(&DestAcl); LaunchPermSD.SetOwner(&SidAdmins); LaunchPermSD.SetGroup(&SidAdmins); if(LaunchPermSD.GetStatus() != 0) return;
// Write it out
reg.SetBinary(__TEXT("LaunchPermission"), (BYTE *)LaunchPermSD.GetPtr(), LaunchPermSD.GetSize()); }
//***************************************************************************
//
// DllRegisterServer
//
// Standard OLE entry point for registering the COM server.
//
// RETURN VALUES:
//
// S_OK Registration was successful
// E_FAIL Registration failed.
//
//***************************************************************************
//
// Phase 1 : Create the MULTI_SZ under the svchost key (AKA, create a group of services)
// If the key is there, check if the WinMgmt service is already there, otherwise add it
// Phase 2 : Use the SCM Api in order to create the service if not there
// otherwise change the service configuration to some known value
// Phase 3 : Creates specific keys under the Services\WinMgmt key.
// cannot be done before, if the service is not already there
// Phase 4 : Expose this service as a COM server, creates CLSID, APPID and misc keys
//
STDAPI DllRegisterServer(void) { LONG lRet; BOOL bRet = TRUE;
//
// Phase 1
//
if (bRet) { HKEY hKey; lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SVCHOST_HOME, 0, KEY_ALL_ACCESS, &hKey); if (ERROR_SUCCESS == lRet) { OnDelete<HKEY,LONG(*)(HKEY),RegCloseKey> cm(hKey); // add the group
LONG lRet2; DWORD dwCurrSize = 0; DWORD dwType; lRet2 = RegQueryValueEx(hKey,SERVICE_NAME_GROUP,0,&dwType,NULL,&dwCurrSize); if (ERROR_SUCCESS == lRet2) { // the key is there, append to the multistring
BYTE * pMulti = new BYTE[(dwCurrSize+sizeof(SERVICE_NAME)+4)]; wmilib::auto_buffer<BYTE> rm4_(pMulti); if (pMulti) { lRet2 = RegQueryValueEx(hKey,SERVICE_NAME_GROUP,0,&dwType,pMulti,&dwCurrSize); if (ERROR_SUCCESS == lRet2 && REG_MULTI_SZ == dwType ) { TCHAR * pInsertPoint = (TCHAR *)(pMulti+dwCurrSize-sizeof(TCHAR)); // verify the multisz
TCHAR *pEnd = (TCHAR *)pMulti; BOOL bIsThere = FALSE;
while (*pEnd) { if (0 == wbem_wcsicmp(pEnd,SERVICE_NAME)) { bIsThere = TRUE; } while (*pEnd){ pEnd++; } pEnd++; // past the zero who terminates the string
} if (!bIsThere) { if ((ULONG_PTR)pEnd == (ULONG_PTR)pInsertPoint) { wcsncpy(pEnd,SERVICE_NAME TEXT("\0"),sizeof(SERVICE_NAME)/sizeof(TCHAR)+1); DWORD dwNowSize = dwCurrSize+sizeof(SERVICE_NAME); RegSetValueEx(hKey,SERVICE_NAME_GROUP,0,REG_MULTI_SZ,pMulti,dwNowSize); } else { bRet = FALSE; } } } else { bRet = FALSE; } } else { bRet = FALSE; } } else if (ERROR_FILE_NOT_FOUND == lRet2) { BYTE * pMulti = (BYTE *)SERVICE_NAME_GROUP TEXT("\0"); lRet = RegSetValueEx(hKey,SERVICE_NAME_GROUP,0,REG_MULTI_SZ,pMulti,sizeof(SERVICE_NAME_GROUP)+sizeof(TEXT(""))); bRet = (ERROR_SUCCESS == lRet)?TRUE:FALSE; } else { bRet = FALSE; }
HKEY hKey2; DWORD dwDisposistion; lRet = RegCreateKeyEx(hKey, SERVICE_NAME_GROUP, 0,NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey2, &dwDisposistion); if (ERROR_SUCCESS == lRet) { OnDelete<HKEY,LONG(*)(HKEY),RegCloseKey> cm2(hKey2); // any value non NULL will work
DWORD dwVal = 1; RegSetValueEx(hKey2,VALUE_COINIT,0,REG_DWORD,(BYTE *)&dwVal,sizeof(DWORD));
// servicehost default + static cloaking
dwVal = EOAC_DISABLE_AAA | EOAC_NO_CUSTOM_MARSHAL | EOAC_STATIC_CLOAKING ; RegSetValueEx(hKey2,VALUE_AUTH,0,REG_DWORD,(BYTE *)&dwVal,sizeof(DWORD)); bRet = TRUE; } else { bRet = FALSE; } } else { bRet = FALSE; } }
//
// Phase 2
//
if (bRet) { SC_HANDLE hSCM = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); if (hSCM) { OnDelete<SC_HANDLE,BOOL(*)(SC_HANDLE),CloseServiceHandle> cm1(hSCM);
DWORD dwTag; TCHAR BinPath[MAX_PATH]; StringCchPrintf(BinPath,MAX_PATH,TEXT("%%systemroot%%\\system32\\svchost.exe -k %s"),SERVICE_NAME_GROUP);
TCHAR * pServiceDisplay = new TCHAR[MAX_BUFF]; wmilib::auto_buffer<TCHAR> rm(pServiceDisplay); if (pServiceDisplay) { int nRet = LoadString(g_hInstance,ID_WINMGMT_SERVICE,pServiceDisplay,MAX_BUFF); } else { bRet = FALSE; }
SC_HANDLE hService = NULL; if (bRet) { hService = OpenService(hSCM,SERVICE_NAME,SERVICE_ALL_ACCESS ); } SC_ACTION ac[2]; ac[0].Type = SC_ACTION_RESTART; ac[0].Delay = 60000; ac[1].Type = SC_ACTION_RESTART; ac[1].Delay = 60000; SERVICE_FAILURE_ACTIONS sf; sf.dwResetPeriod = 86400; sf.lpRebootMsg = NULL; sf.lpCommand = NULL; sf.cActions = 2; sf.lpsaActions = ac; if (hService) { OnDelete<SC_HANDLE,BOOL(*)(SC_HANDLE),CloseServiceHandle> cm2(hService); bRet = ChangeServiceConfig(hService, SERVICE_WIN32_SHARE_PROCESS, SERVICE_AUTO_START, //SERVICE_DEMAND_START,
SERVICE_ERROR_IGNORE, BinPath, NULL, NULL, TEXT("RPCSS\0Eventlog\0\0\0"), NULL, //ACCOUNT_NAME,
NULL, pServiceDisplay); if (bRet) { ChangeServiceConfig2(hService, SERVICE_CONFIG_FAILURE_ACTIONS, &sf); //
// insert code for description here
TCHAR * pBuff = new TCHAR[MAX_BUFF]; if (pBuff) { int nRet = LoadString(g_hInstance,ID_WINMGMT_DESCRIPTION,pBuff,MAX_BUFF); if (nRet) { SERVICE_DESCRIPTION sd; sd.lpDescription = pBuff; ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION,&sd); } delete [] pBuff; } //
//
} else { DBG_PRINTFA((pBuff,"ChangeServiceConfig %d\n",GetLastError())); } } else { // Create it
hService = CreateService(hSCM, SERVICE_NAME, pServiceDisplay, SERVICE_ALL_ACCESS, SERVICE_WIN32_SHARE_PROCESS, SERVICE_AUTO_START, //SERVICE_DEMAND_START,
SERVICE_ERROR_IGNORE, BinPath, NULL, NULL, TEXT("RPCSS\0Eventlog\0\0\0"), NULL, //ACCOUNT_NAME,
NULL); if (hService) { OnDelete<SC_HANDLE,BOOL(*)(SC_HANDLE),CloseServiceHandle> cm3(hService); ChangeServiceConfig2(hService, SERVICE_CONFIG_FAILURE_ACTIONS, &sf);
//
// insert code for description here
TCHAR * pBuff = new TCHAR[MAX_BUFF]; if (pBuff) { int nRet = LoadString(g_hInstance,ID_WINMGMT_DESCRIPTION,pBuff,MAX_BUFF); if (nRet) { SERVICE_DESCRIPTION sd; sd.lpDescription = pBuff; ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION,&sd); } delete [] pBuff; } bRet = TRUE; } else { bRet = FALSE; } } } else { bRet = FALSE; } }
//
// Phase 3
//
if (bRet) { HKEY hKey; lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SERVICE_PATH SERVICE_NAME, 0, KEY_ALL_ACCESS, &hKey); if (ERROR_SUCCESS == lRet) { OnDelete<HKEY,LONG(*)(HKEY),RegCloseKey> cm3(hKey); HKEY hKey3; DWORD dwDisposistion; lRet = RegCreateKeyEx(hKey, TEXT("Parameters"), 0,NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey3, &dwDisposistion); if (ERROR_SUCCESS == lRet) { RegSetValueEx(hKey3,TEXT("ServiceDll"),0,REG_EXPAND_SZ,(BYTE *)DLL_PATH,sizeof(DLL_PATH)-sizeof(TCHAR)); RegSetValueEx(hKey3,TEXT("ServiceMain"),0,REG_SZ,(BYTE *)ENTRY_POINT,sizeof(ENTRY_POINT)-sizeof(TCHAR));
RegCloseKey(hKey3);
bRet = TRUE; } else { bRet = FALSE; } } else { bRet = FALSE; } }
//
// Phase 4
//
if (bRet) { HKEY hKey4; DWORD dwDisposistion; lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, COM_APPID, 0,NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey4, &dwDisposistion); if (ERROR_SUCCESS == lRet) { RegSetValueEx(hKey4,NULL,0,REG_SZ,(BYTE *)DISPLAY_CLSID,sizeof(DISPLAY_CLSID)-sizeof(TCHAR)); RegSetValueEx(hKey4,TEXT("LocalService"),0,REG_SZ,(BYTE *)SERVICE_NAME,sizeof(SERVICE_NAME)-sizeof(TCHAR)); RegCloseKey(hKey4); }
lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, COM_APPID_NAME, 0,NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey4, &dwDisposistion); if (ERROR_SUCCESS == lRet) { RegSetValueEx(hKey4,TEXT("AppID"),0,REG_SZ,(BYTE *)SERVICE_CLSID,sizeof(SERVICE_CLSID)-sizeof(TCHAR)); RegCloseKey(hKey4); }
InitializeLaunchPermissions();
OLECHAR ClsidBuff[40]; TCHAR * ClsidBuff2; TCHAR ClsidPath[MAX_PATH]; StringFromGUID2(CLSID_WbemLevel1Login,ClsidBuff,40); #ifdef UNICODE
ClsidBuff2 = ClsidBuff; #else
TCHAR pTmp_[40]; ClsidBuff2 = pTmp_; WideCharToMultiByte(CP_ACP,0,ClsidBuff,-1,ClsidBuff2,40,NULL,NULL); #endif
StringCchPrintf(ClsidPath,MAX_PATH,TEXT("software\\classes\\CLSID\\%s"),ClsidBuff2); lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, ClsidPath, 0,NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey4, &dwDisposistion); if (ERROR_SUCCESS == lRet) { RegSetValueEx(hKey4,NULL,0,REG_SZ,(BYTE *)DISPLAY_CLSID,sizeof(DISPLAY_CLSID)-sizeof(TCHAR)); RegSetValueEx(hKey4,TEXT("AppId"),0,REG_SZ,(BYTE *)SERVICE_CLSID,sizeof(SERVICE_CLSID)-sizeof(TCHAR)); RegSetValueEx(hKey4,TEXT("LocalService"),0,REG_SZ,(BYTE *)SERVICE_NAME,sizeof(SERVICE_NAME)-sizeof(TCHAR)); RegCloseKey(hKey4); }
StringFromGUID2(CLSID_WbemBackupRestore,ClsidBuff,40); #ifdef UNICODE
ClsidBuff2 = ClsidBuff; #else
WideCharToMultiByte(CP_ACP,0,ClsidBuff,-1,ClsidBuff2,40,NULL,NULL); #endif
StringCchPrintf(ClsidPath,MAX_PATH,TEXT("software\\classes\\CLSID\\%s"),ClsidBuff); lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, ClsidPath, 0,NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey4, &dwDisposistion); if (ERROR_SUCCESS == lRet) { RegSetValueEx(hKey4,NULL,0,REG_SZ,(BYTE *)DISPLAY_BACKUP_CLSID,sizeof(DISPLAY_BACKUP_CLSID)-sizeof(TCHAR)); RegSetValueEx(hKey4,TEXT("AppId"),0,REG_SZ,(BYTE *)SERVICE_CLSID,sizeof(SERVICE_CLSID)-sizeof(TCHAR)); RegSetValueEx(hKey4,TEXT("LocalService"),0,REG_SZ,(BYTE *)SERVICE_NAME,sizeof(SERVICE_NAME)-sizeof(TCHAR)); RegCloseKey(hKey4); }
}
return S_OK; }
//***************************************************************************
//
// DllUnregisterServer
//
// Standard OLE entry point for unregistering the COM server.
//
// RETURN VALUES:
//
// S_OK Unregistration was successful
//
//***************************************************************************
STDAPI DllUnregisterServer(void) { LONG lRet; TCHAR ClsidBuff[40]; TCHAR ClsidPath[MAX_PATH];
#ifdef UNICODE
StringFromCLSID(CLSID_WbemLevel1Login,(LPOLESTR *)ClsidBuff); #else
WCHAR ClsidPath2[40]; StringFromCLSID(CLSID_WbemLevel1Login,(LPOLESTR *)ClsidBuff2); MultiByteToWideChar(CP_ACP,0,ClsidBuff2,-1,ClsidBuff,40); #endif
StringCchPrintf(ClsidPath,MAX_PATH,TEXT("software\\classes\\CLSID\\%s"),ClsidBuff); lRet = RegDeleteKey(HKEY_LOCAL_MACHINE,ClsidPath); if (ERROR_SUCCESS != lRet) return E_FAIL;
#ifdef UNICODE
StringFromCLSID(CLSID_WbemBackupRestore,(LPOLESTR *)ClsidBuff); #else
WCHAR ClsidPath2[40]; StringFromCLSID(CLSID_WbemBackupRestore,(LPOLESTR *)ClsidBuff2); MultiByteToWideChar(CP_ACP,0,ClsidBuff2,-1,ClsidBuff,40); #endif
StringCchPrintf(ClsidPath,MAX_PATH,TEXT("software\\classes\\CLSID\\%s"),ClsidBuff); lRet = RegDeleteKey(HKEY_LOCAL_MACHINE,ClsidPath); if (ERROR_SUCCESS != lRet) return E_FAIL;
lRet = RegDeleteKey(HKEY_LOCAL_MACHINE,COM_APPID); if (ERROR_SUCCESS != lRet) return E_FAIL; lRet = RegDeleteKey(HKEY_LOCAL_MACHINE,COM_APPID_NAME); if (ERROR_SUCCESS != lRet) return E_FAIL; return S_OK; }
|