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.

511 lines
15 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. setup.cpp
  5. Abstract:
  6. This file contains the code responsible for the install/uninstall of the
  7. Help system.
  8. Revision History:
  9. Davide Massarenti (Dmassare) 04/19/2000
  10. created
  11. ******************************************************************************/
  12. #include "stdafx.h"
  13. #include <unattend.h>
  14. #include <aclapi.h>
  15. #include <initguid.h>
  16. #include <mstask.h> // for task scheduler apis
  17. #include <msterr.h>
  18. ////////////////////////////////////////////////////////////////////////////////
  19. static const WCHAR c_szMessageFile [] = HC_ROOT_HELPSVC_BINARIES L"\\HCAppRes.dll";
  20. #define REG_CONTROL L"System\\CurrentControlSet\\Control"
  21. #define REG_TSERVER L"Terminal Server"
  22. #define REG_CONTROL_TSERVER REG_CONTROL L"\\" REG_TSERVER
  23. #define REG_CONTROL_GETHELP REG_CONTROL_TSERVER
  24. #define POLICY_TS_REMDSK_ALLOWTOGETHELP L"fAllowToGetHelp"
  25. static const WCHAR c_szRegistryLog [] = L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\HelpSvc";
  26. static const WCHAR c_szRegistryLog_File [] = L"EventMessageFile";
  27. static const WCHAR c_szRegistryLog_Flags[] = L"TypesSupported";
  28. static const DWORD SETUP_LOCALIZATION_STRINGS = 0x00000001;
  29. static const DWORD SETUP_MESSAGE_FILE = 0x00000002;
  30. static const DWORD SETUP_CREATE_GROUP = 0x00000004;
  31. static const DWORD SETUP_OEMINFO = 0x00000008;
  32. static const DWORD SETUP_SKU_INSTALL = 0x00000010;
  33. static const MPC::StringToBitField c_Setup[] =
  34. {
  35. { L"LOCALIZATION_STRINGS", SETUP_LOCALIZATION_STRINGS, SETUP_LOCALIZATION_STRINGS, -1 },
  36. { L"MESSAGE_FILE" , SETUP_MESSAGE_FILE , SETUP_MESSAGE_FILE , -1 },
  37. { L"CREATE_GROUP" , SETUP_CREATE_GROUP , SETUP_CREATE_GROUP , -1 },
  38. { L"OEMINFO" , SETUP_OEMINFO , SETUP_OEMINFO , -1 },
  39. { L"SKU_INSTALL" , SETUP_SKU_INSTALL , SETUP_SKU_INSTALL , -1 },
  40. { NULL }
  41. };
  42. ////////////////////////////////////////////////////////////////////////////////
  43. static HRESULT DumpSD( /*[in]*/ LPCWSTR szFile ,
  44. /*[in]*/ CPCHSecurityDescriptorDirect& sdd )
  45. {
  46. __MPC_FUNC_ENTRY( COMMONID, "DumpSD" );
  47. HRESULT hr;
  48. CComPtr<CPCHSecurityDescriptor> pNew;
  49. CComPtr<IStream> pStreamIn;
  50. CComPtr<IStream> pStreamOut;
  51. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pNew ));
  52. __MPC_EXIT_IF_METHOD_FAILS(hr, sdd.ConvertSDToCOM( pNew ));
  53. __MPC_EXIT_IF_METHOD_FAILS(hr, pNew->SaveXMLAsStream ( (IUnknown**)&pStreamIn ));
  54. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::OpenStreamForWrite( szFile, &pStreamOut ));
  55. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::BaseStream::TransferData( pStreamIn, pStreamOut ));
  56. hr = S_OK;
  57. __MPC_FUNC_CLEANUP;
  58. __MPC_FUNC_EXIT(hr);
  59. }
  60. ////////////////////////////////////////////////////////////////////////////////
  61. static void local_RemoveRegistryBackup()
  62. {
  63. MPC::RegKey rkBase;
  64. if(SUCCEEDED(rkBase.SetRoot( HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS )) &&
  65. SUCCEEDED(rkBase.Attach ( HC_REGISTRY_HELPSVC L"\\Backup" )) )
  66. {
  67. (void)rkBase.Delete( /*fDeep*/true );
  68. }
  69. }
  70. ////////////////////////////////////////////////////////////////////////////////
  71. HRESULT Local_Install()
  72. {
  73. __HCP_FUNC_ENTRY( "Local_Install" );
  74. HRESULT hr;
  75. MPC::wstring strGroupName;
  76. MPC::wstring strGroupComment;
  77. DWORD dwStatus = SETUP_LOCALIZATION_STRINGS |
  78. SETUP_MESSAGE_FILE |
  79. SETUP_CREATE_GROUP |
  80. SETUP_OEMINFO |
  81. SETUP_SKU_INSTALL;
  82. if(SUCCEEDED(MPC::LocalizeString( IDS_HELPSVC_GROUPNAME , strGroupName )) &&
  83. SUCCEEDED(MPC::LocalizeString( IDS_HELPSVC_GROUPCOMMENT, strGroupComment )) )
  84. {
  85. dwStatus &= ~SETUP_LOCALIZATION_STRINGS;
  86. }
  87. ////////////////////////////////////////////////////////////////////////////////
  88. //
  89. // Register the message file into the registry.
  90. //
  91. {
  92. MPC::wstring strPath ( c_szMessageFile ); MPC::SubstituteEnvVariables( strPath );
  93. MPC::RegKey rkEventLog;
  94. CComVariant vValue;
  95. if(SUCCEEDED(rkEventLog.SetRoot( HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS )) &&
  96. SUCCEEDED(rkEventLog.Attach ( c_szRegistryLog )) &&
  97. SUCCEEDED(rkEventLog.Create ( )) )
  98. {
  99. if(SUCCEEDED(rkEventLog.put_Value( (vValue = strPath.c_str()), c_szRegistryLog_File )) &&
  100. SUCCEEDED(rkEventLog.put_Value( (vValue = (long)0x1F ), c_szRegistryLog_Flags )) )
  101. {
  102. dwStatus &= ~SETUP_MESSAGE_FILE;
  103. }
  104. }
  105. }
  106. ////////////////////////////////////////////////////////////////////////////////
  107. //
  108. // Remove old WinME directory and registry keys.
  109. //
  110. {
  111. MPC::RegKey rkRun;
  112. (void)SVC::RemoveAndRecreateDirectory( HC_ROOT L"\\Support", NULL, /*fRemove*/true, /*fRecreate*/false );
  113. if(SUCCEEDED(rkRun.SetRoot( HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS )) &&
  114. SUCCEEDED(rkRun.Attach ( L"Software\\Microsoft\\Windows\\CurrentVersion\\Run\\PCHealth" )) )
  115. {
  116. (void)rkRun.Delete( true );
  117. }
  118. }
  119. //
  120. // Remove old task scheduler entry.
  121. //
  122. {
  123. CComBSTR bstrTaskName;
  124. if(SUCCEEDED(MPC::LocalizeString( IDS_HELPSVC_TASKNAME, bstrTaskName )))
  125. {
  126. CComPtr<ITaskScheduler> pTaskScheduler;
  127. if(SUCCEEDED(::CoCreateInstance( CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void**)&pTaskScheduler )))
  128. {
  129. (void)pTaskScheduler->Delete( bstrTaskName );
  130. }
  131. }
  132. }
  133. ////////////////////////////////////////////////////////////////////////////////
  134. // Before PCHealthUnAttendedSetup() happens, we need to set the default
  135. // reg key for fAllowToGetHelp (0 for Server and 1 for Per/Pro)
  136. {
  137. BOOL bPerPro = FALSE;
  138. DWORDLONG dwlConditionMask;
  139. OSVERSIONINFOEX osVersionInfo;
  140. RtlZeroMemory(&osVersionInfo, sizeof(OSVERSIONINFOEX));
  141. osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  142. osVersionInfo.wProductType = VER_NT_WORKSTATION;
  143. dwlConditionMask = 0;
  144. VER_SET_CONDITION(dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL);
  145. // Is this machine Personal or Pro? Opposed to Server.
  146. bPerPro = VerifyVersionInfo(
  147. &osVersionInfo,
  148. VER_PRODUCT_TYPE,
  149. dwlConditionMask
  150. );
  151. DWORD dwValue;
  152. DWORD dwStatus;
  153. DWORD dwSize;
  154. DWORD dwType;
  155. HKEY hKey;
  156. //
  157. // Open TS registry key under HKLM\System\CurrentControlSet\Control\Terminal Serv...
  158. //
  159. dwStatus = RegOpenKeyEx(
  160. HKEY_LOCAL_MACHINE,
  161. REG_CONTROL_GETHELP,
  162. 0,
  163. KEY_READ | KEY_WRITE,
  164. &hKey
  165. );
  166. if( ERROR_SUCCESS == dwStatus )
  167. {
  168. dwSize = sizeof(dwValue);
  169. dwStatus = RegQueryValueEx(
  170. hKey,
  171. POLICY_TS_REMDSK_ALLOWTOGETHELP,
  172. 0,
  173. &dwType,
  174. (PBYTE)&dwValue,
  175. &dwSize
  176. );
  177. if( ERROR_FILE_NOT_FOUND == dwStatus || REG_DWORD != dwType )
  178. {
  179. //
  180. // default is not allow to get help if
  181. // value does not exist.
  182. //
  183. if( bPerPro )
  184. {
  185. dwValue = 1;
  186. }
  187. else
  188. {
  189. dwValue = 0;
  190. }
  191. dwStatus = RegSetValueEx(
  192. hKey,
  193. POLICY_TS_REMDSK_ALLOWTOGETHELP,
  194. 0,
  195. REG_DWORD,
  196. (PBYTE)&dwValue,
  197. sizeof(dwValue)
  198. );
  199. }
  200. RegCloseKey( hKey );
  201. }
  202. }
  203. ////////////////////////////////////////////////////////////////////////////////
  204. try
  205. {
  206. ::PCHealthUnAttendedSetup();
  207. }
  208. catch(...)
  209. {
  210. }
  211. ////////////////////////////////////////////////////////////////////////////////
  212. //
  213. // Create our group: "HelpServicesGroup".
  214. //
  215. {
  216. CPCHAccounts acc;
  217. if(SUCCEEDED(acc.CreateGroup( strGroupName.c_str(), strGroupComment.c_str() )))
  218. {
  219. dwStatus &= ~SETUP_CREATE_GROUP;
  220. }
  221. }
  222. ////////////////////////////////////////////////////////////////////////////////
  223. //
  224. // Extract OEM info from oeminfo.ini
  225. //
  226. {
  227. MPC::RegKey rk;
  228. if(SUCCEEDED(rk.SetRoot( HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS )) &&
  229. SUCCEEDED(rk.Attach ( HC_REGISTRY_HELPSVC L"\\OEMInfo" )) &&
  230. SUCCEEDED(rk.Delete ( /*fDeep*/true )) &&
  231. SUCCEEDED(rk.Create ( )) )
  232. {
  233. WCHAR rgLine[512];
  234. MPC::wstring strOEMInfo( L"%WINDIR%\\system32\\oeminfo.ini" ); MPC::SubstituteEnvVariables( strOEMInfo );
  235. MPC::wstring strOEMText;
  236. CComVariant vValue;
  237. int i;
  238. if(::GetPrivateProfileStringW( L"General", L"Manufacturer", L"", rgLine, MAXSTRLEN(rgLine), strOEMInfo.c_str() ) > 0)
  239. {
  240. vValue = rgLine; rk.put_Value( vValue, L"Manufacturer" );
  241. }
  242. if(::GetPrivateProfileStringW( L"General", L"Model", L"", rgLine, MAXSTRLEN(rgLine), strOEMInfo.c_str() ) > 0)
  243. {
  244. vValue = rgLine; rk.put_Value( vValue, L"Model" );
  245. }
  246. for(i=1;;i++)
  247. {
  248. WCHAR rgKey[64];
  249. if (SUCCEEDED(StringCchPrintfW(rgKey, ARRAYSIZE(rgKey), L"Line%d", i)))
  250. {
  251. ::GetPrivateProfileStringW( L"Support Information", rgKey, L"<eof>", rgLine, MAXSTRLEN(rgLine), strOEMInfo.c_str() );
  252. if(!wcscmp( rgLine, L"<eof>" )) break;
  253. if(strOEMText.size()) strOEMText += L"#BR#";
  254. strOEMText += rgLine;
  255. }
  256. }
  257. if(strOEMText.size())
  258. {
  259. vValue = strOEMText.c_str(); rk.put_Value( vValue, L"Text" );
  260. }
  261. dwStatus &= ~SETUP_OEMINFO;
  262. }
  263. }
  264. ////////////////////////////////////////////////////////////////////////////////
  265. local_RemoveRegistryBackup();
  266. //
  267. // Extract all the data files.
  268. //
  269. {
  270. MPC::wstring strCabinet;
  271. //
  272. // Find the best fit.
  273. //
  274. do
  275. {
  276. OSVERSIONINFOEXW ver;
  277. MPC::WStringList lst;
  278. MPC::WStringIter it;
  279. ::ZeroMemory( &ver, sizeof(ver) ); ver.dwOSVersionInfoSize = sizeof(ver);
  280. ::GetVersionExW( (LPOSVERSIONINFOW)&ver );
  281. if(FAILED(SVC::LocateDataArchive( HC_ROOT_HELPSVC_BINARIES, lst ))) break;
  282. if(lst.size() == 0) break;
  283. for(it = lst.begin(); it != lst.end(); it++)
  284. {
  285. Installer::Package pkg;
  286. if(SUCCEEDED(pkg.Init( it->c_str() )) &&
  287. SUCCEEDED(pkg.Load( )) )
  288. {
  289. LPCWSTR szSKU = pkg.GetData().m_ths.GetSKU();
  290. if(ver.wProductType == VER_NT_WORKSTATION)
  291. {
  292. if(ver.wSuiteMask & VER_SUITE_PERSONAL)
  293. {
  294. if(!MPC::StrICmp( szSKU, Taxonomy::s_szSKU_32_PERSONAL )) break;
  295. }
  296. else
  297. {
  298. if(!MPC::StrICmp( szSKU, Taxonomy::s_szSKU_32_PROFESSIONAL )) break;
  299. if(!MPC::StrICmp( szSKU, Taxonomy::s_szSKU_64_PROFESSIONAL )) break;
  300. }
  301. }
  302. else
  303. {
  304. if(ver.wSuiteMask & VER_SUITE_DATACENTER)
  305. {
  306. if(!MPC::StrICmp( szSKU, Taxonomy::s_szSKU_32_DATACENTER )) break;
  307. if(!MPC::StrICmp( szSKU, Taxonomy::s_szSKU_64_DATACENTER )) break;
  308. }
  309. else if(ver.wSuiteMask & VER_SUITE_ENTERPRISE)
  310. {
  311. if(!MPC::StrICmp( szSKU, Taxonomy::s_szSKU_32_ADVANCED_SERVER )) break;
  312. if(!MPC::StrICmp( szSKU, Taxonomy::s_szSKU_64_ADVANCED_SERVER )) break;
  313. }
  314. else
  315. {
  316. if(!MPC::StrICmp( szSKU, Taxonomy::s_szSKU_32_SERVER )) break;
  317. }
  318. }
  319. }
  320. }
  321. strCabinet = *(it == lst.end() ? lst.begin() : it);
  322. }
  323. while(0);
  324. if(strCabinet.size())
  325. {
  326. Installer::Package pkg;
  327. if(SUCCEEDED(pkg.Init( strCabinet.c_str() )) &&
  328. SUCCEEDED(pkg.Load( )) )
  329. {
  330. CComPtr<CPCHSetOfHelpTopics> sht;
  331. if(SUCCEEDED(MPC::CreateInstance( &sht )))
  332. {
  333. if(SUCCEEDED(sht->DirectInstall( pkg, /*fSetup*/true, /*fSystem*/true, /*fMUI*/false )))
  334. {
  335. dwStatus &= ~SETUP_SKU_INSTALL;
  336. }
  337. }
  338. }
  339. }
  340. }
  341. ////////////////////////////////////////////////////////////////////////////////
  342. {
  343. MPC::wstring strText;
  344. CComVariant v;
  345. if(dwStatus)
  346. {
  347. if(SUCCEEDED(MPC::ConvertBitFieldToString( dwStatus, strText, c_Setup )))
  348. {
  349. v = strText.c_str();
  350. }
  351. else
  352. {
  353. v = (long)dwStatus;
  354. }
  355. }
  356. (void)MPC::RegKey_Value_Write( v, HC_REGISTRY_HELPSVC, L"SetupProblems" );
  357. }
  358. hr = S_OK;
  359. __HCP_FUNC_EXIT(hr);
  360. }
  361. HRESULT Local_Uninstall()
  362. {
  363. __HCP_FUNC_ENTRY( "Local_Uninstall" );
  364. HRESULT hr;
  365. MPC::wstring strGroupName;
  366. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::LocalizeString( IDS_HELPSVC_GROUPNAME, strGroupName ));
  367. ////////////////////////////////////////////////////////////////////////////////
  368. //
  369. // Register the message file into the registry.
  370. //
  371. {
  372. MPC::RegKey rkEventLog;
  373. if(SUCCEEDED(rkEventLog.SetRoot( HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS )) &&
  374. SUCCEEDED(rkEventLog.Attach ( c_szRegistryLog )) )
  375. {
  376. (void)rkEventLog.Delete( /*fDeep*/true );
  377. }
  378. }
  379. ////////////////////////////////////////////////////////////////////////////////
  380. //
  381. // Create our group: "HelpServicesGroup".
  382. //
  383. {
  384. CPCHAccounts acc;
  385. (void)acc.DeleteGroup( strGroupName.c_str() );
  386. }
  387. ////////////////////////////////////////////////////////////////////////////////
  388. {
  389. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT_HELPSVC , NULL, /*fRemove*/true, /*fRecreate*/false ));
  390. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT L"\\UploadLB", NULL, /*fRemove*/true, /*fRecreate*/false ));
  391. }
  392. local_RemoveRegistryBackup();
  393. hr = S_OK;
  394. __HCP_FUNC_CLEANUP;
  395. __HCP_FUNC_EXIT(hr);
  396. }