Source code of Windows XP (NT5)
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.

1326 lines
34 KiB

  1. /*
  2. * Copyright (c) 2001 Microsoft Corporation
  3. *
  4. * Module Name:
  5. *
  6. * ocgen.cpp
  7. *
  8. * Abstract:
  9. *
  10. * This file handles all messages passed by the OC Manager
  11. *
  12. * Author:
  13. *
  14. * Michael Zoran (mzoran) Dec-2001
  15. *
  16. * Environment:
  17. *
  18. * User Mode
  19. */
  20. #define _OCGEN_CPP_
  21. #include <stdlib.h>
  22. #include <assert.h>
  23. #include <tchar.h>
  24. #include <objbase.h>
  25. #include <shlwapi.h>
  26. #include <lm.h>
  27. #include <malloc.h>
  28. #include "ocgen.h"
  29. #pragma hdrstop
  30. // also referred to in ocgen.h // forward reference
  31. struct BITS_SUBCOMPONENT_DATA
  32. {
  33. const TCHAR * SubcomponentName;
  34. const TCHAR * SubcomponentKeyFileName;
  35. UINT64 FileVersion;
  36. BOOL Preinstalled;
  37. BOOL ShouldUpgrade;
  38. };
  39. DWORD OnInitComponent(LPCTSTR ComponentId, PSETUP_INIT_COMPONENT psc);
  40. DWORD_PTR OnQueryImage();
  41. DWORD OnQuerySelStateChange(LPCTSTR ComponentId, LPCTSTR SubcomponentId, UINT state, UINT flags);
  42. DWORD OnCalcDiskSpace(LPCTSTR ComponentId, LPCTSTR SubcomponentId, DWORD addComponent, HDSKSPC dspace);
  43. DWORD OnQueueFileOps(LPCTSTR ComponentId, LPCTSTR SubcomponentId, HSPFILEQ queue);
  44. DWORD OnCompleteInstallation(LPCTSTR ComponentId, LPCTSTR SubcomponentId);
  45. DWORD OnQueryState(LPCTSTR ComponentId, LPCTSTR SubcomponentId, UINT state);
  46. DWORD OnAboutToCommitQueue(LPCTSTR ComponentId, LPCTSTR SubcomponentId);
  47. DWORD OnExtraRoutines(LPCTSTR ComponentId, PEXTRA_ROUTINES per);
  48. BOOL VerifyComponent(LPCTSTR ComponentId);
  49. BOOL StateInfo(LPCTSTR SubcomponentId, BOOL *state);
  50. DWORD RegisterServers(HINF hinf, LPCTSTR component, DWORD state);
  51. DWORD EnumSections(HINF hinf, const TCHAR *component, const TCHAR *key, DWORD index, INFCONTEXT *pic, TCHAR *name);
  52. DWORD RegisterServices(PPER_COMPONENT_DATA cd, LPCTSTR component, DWORD state);
  53. DWORD CleanupNetShares(PPER_COMPONENT_DATA cd, LPCTSTR component, DWORD state);
  54. DWORD RunExternalProgram(PPER_COMPONENT_DATA cd, LPCTSTR component, DWORD state);
  55. BITS_SUBCOMPONENT_DATA* FindSubcomponent( LPCTSTR SubcomponentId );
  56. DWORD InitializeSubcomponentStates( );
  57. DWORD GetFileVersion64( LPCTSTR szFullPath, ULONG64 *pVer );
  58. DWORD GetModuleVersion64( HMODULE hDll, ULONG64 * pVer );
  59. HRESULT StopIIS();
  60. // for registering dlls
  61. typedef HRESULT (__stdcall *pfn)(void);
  62. #define KEYWORD_REGSVR TEXT("RegSvr")
  63. #define KEYWORD_UNREGSVR TEXT("UnregSvr")
  64. #define KEYWORD_UNINSTALL TEXT("Uninstall")
  65. #define KEYWORD_SOURCEPATH TEXT("SourcePath")
  66. #define KEYWORD_DELSHARE TEXT("DelShare")
  67. #define KEYWORD_ADDSERVICE TEXT("AddService")
  68. #define KEYWORD_DELSERVICE TEXT("DelService")
  69. #define KEYWORD_SHARENAME TEXT("Share")
  70. #define KEYWORD_RUN TEXT("Run")
  71. #define KEYVAL_SYSTEMSRC TEXT("SystemSrc")
  72. #define KEYWORD_COMMANDLINE TEXT("CommandLine")
  73. #define KEYWORD_TICKCOUNT TEXT("TickCount")
  74. // Services keywords/options
  75. #define KEYWORD_SERVICENAME TEXT("ServiceName")
  76. #define KEYWORD_DISPLAYNAME TEXT("DisplayName")
  77. #define KEYWORD_SERVICETYPE TEXT("ServiceType")
  78. #define KEYWORD_STARTTYPE TEXT("StartType")
  79. #define KEYWORD_ERRORCONTROL TEXT("ErrorControl")
  80. #define KEYWORD_IMAGEPATH TEXT("BinaryPathName")
  81. #define KEYWORD_LOADORDER TEXT("LoadOrderGroup")
  82. #define KEYWORD_DEPENDENCIES TEXT("Dependencies")
  83. #define KEYWORD_STARTNAME TEXT("ServiceStartName")
  84. #define KEYWORD_PASSWORD TEXT("Password")
  85. #define KEYVAL_ON TEXT("on")
  86. #define KEYVAL_OFF TEXT("off")
  87. #define KEYVAL_DEFAULT TEXT("default")
  88. const char gszRegisterSvrRoutine[] = "DllRegisterServer";
  89. const char gszUnregisterSvrRoutine[] = "DllUnregisterServer";
  90. BOOL g_fRebootNeed = FALSE;
  91. BITS_SUBCOMPONENT_DATA g_Subcomponents[] =
  92. {
  93. {
  94. TEXT("BITSServerExtensionsManager"),
  95. TEXT("bitsmgr.dll"),
  96. 0,
  97. FALSE,
  98. FALSE
  99. },
  100. {
  101. TEXT("BITSServerExtensionsISAPI"),
  102. TEXT("bitssrv.dll"),
  103. 0,
  104. FALSE,
  105. FALSE
  106. }
  107. };
  108. const ULONG g_NumberSubcomponents = 2;
  109. BOOL g_AllSubcomponentsPreinstalled = FALSE;
  110. BOOL g_UpdateNeeded = FALSE;
  111. BOOL g_IISStopped = FALSE;
  112. PER_COMPONENT_DATA g_Component;
  113. /*
  114. * called by CRT when _DllMainCRTStartup is the DLL entry point
  115. */
  116. BOOL
  117. WINAPI
  118. DllMain(
  119. IN HINSTANCE hinstance,
  120. IN DWORD reason,
  121. IN LPVOID reserved
  122. )
  123. {
  124. BOOL b;
  125. UNREFERENCED_PARAMETER(reserved);
  126. b = true;
  127. switch(reason)
  128. {
  129. case DLL_PROCESS_ATTACH:
  130. ghinst = hinstance;
  131. loginit();
  132. // Fall through to process first thread
  133. case DLL_THREAD_ATTACH:
  134. b = true;
  135. break;
  136. case DLL_PROCESS_DETACH:
  137. break;
  138. case DLL_THREAD_DETACH:
  139. break;
  140. }
  141. return(b);
  142. }
  143. DWORD_PTR
  144. OcEntry(
  145. IN LPCTSTR ComponentId,
  146. IN LPCTSTR SubcomponentId,
  147. IN UINT Function,
  148. IN UINT Param1,
  149. IN OUT PVOID Param2
  150. )
  151. {
  152. DWORD_PTR rc;
  153. DebugTraceOCNotification(Function, ComponentId);
  154. logOCNotification(Function, ComponentId);
  155. switch(Function)
  156. {
  157. case OC_PREINITIALIZE:
  158. #ifdef ANSI
  159. rc = OCFLAG_ANSI;
  160. #else
  161. rc = OCFLAG_UNICODE;
  162. #endif
  163. break;
  164. case OC_INIT_COMPONENT:
  165. rc = OnInitComponent(ComponentId, (PSETUP_INIT_COMPONENT)Param2);
  166. break;
  167. case OC_EXTRA_ROUTINES:
  168. rc = OnExtraRoutines(ComponentId, (PEXTRA_ROUTINES)Param2);
  169. break;
  170. case OC_SET_LANGUAGE:
  171. rc = (DWORD_PTR)false;
  172. break;
  173. case OC_QUERY_IMAGE:
  174. rc = OnQueryImage();
  175. break;
  176. case OC_REQUEST_PAGES:
  177. rc = 0;
  178. break;
  179. case OC_QUERY_CHANGE_SEL_STATE:
  180. rc = OnQuerySelStateChange(ComponentId, SubcomponentId, Param1, (UINT)((UINT_PTR)Param2));
  181. break;
  182. case OC_CALC_DISK_SPACE:
  183. rc = OnCalcDiskSpace(ComponentId, SubcomponentId, Param1, Param2);
  184. break;
  185. case OC_QUEUE_FILE_OPS:
  186. rc = OnQueueFileOps(ComponentId, SubcomponentId, (HSPFILEQ)Param2);
  187. break;
  188. case OC_NOTIFICATION_FROM_QUEUE:
  189. rc = NO_ERROR;
  190. break;
  191. case OC_QUERY_STEP_COUNT:
  192. rc = 2;
  193. break;
  194. case OC_COMPLETE_INSTALLATION:
  195. rc = OnCompleteInstallation(ComponentId, SubcomponentId);
  196. break;
  197. case OC_CLEANUP:
  198. rc = NO_ERROR;
  199. break;
  200. case OC_QUERY_STATE:
  201. rc = OnQueryState(ComponentId, SubcomponentId, Param1);
  202. break;
  203. case OC_NEED_MEDIA:
  204. rc = false;
  205. break;
  206. case OC_ABOUT_TO_COMMIT_QUEUE:
  207. rc = OnAboutToCommitQueue(ComponentId,SubcomponentId);
  208. break;
  209. case OC_QUERY_SKIP_PAGE:
  210. rc = false;
  211. break;
  212. case OC_WIZARD_CREATED:
  213. rc = NO_ERROR;
  214. break;
  215. default:
  216. rc = NO_ERROR;
  217. break;
  218. }
  219. DebugTrace(1, TEXT("processing completed"));
  220. logOCNotificationCompletion();
  221. return rc;
  222. }
  223. /*-------------------------------------------------------*/
  224. /*
  225. * OC Manager message handlers
  226. *
  227. *-------------------------------------------------------*/
  228. /*
  229. * OnInitComponent()
  230. *
  231. * handler for OC_INIT_COMPONENT
  232. */
  233. DWORD OnInitComponent(LPCTSTR ComponentId, PSETUP_INIT_COMPONENT psc)
  234. {
  235. INFCONTEXT context;
  236. TCHAR buf[256];
  237. HINF hinf;
  238. BOOL rc;
  239. memset( &g_Component, 0, sizeof( g_Component ) );
  240. if (!VerifyComponent( ComponentId ) )
  241. return NO_ERROR;
  242. DWORD dwResult = InitializeSubcomponentStates();
  243. if ( ERROR_SUCCESS != dwResult )
  244. return dwResult;
  245. g_IISStopped = FALSE;
  246. // store component inf handle
  247. g_Component.hinf = (psc->ComponentInfHandle == INVALID_HANDLE_VALUE)
  248. ? NULL
  249. : psc->ComponentInfHandle;
  250. // open the inf
  251. if (g_Component.hinf)
  252. SetupOpenAppendInfFile(NULL, g_Component.hinf,NULL);
  253. // copy helper routines and flags
  254. g_Component.HelperRoutines = psc->HelperRoutines;
  255. g_Component.Flags = psc->SetupData.OperationFlags;
  256. g_Component.SourcePath = NULL;
  257. // play
  258. srand(GetTickCount());
  259. return NO_ERROR;
  260. }
  261. /*
  262. * OnExtraRoutines()
  263. *
  264. * handler for OC_EXTRA_ROUTINES
  265. */
  266. DWORD OnExtraRoutines(LPCTSTR ComponentId, PEXTRA_ROUTINES per)
  267. {
  268. if (!VerifyComponent( ComponentId ) )
  269. return NO_ERROR;
  270. memcpy(&g_Component.ExtraRoutines, per, sizeof( g_Component.ExtraRoutines ) );
  271. g_Component.ExtraRoutines.size = sizeof( g_Component.ExtraRoutines );
  272. return NO_ERROR;
  273. }
  274. /*
  275. * OnSetLanguage()
  276. *
  277. * handler for OC_SET_LANGUAGE
  278. */
  279. DWORD_PTR OnQueryImage()
  280. {
  281. return (DWORD_PTR)LoadBitmap(NULL,MAKEINTRESOURCE(32754)); // OBM_CLOSE
  282. }
  283. /*
  284. * OnQuerySelStateChange()
  285. *
  286. * don't let the user deselect the sam component
  287. */
  288. DWORD OnQuerySelStateChange(LPCTSTR ComponentId,
  289. LPCTSTR SubcomponentId,
  290. UINT state,
  291. UINT flags)
  292. {
  293. DWORD rc = true;
  294. if ( !VerifyComponent( ComponentId ) )
  295. return rc;
  296. if ( !_tcsicmp( SubcomponentId, TEXT( "BITSServerExtensions" ) ) )
  297. {
  298. if ( state )
  299. {
  300. if ( flags & OCQ_DEPENDENT_SELECTION )
  301. {
  302. rc = false;
  303. }
  304. }
  305. }
  306. return rc;
  307. }
  308. /*
  309. * OnCalcDiskSpace()
  310. *
  311. * handler for OC_ON_CALC_DISK_SPACE
  312. */
  313. DWORD OnCalcDiskSpace(LPCTSTR ComponentId,
  314. LPCTSTR SubcomponentId,
  315. DWORD addComponent,
  316. HDSKSPC dspace)
  317. {
  318. DWORD rc = NO_ERROR;
  319. TCHAR section[S_SIZE];
  320. //
  321. // Param1 = 0 if for removing component or non-0 if for adding component
  322. // Param2 = HDSKSPC to operate on
  323. //
  324. // Return value is Win32 error code indicating outcome.
  325. //
  326. // In our case the private section for this component/subcomponent pair
  327. // is a simple standard inf install section, so we can use the high-level
  328. // disk space list api to do what we want.
  329. //
  330. if (!VerifyComponent( ComponentId ) )
  331. return NO_ERROR;
  332. StringCchCopy(section, S_SIZE, SubcomponentId);
  333. if (addComponent)
  334. {
  335. rc = SetupAddInstallSectionToDiskSpaceList(dspace,
  336. g_Component.hinf,
  337. NULL,
  338. section,
  339. 0,
  340. 0);
  341. }
  342. else
  343. {
  344. rc = SetupRemoveInstallSectionFromDiskSpaceList(dspace,
  345. g_Component.hinf,
  346. NULL,
  347. section,
  348. 0,
  349. 0);
  350. }
  351. if (!rc)
  352. rc = GetLastError();
  353. else
  354. rc = NO_ERROR;
  355. return rc;
  356. }
  357. /*
  358. * OnQueueFileOps()
  359. *
  360. * handler for OC_QUEUE_FILE_OPS
  361. */
  362. DWORD OnQueueFileOps(LPCTSTR ComponentId, LPCTSTR SubcomponentId, HSPFILEQ queue)
  363. {
  364. BOOL state;
  365. BOOL rc;
  366. INFCONTEXT context;
  367. TCHAR section[256];
  368. TCHAR srcpathbuf[256];
  369. TCHAR *srcpath;
  370. if (!VerifyComponent(ComponentId))
  371. return NO_ERROR;
  372. if (!SubcomponentId || !*SubcomponentId)
  373. return NO_ERROR;
  374. g_Component.queue = queue;
  375. if (!StateInfo(SubcomponentId, &state))
  376. return NO_ERROR;
  377. StringCchPrintfW(section, 256, SubcomponentId);
  378. rc = TRUE;
  379. if (!state) {
  380. // being uninstalled. Fetch uninstall section name.
  381. rc = SetupFindFirstLine(g_Component.hinf,
  382. SubcomponentId,
  383. KEYWORD_UNINSTALL,
  384. &context);
  385. if (rc) {
  386. rc = SetupGetStringField(&context,
  387. 1,
  388. section,
  389. sizeof(section) / sizeof(TCHAR),
  390. NULL);
  391. }
  392. // also, unregister the dlls and kill services before deletion
  393. SetupInstallServicesFromInfSection(g_Component.hinf, section, 0);
  394. SetupInstallFromInfSection(NULL,g_Component.hinf,section,SPINST_UNREGSVR,NULL,NULL,0,NULL,NULL,NULL,NULL);
  395. }
  396. if (rc) {
  397. // if uninstalling, don't use version checks
  398. rc = SetupInstallFilesFromInfSection(g_Component.hinf,
  399. NULL,
  400. queue,
  401. section,
  402. g_Component.SourcePath,
  403. // state ? SP_COPY_NEWER : 0);
  404. 0 );
  405. }
  406. if (!rc)
  407. return GetLastError();
  408. return NO_ERROR;
  409. }
  410. /*
  411. * OnCompleteInstallation
  412. *
  413. * handler for OC_COMPLETE_INSTALLATION
  414. */
  415. DWORD OnCompleteInstallation(LPCTSTR ComponentId, LPCTSTR SubcomponentId)
  416. {
  417. INFCONTEXT context;
  418. TCHAR section[256];
  419. BOOL state;
  420. BOOL rc;
  421. DWORD Error = NO_ERROR;
  422. // Do post-installation processing in the cleanup section.
  423. // This way we know all compoents queued for installation
  424. // have beein installed before we do our stuff.
  425. if (!VerifyComponent(ComponentId))
  426. return NO_ERROR;
  427. if (!SubcomponentId || !*SubcomponentId)
  428. return NO_ERROR;
  429. // if this is gui mode setup, need to regsvr just in case something
  430. // changed even if the files are not being replaced.
  431. if ( !(g_Component.Flags & SETUPOP_STANDALONE) &&
  432. ( ( _tcsicmp( TEXT("BITSServerExtensionsManager"), SubcomponentId ) == 0 ) ||
  433. ( _tcsicmp( TEXT("BITSServerExtensionsISAPI"), SubcomponentId ) == 0 ) ) )
  434. {
  435. BOOL SettingChanged = StateInfo( SubcomponentId, &state );
  436. if ( !SettingChanged && !state )
  437. return NO_ERROR; // if its not installed, leave it uninstalled.
  438. }
  439. else if ( !StateInfo( SubcomponentId, &state) )
  440. return NO_ERROR;
  441. StringCchPrintfW(section, 256, SubcomponentId);
  442. rc = TRUE;
  443. if (!state) {
  444. // being uninstalled. Fetch uninstall section name.
  445. rc = SetupFindFirstLine(g_Component.hinf,
  446. SubcomponentId,
  447. KEYWORD_UNINSTALL,
  448. &context);
  449. if (rc) {
  450. rc = SetupGetStringField(&context,
  451. 1,
  452. section,
  453. sizeof(section) / sizeof(TCHAR),
  454. NULL);
  455. }
  456. }
  457. if (state) {
  458. //
  459. // installation
  460. //
  461. if (rc) {
  462. // process the inf file
  463. rc = SetupInstallFromInfSection(NULL, // hwndOwner
  464. g_Component.hinf, // inf handle
  465. section, // name of component
  466. SPINST_ALL & ~SPINST_FILES,
  467. NULL, // relative key root
  468. NULL, // source root path
  469. 0, // copy flags
  470. NULL, // callback routine
  471. NULL, // callback routine context
  472. NULL, // device info set
  473. NULL); // device info struct
  474. if (rc) {
  475. rc = SetupInstallServicesFromInfSection(g_Component.hinf, section, 0);
  476. Error = GetLastError();
  477. if (!rc && Error == ERROR_SECTION_NOT_FOUND) {
  478. rc = TRUE;
  479. Error = NO_ERROR;
  480. }
  481. if (rc) {
  482. if (Error == ERROR_SUCCESS_REBOOT_REQUIRED) {
  483. g_Component.HelperRoutines.SetReboot(g_Component.HelperRoutines.OcManagerContext,TRUE);
  484. }
  485. Error = NO_ERROR;
  486. rc = RunExternalProgram(&g_Component, section, state);
  487. }
  488. }
  489. }
  490. } else {
  491. //
  492. // uninstallation
  493. //
  494. if (rc)
  495. {
  496. rc = RunExternalProgram(&g_Component, section, state);
  497. }
  498. if (rc) {
  499. rc = CleanupNetShares(&g_Component, section, state);
  500. }
  501. }
  502. if (!rc && (Error == NO_ERROR) ) {
  503. Error = GetLastError( );
  504. }
  505. return Error;
  506. }
  507. /*
  508. * OnQueryState()
  509. *
  510. * handler for OC_QUERY_STATE
  511. */
  512. DWORD OnQueryState(LPCTSTR ComponentId,
  513. LPCTSTR SubcomponentId,
  514. UINT state)
  515. {
  516. if ( !VerifyComponent( ComponentId ) )
  517. return SubcompUseOcManagerDefault;
  518. BITS_SUBCOMPONENT_DATA* SubcomponentData =
  519. FindSubcomponent( SubcomponentId );
  520. if ( !SubcomponentData )
  521. {
  522. if ( !_tcsicmp( TEXT( "BITSServerExtensions" ), SubcomponentId ) )
  523. {
  524. if ( OCSELSTATETYPE_ORIGINAL == state &&
  525. g_AllSubcomponentsPreinstalled )
  526. return SubcompOn;
  527. else
  528. return SubcompUseOcManagerDefault;
  529. }
  530. else
  531. return SubcompUseOcManagerDefault;
  532. }
  533. if ( OCSELSTATETYPE_ORIGINAL == state )
  534. {
  535. return SubcomponentData->Preinstalled ? SubcompOn : SubcompOff;
  536. }
  537. return SubcompUseOcManagerDefault;
  538. }
  539. /*
  540. * OnAboutToCommitQueue()
  541. *
  542. * handler for OC_ABOUT_TO_COMMIT_QUEUE
  543. */
  544. DWORD OnAboutToCommitQueue(LPCTSTR ComponentId, LPCTSTR SubcomponentId)
  545. {
  546. BOOL state;
  547. BOOL rc;
  548. INFCONTEXT context;
  549. TCHAR section[256];
  550. TCHAR srcpathbuf[256];
  551. TCHAR *srcpath;
  552. if (!VerifyComponent( ComponentId ))
  553. return NO_ERROR;
  554. if (!SubcomponentId || !*SubcomponentId)
  555. return NO_ERROR;
  556. if (!StateInfo( SubcomponentId, &state))
  557. return NO_ERROR;
  558. if (state) {
  559. if ( g_UpdateNeeded )
  560. {
  561. if ( !g_IISStopped )
  562. {
  563. StopIIS();
  564. g_IISStopped = FALSE;
  565. }
  566. }
  567. return NO_ERROR;
  568. }
  569. // Fetch uninstall section name.
  570. rc = SetupFindFirstLine(
  571. g_Component.hinf,
  572. SubcomponentId,
  573. KEYWORD_UNINSTALL,
  574. &context);
  575. if (rc) {
  576. rc = SetupGetStringField(
  577. &context,
  578. 1,
  579. section,
  580. sizeof(section) / sizeof(TCHAR),
  581. NULL);
  582. }
  583. if (rc)
  584. rc = SetupInstallServicesFromInfSection(g_Component.hinf, section, 0);
  585. if (rc) {
  586. rc = SetupInstallFromInfSection(
  587. NULL,
  588. g_Component.hinf,
  589. section,
  590. SPINST_ALL & ~SPINST_FILES,
  591. NULL,
  592. NULL,
  593. 0,
  594. NULL,
  595. NULL,
  596. NULL,
  597. NULL);
  598. }
  599. if (rc) {
  600. SetLastError(NO_ERROR);
  601. }
  602. return GetLastError();
  603. }
  604. BOOL VerifyComponent( LPCTSTR ComponentId )
  605. {
  606. if ( !_tcsicmp( ComponentId, TEXT("BITSServerExtensions") ) )
  607. return TRUE;
  608. return FALSE;
  609. }
  610. // loads current selection state info into "state" and
  611. // returns whether the selection state was changed
  612. BOOL
  613. StateInfo(
  614. LPCTSTR SubcomponentId,
  615. BOOL *state
  616. )
  617. {
  618. BOOL rc = TRUE;
  619. assert(state);
  620. // otherwise, check for a change in installation state
  621. *state = g_Component.HelperRoutines.QuerySelectionState(
  622. g_Component.HelperRoutines.OcManagerContext,
  623. SubcomponentId,
  624. OCSELSTATETYPE_CURRENT);
  625. if (*state == g_Component.HelperRoutines.QuerySelectionState(
  626. g_Component.HelperRoutines.OcManagerContext,
  627. SubcomponentId,
  628. OCSELSTATETYPE_ORIGINAL))
  629. {
  630. // no change
  631. rc = FALSE;
  632. }
  633. if ( *state )
  634. {
  635. BITS_SUBCOMPONENT_DATA* SubcomponentData = FindSubcomponent( SubcomponentId );
  636. if ( SubcomponentData && g_UpdateNeeded )
  637. rc = TRUE;
  638. }
  639. return rc;
  640. }
  641. /*
  642. * EnumSections()
  643. *
  644. * finds the name of a section for a specified keyword
  645. */
  646. DWORD
  647. EnumSections(
  648. HINF hinf,
  649. const TCHAR *component,
  650. const TCHAR *key,
  651. DWORD index,
  652. INFCONTEXT *pic,
  653. TCHAR *name
  654. )
  655. {
  656. TCHAR section[S_SIZE];
  657. if (!SetupFindFirstLine(hinf, component, NULL, pic))
  658. return 0;
  659. if (!SetupFindNextMatchLine(pic, key, pic))
  660. return 0;
  661. if (index > SetupGetFieldCount(pic))
  662. return 0;
  663. if (!SetupGetStringField(pic, index, section, SBUF_SIZE, NULL))
  664. return 0;
  665. if (name)
  666. StringCchCopy(name, S_SIZE, section);
  667. return SetupFindFirstLine(hinf, section, NULL, pic);
  668. }
  669. DWORD
  670. OcLog(
  671. LPCTSTR ComponentId,
  672. UINT level,
  673. LPCTSTR sz
  674. )
  675. {
  676. TCHAR fmt[5000];
  677. PPER_COMPONENT_DATA cd;
  678. if (!VerifyComponent( ComponentId ) )
  679. return NO_ERROR;
  680. assert(g_Component.ExtraRoutines.LogError);
  681. assert(level);
  682. assert(sz);
  683. StringCchCopy(fmt, 5000, TEXT("%s: %s"));
  684. return g_Component.ExtraRoutines.LogError(
  685. g_Component.HelperRoutines.OcManagerContext,
  686. level,
  687. fmt,
  688. ComponentId,
  689. sz);
  690. }
  691. DWORD
  692. CleanupNetShares(
  693. PPER_COMPONENT_DATA cd,
  694. LPCTSTR component,
  695. DWORD state)
  696. {
  697. INFCONTEXT ic;
  698. TCHAR sname[S_SIZE];
  699. DWORD section;
  700. TCHAR *keyword;
  701. if (state) {
  702. return NO_ERROR;
  703. } else {
  704. keyword = KEYWORD_DELSHARE;
  705. }
  706. for (section = 1;
  707. EnumSections(cd->hinf, component, keyword, section, &ic, sname);
  708. section++)
  709. {
  710. INFCONTEXT sic;
  711. NET_API_STATUS netStat;
  712. CHAR Temp[SBUF_SIZE];
  713. TCHAR ShareName[ SBUF_SIZE ];
  714. if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_SHARENAME, &sic))
  715. {
  716. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_SHARENAME );
  717. continue;
  718. }
  719. if (!SetupGetStringField(&sic, 1, ShareName, SBUF_SIZE, NULL))
  720. {
  721. log( TEXT("OCGEN: %s INF error - incorrect %s line\r\n"), keyword, KEYWORD_SHARENAME );
  722. continue;
  723. }
  724. #ifdef UNICODE
  725. netStat = NetShareDel( NULL, ShareName, 0 );
  726. #else // UNICODE
  727. WCHAR ShareNameW[ SBUF_SIZE ];
  728. mbstowcs( ShareNameW, ShareName, lstrlen(ShareName));
  729. netStat = NetShareDel( NULL, ShareNameW, 0 );
  730. #endif // UNICODE
  731. if ( netStat != NERR_Success )
  732. {
  733. log( TEXT("OCGEN: Failed to remove %s share. Error 0x%08x\r\n"), ShareName, netStat );
  734. continue;
  735. }
  736. log( TEXT("OCGEN: %s share removed successfully.\r\n"), ShareName );
  737. }
  738. return TRUE;
  739. }
  740. DWORD
  741. RunExternalProgram(
  742. PPER_COMPONENT_DATA cd,
  743. LPCTSTR component,
  744. DWORD state)
  745. {
  746. INFCONTEXT ic;
  747. TCHAR sname[S_SIZE];
  748. DWORD section;
  749. TCHAR *keyword;
  750. keyword = KEYWORD_RUN;
  751. for (section = 1;
  752. EnumSections(cd->hinf, component, keyword, section, &ic, sname);
  753. section++)
  754. {
  755. INFCONTEXT sic;
  756. TCHAR CommandLine[ SBUF_SIZE ];
  757. CHAR szTickCount[ SBUF_SIZE ];
  758. ULONG TickCount;
  759. BOOL b;
  760. STARTUPINFO startupinfo;
  761. PROCESS_INFORMATION process_information;
  762. DWORD dwErr;
  763. if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_COMMANDLINE , &sic))
  764. {
  765. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_COMMANDLINE );
  766. continue;
  767. }
  768. if (!SetupGetStringField(&sic, 1, CommandLine, SBUF_SIZE, NULL))
  769. {
  770. log( TEXT("OCGEN: %s INF error - incorrect %s line\r\n"), keyword, KEYWORD_COMMANDLINE );
  771. continue;
  772. }
  773. if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_TICKCOUNT, &sic))
  774. {
  775. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_TICKCOUNT );
  776. continue;
  777. }
  778. if (!SetupGetStringFieldA(&sic, 1, szTickCount, SBUF_SIZE, NULL))
  779. {
  780. log( TEXT("OCGEN: %s INF error - incorrect %s line\r\n"), keyword, KEYWORD_TICKCOUNT );
  781. continue;
  782. }
  783. TickCount = atoi( szTickCount );
  784. ZeroMemory( &startupinfo, sizeof(startupinfo) );
  785. startupinfo.cb = sizeof(startupinfo);
  786. startupinfo.dwFlags = STARTF_USESHOWWINDOW;
  787. startupinfo.wShowWindow = SW_HIDE | SW_SHOWMINNOACTIVE;
  788. b = CreateProcess( NULL,
  789. CommandLine,
  790. NULL,
  791. NULL,
  792. FALSE,
  793. CREATE_DEFAULT_ERROR_MODE,
  794. NULL,
  795. NULL,
  796. &startupinfo,
  797. &process_information );
  798. if ( !b )
  799. {
  800. log( TEXT("OCGEN: failed to spawn %s process.\r\n"), CommandLine );
  801. continue;
  802. }
  803. dwErr = WaitForSingleObject( process_information.hProcess, TickCount * 1000 );
  804. if ( dwErr != NO_ERROR )
  805. {
  806. log( TEXT("OCGEN: WaitForSingleObject() failed. Error 0x%08x\r\n"), dwErr );
  807. TerminateProcess( process_information.hProcess, -1 );
  808. CloseHandle( process_information.hProcess );
  809. CloseHandle( process_information.hThread );
  810. continue;
  811. }
  812. CloseHandle( process_information.hProcess );
  813. CloseHandle( process_information.hThread );
  814. log( TEXT("OCGEN: %s successfully completed within %u seconds.\r\n"), CommandLine, TickCount );
  815. }
  816. return TRUE;
  817. }
  818. BITS_SUBCOMPONENT_DATA*
  819. FindSubcomponent( LPCTSTR SubcomponentId )
  820. {
  821. for( unsigned int i = 0; i < g_NumberSubcomponents; i++ )
  822. {
  823. if ( _tcsicmp( SubcomponentId, g_Subcomponents[i].SubcomponentName ) == 0 )
  824. return &g_Subcomponents[i];
  825. }
  826. return NULL;
  827. }
  828. DWORD
  829. InitializeSubcomponentStates()
  830. {
  831. // Load this module's version information
  832. DWORD dwResult;
  833. ULONG64 ThisModuleVersion;
  834. BOOL AllSubcomponentsPreinstalled = TRUE;
  835. BOOL UpdateNeeded = TRUE;
  836. dwResult = GetModuleVersion64( ghinst, &ThisModuleVersion );
  837. if ( ERROR_SUCCESS != dwResult )
  838. return dwResult;
  839. TCHAR SystemDirectory[ MAX_PATH * 2 ];
  840. GetSystemWindowsDirectory( SystemDirectory, MAX_PATH + 1 );
  841. StringCchCat( SystemDirectory, MAX_PATH * 2, TEXT("\\System32\\") );
  842. for( unsigned int i = 0; i < g_NumberSubcomponents; i++ )
  843. {
  844. TCHAR FileName[ MAX_PATH * 2 ];
  845. StringCchCopy( FileName, MAX_PATH * 2, SystemDirectory );
  846. StringCchCatW( FileName, MAX_PATH * 2, g_Subcomponents[ i ].SubcomponentKeyFileName );
  847. dwResult = GetFileVersion64( FileName, &g_Subcomponents[ i ].FileVersion );
  848. // If the file isn't found, skip it
  849. if ( ERROR_FILE_NOT_FOUND == dwResult ||
  850. ERROR_PATH_NOT_FOUND == dwResult )
  851. {
  852. AllSubcomponentsPreinstalled = FALSE;
  853. continue;
  854. }
  855. if ( dwResult != ERROR_SUCCESS )
  856. return dwResult;
  857. g_Subcomponents[ i ].Preinstalled = TRUE;
  858. g_Subcomponents[ i ].ShouldUpgrade = g_Subcomponents[ i ].FileVersion < ThisModuleVersion;
  859. if ( g_Subcomponents[i].ShouldUpgrade )
  860. UpdateNeeded = TRUE;
  861. }
  862. g_AllSubcomponentsPreinstalled = AllSubcomponentsPreinstalled;
  863. g_UpdateNeeded = TRUE;
  864. return ERROR_SUCCESS;
  865. }
  866. DWORD
  867. GetFileVersion64(
  868. LPCTSTR szFullPath,
  869. ULONG64 * pVer
  870. )
  871. {
  872. DWORD dwHandle;
  873. DWORD dwLen;
  874. *pVer = 0;
  875. //
  876. // Check to see if the file exists
  877. //
  878. DWORD dwAttributes = GetFileAttributes( szFullPath );
  879. if ( INVALID_FILE_ATTRIBUTES == dwAttributes )
  880. return GetLastError();
  881. //
  882. // Get the file version info size
  883. //
  884. if ((dwLen = GetFileVersionInfoSize( (LPTSTR)szFullPath, &dwHandle)) == 0)
  885. return GetLastError();
  886. //
  887. // Allocate enough size to hold version info
  888. //
  889. char * VersionInfo = new char[ dwLen ];
  890. if ( !VersionInfo )
  891. return ERROR_NOT_ENOUGH_MEMORY;
  892. //
  893. // Get the version info
  894. //
  895. if (!GetFileVersionInfo( (LPTSTR)szFullPath, dwHandle, dwLen, VersionInfo ))
  896. {
  897. DWORD Error = GetLastError();
  898. delete[] VersionInfo;
  899. return Error;
  900. }
  901. {
  902. VS_FIXEDFILEINFO *pvsfi;
  903. UINT dwLen2;
  904. if ( VerQueryValue(
  905. VersionInfo,
  906. TEXT("\\"),
  907. (LPVOID *)&pvsfi,
  908. &dwLen2
  909. ) )
  910. {
  911. *pVer = ( ULONG64(pvsfi->dwFileVersionMS) << 32) | (pvsfi->dwFileVersionLS);
  912. }
  913. }
  914. delete[] VersionInfo;
  915. return ERROR_SUCCESS;
  916. }
  917. //
  918. // This ungainly typedef seems to have no global definition. There are several identical
  919. // definitions in the Windows NT sources, each of which has that bizarre bit-stripping
  920. // on szKey. I got mine from \nt\base\ntsetup\srvpack\update\splib\common.h.
  921. //
  922. typedef struct tagVERHEAD {
  923. WORD wTotLen;
  924. WORD wValLen;
  925. WORD wType; /* always 0 */
  926. WCHAR szKey[(sizeof("VS_VERSION_INFO")+3)&~03];
  927. VS_FIXEDFILEINFO vsf;
  928. } VERHEAD ;
  929. DWORD
  930. GetModuleVersion64(
  931. HMODULE hDll,
  932. ULONG64 * pVer
  933. )
  934. {
  935. DWORD* pdwTranslation;
  936. VS_FIXEDFILEINFO* pFileInfo;
  937. UINT uiSize;
  938. *pVer = 0;
  939. HRSRC hrsrcVersion = FindResource(
  940. hDll,
  941. MAKEINTRESOURCE(VS_VERSION_INFO),
  942. RT_VERSION);
  943. if (!hrsrcVersion)
  944. return GetLastError();
  945. HGLOBAL hglobalVersion = LoadResource(hDll, hrsrcVersion);
  946. if (!hglobalVersion)
  947. return GetLastError();
  948. VERHEAD * pVerHead = (VERHEAD *) LockResource(hglobalVersion);
  949. if (!pVerHead)
  950. return GetLastError();
  951. // I stole this code from \nt\com\complus\src\shared\util\svcerr.cpp,
  952. // and the comment is theirs:
  953. //
  954. // VerQueryValue will write to the memory, for some reason.
  955. // Therefore we must make a writable copy of the version
  956. // resource info before calling that API.
  957. void *pvVersionInfo = new char[ pVerHead->wTotLen + pVerHead->wTotLen/2 ];
  958. if ( !pvVersionInfo )
  959. return ERROR_NOT_ENOUGH_MEMORY;
  960. memcpy(pvVersionInfo, pVerHead, pVerHead->wTotLen);
  961. // Retrieve file version info
  962. if ( VerQueryValue( pvVersionInfo,
  963. L"\\",
  964. (void**)&pFileInfo,
  965. &uiSize) )
  966. {
  967. *pVer = (ULONG64(pFileInfo->dwFileVersionMS) << 32) | (pFileInfo->dwFileVersionLS);
  968. }
  969. delete[] pvVersionInfo;
  970. return ERROR_SUCCESS;
  971. }
  972. HRESULT
  973. BITSGetStartupInfo(
  974. LPSTARTUPINFOA lpStartupInfo )
  975. {
  976. __try
  977. {
  978. GetStartupInfoA( lpStartupInfo );
  979. }
  980. __except( EXCEPTION_EXECUTE_HANDLER )
  981. {
  982. return E_OUTOFMEMORY;
  983. }
  984. return S_OK;
  985. }
  986. HRESULT StopIIS()
  987. {
  988. //
  989. // Restarts IIS by calling "iisreset /stop" at the commandline.
  990. //
  991. STARTUPINFOA StartupInfo;
  992. HRESULT Hr = BITSGetStartupInfo( &StartupInfo );
  993. if ( FAILED( Hr ) )
  994. return Hr;
  995. #define IISSTOP_EXE "iisreset.exe"
  996. #define IISSTOP_CMDLINE "iisreset /stop"
  997. PROCESS_INFORMATION ProcessInfo;
  998. CHAR sApplicationPath[MAX_PATH];
  999. CHAR *pApplicationName = NULL;
  1000. CHAR sCmdLine[MAX_PATH];
  1001. DWORD dwLen = MAX_PATH;
  1002. DWORD dwCount;
  1003. dwCount = SearchPathA(NULL, // Search Path, NULL is PATH
  1004. IISSTOP_EXE, // Application
  1005. NULL, // Extension (already specified)
  1006. dwLen, // Length (char's) of sApplicationPath
  1007. sApplicationPath, // Path + Name for application
  1008. &pApplicationName ); // File part of sApplicationPath
  1009. if (dwCount == 0)
  1010. {
  1011. return HRESULT_FROM_WIN32( GetLastError() );
  1012. }
  1013. if (dwCount > dwLen)
  1014. {
  1015. return HRESULT_FROM_WIN32( ERROR_BUFFER_OVERFLOW );
  1016. }
  1017. StringCbCopyA(sCmdLine, MAX_PATH, IISSTOP_CMDLINE);
  1018. BOOL RetVal = CreateProcessA(
  1019. sApplicationPath, // name of executable module
  1020. sCmdLine, // command line string
  1021. NULL, // SD
  1022. NULL, // SD
  1023. FALSE, // handle inheritance option
  1024. CREATE_NO_WINDOW, // creation flags
  1025. NULL, // new environment block
  1026. NULL, // current directory name
  1027. &StartupInfo, // startup information
  1028. &ProcessInfo // process information
  1029. );
  1030. if ( !RetVal )
  1031. return HRESULT_FROM_WIN32( GetLastError() );
  1032. WaitForSingleObject( ProcessInfo.hProcess, INFINITE );
  1033. DWORD Status;
  1034. GetExitCodeProcess( ProcessInfo.hProcess, &Status );
  1035. CloseHandle( ProcessInfo.hProcess );
  1036. CloseHandle( ProcessInfo.hThread );
  1037. return HRESULT_FROM_WIN32( Status );
  1038. }