/****************************************************************************** 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 #include #include #include // for task scheduler apis #include //////////////////////////////////////////////////////////////////////////////// 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 pNew; CComPtr pStreamIn; CComPtr 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 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"", rgLine, MAXSTRLEN(rgLine), strOEMInfo.c_str() ); if(!wcscmp( rgLine, L"" )) 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 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); }