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.

999 lines
30 KiB

  1. /*++
  2. 1998 Seagate Software, Inc. All rights reserved.
  3. Module Name:
  4. Uninstal.h
  5. Abstract:
  6. Implementation of uninstall.
  7. Author:
  8. Rohde Wakefield [rohde] 09-Oct-1997
  9. Revision History:
  10. Carl Hagerstrom [carlh] 01-Sep-1998
  11. Added QueryChangeSelState and modified CompleteInstallation
  12. to force enabling of last access date updating.
  13. Carl Hagerstrom [carlh] 25-Sep-1998
  14. Added the check for and recovery from partial uninstalls when
  15. services will not stop.
  16. --*/
  17. #include "stdafx.h"
  18. #include "Uninstal.h"
  19. #include "UnInsChk.h"
  20. #include "rsevents.h"
  21. #include <mstask.h>
  22. int StopServiceAndDependencies(LPCTSTR ServiceName);
  23. HRESULT CallExeWithParameters(LPCTSTR pszEXEName, LPCTSTR pszParameters );
  24. //////////////////////////////////////////////////////////////////////
  25. // Construction/Destruction
  26. //////////////////////////////////////////////////////////////////////
  27. CRsUninstall::CRsUninstall()
  28. {
  29. m_removeRsData = TRUE;
  30. m_stopUninstall = FALSE;
  31. m_win2kUpgrade = FALSE;
  32. }
  33. CRsUninstall::~CRsUninstall()
  34. {
  35. }
  36. LPCTSTR
  37. CRsUninstall::StringFromId( SHORT SubcomponentId )
  38. {
  39. switch( SubcomponentId ) {
  40. case RSOPTCOM_ID_NONE:
  41. case RSOPTCOM_ID_ROOT:
  42. return( RSOPTCOM_SUB_ROOT );
  43. }
  44. return( TEXT("") );
  45. }
  46. SHORT
  47. CRsUninstall::IdFromString( LPCTSTR SubcomponentId )
  48. {
  49. if( !SubcomponentId ) {
  50. return( RSOPTCOM_ID_NONE );
  51. } else if( _tcsicmp( SubcomponentId, RSOPTCOM_SUB_ROOT ) == 0 ) {
  52. return( RSOPTCOM_ID_ROOT );
  53. }
  54. return( RSOPTCOM_ID_ERROR );
  55. }
  56. HBITMAP
  57. CRsUninstall::QueryImage(
  58. IN SHORT SubcomponentId,
  59. IN SubComponentInfo /*WhichImage*/,
  60. IN WORD /*Width*/,
  61. IN WORD /*Height*/
  62. )
  63. {
  64. TRACEFN( "CRsUninstall::QueryImage" );
  65. TRACE( _T("SubcomponentId = <%hd>"), SubcomponentId );
  66. HBITMAP retval = 0;
  67. AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );
  68. switch( SubcomponentId ) {
  69. case RSOPTCOM_ID_NONE:
  70. case RSOPTCOM_ID_ROOT:
  71. retval = ::LoadBitmap( AfxGetApp( )->m_hInstance, MAKEINTRESOURCE( IDB_RSTORAGE_SMALL ) );
  72. break;
  73. }
  74. return( retval );
  75. }
  76. BOOL
  77. CRsUninstall::QueryImageEx(
  78. IN SHORT SubcomponentId,
  79. IN OC_QUERY_IMAGE_INFO* /*pQueryImageInfo*/,
  80. OUT HBITMAP *phBitmap
  81. )
  82. {
  83. TRACEFNBOOL( "CRsUninstall::QueryImageEx" );
  84. TRACE( _T("SubcomponentId = <%hd>, phBitmap = <0x%p>"), SubcomponentId, phBitmap );
  85. boolRet = FALSE;
  86. if (phBitmap) {
  87. *phBitmap = NULL;
  88. AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );
  89. switch( SubcomponentId ) {
  90. case RSOPTCOM_ID_NONE:
  91. case RSOPTCOM_ID_ROOT:
  92. *phBitmap = ::LoadBitmap( AfxGetApp( )->m_hInstance, MAKEINTRESOURCE( IDB_RSTORAGE_SMALL ) );
  93. if ((*phBitmap) != NULL) {
  94. boolRet = TRUE;
  95. }
  96. break;
  97. }
  98. }
  99. return (boolRet);
  100. }
  101. LONG
  102. CRsUninstall::QueryStepCount(
  103. IN SHORT /*SubcomponentId*/
  104. )
  105. {
  106. TRACEFNLONG( "CRsUninstall::QueryStepCount" );
  107. DWORD retval = 2;
  108. return( retval );
  109. }
  110. BOOL
  111. CRsUninstall::QueryChangeSelState(
  112. IN SHORT SubcomponentId,
  113. IN BOOL SelectedState,
  114. IN DWORD Flags
  115. )
  116. {
  117. TRACEFNBOOL( "CRsUninstall::QueryChangeSelState" );
  118. HRESULT hrRet = S_OK;
  119. DWORDLONG opFlags = m_SetupData.OperationFlags;
  120. boolRet = TRUE;
  121. AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );
  122. try {
  123. // When the user attempts to check the box for installing Remote Storage,
  124. // and updating last access date is disabled in the registry, force
  125. // the user to agree to changing the registry before the box is checked.
  126. // The message box does not appear during unattended install but the
  127. // registry will be changed anyway. The registry change occurs in
  128. // CompleteInstallation.
  129. if( SubcomponentId == RSOPTCOM_ID_ROOT
  130. && SelectedState
  131. && Flags & OCQ_ACTUAL_SELECTION ) {
  132. CLaDate lad;
  133. CLaDate::LAD_STATE ladState;
  134. RsOptAffirmDw( lad.GetLadState( &ladState ) );
  135. if( ladState == CLaDate::LAD_DISABLED ) {
  136. if( !( opFlags & SETUPOP_BATCH ) ) {
  137. if( IDNO == AfxMessageBox( IDS_LA_DATE_CHANGE, MB_YESNO ) ) {
  138. boolRet = FALSE;
  139. }
  140. }
  141. }
  142. }
  143. } RsOptCatch( hrRet );
  144. if( hrRet != S_OK ) {
  145. // If the registry cannot be accessed, user will be
  146. // allowed to select Remote Storage install anyway.
  147. boolRet = TRUE;
  148. }
  149. return( boolRet );
  150. }
  151. DWORD
  152. CRsUninstall::CalcDiskSpace(
  153. IN SHORT SubcomponentId,
  154. IN BOOL AddSpace,
  155. IN HDSKSPC hDiskSpace
  156. )
  157. {
  158. TRACEFNDW( "CRsUninstall::CalcDiskSpace" );
  159. dwRet = NO_ERROR;
  160. switch( SubcomponentId ) {
  161. case RSOPTCOM_ID_ROOT:
  162. dwRet = DoCalcDiskSpace( AddSpace, hDiskSpace, RSOPTCOM_SECT_INSTALL_ROOT );
  163. break;
  164. }
  165. return( dwRet );
  166. }
  167. DWORD
  168. CRsUninstall::QueueFileOps(
  169. IN SHORT SubcomponentId,
  170. IN HSPFILEQ hFileQueue
  171. )
  172. {
  173. TRACEFNDW( "CRsUninstall::QueueFileOps" );
  174. HRESULT hrRet = S_OK;
  175. dwRet = NO_ERROR;
  176. RSOPTCOM_ACTION action = GetSubAction( SubcomponentId );
  177. if( !m_stopUninstall ) {
  178. try {
  179. switch( SubcomponentId ) {
  180. case RSOPTCOM_ID_ROOT:
  181. switch( action ) {
  182. case ACTION_UPGRADE :
  183. {
  184. CRsRegKey keyRSEngine;
  185. // Check if Win2K services exist, if so - stop them
  186. if( NO_ERROR == keyRSEngine.Open( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Remote_Storage_Engine"), KEY_QUERY_VALUE) ) {
  187. m_win2kUpgrade = TRUE;
  188. RsOptAffirmDw( StopServiceAndDependencies( TEXT("Remote_Storage_Engine") ) );
  189. }
  190. if( NO_ERROR == keyRSEngine.Open( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Remote_Storage_File_System_Agent"), KEY_QUERY_VALUE) ) {
  191. m_win2kUpgrade = TRUE;
  192. RsOptAffirmDw( StopServiceAndDependencies( TEXT("Remote_Storage_File_System_Agent") ) );
  193. }
  194. if( NO_ERROR == keyRSEngine.Open( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Remote_Storage_Subsystem"), KEY_QUERY_VALUE) ) {
  195. m_win2kUpgrade = TRUE;
  196. RsOptAffirmDw( StopServiceAndDependencies( TEXT("Remote_Storage_Subsystem") ) );
  197. }
  198. // Stop the current RS services
  199. // Note: in case of upgrade from Win2K, these services don't exist but
  200. // StopServiceAndDependencies ignores such a case (no error returned)
  201. RsOptAffirmDw( StopServiceAndDependencies( TEXT("Remote_Storage_Server") ) );
  202. RsOptAffirmDw( StopServiceAndDependencies( TEXT("Remote_Storage_User_Link") ) );
  203. }
  204. // fall through...
  205. case ACTION_INSTALL :
  206. RsOptAffirmDw( DoQueueFileOps( SubcomponentId, hFileQueue, RSOPTCOM_SECT_INSTALL_ROOT, RSOPTCOM_SECT_UNINSTALL_ROOT ) );
  207. break;
  208. case ACTION_UNINSTALL :
  209. {
  210. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  211. CUninstallCheck dlg( this );
  212. m_pRsCln = new CRsClnServer();
  213. RsOptAffirmPointer( m_pRsCln );
  214. if( dlg.DoModal() == IDOK ) {
  215. // stop the services
  216. RsOptAffirmDw( StopServiceAndDependencies( TEXT("Remote_Storage_Server") ) );
  217. RsOptAffirmDw( StopServiceAndDependencies( TEXT("Remote_Storage_User_Link") ) );
  218. // Queue the file operations
  219. RsOptAffirmDw( DoQueueFileOps( SubcomponentId, hFileQueue, RSOPTCOM_SECT_INSTALL_ROOT, RSOPTCOM_SECT_UNINSTALL_ROOT ) );
  220. } else {
  221. m_stopUninstall = TRUE;
  222. }
  223. }
  224. break;
  225. }
  226. }
  227. } RsOptCatch( hrRet );
  228. if( FAILED( hrRet ) ) {
  229. m_stopUninstall = TRUE;
  230. }
  231. }
  232. return( dwRet );
  233. }
  234. //
  235. // On Install, register all our stuff that we want
  236. //
  237. DWORD
  238. CRsUninstall::CompleteInstallation(
  239. IN SHORT SubcomponentId
  240. )
  241. {
  242. TRACEFNDW( "CRsUninstall::CompleteInstallation" );
  243. AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );
  244. HRESULT hrRet = S_OK;
  245. dwRet = NO_ERROR;
  246. RSOPTCOM_ACTION action = GetSubAction( SubcomponentId );
  247. if( m_stopUninstall ) {
  248. action = ACTION_NONE;
  249. }
  250. CString szStatus;
  251. switch( action ) {
  252. case ACTION_UPGRADE:
  253. case ACTION_INSTALL:
  254. switch( SubcomponentId ) {
  255. case RSOPTCOM_ID_ROOT:
  256. szStatus.LoadString( ( action == ACTION_INSTALL ) ? IDS_RS_INSTALL_SVCS : IDS_RS_UPGRADE_SVCS );
  257. SetProgressText( szStatus );
  258. // Change NtfsDisableLastAccessUpdate registry
  259. // value if it was previously set. Updating last
  260. // access date cannot be disabled or Remote Storage
  261. // will not work.
  262. try {
  263. CLaDate lad;
  264. CLaDate::LAD_STATE ladState;
  265. RsOptAffirmDw( lad.GetLadState( &ladState ) );
  266. if( ladState == CLaDate::LAD_DISABLED ) {
  267. RsOptAffirmDw( lad.SetLadState( CLaDate::LAD_ENABLED ) );
  268. }
  269. } RsOptCatch( hrRet );
  270. if( hrRet != S_OK ) {
  271. // Failure to read or update registry is not serious
  272. // enough to fail installation.
  273. dwRet = NO_ERROR;
  274. }
  275. // Register the filter
  276. HRESULT hrRegister;
  277. BOOL registered = SetupInstallServicesFromInfSection( m_ComponentInfHandle, RSOPTCOM_SECT_INSTALL_FILTER, SPSVCINST_TAGTOFRONT );
  278. hrRegister = ( registered ) ? S_OK : HRESULT_FROM_WIN32( RsOptLastError );
  279. // If Rsfilter does not register correctly we need to set the error code.
  280. // Usually this is caused by the user not rebooting after unregistering RsFilter.
  281. // If it is marked for deletion then we cannot register it again. We also don't
  282. // want the component manager to think everything worked.
  283. if( FAILED( hrRegister ) ) {
  284. if( FACILITY_WIN32 == HRESULT_FACILITY( hrRegister ) ) {
  285. dwRet = HRESULT_CODE( hrRegister );
  286. if( ERROR_SERVICE_EXISTS == dwRet ) {
  287. dwRet = NO_ERROR;
  288. }
  289. } else {
  290. dwRet = ERROR_SERVICE_NOT_FOUND;
  291. }
  292. RsOptAffirmDw( dwRet );
  293. }
  294. // Register the dlls
  295. CallDllEntryPoint( TEXT("RsEngPs.dll"), "DllRegisterServer" );
  296. CallDllEntryPoint( TEXT("RsSubPs.dll"), "DllRegisterServer" );
  297. CallDllEntryPoint( TEXT("RsServPs.dll"), "DllRegisterServer" );
  298. CallDllEntryPoint( TEXT("RsAdmin.dll"), "DllRegisterServer" );
  299. CallDllEntryPoint( TEXT("RsCommon.dll"), "DllRegisterServer" );
  300. CallDllEntryPoint( TEXT("RsShell.dll"), "DllRegisterServer" );
  301. CallDllEntryPoint( TEXT("RsJob.dll"), "DllRegisterServer" );
  302. CallDllEntryPoint( TEXT("RsIdb.dll"), "DllRegisterServer" );
  303. CallDllEntryPoint( TEXT("RsTask.dll"), "DllRegisterServer" );
  304. CallDllEntryPoint( TEXT("RsMover.dll"), "DllRegisterServer" );
  305. CallDllEntryPoint( TEXT("RsSub.dll"), "DllRegisterServer" );
  306. CallDllEntryPoint( TEXT("RsFsa.dll"), "DllRegisterServer" );
  307. CallDllEntryPoint( TEXT("RsEng.dll"), "DllRegisterServer" );
  308. // Register the services
  309. CallExeWithParameters( TEXT("RsServ.exe"), TEXT(" /regserver") );
  310. CallExeWithParameters( TEXT("RsLnk.exe"), TEXT(" /regserver") );
  311. // Ensure NT Backup settings (exclude some RS files from backup)
  312. //
  313. // Note: In Whistler NTBackup, these setting apply only when the backup
  314. // is a non-snapshot backup. In this case, we still want to exclude the files.
  315. // In case of a snapshot backup, the exclude settings are determined by
  316. // the writer class in the Engine.
  317. EnsureBackupSettings ();
  318. // If we get this far,
  319. // we should go ahead and set to reboot if needed
  320. if( ( S_OK == hrRegister ) && ( ACTION_INSTALL == action ) ) {
  321. // Tell the user they do need to reboot
  322. SetReboot();
  323. }
  324. // Add shortcut to start menu
  325. CString itemDesc, desc;
  326. itemDesc.LoadString( IDS_ITEM_DESCRIPTION );
  327. desc.LoadString( IDS_RS_DESCRIPTION );
  328. AddItem( CSIDL_COMMON_ADMINTOOLS, itemDesc, TEXT("%SystemRoot%\\System32\\RsAdmin.msc"), TEXT(""), TEXT("%HOMEDRIVE%%HOMEPATH%"), desc,
  329. IDS_ITEM_DESCRIPTION, IDS_RS_DESCRIPTION, TEXT("%SystemRoot%\\System32\\RsAdmin.dll"), 0 );
  330. break;
  331. }
  332. break;
  333. case ACTION_UNINSTALL:
  334. switch( SubcomponentId ) {
  335. case RSOPTCOM_ID_ROOT:
  336. // removing shortcut from start menu
  337. CString itemDesc;
  338. itemDesc.LoadString( IDS_ITEM_DESCRIPTION );
  339. DeleteItem( CSIDL_COMMON_ADMINTOOLS, itemDesc );
  340. try {
  341. // For some reason, rscommon.dll is not getting removed. This
  342. // will schedule it to be removed on the next system startup.
  343. CString path( getenv( "SystemRoot" ) );
  344. path += "\\system32\\rscommon.dll";
  345. RsOptAffirmStatus( MoveFileEx( path, NULL, MOVEFILE_DELAY_UNTIL_REBOOT ) );
  346. } RsOptCatch( hrRet );
  347. if( m_removeRsData ) {
  348. // user chose to remove all data managed by Remote Storage
  349. szStatus.LoadString( IDS_RS_REMOVE_SVCS );
  350. SetProgressText( szStatus );
  351. // remove reparse points and truncated files
  352. m_pRsCln->CleanServer();
  353. delete m_pRsCln;
  354. // remove our subdirectory
  355. //
  356. // TBD (ravisp): in a clustering environment the RemoteStorage directory
  357. // is relocatable. We would need to get the real metadata path
  358. // and blow it away
  359. //
  360. CallExeWithParameters( TEXT("CMD.EXE"), TEXT(" /C del %SystemRoot%\\system32\\RemoteStorage\\*.* /q") );
  361. CallExeWithParameters( TEXT("CMD.EXE"), TEXT(" /C rd %SystemRoot%\\system32\\RemoteStorage /s /q") );
  362. }
  363. break;
  364. }
  365. break;
  366. }
  367. TickGauge( );
  368. return( dwRet );
  369. }
  370. void RemoveTasks()
  371. {
  372. TRACEFNHR( "RemoveTasks" );
  373. AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );
  374. CComPtr <ITaskScheduler> pSchedAgent; // Pointer to Scheduling Agent
  375. CComPtr <IEnumWorkItems> pEnumWorkItems; // Pointer to Scheduling Agent
  376. LPWSTR *rgpwszName;
  377. ULONG celtFetched;
  378. CString creatorName;
  379. creatorName.LoadString( IDS_PRODUCT_NAME );
  380. try {
  381. hrRet = CoInitialize ( NULL );
  382. RsOptAffirmHr(hrRet);
  383. hrRet = CoCreateInstance( CLSID_CSchedulingAgent, 0, CLSCTX_SERVER,
  384. IID_ISchedulingAgent, (void **) &pSchedAgent ) ;
  385. RsOptAffirmHr(hrRet);
  386. pSchedAgent->Enum( &pEnumWorkItems );
  387. pEnumWorkItems->Next( 1, &rgpwszName , &celtFetched ) ;
  388. while( 1 == celtFetched ) {
  389. CComPtr <ITask> pTask; // Pointer to a specific task
  390. CComPtr <IUnknown> pIU;
  391. LPWSTR pwszCreator;
  392. // using pSchedAgent->Activate( )
  393. // Get the task we're interested in
  394. if( S_OK == pSchedAgent->Activate( *rgpwszName, IID_ITask, &pIU) ) {
  395. // QI to the task interface
  396. hrRet = pIU->QueryInterface(IID_ITask, (void **) &pTask);
  397. RsOptAffirmHr(hrRet);
  398. //
  399. // If it matches then we need to delete it
  400. //
  401. pTask->GetCreator( &pwszCreator );
  402. // dereference
  403. pTask.Release();
  404. if( 0 == creatorName.Compare( pwszCreator ) ) {
  405. pSchedAgent->Delete( *rgpwszName );
  406. //then delete using pSchedAgent->Delete()
  407. pEnumWorkItems->Reset();
  408. }
  409. CoTaskMemFree( pwszCreator );
  410. pwszCreator = 0;
  411. }
  412. // Free the memory from the Next
  413. CoTaskMemFree( *rgpwszName );
  414. rgpwszName = 0;
  415. pEnumWorkItems->Next( 1, &rgpwszName, &celtFetched ) ;
  416. }
  417. } RsOptCatch( hrRet );
  418. }
  419. //
  420. // On Uninstall, unregister everything and get us cleaned up
  421. //
  422. DWORD
  423. CRsUninstall::AboutToCommitQueue(
  424. IN SHORT SubcomponentId
  425. )
  426. {
  427. TRACEFNHR( "CRsUninstall::AboutToCommitQueue" );
  428. RSOPTCOM_ACTION action = GetSubAction( SubcomponentId );
  429. if( m_stopUninstall ) {
  430. action = ACTION_NONE;
  431. }
  432. CString szStatus;
  433. AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );
  434. try {
  435. switch( action ) {
  436. case ACTION_INSTALL:
  437. break;
  438. case ACTION_UNINSTALL:
  439. switch( SubcomponentId ) {
  440. case RSOPTCOM_ID_ROOT:
  441. // remove our entries from Directory Services
  442. // MGL: To do
  443. // Remove Display specifier for our node and our node on the computer
  444. // CallDllEntryPoint( TEXT("RsConn.dll"), "RsDirectoryServiceUninstall" );
  445. szStatus.LoadString( IDS_RS_REMOVE_SVCS );
  446. SetProgressText( szStatus );
  447. // Unregister the filter and indicate that the system must be rebooted
  448. SetupInstallServicesFromInfSection( m_ComponentInfHandle, RSOPTCOM_SECT_UNINSTALL_FILTER, 0 );
  449. SetReboot();
  450. // Unregister the services
  451. CallExeWithParameters( TEXT("RsServ.exe"), TEXT(" /unregserver") );
  452. CallExeWithParameters( TEXT("RsLnk.exe"), TEXT(" /unregserver") );
  453. // Unregister the dlls
  454. CallDllEntryPoint( TEXT("RsEngPs.dll"), "DllUnregisterServer" );
  455. CallDllEntryPoint( TEXT("RsSubPs.dll"), "DllUnregisterServer" );
  456. CallDllEntryPoint( TEXT("RsServPs.dll"), "DllUnregisterServer" );
  457. CallDllEntryPoint( TEXT("RsAdmin.dll"), "DllUnregisterServer" );
  458. CallDllEntryPoint( TEXT("RsShell.dll"), "DllUnregisterServer" );
  459. CallDllEntryPoint( TEXT("RsJob.dll"), "DllUnregisterServer" );
  460. CallDllEntryPoint( TEXT("RsIdb.dll"), "DllUnregisterServer" );
  461. CallDllEntryPoint( TEXT("RsTask.dll"), "DllUnregisterServer" );
  462. CallDllEntryPoint( TEXT("RsMover.dll"), "DllUnregisterServer" );
  463. CallDllEntryPoint( TEXT("RsSub.dll"), "DllUnregisterServer" );
  464. CallDllEntryPoint( TEXT("RsFsa.dll"), "DllUnregisterServer" );
  465. CallDllEntryPoint( TEXT("RsEng.dll"), "DllUnregisterServer" );
  466. CallDllEntryPoint( TEXT("RsCommon.dll"), "DllUnregisterServer" );
  467. // remove our jobs from the job scheduler if we are removing the
  468. // Remote Storage Data.
  469. if( m_removeRsData ) {
  470. RemoveTasks();
  471. }
  472. break;
  473. }
  474. break;
  475. case ACTION_UPGRADE:
  476. switch( SubcomponentId ) {
  477. case RSOPTCOM_ID_ROOT:
  478. // Check if this is an upgrade from Win2K, if so:
  479. // 1. Unregister obsolete services
  480. // 2. Delete obsolete binary files
  481. if (m_win2kUpgrade) {
  482. CallExeWithParameters( TEXT("RsEng.exe"), TEXT(" /unregserver") );
  483. CallExeWithParameters( TEXT("RsFsa.exe"), TEXT(" /unregserver") );
  484. CallExeWithParameters( TEXT("RsSub.exe"), TEXT(" /unregserver") );
  485. CString path( getenv( "SystemRoot" ) );
  486. path += TEXT("\\system32\\");
  487. CString fileName = path;
  488. fileName += TEXT("RsEng.exe");
  489. DeleteFile(fileName);
  490. fileName = path;
  491. fileName += TEXT("rsFsa.exe");
  492. DeleteFile(fileName);
  493. fileName = path;
  494. fileName += TEXT("RsSub.exe");
  495. DeleteFile(fileName);
  496. }
  497. break;
  498. }
  499. break;
  500. }
  501. } RsOptCatch( hrRet ) ;
  502. TickGauge( );
  503. return( SUCCEEDED( hrRet ) ? NO_ERROR : HRESULT_CODE( hrRet ) );
  504. }
  505. //
  506. // If there is a problem with install or uninstall which might leave it
  507. // in a partially installed or uninstalled state, set the subcomponent
  508. // state to redo this install or uninstall.
  509. //
  510. SubComponentState
  511. CRsUninstall::QueryState(
  512. IN SHORT SubcomponentId
  513. )
  514. {
  515. TRACEFN( "CRsUninstall::QueryState" );
  516. SubComponentState retval = SubcompUseOcManagerDefault;
  517. RSOPTCOM_ACTION action = GetSubAction( SubcomponentId );
  518. //
  519. // Need to check and see if we are upgrading from previous to
  520. // 393 build which had rsengine entry, but no rstorage entry.
  521. //
  522. if( RSOPTCOM_ID_ROOT == SubcomponentId ) {
  523. BOOL originalState = QuerySelectionState( SubcomponentId, OCSELSTATETYPE_ORIGINAL );
  524. if( !originalState ) {
  525. CRsRegKey keyRSEngine;
  526. LONG regRet = keyRSEngine.Open( HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\OC Manager\\Subcomponents") );
  527. if( NO_ERROR == regRet ) {
  528. DWORD engineState;
  529. regRet = keyRSEngine.QueryValue( engineState, TEXT("rsengine") );
  530. if( ( NO_ERROR == regRet ) && engineState ) {
  531. //
  532. // Had old style engine entry, and was on, so do fix up
  533. //
  534. retval = SubcompOn;
  535. regRet = keyRSEngine.SetValue( engineState, TEXT("rstorage") );
  536. if( NO_ERROR == regRet ) {
  537. keyRSEngine.DeleteValue( TEXT("rsengine") );
  538. keyRSEngine.DeleteValue( TEXT("rsui") );
  539. }
  540. }
  541. }
  542. }
  543. }
  544. switch( action ) {
  545. case ACTION_UPGRADE:
  546. case ACTION_INSTALL:
  547. if( m_stopUninstall ) {
  548. retval = SubcompOff;
  549. }
  550. break;
  551. case ACTION_UNINSTALL:
  552. if( m_stopUninstall ) {
  553. retval = SubcompOn;
  554. }
  555. break;
  556. }
  557. return( retval );
  558. }
  559. //
  560. //Routine Description:
  561. // Stop the named service and all those services which depend upon it
  562. //
  563. //Arguments:
  564. // ServiceName (Name of service to stop)
  565. //
  566. //Return Status:
  567. // TRUE - Indicates service successfully stopped
  568. // FALSE - Timeout occurred.
  569. //
  570. int StopServiceAndDependencies(LPCTSTR ServiceName)
  571. {
  572. TRACEFNHR( "StopServiceAndDependencies" );
  573. TRACE( _T("ServiceName <%s>"), ServiceName );
  574. DWORD err = NO_ERROR;
  575. SC_HANDLE hScManager = 0;
  576. SC_HANDLE hService = 0;
  577. SERVICE_STATUS statusService;
  578. AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );
  579. try {
  580. //
  581. // Open a handle to the Service.
  582. //
  583. hScManager = OpenSCManager( NULL,NULL,SC_MANAGER_CONNECT );
  584. RsOptAffirmStatus( hScManager );
  585. hService = OpenService(hScManager,ServiceName,SERVICE_QUERY_STATUS | SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_STOP | SERVICE_QUERY_CONFIG );
  586. if( !hService ) {
  587. err = GetLastError();
  588. RsOptAffirm( ERROR_SERVICE_DOES_NOT_EXIST == err, HRESULT_FROM_WIN32( err ) );
  589. RsOptThrow( S_OK );
  590. }
  591. //
  592. // Ask the service to stop.
  593. //
  594. if( !ControlService( hService, SERVICE_CONTROL_STOP, &statusService) ) {
  595. err = GetLastError();
  596. switch( err ) {
  597. case ERROR_DEPENDENT_SERVICES_RUNNING:
  598. {
  599. //
  600. // If there are dependent services running,
  601. // determine their names and stop them.
  602. //
  603. BYTE ConfigBuffer[4096];
  604. LPENUM_SERVICE_STATUS ServiceConfig = (LPENUM_SERVICE_STATUS) &ConfigBuffer;
  605. DWORD BytesNeeded, ServiceCount, ServiceIndex;
  606. //
  607. // Get the names of the dependent services.
  608. //
  609. RsOptAffirmStatus(
  610. EnumDependentServices( hService, SERVICE_ACTIVE, ServiceConfig, sizeof(ConfigBuffer), &BytesNeeded, &ServiceCount ) );
  611. //
  612. // Stop those services.
  613. //
  614. for( ServiceIndex = 0; ServiceIndex < ServiceCount; ServiceIndex++ ) {
  615. StopServiceAndDependencies( ServiceConfig[ServiceIndex].lpServiceName );
  616. }
  617. //
  618. // Ask the original service to stop.
  619. //
  620. RsOptAffirmStatus( ControlService( hService, SERVICE_CONTROL_STOP, &statusService ) );
  621. break;
  622. }
  623. case ERROR_SERVICE_CANNOT_ACCEPT_CTRL:
  624. case ERROR_SERVICE_NOT_ACTIVE:
  625. //
  626. // check if the service is already stopped..
  627. //
  628. RsOptAffirmStatus( QueryServiceStatus( hService, &statusService ) );
  629. if( SERVICE_STOPPED == statusService.dwCurrentState || SERVICE_STOP_PENDING == statusService.dwCurrentState ) {
  630. RsOptThrow( S_OK );
  631. }
  632. // Fall through
  633. default:
  634. RsOptThrow( HRESULT_FROM_WIN32( err ) );
  635. }
  636. }
  637. //
  638. // Loop waiting for the service to stop.
  639. //
  640. for( DWORD Timeout = 0; Timeout < 45; Timeout++ ) {
  641. //
  642. // Return or continue waiting depending on the state of
  643. // the service.
  644. //
  645. if( SERVICE_STOPPED == statusService.dwCurrentState ) {
  646. break;
  647. }
  648. //
  649. // Wait a second for the service to finish stopping.
  650. //
  651. Sleep( 1000 );
  652. //
  653. // Query the status of the service again.
  654. //
  655. RsOptAffirmStatus( QueryServiceStatus( hService, &statusService ) );
  656. }
  657. if( SERVICE_STOPPED != statusService.dwCurrentState ) {
  658. RsOptThrow( HRESULT_FROM_WIN32( ERROR_SERVICE_REQUEST_TIMEOUT ) );
  659. }
  660. } RsOptCatch( hrRet );
  661. if( hScManager ) CloseServiceHandle( hScManager );
  662. if( hService ) CloseServiceHandle( hService );
  663. if ( FAILED( hrRet ) ) {
  664. CString message;
  665. AfxFormatString1( message, IDS_CANNOT_STOP_SERVICES, ServiceName );
  666. AfxMessageBox( message, MB_OK | MB_ICONEXCLAMATION );
  667. }
  668. return( hrRet );
  669. }
  670. HRESULT
  671. CallExeWithParameters(
  672. LPCTSTR pszEXEName,
  673. LPCTSTR pszParameters
  674. )
  675. {
  676. TRACEFNHR( "CallExeWithParameters" );
  677. TRACE( _T("Exe <%s> Params <%s>"), pszEXEName, pszParameters );
  678. PROCESS_INFORMATION exeInfo;
  679. STARTUPINFO startupInfo;
  680. memset( &startupInfo, 0, sizeof( startupInfo ) );
  681. startupInfo.cb = sizeof( startupInfo );
  682. startupInfo.wShowWindow = SW_HIDE;
  683. startupInfo.dwFlags = STARTF_USESHOWWINDOW;
  684. CString exeCmd( pszEXEName );
  685. exeCmd += pszParameters;
  686. try {
  687. RsOptAffirmStatus( CreateProcess( 0, (LPWSTR)(LPCWSTR)exeCmd, 0, 0, FALSE, 0, 0, 0, &startupInfo, &exeInfo ) );
  688. RsOptAffirmStatus( WAIT_FAILED != WaitForSingleObject( exeInfo.hProcess, 30000 ) );
  689. } RsOptCatch( hrRet ) ;
  690. return( hrRet );
  691. }
  692. //
  693. //Method Description:
  694. // Ensure that NT Backup Registry settings exclude some RS files from backup
  695. // Don't check faiures since we want to install even if there are errors here
  696. //
  697. void CRsUninstall::EnsureBackupSettings ()
  698. {
  699. HKEY regKey = 0;
  700. WCHAR *regPath = L"System\\CurrentControlSet\\Control\\BackupRestore\\FilesNotToBackup";
  701. // open backup key
  702. if( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, regPath, (DWORD)0,
  703. KEY_ALL_ACCESS, &regKey) ) {
  704. // prepare strings
  705. //
  706. // Don't add the additional \0 at the end, the compiler will add
  707. // the additional NULL. This ensures that when we use sizeof on the string
  708. // we get the right size (including 2 NULLs at the end)
  709. //
  710. WCHAR regData[] = L"%SystemRoot%\\System32\\RemoteStorage\\*.col\0"
  711. L"%SystemRoot%\\System32\\RemoteStorage\\EngDb\\*\0"
  712. L"%SystemRoot%\\System32\\RemoteStorage\\FsaDb\\*\0"
  713. L"%SystemRoot%\\System32\\RemoteStorage\\Trace\\*\0";
  714. // set RS exclude values
  715. RegSetValueEx( regKey, RSS_BACKUP_NAME, (DWORD)0, REG_MULTI_SZ, (BYTE*)regData, sizeof(regData));
  716. // close opened key
  717. RegCloseKey (regKey);
  718. }
  719. }