Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1245 lines
46 KiB

////////////////////////////////////////////////////////////////////////
//
// 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;
}