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.

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