////////////////////////////////////////////////////////////////////////
//
//  regcode.cpp
//
//	Module:	
//
//  History:
//	ivanbrug      17-09-2000		Create
//
//
//  Copyright (c) 1997-2001 Microsoft Corporation, All rights reserved
//
////////////////////////////////////////////////////////////////////////

#include "precomp.h"
#include <winmgmt.h>
#include <strings.h> // for LoadString
#include <malloc.h>
#include <winntsec.h>
#include <autoptr.h>
#include <helper.h>
#include <tchar.h>


#define SVCHOST_HOME  _T("Software\\Microsoft\\Windows NT\\CurrentVersion\\SvcHost") 
#define SERVICE_PATH  _T("System\\CurrentControlSet\\Services\\")
#define DLL_PATH      _T("%SystemRoot%\\system32\\wbem\\WMIsvc.dll")
#define ENTRY_POINT   _T("ServiceMain")

#define COM_APPID _T("Software\\classes\\AppID\\{8BC3F05E-D86B-11D0-A075-00C04FB68820}")
    //= Windows Management Instrumentation
    //LocalService = WinMgmt

#define COM_APPID_NAME _T("Software\\classes\\AppID\\winmgmt")
    //AppID = {8BC3F05E-D86B-11D0-A075-00C04FB68820}
    
#define SERVICE_CLSID _T("{8BC3F05E-D86B-11D0-A075-00C04FB68820}")


#define SERVICE_NAME_GROUP_ALONE _T("winmgmt")
#define SERVICE_NAME_GROUP _T("netsvcs")
#define SERVICE_NAME_GROUP_TOGETHER _T("netsvcs")


// see winmgmt.h
//#define SERVICE_NAME       _T("winmgmt")

#define VALUE_AUTH   _T("AuthenticationCapabilities")
#define VALUE_COINIT _T("CoInitializeSecurityParam")
#define VALUE_AUTZN  _T("AuthenticationLevel")
#define VALUE_IMPER  _T("ImpersonationLevel") 

#define ACCOUNT_NAME   _T("LocalService") // unused, for now
#define DISPLAY_CLSID        _T("Windows Management and Instrumentation")
#define DISPLAY_BACKUP_CLSID _T("Windows Management Instrumentation Backup and Recovery")

//
// how verbose can PMs be ?
//
#define MAX_BUFF 2048

//
//
// this is the rundll32 interface
//
//
//////////////////////////////////////////////////////////////////

void CALLBACK 
MoveToAlone(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) //RPC_C_AUTHN_LEVEL_CONNECT
{
    BOOL bRet = TRUE;
    LONG lRet;
    HKEY hKey;

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

    // create the new group key under svchost
	if (bRet)
	{
		lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
			                SVCHOST_HOME,
							0,
							KEY_ALL_ACCESS,
							&hKey);
		if (ERROR_SUCCESS == lRet)
		{
			
			// 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+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) // add REG_MULITSZ check
	                {
	                    TCHAR * pInsertPoint = (TCHAR *)(pMulti+dwCurrSize-sizeof(TCHAR));
	                    // verify the multisz  
	                    TCHAR *pEnd = (TCHAR *)pMulti;
	                    BOOL bIsThere = FALSE;

	                    while (*pEnd) 
	                    {
	                        if (0 == _tcsicmp(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)
		                    {
		                        _tcsncpy(pEnd,SERVICE_NAME _T("\0"),sizeof(SERVICE_NAME)/sizeof(TCHAR)+1);
		                        DWORD dwNowSize = dwCurrSize+sizeof(SERVICE_NAME);
		                        RegSetValueEx(hKey,SERVICE_NAME_GROUP_ALONE,0,REG_MULTI_SZ,pMulti,dwNowSize);
		                    }
		                    else
		                    {
		                        bRet = FALSE;
		                    }
	                    }
		            }
		        }
            }
            else if (ERROR_FILE_NOT_FOUND == lRet2) 
            {
				BYTE * pMulti = (BYTE *)SERVICE_NAME_GROUP_ALONE _T("\0");				
	            RegSetValueEx(hKey,SERVICE_NAME_GROUP_ALONE,0,REG_MULTI_SZ,pMulti,sizeof(SERVICE_NAME_GROUP)+sizeof(_T("")));            
            }
            else
            {
                // what to do ?
            }

			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)
			{
				// 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));

				RegCloseKey(hKey2);

				bRet = TRUE;
			}
		}
	}

    if (bRet)
    {
	    SC_HANDLE scHandle;

	    scHandle = OpenSCManager(NULL,SERVICES_ACTIVE_DATABASE,SC_MANAGER_ALL_ACCESS);

	    if (scHandle)
	    {
	        SC_HANDLE scService;

	        scService = OpenService(scHandle,SERVICE_NAME,SERVICE_ALL_ACCESS);

	        if (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];
	                		  wsprintf(BinPath,_T("%%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;
	                }
	            }
	            
	            CloseServiceHandle(scService);
	        }
	        else
	        {
	            // the service was not there or other error
    	        DBG_PRINTFA((pBuff,"MoveToStandalone OpenService %d\n",GetLastError()));	            
	            bRet = FALSE;
	        }

	        CloseServiceHandle(scHandle);
	    }
	    else
	    {
	        DBG_PRINTFA((pBuff,"MoveToStandalone OpenSCManager %d\n",GetLastError()));
	        bRet = FALSE;
	    }
    }

    if (bRet)
    {
    //
    //  remove the winmgmt string from the multi-sz of winmgmt
    //    

		lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
			                SVCHOST_HOME,
							0,
							KEY_ALL_ACCESS,
							&hKey);
		if (ERROR_SUCCESS == lRet)
		{
			
			// add the group

            LONG lRet2;
            DWORD dwCurrSize;
            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) // add REG_MULITSZ check
	                {
	                    
	                    // verify the multisz  
	                    TCHAR *pEnd = (TCHAR *)pMulti;
	                    BOOL bIsThere = FALSE;

	                    while (*pEnd) 
	                    {
	                        if (0 == _tcsicmp(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
            {
                //
                //  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;
    HKEY hKey;

    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)
	{
		lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
			                SVCHOST_HOME,
							0,
							KEY_ALL_ACCESS,
							&hKey);
		if (ERROR_SUCCESS == lRet)
		{
			
			// add the group

            LONG lRet2;
            DWORD dwCurrSize;
            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) // add REG_MULITSZ check
	                {
	                    TCHAR * pInsertPoint = (TCHAR *)(pMulti+dwCurrSize-sizeof(TCHAR));
	                    // verify the multisz  
	                    TCHAR *pEnd = (TCHAR *)pMulti;
	                    BOOL bIsThere = FALSE;

	                    while (*pEnd) 
	                    {
	                        if (0 == _tcsicmp(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)
		                    {
		                        _tcsncpy(pEnd,SERVICE_NAME _T("\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;
		                        DebugBreak();
		                    }
	                    }
	                }
	            }
	            else
	            {
    	            bRet = FALSE;
	            }
            }
            else if (ERROR_FILE_NOT_FOUND == lRet2) 
            {
				BYTE * pMulti = (BYTE *)SERVICE_NAME_GROUP_TOGETHER _T("\0");				
	            RegSetValueEx(hKey,SERVICE_NAME_GROUP_TOGETHER,0,REG_MULTI_SZ,pMulti,sizeof(SERVICE_NAME_GROUP)+sizeof(_T("")));            
            }
            else
            {
                // what to do ?
            }

			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)
			{
				// 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));

				RegCloseKey(hKey2);

				bRet = TRUE;
			}
			else
			{
			    DebugBreak();
			}
		}
	}

    //
    //  changes the SCM database
    //
    if (bRet)
    {
	    SC_HANDLE scHandle;

	    scHandle = OpenSCManager(NULL,SERVICES_ACTIVE_DATABASE,SC_MANAGER_ALL_ACCESS);

	    if (scHandle)
	    {
	        SC_HANDLE scService;

	        scService = OpenService(scHandle,SERVICE_NAME,SERVICE_ALL_ACCESS);

	        if (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];
	                		  wsprintf(BinPath,_T("%%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;
		            }
	            }
	            
	            CloseServiceHandle(scService);
	        }
	        else
	        {
	            // the service was not there or other error
    	        DBG_PRINTFA((pBuff,"MoveToShared OpenService %d\n",GetLastError()));	            
	            bRet = FALSE;
	        }

	        CloseServiceHandle(scHandle);
	    }
	    else
	    {
	        DBG_PRINTFA((pBuff,"MoveToStandalone OpenSCManager %d\n",GetLastError()));
	        bRet = FALSE;
	    }
    }


    if (bRet)
    {
    //
    //  remove the winmgmt string from the multi-sz of winmgmt
    //    

		lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
			                SVCHOST_HOME,
							0,
							KEY_ALL_ACCESS,
							&hKey);
		if (ERROR_SUCCESS == lRet)
		{
			
			// 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) // add REG_MULITSZ check
	                {
	                    
	                    // verify the multisz  
	                    TCHAR *pEnd = (TCHAR *)pMulti;
	                    BOOL bIsThere = FALSE;

	                    while (*pEnd) 
	                    {
	                        if (0 == _tcsicmp(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
            {
                //
                //  the netsvcs multi sz MUST be 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 server.
//
//  RETURN VALUES:
//
//      S_OK        Registration was successful
//      E_FAIL      Registration failed.
//
//***************************************************************************

STDAPI DllRegisterServer(void)
{

	// set the group

    HKEY hKey;
    LONG lRet;
    BOOL bRet = TRUE;

	if (bRet)
	{
		lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
			                SVCHOST_HOME,
							0,
							KEY_ALL_ACCESS,
							&hKey);
		if (ERROR_SUCCESS == lRet)
		{
			
			// add the group

            LONG lRet2;
            DWORD dwCurrSize;
            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) // add REG_MULITSZ check
	                {
	                    TCHAR * pInsertPoint = (TCHAR *)(pMulti+dwCurrSize-sizeof(TCHAR));
	                    // verify the multisz  
	                    TCHAR *pEnd = (TCHAR *)pMulti;
	                    BOOL bIsThere = FALSE;

	                    while (*pEnd) 
	                    {
	                        if (0 == _tcsicmp(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)
		                    {
		                        _tcsncpy(pEnd,SERVICE_NAME _T("\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
		                    {
		                        DebugBreak();
		                    }
	                    }
	                }
	            }
	            else
	            {
	                bRet = FALSE;
	            }
            }
            else if (ERROR_FILE_NOT_FOUND == lRet2) 
            {
				BYTE * pMulti = (BYTE *)SERVICE_NAME_GROUP _T("\0");				
	            RegSetValueEx(hKey,SERVICE_NAME_GROUP,0,REG_MULTI_SZ,pMulti,sizeof(SERVICE_NAME_GROUP)+sizeof(_T("")));            
            }
            else
            {
                // what to do ?
            }

			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)
			{
				// 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));
				
				RegCloseKey(hKey2);

				bRet = TRUE;
			}
		}
	}

	BOOL bCreated = FALSE;

	if (bRet)
	{
		SC_HANDLE hSCM = NULL;
        hSCM = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
		if (hSCM)
		{

			DWORD dwTag;
			TCHAR BinPath[MAX_PATH];
			
			wsprintf(BinPath,_T("%%systemroot%%\\system32\\svchost.exe -k %s"),SERVICE_NAME_GROUP);

			TCHAR * pServiceDisplay = new TCHAR[MAX_BUFF];
			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)
			{
				bRet = ChangeServiceConfig(hService,										 
                                         SERVICE_WIN32_SHARE_PROCESS,
										 SERVICE_AUTO_START, //SERVICE_DEMAND_START,
										 SERVICE_ERROR_IGNORE,
										 BinPath,
										 NULL,
										 NULL,
										 _T("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()));
                }

				CloseServiceHandle(hService);
			}
			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,
										 _T("RPCSS\0Eventlog\0\0\0"),
										 NULL, //ACCOUNT_NAME,
										 NULL);
				if (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;
			        }
				    //
				    //

				
					CloseServiceHandle(hService);
					bRet = TRUE;
				};
				
			}
			
			if (pServiceDisplay)
			{
			    delete [] pServiceDisplay;
			}
			CloseServiceHandle(hSCM);
		}
	}

	if (bRet)
	{
		lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
			                SERVICE_PATH SERVICE_NAME,
							0,
							KEY_ALL_ACCESS,
							&hKey);
		if (ERROR_SUCCESS == lRet)
		{
			HKEY hKey3;
			DWORD dwDisposistion;
			lRet = RegCreateKeyEx(hKey,
				                  _T("Parameters"),
								  0,NULL,
								  REG_OPTION_NON_VOLATILE,
								  KEY_ALL_ACCESS,
								  NULL,
								  &hKey3,
								  &dwDisposistion);
			if (ERROR_SUCCESS == lRet)
			{
				
				
				RegSetValueEx(hKey3,_T("ServiceDll"),0,REG_EXPAND_SZ,(BYTE *)DLL_PATH,sizeof(DLL_PATH)-sizeof(TCHAR));
				
                RegSetValueEx(hKey3,_T("ServiceMain"),0,REG_SZ,(BYTE *)ENTRY_POINT,sizeof(ENTRY_POINT)-sizeof(TCHAR));

				RegCloseKey(hKey3);

				bRet = TRUE;
			};

			RegCloseKey(hKey);
		}
	}

	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,_T("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,_T("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];
        ClsidPath2 = pTmp_;
        WideCharToMultiByte(CP_ACP,0,ClsidBuff,-1,ClsidBuff2,40,NULL,NULL);
#endif
        
        wsprintf(ClsidPath,_T("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,_T("AppId"),0,REG_SZ,(BYTE *)SERVICE_CLSID,sizeof(SERVICE_CLSID)-sizeof(TCHAR));
			RegSetValueEx(hKey4,_T("LocalService"),0,REG_SZ,(BYTE *)SERVICE_NAME,sizeof(SERVICE_NAME)-sizeof(TCHAR));
			RegCloseKey(hKey4);
		}

        StringFromGUID2(CLSID_WbemBackupRestore,ClsidBuff,40);
#ifdef UNICODE
        ClsidBuff2 = ClsidBuff;
#else
        // already _alloca-ted at this point
        //ClsidPath2 = (TCHAR *)_alloca(40*sizeof(TCHAR));
        WideCharToMultiByte(CP_ACP,0,ClsidBuff,-1,ClsidBuff2,40,NULL,NULL);
#endif

        wsprintf(ClsidPath,_T("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,_T("AppId"),0,REG_SZ,(BYTE *)SERVICE_CLSID,sizeof(SERVICE_CLSID)-sizeof(TCHAR));
			RegSetValueEx(hKey4,_T("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 server.
//
//  RETURN VALUES:
//
//      S_OK        Unregistration was successful
//      E_FAIL      Unregistration failed.
//
//***************************************************************************

STDAPI DllUnregisterServer(void)
{
    HKEY hKey;
    LONG lRet;
    BOOL bRet = TRUE;

    if (bRet)
    {
        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

        wsprintf(ClsidPath,_T("software\\classes\\CLSID\\%s"),ClsidBuff);
        
		lRet = RegDeleteKey(HKEY_LOCAL_MACHINE,ClsidPath);

#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

        wsprintf(ClsidPath,_T("software\\classes\\CLSID\\%s"),ClsidBuff);
        
		lRet = RegDeleteKey(HKEY_LOCAL_MACHINE,ClsidPath);

		lRet = RegDeleteKey(HKEY_LOCAL_MACHINE,COM_APPID);
		
		lRet = RegDeleteKey(HKEY_LOCAL_MACHINE,COM_APPID_NAME);
    
    }

	return S_OK;
}