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.
511 lines
15 KiB
511 lines
15 KiB
/******************************************************************************
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
setup.cpp
|
|
|
|
Abstract:
|
|
This file contains the code responsible for the install/uninstall of the
|
|
Help system.
|
|
|
|
Revision History:
|
|
Davide Massarenti (Dmassare) 04/19/2000
|
|
created
|
|
|
|
******************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include <unattend.h>
|
|
|
|
#include <aclapi.h>
|
|
|
|
#include <initguid.h>
|
|
#include <mstask.h> // for task scheduler apis
|
|
#include <msterr.h>
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static const WCHAR c_szMessageFile [] = HC_ROOT_HELPSVC_BINARIES L"\\HCAppRes.dll";
|
|
|
|
#define REG_CONTROL L"System\\CurrentControlSet\\Control"
|
|
#define REG_TSERVER L"Terminal Server"
|
|
#define REG_CONTROL_TSERVER REG_CONTROL L"\\" REG_TSERVER
|
|
#define REG_CONTROL_GETHELP REG_CONTROL_TSERVER
|
|
|
|
#define POLICY_TS_REMDSK_ALLOWTOGETHELP L"fAllowToGetHelp"
|
|
|
|
static const WCHAR c_szRegistryLog [] = L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\HelpSvc";
|
|
static const WCHAR c_szRegistryLog_File [] = L"EventMessageFile";
|
|
static const WCHAR c_szRegistryLog_Flags[] = L"TypesSupported";
|
|
|
|
static const DWORD SETUP_LOCALIZATION_STRINGS = 0x00000001;
|
|
static const DWORD SETUP_MESSAGE_FILE = 0x00000002;
|
|
static const DWORD SETUP_CREATE_GROUP = 0x00000004;
|
|
static const DWORD SETUP_OEMINFO = 0x00000008;
|
|
static const DWORD SETUP_SKU_INSTALL = 0x00000010;
|
|
|
|
static const MPC::StringToBitField c_Setup[] =
|
|
{
|
|
{ L"LOCALIZATION_STRINGS", SETUP_LOCALIZATION_STRINGS, SETUP_LOCALIZATION_STRINGS, -1 },
|
|
{ L"MESSAGE_FILE" , SETUP_MESSAGE_FILE , SETUP_MESSAGE_FILE , -1 },
|
|
{ L"CREATE_GROUP" , SETUP_CREATE_GROUP , SETUP_CREATE_GROUP , -1 },
|
|
{ L"OEMINFO" , SETUP_OEMINFO , SETUP_OEMINFO , -1 },
|
|
{ L"SKU_INSTALL" , SETUP_SKU_INSTALL , SETUP_SKU_INSTALL , -1 },
|
|
|
|
{ NULL }
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static HRESULT DumpSD( /*[in]*/ LPCWSTR szFile ,
|
|
/*[in]*/ CPCHSecurityDescriptorDirect& sdd )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "DumpSD" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<CPCHSecurityDescriptor> pNew;
|
|
CComPtr<IStream> pStreamIn;
|
|
CComPtr<IStream> pStreamOut;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pNew ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, sdd.ConvertSDToCOM( pNew ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pNew->SaveXMLAsStream ( (IUnknown**)&pStreamIn ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::OpenStreamForWrite( szFile, &pStreamOut ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::BaseStream::TransferData( pStreamIn, pStreamOut ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void local_RemoveRegistryBackup()
|
|
{
|
|
MPC::RegKey rkBase;
|
|
|
|
if(SUCCEEDED(rkBase.SetRoot( HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS )) &&
|
|
SUCCEEDED(rkBase.Attach ( HC_REGISTRY_HELPSVC L"\\Backup" )) )
|
|
{
|
|
(void)rkBase.Delete( /*fDeep*/true );
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT Local_Install()
|
|
{
|
|
__HCP_FUNC_ENTRY( "Local_Install" );
|
|
|
|
HRESULT hr;
|
|
MPC::wstring strGroupName;
|
|
MPC::wstring strGroupComment;
|
|
DWORD dwStatus = SETUP_LOCALIZATION_STRINGS |
|
|
SETUP_MESSAGE_FILE |
|
|
SETUP_CREATE_GROUP |
|
|
SETUP_OEMINFO |
|
|
SETUP_SKU_INSTALL;
|
|
|
|
|
|
if(SUCCEEDED(MPC::LocalizeString( IDS_HELPSVC_GROUPNAME , strGroupName )) &&
|
|
SUCCEEDED(MPC::LocalizeString( IDS_HELPSVC_GROUPCOMMENT, strGroupComment )) )
|
|
{
|
|
dwStatus &= ~SETUP_LOCALIZATION_STRINGS;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Register the message file into the registry.
|
|
//
|
|
{
|
|
MPC::wstring strPath ( c_szMessageFile ); MPC::SubstituteEnvVariables( strPath );
|
|
MPC::RegKey rkEventLog;
|
|
CComVariant vValue;
|
|
|
|
|
|
if(SUCCEEDED(rkEventLog.SetRoot( HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS )) &&
|
|
SUCCEEDED(rkEventLog.Attach ( c_szRegistryLog )) &&
|
|
SUCCEEDED(rkEventLog.Create ( )) )
|
|
{
|
|
if(SUCCEEDED(rkEventLog.put_Value( (vValue = strPath.c_str()), c_szRegistryLog_File )) &&
|
|
SUCCEEDED(rkEventLog.put_Value( (vValue = (long)0x1F ), c_szRegistryLog_Flags )) )
|
|
{
|
|
dwStatus &= ~SETUP_MESSAGE_FILE;
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Remove old WinME directory and registry keys.
|
|
//
|
|
{
|
|
MPC::RegKey rkRun;
|
|
|
|
(void)SVC::RemoveAndRecreateDirectory( HC_ROOT L"\\Support", NULL, /*fRemove*/true, /*fRecreate*/false );
|
|
|
|
if(SUCCEEDED(rkRun.SetRoot( HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS )) &&
|
|
SUCCEEDED(rkRun.Attach ( L"Software\\Microsoft\\Windows\\CurrentVersion\\Run\\PCHealth" )) )
|
|
{
|
|
(void)rkRun.Delete( true );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Remove old task scheduler entry.
|
|
//
|
|
{
|
|
CComBSTR bstrTaskName;
|
|
|
|
if(SUCCEEDED(MPC::LocalizeString( IDS_HELPSVC_TASKNAME, bstrTaskName )))
|
|
{
|
|
CComPtr<ITaskScheduler> pTaskScheduler;
|
|
|
|
if(SUCCEEDED(::CoCreateInstance( CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void**)&pTaskScheduler )))
|
|
{
|
|
(void)pTaskScheduler->Delete( bstrTaskName );
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Before PCHealthUnAttendedSetup() happens, we need to set the default
|
|
// reg key for fAllowToGetHelp (0 for Server and 1 for Per/Pro)
|
|
|
|
{
|
|
BOOL bPerPro = FALSE;
|
|
DWORDLONG dwlConditionMask;
|
|
OSVERSIONINFOEX osVersionInfo;
|
|
|
|
RtlZeroMemory(&osVersionInfo, sizeof(OSVERSIONINFOEX));
|
|
osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
|
osVersionInfo.wProductType = VER_NT_WORKSTATION;
|
|
|
|
dwlConditionMask = 0;
|
|
VER_SET_CONDITION(dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL);
|
|
|
|
// Is this machine Personal or Pro? Opposed to Server.
|
|
|
|
bPerPro = VerifyVersionInfo(
|
|
&osVersionInfo,
|
|
VER_PRODUCT_TYPE,
|
|
dwlConditionMask
|
|
);
|
|
|
|
DWORD dwValue;
|
|
DWORD dwStatus;
|
|
DWORD dwSize;
|
|
DWORD dwType;
|
|
HKEY hKey;
|
|
|
|
//
|
|
// Open TS registry key under HKLM\System\CurrentControlSet\Control\Terminal Serv...
|
|
//
|
|
dwStatus = RegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
REG_CONTROL_GETHELP,
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
&hKey
|
|
);
|
|
|
|
if( ERROR_SUCCESS == dwStatus )
|
|
{
|
|
dwSize = sizeof(dwValue);
|
|
dwStatus = RegQueryValueEx(
|
|
hKey,
|
|
POLICY_TS_REMDSK_ALLOWTOGETHELP,
|
|
0,
|
|
&dwType,
|
|
(PBYTE)&dwValue,
|
|
&dwSize
|
|
);
|
|
|
|
if( ERROR_FILE_NOT_FOUND == dwStatus || REG_DWORD != dwType )
|
|
{
|
|
//
|
|
// default is not allow to get help if
|
|
// value does not exist.
|
|
//
|
|
if( bPerPro )
|
|
{
|
|
dwValue = 1;
|
|
}
|
|
else
|
|
{
|
|
dwValue = 0;
|
|
}
|
|
|
|
dwStatus = RegSetValueEx(
|
|
hKey,
|
|
POLICY_TS_REMDSK_ALLOWTOGETHELP,
|
|
0,
|
|
REG_DWORD,
|
|
(PBYTE)&dwValue,
|
|
sizeof(dwValue)
|
|
);
|
|
}
|
|
|
|
RegCloseKey( hKey );
|
|
}
|
|
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
try
|
|
{
|
|
::PCHealthUnAttendedSetup();
|
|
}
|
|
catch(...)
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Create our group: "HelpServicesGroup".
|
|
//
|
|
{
|
|
CPCHAccounts acc;
|
|
|
|
if(SUCCEEDED(acc.CreateGroup( strGroupName.c_str(), strGroupComment.c_str() )))
|
|
{
|
|
dwStatus &= ~SETUP_CREATE_GROUP;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Extract OEM info from oeminfo.ini
|
|
//
|
|
{
|
|
MPC::RegKey rk;
|
|
|
|
if(SUCCEEDED(rk.SetRoot( HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS )) &&
|
|
SUCCEEDED(rk.Attach ( HC_REGISTRY_HELPSVC L"\\OEMInfo" )) &&
|
|
SUCCEEDED(rk.Delete ( /*fDeep*/true )) &&
|
|
SUCCEEDED(rk.Create ( )) )
|
|
{
|
|
WCHAR rgLine[512];
|
|
MPC::wstring strOEMInfo( L"%WINDIR%\\system32\\oeminfo.ini" ); MPC::SubstituteEnvVariables( strOEMInfo );
|
|
MPC::wstring strOEMText;
|
|
CComVariant vValue;
|
|
int i;
|
|
|
|
if(::GetPrivateProfileStringW( L"General", L"Manufacturer", L"", rgLine, MAXSTRLEN(rgLine), strOEMInfo.c_str() ) > 0)
|
|
{
|
|
vValue = rgLine; rk.put_Value( vValue, L"Manufacturer" );
|
|
}
|
|
|
|
if(::GetPrivateProfileStringW( L"General", L"Model", L"", rgLine, MAXSTRLEN(rgLine), strOEMInfo.c_str() ) > 0)
|
|
{
|
|
vValue = rgLine; rk.put_Value( vValue, L"Model" );
|
|
}
|
|
|
|
for(i=1;;i++)
|
|
{
|
|
WCHAR rgKey[64];
|
|
if (SUCCEEDED(StringCchPrintfW(rgKey, ARRAYSIZE(rgKey), L"Line%d", i)))
|
|
{
|
|
::GetPrivateProfileStringW( L"Support Information", rgKey, L"<eof>", rgLine, MAXSTRLEN(rgLine), strOEMInfo.c_str() );
|
|
if(!wcscmp( rgLine, L"<eof>" )) break;
|
|
|
|
if(strOEMText.size()) strOEMText += L"#BR#";
|
|
|
|
strOEMText += rgLine;
|
|
}
|
|
}
|
|
|
|
if(strOEMText.size())
|
|
{
|
|
vValue = strOEMText.c_str(); rk.put_Value( vValue, L"Text" );
|
|
}
|
|
|
|
dwStatus &= ~SETUP_OEMINFO;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
local_RemoveRegistryBackup();
|
|
|
|
//
|
|
// Extract all the data files.
|
|
//
|
|
{
|
|
MPC::wstring strCabinet;
|
|
|
|
//
|
|
// Find the best fit.
|
|
//
|
|
do
|
|
{
|
|
OSVERSIONINFOEXW ver;
|
|
MPC::WStringList lst;
|
|
MPC::WStringIter it;
|
|
|
|
::ZeroMemory( &ver, sizeof(ver) ); ver.dwOSVersionInfoSize = sizeof(ver);
|
|
|
|
::GetVersionExW( (LPOSVERSIONINFOW)&ver );
|
|
|
|
if(FAILED(SVC::LocateDataArchive( HC_ROOT_HELPSVC_BINARIES, lst ))) break;
|
|
if(lst.size() == 0) break;
|
|
|
|
for(it = lst.begin(); it != lst.end(); it++)
|
|
{
|
|
Installer::Package pkg;
|
|
|
|
if(SUCCEEDED(pkg.Init( it->c_str() )) &&
|
|
SUCCEEDED(pkg.Load( )) )
|
|
{
|
|
LPCWSTR szSKU = pkg.GetData().m_ths.GetSKU();
|
|
|
|
if(ver.wProductType == VER_NT_WORKSTATION)
|
|
{
|
|
if(ver.wSuiteMask & VER_SUITE_PERSONAL)
|
|
{
|
|
if(!MPC::StrICmp( szSKU, Taxonomy::s_szSKU_32_PERSONAL )) break;
|
|
}
|
|
else
|
|
{
|
|
if(!MPC::StrICmp( szSKU, Taxonomy::s_szSKU_32_PROFESSIONAL )) break;
|
|
if(!MPC::StrICmp( szSKU, Taxonomy::s_szSKU_64_PROFESSIONAL )) break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(ver.wSuiteMask & VER_SUITE_DATACENTER)
|
|
{
|
|
if(!MPC::StrICmp( szSKU, Taxonomy::s_szSKU_32_DATACENTER )) break;
|
|
if(!MPC::StrICmp( szSKU, Taxonomy::s_szSKU_64_DATACENTER )) break;
|
|
}
|
|
else if(ver.wSuiteMask & VER_SUITE_ENTERPRISE)
|
|
{
|
|
if(!MPC::StrICmp( szSKU, Taxonomy::s_szSKU_32_ADVANCED_SERVER )) break;
|
|
if(!MPC::StrICmp( szSKU, Taxonomy::s_szSKU_64_ADVANCED_SERVER )) break;
|
|
}
|
|
else
|
|
{
|
|
if(!MPC::StrICmp( szSKU, Taxonomy::s_szSKU_32_SERVER )) break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
strCabinet = *(it == lst.end() ? lst.begin() : it);
|
|
}
|
|
while(0);
|
|
|
|
if(strCabinet.size())
|
|
{
|
|
Installer::Package pkg;
|
|
|
|
if(SUCCEEDED(pkg.Init( strCabinet.c_str() )) &&
|
|
SUCCEEDED(pkg.Load( )) )
|
|
{
|
|
CComPtr<CPCHSetOfHelpTopics> sht;
|
|
|
|
if(SUCCEEDED(MPC::CreateInstance( &sht )))
|
|
{
|
|
if(SUCCEEDED(sht->DirectInstall( pkg, /*fSetup*/true, /*fSystem*/true, /*fMUI*/false )))
|
|
{
|
|
dwStatus &= ~SETUP_SKU_INSTALL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
{
|
|
MPC::wstring strText;
|
|
CComVariant v;
|
|
|
|
if(dwStatus)
|
|
{
|
|
if(SUCCEEDED(MPC::ConvertBitFieldToString( dwStatus, strText, c_Setup )))
|
|
{
|
|
v = strText.c_str();
|
|
}
|
|
else
|
|
{
|
|
v = (long)dwStatus;
|
|
}
|
|
}
|
|
|
|
(void)MPC::RegKey_Value_Write( v, HC_REGISTRY_HELPSVC, L"SetupProblems" );
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT Local_Uninstall()
|
|
{
|
|
__HCP_FUNC_ENTRY( "Local_Uninstall" );
|
|
|
|
HRESULT hr;
|
|
MPC::wstring strGroupName;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::LocalizeString( IDS_HELPSVC_GROUPNAME, strGroupName ));
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Register the message file into the registry.
|
|
//
|
|
{
|
|
MPC::RegKey rkEventLog;
|
|
|
|
if(SUCCEEDED(rkEventLog.SetRoot( HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS )) &&
|
|
SUCCEEDED(rkEventLog.Attach ( c_szRegistryLog )) )
|
|
{
|
|
(void)rkEventLog.Delete( /*fDeep*/true );
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Create our group: "HelpServicesGroup".
|
|
//
|
|
{
|
|
CPCHAccounts acc;
|
|
|
|
(void)acc.DeleteGroup( strGroupName.c_str() );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT_HELPSVC , NULL, /*fRemove*/true, /*fRecreate*/false ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT L"\\UploadLB", NULL, /*fRemove*/true, /*fRecreate*/false ));
|
|
}
|
|
|
|
local_RemoveRegistryBackup();
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|