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.

1548 lines
39 KiB

  1. /*
  2. * Copyright (c) 1996 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. * Pat Styles (patst) Jan-20-1998
  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 "ocgen.h"
  28. #pragma hdrstop
  29. // also referred to in ocgen.h // forward reference
  30. DWORD OnPreinitialize();
  31. DWORD OnInitComponent(LPCTSTR ComponentId, PSETUP_INIT_COMPONENT psc);
  32. DWORD OnSetLanguage();
  33. DWORD_PTR OnQueryImage();
  34. DWORD OnSetupRequestPages(UINT type, PVOID srp);
  35. DWORD OnQuerySelStateChange(LPCTSTR ComponentId, LPCTSTR SubcomponentId, UINT state, UINT flags);
  36. DWORD OnCalcDiskSpace(LPCTSTR ComponentId, LPCTSTR SubcomponentId, DWORD addComponent, HDSKSPC dspace);
  37. DWORD OnQueueFileOps(LPCTSTR ComponentId, LPCTSTR SubcomponentId, HSPFILEQ queue);
  38. DWORD OnNotificationFromQueue();
  39. DWORD OnQueryStepCount();
  40. DWORD OnCompleteInstallation(LPCTSTR ComponentId, LPCTSTR SubcomponentId);
  41. DWORD OnCleanup();
  42. DWORD OnQueryState(LPCTSTR ComponentId, LPCTSTR SubcomponentId, UINT state);
  43. DWORD OnNeedMedia();
  44. DWORD OnAboutToCommitQueue(LPCTSTR ComponentId, LPCTSTR SubcomponentId);
  45. DWORD OnQuerySkipPage();
  46. DWORD OnWizardCreated();
  47. DWORD OnExtraRoutines(LPCTSTR ComponentId, PEXTRA_ROUTINES per);
  48. PPER_COMPONENT_DATA AddNewComponent(LPCTSTR ComponentId);
  49. PPER_COMPONENT_DATA LocateComponent(LPCTSTR ComponentId);
  50. VOID RemoveComponent(LPCTSTR ComponentId);
  51. BOOL StateInfo(PPER_COMPONENT_DATA cd, LPCTSTR SubcomponentId, BOOL *state);
  52. DWORD RegisterServers(HINF hinf, LPCTSTR component, DWORD state);
  53. DWORD EnumSections(HINF hinf, const TCHAR *component, const TCHAR *key, DWORD index, INFCONTEXT *pic, TCHAR *name);
  54. DWORD RegisterServices(PPER_COMPONENT_DATA cd, LPCTSTR component, DWORD state);
  55. DWORD CleanupNetShares(PPER_COMPONENT_DATA cd, LPCTSTR component, DWORD state);
  56. DWORD RunExternalProgram(PPER_COMPONENT_DATA cd, LPCTSTR component, DWORD state);
  57. // for registering dlls
  58. typedef HRESULT (__stdcall *pfn)(void);
  59. #define KEYWORD_REGSVR TEXT("RegSvr")
  60. #define KEYWORD_UNREGSVR TEXT("UnregSvr")
  61. #define KEYWORD_UNINSTALL TEXT("Uninstall")
  62. #define KEYWORD_SOURCEPATH TEXT("SourcePath")
  63. #define KEYWORD_DELSHARE TEXT("DelShare")
  64. #define KEYWORD_ADDSERVICE TEXT("AddService")
  65. #define KEYWORD_DELSERVICE TEXT("DelService")
  66. #define KEYWORD_SHARENAME TEXT("Share")
  67. #define KEYWORD_RUN TEXT("Run")
  68. #define KEYVAL_SYSTEMSRC TEXT("SystemSrc")
  69. #define KEYWORD_COMMANDLINE TEXT("CommandLine")
  70. #define KEYWORD_TICKCOUNT TEXT("TickCount")
  71. // Services keywords/options
  72. #define KEYWORD_SERVICENAME TEXT("ServiceName")
  73. #define KEYWORD_DISPLAYNAME TEXT("DisplayName")
  74. #define KEYWORD_SERVICETYPE TEXT("ServiceType")
  75. #define KEYWORD_STARTTYPE TEXT("StartType")
  76. #define KEYWORD_ERRORCONTROL TEXT("ErrorControl")
  77. #define KEYWORD_IMAGEPATH TEXT("BinaryPathName")
  78. #define KEYWORD_LOADORDER TEXT("LoadOrderGroup")
  79. #define KEYWORD_DEPENDENCIES TEXT("Dependencies")
  80. #define KEYWORD_STARTNAME TEXT("ServiceStartName")
  81. #define KEYWORD_PASSWORD TEXT("Password")
  82. #define KEYVAL_ON TEXT("on")
  83. #define KEYVAL_OFF TEXT("off")
  84. #define KEYVAL_DEFAULT TEXT("default")
  85. const char gszRegisterSvrRoutine[] = "DllRegisterServer";
  86. const char gszUnregisterSvrRoutine[] = "DllUnregisterServer";
  87. BOOL g_fRebootNeed = FALSE;
  88. PPER_COMPONENT_DATA _cd;
  89. void av()
  90. {
  91. _cd = NULL;
  92. _cd->hinf = NULL;
  93. }
  94. /*
  95. * called by CRT when _DllMainCRTStartup is the DLL entry point
  96. */
  97. BOOL
  98. WINAPI
  99. DllMain(
  100. IN HINSTANCE hinstance,
  101. IN DWORD reason,
  102. IN LPVOID reserved
  103. )
  104. {
  105. BOOL b;
  106. UNREFERENCED_PARAMETER(reserved);
  107. b = true;
  108. switch(reason)
  109. {
  110. case DLL_PROCESS_ATTACH:
  111. ghinst = hinstance;
  112. loginit();
  113. // Fall through to process first thread
  114. case DLL_THREAD_ATTACH:
  115. b = true;
  116. break;
  117. case DLL_PROCESS_DETACH:
  118. break;
  119. case DLL_THREAD_DETACH:
  120. break;
  121. }
  122. return(b);
  123. }
  124. DWORD_PTR
  125. OcEntry(
  126. IN LPCTSTR ComponentId,
  127. IN LPCTSTR SubcomponentId,
  128. IN UINT Function,
  129. IN UINT Param1,
  130. IN OUT PVOID Param2
  131. )
  132. {
  133. DWORD_PTR rc;
  134. DebugTraceOCNotification(Function, ComponentId);
  135. logOCNotification(Function, ComponentId);
  136. switch(Function)
  137. {
  138. case OC_PREINITIALIZE:
  139. rc = OnPreinitialize();
  140. break;
  141. case OC_INIT_COMPONENT:
  142. rc = OnInitComponent(ComponentId, (PSETUP_INIT_COMPONENT)Param2);
  143. break;
  144. case OC_EXTRA_ROUTINES:
  145. rc = OnExtraRoutines(ComponentId, (PEXTRA_ROUTINES)Param2);
  146. break;
  147. case OC_SET_LANGUAGE:
  148. rc = OnSetLanguage();
  149. break;
  150. case OC_QUERY_IMAGE:
  151. rc = OnQueryImage();
  152. break;
  153. case OC_REQUEST_PAGES:
  154. rc = OnSetupRequestPages(Param1, Param2);
  155. break;
  156. case OC_QUERY_CHANGE_SEL_STATE:
  157. rc = OnQuerySelStateChange(ComponentId, SubcomponentId, Param1, (UINT)((UINT_PTR)Param2));
  158. break;
  159. case OC_CALC_DISK_SPACE:
  160. rc = OnCalcDiskSpace(ComponentId, SubcomponentId, Param1, Param2);
  161. break;
  162. case OC_QUEUE_FILE_OPS:
  163. rc = OnQueueFileOps(ComponentId, SubcomponentId, (HSPFILEQ)Param2);
  164. break;
  165. case OC_NOTIFICATION_FROM_QUEUE:
  166. rc = OnNotificationFromQueue();
  167. break;
  168. case OC_QUERY_STEP_COUNT:
  169. rc = OnQueryStepCount();
  170. break;
  171. case OC_COMPLETE_INSTALLATION:
  172. rc = OnCompleteInstallation(ComponentId, SubcomponentId);
  173. break;
  174. case OC_CLEANUP:
  175. rc = OnCleanup();
  176. break;
  177. case OC_QUERY_STATE:
  178. rc = OnQueryState(ComponentId, SubcomponentId, Param1);
  179. break;
  180. case OC_NEED_MEDIA:
  181. rc = OnNeedMedia();
  182. break;
  183. case OC_ABOUT_TO_COMMIT_QUEUE:
  184. rc = OnAboutToCommitQueue(ComponentId,SubcomponentId);
  185. break;
  186. case OC_QUERY_SKIP_PAGE:
  187. rc = OnQuerySkipPage();
  188. break;
  189. case OC_WIZARD_CREATED:
  190. rc = OnWizardCreated();
  191. break;
  192. default:
  193. rc = NO_ERROR;
  194. break;
  195. }
  196. DebugTrace(1, TEXT("processing completed"));
  197. logOCNotificationCompletion();
  198. return rc;
  199. }
  200. /*-------------------------------------------------------*/
  201. /*
  202. * OC Manager message handlers
  203. *
  204. *-------------------------------------------------------*/
  205. /* OnPreinitialize()
  206. *
  207. * handler for OC_PREINITIALIZE
  208. */
  209. DWORD
  210. OnPreinitialize(
  211. VOID
  212. )
  213. {
  214. #ifdef ANSI
  215. return OCFLAG_ANSI;
  216. #else
  217. return OCFLAG_UNICODE;
  218. #endif
  219. }
  220. /*
  221. * OnInitComponent()
  222. *
  223. * handler for OC_INIT_COMPONENT
  224. */
  225. DWORD OnInitComponent(LPCTSTR ComponentId, PSETUP_INIT_COMPONENT psc)
  226. {
  227. PPER_COMPONENT_DATA cd;
  228. INFCONTEXT context;
  229. TCHAR buf[256];
  230. HINF hinf;
  231. BOOL rc;
  232. // assert(0);
  233. // av();
  234. // add component to linked list
  235. if (!(cd = AddNewComponent(ComponentId)))
  236. return ERROR_NOT_ENOUGH_MEMORY;
  237. // store component inf handle
  238. cd->hinf = (psc->ComponentInfHandle == INVALID_HANDLE_VALUE)
  239. ? NULL
  240. : psc->ComponentInfHandle;
  241. // open the inf
  242. if (cd->hinf)
  243. SetupOpenAppendInfFile(NULL, cd->hinf,NULL);
  244. // copy helper routines and flags
  245. cd->HelperRoutines = psc->HelperRoutines;
  246. cd->Flags = psc->SetupData.OperationFlags;
  247. cd->SourcePath = NULL;
  248. #if 0
  249. // Setup the SourcePath. Read inf and see if we should use the NT setup source.
  250. // If so, set to null and setupapi will take care of this for us. If there is
  251. // something specified in the inf, use it, otherwise use what is passed to us.
  252. *buf = 0;
  253. rc = SetupFindFirstLine(cd->hinf,
  254. ComponentId,
  255. KEYWORD_SOURCEPATH,
  256. &context);
  257. if (rc) {
  258. rc = SetupGetStringField(&context,
  259. 1,
  260. buf,
  261. sizeof(buf) / sizeof(TCHAR),
  262. NULL);
  263. }
  264. if (!_tcsicmp(buf, KEYVAL_SYSTEMSRC)) {
  265. cd->SourcePath = NULL;
  266. } else {
  267. cd->SourcePath = (TCHAR *)LocalAlloc(LMEM_FIXED, SBUF_SIZE);
  268. if (!cd->SourcePath)
  269. return ERROR_CANCELLED;
  270. if (!*buf)
  271. _tcscpy(cd->SourcePath, psc->SetupData.SourcePath);
  272. else
  273. ExpandEnvironmentStrings(buf, cd->SourcePath, S_SIZE);
  274. }
  275. #endif
  276. // play
  277. srand(GetTickCount());
  278. return NO_ERROR;
  279. }
  280. /*
  281. * OnExtraRoutines()
  282. *
  283. * handler for OC_EXTRA_ROUTINES
  284. */
  285. DWORD OnExtraRoutines(LPCTSTR ComponentId, PEXTRA_ROUTINES per)
  286. {
  287. PPER_COMPONENT_DATA cd;
  288. if (!(cd = LocateComponent(ComponentId)))
  289. return NO_ERROR;
  290. memcpy(&cd->ExtraRoutines, per, per->size);
  291. return NO_ERROR;
  292. }
  293. /*
  294. * OnSetLanguage()
  295. *
  296. * handler for OC_SET_LANGUAGE
  297. */
  298. DWORD OnSetLanguage()
  299. {
  300. return false;
  301. }
  302. /*
  303. * OnSetLanguage()
  304. *
  305. * handler for OC_SET_LANGUAGE
  306. */
  307. DWORD_PTR OnQueryImage()
  308. {
  309. return (DWORD_PTR)LoadBitmap(NULL,MAKEINTRESOURCE(32754)); // OBM_CLOSE
  310. }
  311. /*
  312. * OnSetupRequestPages
  313. *
  314. * Prepares wizard pages and returns them to the OC Manager
  315. */
  316. DWORD OnSetupRequestPages(UINT type, PVOID srp)
  317. {
  318. return 0;
  319. }
  320. /*
  321. * OnWizardCreated()
  322. */
  323. DWORD OnWizardCreated()
  324. {
  325. return NO_ERROR;
  326. }
  327. /*
  328. * OnQuerySkipPage()
  329. *
  330. * don't let the user deselect the sam component
  331. */
  332. DWORD OnQuerySkipPage()
  333. {
  334. return false;
  335. }
  336. /*
  337. * OnQuerySelStateChange()
  338. *
  339. * don't let the user deselect the sam component
  340. */
  341. DWORD OnQuerySelStateChange(LPCTSTR ComponentId,
  342. LPCTSTR SubcomponentId,
  343. UINT state,
  344. UINT flags)
  345. {
  346. DWORD rc = true;
  347. #if 0
  348. // if (!(flags & OCQ_ACTUAL_SELECTION)) {
  349. if (!_tcsicmp(SubcomponentId, TEXT("three"))) {
  350. if (!state) {
  351. return false;
  352. }
  353. }
  354. if (!_tcsicmp(ComponentId, TEXT("three"))) {
  355. if (!state) {
  356. return false;
  357. }
  358. }
  359. if (!_tcsicmp(SubcomponentId, TEXT("gs7"))) {
  360. if (state) {
  361. return false;
  362. }
  363. }
  364. if (!_tcsicmp(ComponentId, TEXT("gs7"))) {
  365. if (state) {
  366. return false;
  367. }
  368. }
  369. // }
  370. #endif
  371. if (!rc && (flags & OCQ_ACTUAL_SELECTION))
  372. MessageBeep(MB_ICONEXCLAMATION);
  373. return rc;
  374. }
  375. /*
  376. * OnCalcDiskSpace()
  377. *
  378. * handler for OC_ON_CALC_DISK_SPACE
  379. */
  380. DWORD OnCalcDiskSpace(LPCTSTR ComponentId,
  381. LPCTSTR SubcomponentId,
  382. DWORD addComponent,
  383. HDSKSPC dspace)
  384. {
  385. DWORD rc = NO_ERROR;
  386. TCHAR section[S_SIZE];
  387. PPER_COMPONENT_DATA cd;
  388. //
  389. // Param1 = 0 if for removing component or non-0 if for adding component
  390. // Param2 = HDSKSPC to operate on
  391. //
  392. // Return value is Win32 error code indicating outcome.
  393. //
  394. // In our case the private section for this component/subcomponent pair
  395. // is a simple standard inf install section, so we can use the high-level
  396. // disk space list api to do what we want.
  397. //
  398. if (!(cd = LocateComponent(ComponentId)))
  399. return NO_ERROR;
  400. _tcscpy(section, SubcomponentId);
  401. if (addComponent)
  402. {
  403. rc = SetupAddInstallSectionToDiskSpaceList(dspace,
  404. cd->hinf,
  405. NULL,
  406. section,
  407. 0,
  408. 0);
  409. }
  410. else
  411. {
  412. rc = SetupRemoveInstallSectionFromDiskSpaceList(dspace,
  413. cd->hinf,
  414. NULL,
  415. section,
  416. 0,
  417. 0);
  418. }
  419. if (!rc)
  420. rc = GetLastError();
  421. else
  422. rc = NO_ERROR;
  423. return rc;
  424. }
  425. /*
  426. * OnQueueFileOps()
  427. *
  428. * handler for OC_QUEUE_FILE_OPS
  429. */
  430. DWORD OnQueueFileOps(LPCTSTR ComponentId, LPCTSTR SubcomponentId, HSPFILEQ queue)
  431. {
  432. PPER_COMPONENT_DATA cd;
  433. BOOL state;
  434. BOOL rc;
  435. INFCONTEXT context;
  436. TCHAR section[256];
  437. TCHAR srcpathbuf[256];
  438. TCHAR *srcpath;
  439. if (!(cd = LocateComponent(ComponentId)))
  440. return NO_ERROR;
  441. if (!SubcomponentId || !*SubcomponentId)
  442. return NO_ERROR;
  443. cd->queue = queue;
  444. if (!StateInfo(cd, SubcomponentId, &state))
  445. return NO_ERROR;
  446. wsprintf(section, SubcomponentId);
  447. rc = TRUE;
  448. if (!state) {
  449. // being uninstalled. Fetch uninstall section name.
  450. rc = SetupFindFirstLine(cd->hinf,
  451. SubcomponentId,
  452. KEYWORD_UNINSTALL,
  453. &context);
  454. if (rc) {
  455. rc = SetupGetStringField(&context,
  456. 1,
  457. section,
  458. sizeof(section) / sizeof(TCHAR),
  459. NULL);
  460. }
  461. // also, unregister the dlls and kill services before deletion
  462. SetupInstallServicesFromInfSection(cd->hinf, section, 0);
  463. SetupInstallFromInfSection(NULL,cd->hinf,section,SPINST_UNREGSVR,NULL,NULL,0,NULL,NULL,NULL,NULL);
  464. }
  465. if (rc) {
  466. // if uninstalling, don't use version checks
  467. rc = SetupInstallFilesFromInfSection(cd->hinf,
  468. NULL,
  469. queue,
  470. section,
  471. cd->SourcePath,
  472. state ? SP_COPY_NEWER : 0);
  473. }
  474. if (!rc)
  475. return GetLastError();
  476. return NO_ERROR;
  477. }
  478. /*
  479. * OnNotificationFromQueue()
  480. *
  481. * handler for OC_NOTIFICATION_FROM_QUEUE
  482. *
  483. * NOTE: although this notification is defined,
  484. * it is currently unimplemented in oc manager
  485. */
  486. DWORD OnNotificationFromQueue()
  487. {
  488. return NO_ERROR;
  489. }
  490. /*
  491. * OnQueryStepCount
  492. *
  493. * handler forOC_QUERY_STEP_COUNT
  494. */
  495. DWORD OnQueryStepCount()
  496. {
  497. return 2;
  498. }
  499. /*
  500. * OnCompleteInstallation
  501. *
  502. * handler for OC_COMPLETE_INSTALLATION
  503. */
  504. DWORD OnCompleteInstallation(LPCTSTR ComponentId, LPCTSTR SubcomponentId)
  505. {
  506. PPER_COMPONENT_DATA cd;
  507. INFCONTEXT context;
  508. TCHAR section[256];
  509. BOOL state;
  510. BOOL rc;
  511. DWORD Error = NO_ERROR;
  512. // Do post-installation processing in the cleanup section.
  513. // This way we know all compoents queued for installation
  514. // have beein installed before we do our stuff.
  515. if (!(cd = LocateComponent(ComponentId)))
  516. return NO_ERROR;
  517. if (!SubcomponentId || !*SubcomponentId)
  518. return NO_ERROR;
  519. if (!StateInfo(cd, SubcomponentId, &state))
  520. return NO_ERROR;
  521. wsprintf(section, SubcomponentId);
  522. rc = TRUE;
  523. if (!state) {
  524. // being uninstalled. Fetch uninstall section name.
  525. rc = SetupFindFirstLine(cd->hinf,
  526. SubcomponentId,
  527. KEYWORD_UNINSTALL,
  528. &context);
  529. if (rc) {
  530. rc = SetupGetStringField(&context,
  531. 1,
  532. section,
  533. sizeof(section) / sizeof(TCHAR),
  534. NULL);
  535. }
  536. }
  537. if (state) {
  538. //
  539. // installation
  540. //
  541. if (rc) {
  542. // process the inf file
  543. rc = SetupInstallFromInfSection(NULL, // hwndOwner
  544. cd->hinf, // inf handle
  545. section, // name of component
  546. SPINST_ALL & ~SPINST_FILES,
  547. NULL, // relative key root
  548. NULL, // source root path
  549. 0, // copy flags
  550. NULL, // callback routine
  551. NULL, // callback routine context
  552. NULL, // device info set
  553. NULL); // device info struct
  554. if (rc) {
  555. rc = SetupInstallServicesFromInfSection(cd->hinf, section, 0);
  556. Error = GetLastError();
  557. if (!rc && Error == ERROR_SECTION_NOT_FOUND) {
  558. rc = TRUE;
  559. Error = NO_ERROR;
  560. }
  561. if (rc) {
  562. if (Error == ERROR_SUCCESS_REBOOT_REQUIRED) {
  563. cd->HelperRoutines.SetReboot(cd->HelperRoutines.OcManagerContext,TRUE);
  564. }
  565. Error = NO_ERROR;
  566. rc = RunExternalProgram(cd, section, state);
  567. }
  568. }
  569. }
  570. } else {
  571. //
  572. // uninstallation
  573. //
  574. if (rc)
  575. {
  576. rc = RunExternalProgram(cd, section, state);
  577. }
  578. if (rc) {
  579. rc = CleanupNetShares(cd, section, state);
  580. }
  581. }
  582. if (!rc && (Error == NO_ERROR) ) {
  583. Error = GetLastError( );
  584. }
  585. return Error;
  586. }
  587. /*
  588. * OnCleanup()
  589. *
  590. * handler for OC_CLEANUP
  591. */
  592. DWORD OnCleanup()
  593. {
  594. return NO_ERROR;
  595. }
  596. /*
  597. * OnQueryState()
  598. *
  599. * handler for OC_QUERY_STATE
  600. */
  601. DWORD OnQueryState(LPCTSTR ComponentId,
  602. LPCTSTR SubcomponentId,
  603. UINT state)
  604. {
  605. PPER_COMPONENT_DATA cd;
  606. #if 0
  607. if (!_tcsicmp(SubcomponentId, TEXT("alone2"))
  608. || !_tcsicmp(ComponentId, TEXT("alone2"))) {
  609. if (state == OCSELSTATETYPE_CURRENT) {
  610. if (!_tcsicmp(SubcomponentId, TEXT("alone2"))) {
  611. return SubcompOff;
  612. }
  613. }
  614. }
  615. #endif
  616. #if 0
  617. if (state == OCSELSTATETYPE_FINAL) {
  618. if (!_tcsicmp(SubcomponentId, TEXT("four"))) {
  619. tmbox(SubcomponentId);
  620. }
  621. }
  622. #endif
  623. return SubcompUseOcManagerDefault;
  624. }
  625. /*
  626. * OnNeedMedia()
  627. *
  628. * handler for OC_NEED_MEDIA
  629. */
  630. DWORD OnNeedMedia()
  631. {
  632. return false;
  633. }
  634. /*
  635. * OnAboutToCommitQueue()
  636. *
  637. * handler for OC_ABOUT_TO_COMMIT_QUEUE
  638. */
  639. DWORD OnAboutToCommitQueue(LPCTSTR ComponentId, LPCTSTR SubcomponentId)
  640. {
  641. PPER_COMPONENT_DATA cd;
  642. BOOL state;
  643. BOOL rc;
  644. INFCONTEXT context;
  645. TCHAR section[256];
  646. TCHAR srcpathbuf[256];
  647. TCHAR *srcpath;
  648. if (!(cd = LocateComponent(ComponentId)))
  649. return NO_ERROR;
  650. if (!SubcomponentId || !*SubcomponentId)
  651. return NO_ERROR;
  652. if (!StateInfo(cd, SubcomponentId, &state))
  653. return NO_ERROR;
  654. //
  655. // only do stuff on uninstall
  656. //
  657. if (state) {
  658. return NO_ERROR;
  659. }
  660. // Fetch uninstall section name.
  661. rc = SetupFindFirstLine(
  662. cd->hinf,
  663. SubcomponentId,
  664. KEYWORD_UNINSTALL,
  665. &context);
  666. if (rc) {
  667. rc = SetupGetStringField(
  668. &context,
  669. 1,
  670. section,
  671. sizeof(section) / sizeof(TCHAR),
  672. NULL);
  673. }
  674. if (rc)
  675. rc = SetupInstallServicesFromInfSection(cd->hinf, section, 0);
  676. if (rc) {
  677. rc = SetupInstallFromInfSection(
  678. NULL,
  679. cd->hinf,
  680. section,
  681. SPINST_ALL & ~SPINST_FILES,
  682. NULL,
  683. NULL,
  684. 0,
  685. NULL,
  686. NULL,
  687. NULL,
  688. NULL);
  689. }
  690. if (rc) {
  691. SetLastError(NO_ERROR);
  692. }
  693. return GetLastError();
  694. }
  695. /*
  696. * AddNewComponent()
  697. *
  698. * add new compononent to the top of the component list
  699. */
  700. PPER_COMPONENT_DATA AddNewComponent(LPCTSTR ComponentId)
  701. {
  702. PPER_COMPONENT_DATA data;
  703. data = (PPER_COMPONENT_DATA)LocalAlloc(LPTR,sizeof(PER_COMPONENT_DATA));
  704. if (!data)
  705. return data;
  706. data->ComponentId = (TCHAR *)LocalAlloc(LMEM_FIXED,
  707. (_tcslen(ComponentId) + 1) * sizeof(TCHAR));
  708. if(data->ComponentId)
  709. {
  710. _tcscpy((TCHAR *)data->ComponentId, ComponentId);
  711. // Stick at head of list
  712. data->Next = gcd;
  713. gcd = data;
  714. }
  715. else
  716. {
  717. LocalFree((HLOCAL)data);
  718. data = NULL;
  719. }
  720. return(data);
  721. }
  722. /*
  723. * LocateComponent()
  724. *
  725. * returns a compoent struct that matches the
  726. * passed component id.
  727. */
  728. PPER_COMPONENT_DATA LocateComponent(LPCTSTR ComponentId)
  729. {
  730. PPER_COMPONENT_DATA p;
  731. for (p = gcd; p; p=p->Next)
  732. {
  733. if (!_tcsicmp(p->ComponentId, ComponentId))
  734. return p;
  735. }
  736. return NULL;
  737. }
  738. /*
  739. * RemoveComponent()
  740. *
  741. * yanks a component from our linked list of components
  742. */
  743. VOID RemoveComponent(LPCTSTR ComponentId)
  744. {
  745. PPER_COMPONENT_DATA p, prev;
  746. for (prev = NULL, p = gcd; p; prev = p, p = p->Next)
  747. {
  748. if (!_tcsicmp(p->ComponentId, ComponentId))
  749. {
  750. LocalFree((HLOCAL)p->ComponentId);
  751. if (p->SourcePath)
  752. LocalFree((HLOCAL)p->SourcePath);
  753. if (prev)
  754. prev->Next = p->Next;
  755. else
  756. gcd = p->Next;
  757. LocalFree((HLOCAL)p);
  758. return;
  759. }
  760. }
  761. }
  762. // loads current selection state info into "state" and
  763. // returns whether the selection state was changed
  764. BOOL
  765. StateInfo(
  766. PPER_COMPONENT_DATA cd,
  767. LPCTSTR SubcomponentId,
  768. BOOL *state
  769. )
  770. {
  771. BOOL rc = TRUE;
  772. assert(state);
  773. // otherwise, check for a change in installation state
  774. *state = cd->HelperRoutines.QuerySelectionState(cd->HelperRoutines.OcManagerContext,
  775. SubcomponentId,
  776. OCSELSTATETYPE_CURRENT);
  777. if (*state == cd->HelperRoutines.QuerySelectionState(cd->HelperRoutines.OcManagerContext,
  778. SubcomponentId,
  779. OCSELSTATETYPE_ORIGINAL))
  780. {
  781. // no change
  782. rc = FALSE;
  783. }
  784. // if this is gui mode setup, presume the state has changed to force
  785. // an installation (or uninstallation)
  786. if (!(cd->Flags & SETUPOP_STANDALONE) && *state)
  787. rc = TRUE;
  788. return rc;
  789. }
  790. #if 0
  791. //
  792. // Andrewr -- get rid of RegisterServices and RegisterServers and have the oc gen component use setupapi instead.
  793. // this reduces the amount of redundant code
  794. //
  795. DWORD RegisterServices(
  796. PPER_COMPONENT_DATA cd,
  797. LPCTSTR component,
  798. DWORD state)
  799. {
  800. INFCONTEXT ic;
  801. TCHAR buf[MAX_PATH];
  802. TCHAR path[MAX_PATH];
  803. TCHAR sname[S_SIZE];
  804. TCHAR file[MAX_PATH];
  805. DWORD section;
  806. ULONG size;
  807. pfn pfreg;
  808. HINSTANCE hinst;
  809. HRESULT hr;
  810. TCHAR *keyword;
  811. SC_HANDLE schSystem;
  812. schSystem = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
  813. if ( !schSystem ) {
  814. DWORD dwError = GetLastError( );
  815. if( !IsNT() && ( ERROR_CALL_NOT_IMPLEMENTED == dwError ) )
  816. {
  817. return( NO_ERROR );
  818. }
  819. else
  820. {
  821. return( dwError );
  822. }
  823. }
  824. if (state) {
  825. keyword = KEYWORD_ADDSERVICE;
  826. } else {
  827. keyword = KEYWORD_DELSERVICE;
  828. }
  829. for (section = 1;
  830. EnumSections(cd->hinf, component, keyword, section, &ic, sname);
  831. section++)
  832. {
  833. INFCONTEXT sic;
  834. SC_HANDLE schService;
  835. CHAR Temp[SBUF_SIZE];
  836. TCHAR ServiceName[ SBUF_SIZE ];
  837. TCHAR DisplayName[ SBUF_SIZE ];
  838. DWORD ServiceType;
  839. DWORD StartType;
  840. DWORD ErrorControl;
  841. TCHAR ImagePath[ SBUF_SIZE ];
  842. TCHAR LoadOrder[ SBUF_SIZE ];
  843. TCHAR Dependencies[ SBUF_SIZE ];
  844. TCHAR StartName[ SBUF_SIZE ];
  845. TCHAR Password[ SBUF_SIZE ];
  846. BOOL fDisplayName = FALSE;
  847. BOOL fServiceType = FALSE;
  848. BOOL fStartType = FALSE;
  849. BOOL fErrorControl = FALSE;
  850. BOOL fLoadOrder = FALSE;
  851. BOOL fDependencies = FALSE;
  852. BOOL fStartName = FALSE;
  853. BOOL fPassword = FALSE;
  854. BOOL fDontReboot = FALSE;
  855. //
  856. // Must have ServiceName
  857. //
  858. if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_SERVICENAME, &sic))
  859. {
  860. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_SERVICENAME );
  861. continue;
  862. }
  863. if (!SetupGetStringField(&sic, 1, ServiceName, SBUF_SIZE, NULL))
  864. {
  865. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_SERVICENAME );
  866. continue;
  867. }
  868. if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_STARTTYPE, &sic))
  869. {
  870. if (SetupGetStringFieldA(&sic, 1, Temp, SBUF_SIZE, NULL))
  871. {
  872. StartType = atoi( Temp );
  873. fStartType = TRUE;
  874. }
  875. }
  876. if ( state )
  877. {
  878. if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_DISPLAYNAME, &sic))
  879. {
  880. if (SetupGetStringField(&sic, 1, DisplayName, SBUF_SIZE, NULL))
  881. {
  882. fDisplayName = TRUE;
  883. }
  884. }
  885. if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_SERVICETYPE, &sic))
  886. {
  887. if (SetupGetStringFieldA(&sic, 1, Temp, SBUF_SIZE, NULL))
  888. {
  889. ServiceType = atoi( Temp );
  890. fServiceType = TRUE;
  891. }
  892. }
  893. if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_ERRORCONTROL, &sic))
  894. {
  895. if (SetupGetStringFieldA(&sic, 1, Temp, SBUF_SIZE, NULL))
  896. {
  897. ErrorControl = atoi( Temp );
  898. fErrorControl = TRUE;
  899. }
  900. }
  901. //
  902. // Must have ImagePath
  903. //
  904. if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_IMAGEPATH, &sic))
  905. {
  906. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_IMAGEPATH );
  907. continue;
  908. }
  909. if (!SetupGetStringField(&sic, 1, ImagePath, SBUF_SIZE, NULL))
  910. {
  911. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_IMAGEPATH );
  912. continue;
  913. }
  914. if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_LOADORDER, &sic))
  915. {
  916. if (SetupGetStringField(&sic, 1, LoadOrder, SBUF_SIZE, NULL))
  917. {
  918. fLoadOrder = TRUE;
  919. }
  920. }
  921. if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_DEPENDENCIES, &sic))
  922. {
  923. if (SetupGetStringField(&sic, 1, Dependencies, SBUF_SIZE-1, NULL))
  924. {
  925. LPTSTR psz = Dependencies;
  926. // needs to be a double-null terminated string
  927. Dependencies[ lstrlen(Dependencies) + 1] = TEXT('\0');
  928. // change commas into NULL characters
  929. while ( *psz )
  930. {
  931. if ( *psz == TEXT(',') )
  932. {
  933. *psz = TEXT('\0');
  934. }
  935. psz++;
  936. }
  937. fDependencies = TRUE;
  938. }
  939. }
  940. if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_STARTNAME, &sic))
  941. {
  942. if (SetupGetStringField(&sic, 1, StartName, SBUF_SIZE, NULL))
  943. {
  944. fStartName = TRUE;
  945. }
  946. }
  947. if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_PASSWORD, &sic))
  948. {
  949. if (SetupGetStringField(&sic, 1, Password, SBUF_SIZE, NULL))
  950. {
  951. fPassword = TRUE;
  952. }
  953. }
  954. schService = CreateService(
  955. schSystem,
  956. ServiceName,
  957. ( fDisplayName == TRUE ? DisplayName : ServiceName ),
  958. STANDARD_RIGHTS_REQUIRED | SERVICE_START,
  959. ( fServiceType == TRUE ? ServiceType : SERVICE_WIN32_OWN_PROCESS),
  960. ( fStartType == TRUE ? StartType : SERVICE_AUTO_START),
  961. ( fErrorControl == TRUE ? ErrorControl : SERVICE_ERROR_NORMAL),
  962. ImagePath,
  963. (fLoadOrder == TRUE ? LoadOrder : NULL),
  964. NULL, // tag id
  965. ( fDependencies == TRUE ? Dependencies : NULL ),
  966. ( fStartName == TRUE ? StartName : NULL),
  967. ( fPassword == TRUE ? Password : NULL ));
  968. if ( !schService )
  969. {
  970. DWORD Error = GetLastError( );
  971. log( TEXT("OCGEN: CreateService() error 0x%08x\r\n"), Error );
  972. return Error;
  973. }
  974. if ( (!fStartType)
  975. || ( fStartType && StartType == SERVICE_AUTO_START ))
  976. {
  977. if( !StartService( schService, 0, NULL ) )
  978. {
  979. DWORD Error = GetLastError( );
  980. switch ( Error )
  981. {
  982. case ERROR_SERVICE_EXISTS:
  983. {
  984. log( TEXT("OCGEN: %s was already exists.\r\n"), ServiceName );
  985. if ( fStartType && StartType == SERVICE_BOOT_START )
  986. {
  987. fDontReboot = TRUE;
  988. }
  989. }
  990. break;
  991. case ERROR_SERVICE_ALREADY_RUNNING:
  992. {
  993. log( TEXT("OCGEN: %s was already started.\r\n"), ServiceName );
  994. if ( fStartType && StartType == SERVICE_BOOT_START )
  995. {
  996. fDontReboot = TRUE;
  997. }
  998. }
  999. break;
  1000. default:
  1001. log( TEXT("OCGEN: StartService() error 0x%08x\r\n"), Error );
  1002. return Error;
  1003. }
  1004. }
  1005. }
  1006. }
  1007. else
  1008. {
  1009. schService = OpenService( schSystem,
  1010. ServiceName,
  1011. STANDARD_RIGHTS_REQUIRED | DELETE );
  1012. if ( schService )
  1013. {
  1014. SERVICE_STATUS ss;
  1015. DeleteService( schService );
  1016. ControlService( schService, SERVICE_CONTROL_STOP, &ss );
  1017. }
  1018. }
  1019. //
  1020. // BOOT drivers require a reboot unless they were already started.
  1021. //
  1022. if ( schService
  1023. && fStartType && StartType == SERVICE_BOOT_START
  1024. && fDontReboot == FALSE)
  1025. {
  1026. cd->HelperRoutines.SetReboot(cd->HelperRoutines.OcManagerContext, NULL);
  1027. }
  1028. if ( schService )
  1029. {
  1030. CloseServiceHandle( schService );
  1031. }
  1032. }
  1033. return NO_ERROR;
  1034. }
  1035. #endif
  1036. #if 0
  1037. DWORD
  1038. RegisterServers(
  1039. HINF hinf,
  1040. LPCTSTR component,
  1041. DWORD state
  1042. )
  1043. {
  1044. INFCONTEXT ic;
  1045. TCHAR buf[MAX_PATH];
  1046. TCHAR path[MAX_PATH];
  1047. TCHAR sname[S_SIZE];
  1048. TCHAR file[MAX_PATH];
  1049. DWORD section;
  1050. ULONG size;
  1051. pfn pfreg;
  1052. HINSTANCE hinst;
  1053. HRESULT hr;
  1054. TCHAR *keyword;
  1055. LPCSTR routine;
  1056. CoInitialize(NULL);
  1057. if (state) {
  1058. keyword = KEYWORD_REGSVR;
  1059. routine = (LPCSTR)gszRegisterSvrRoutine;
  1060. } else {
  1061. keyword = KEYWORD_UNREGSVR;
  1062. routine = (LPCSTR)gszUnregisterSvrRoutine;
  1063. }
  1064. for (section = 1;
  1065. EnumSections(hinf, component, keyword, section, &ic, sname);
  1066. section++)
  1067. {
  1068. if (!SetupGetTargetPath(hinf, NULL, sname, path, sizeof(path), &size))
  1069. continue;
  1070. PathAddBackslash(path);
  1071. do {
  1072. // get fully qualified path to dll to register
  1073. if (!SetupGetStringField(&ic, 0, buf, sizeof(buf), NULL))
  1074. continue;
  1075. _tcscpy(file, path);
  1076. _tcscat(file, buf);
  1077. // call the dll's RegisterServer routine
  1078. if (!(hinst = LoadLibrary(file)))
  1079. continue;
  1080. if (!(pfreg = (pfn)GetProcAddress(hinst, routine)))
  1081. continue;
  1082. hr = pfreg();
  1083. assert(hr == NO_ERROR);
  1084. FreeLibrary(hinst);
  1085. // on to the next
  1086. } while (SetupFindNextLine(&ic, &ic));
  1087. }
  1088. CoUninitialize();
  1089. return TRUE;
  1090. }
  1091. #endif
  1092. /*
  1093. * EnumSections()
  1094. *
  1095. * finds the name of a section for a specified keyword
  1096. */
  1097. DWORD
  1098. EnumSections(
  1099. HINF hinf,
  1100. const TCHAR *component,
  1101. const TCHAR *key,
  1102. DWORD index,
  1103. INFCONTEXT *pic,
  1104. TCHAR *name
  1105. )
  1106. {
  1107. TCHAR section[S_SIZE];
  1108. if (!SetupFindFirstLine(hinf, component, NULL, pic))
  1109. return 0;
  1110. if (!SetupFindNextMatchLine(pic, key, pic))
  1111. return 0;
  1112. if (index > SetupGetFieldCount(pic))
  1113. return 0;
  1114. if (!SetupGetStringField(pic, index, section, SBUF_SIZE, NULL))
  1115. return 0;
  1116. if (name)
  1117. _tcscpy(name, section);
  1118. return SetupFindFirstLine(hinf, section, NULL, pic);
  1119. }
  1120. DWORD
  1121. OcLog(
  1122. LPCTSTR ComponentId,
  1123. UINT level,
  1124. LPCTSTR sz
  1125. )
  1126. {
  1127. TCHAR fmt[5000];
  1128. PPER_COMPONENT_DATA cd;
  1129. if (!(cd = LocateComponent(ComponentId)))
  1130. return NO_ERROR;
  1131. assert(cd->ExtraRoutines.LogError);
  1132. assert(level);
  1133. assert(sz);
  1134. _tcscpy(fmt, TEXT("%s: %s"));
  1135. return cd->ExtraRoutines.LogError(cd->HelperRoutines.OcManagerContext,
  1136. level,
  1137. fmt,
  1138. ComponentId,
  1139. sz);
  1140. }
  1141. DWORD
  1142. CleanupNetShares(
  1143. PPER_COMPONENT_DATA cd,
  1144. LPCTSTR component,
  1145. DWORD state)
  1146. {
  1147. INFCONTEXT ic;
  1148. TCHAR sname[S_SIZE];
  1149. DWORD section;
  1150. TCHAR *keyword;
  1151. if (state) {
  1152. return NO_ERROR;
  1153. } else {
  1154. keyword = KEYWORD_DELSHARE;
  1155. }
  1156. for (section = 1;
  1157. EnumSections(cd->hinf, component, keyword, section, &ic, sname);
  1158. section++)
  1159. {
  1160. INFCONTEXT sic;
  1161. NET_API_STATUS netStat;
  1162. CHAR Temp[SBUF_SIZE];
  1163. TCHAR ShareName[ SBUF_SIZE ];
  1164. if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_SHARENAME, &sic))
  1165. {
  1166. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_SHARENAME );
  1167. continue;
  1168. }
  1169. if (!SetupGetStringField(&sic, 1, ShareName, SBUF_SIZE, NULL))
  1170. {
  1171. log( TEXT("OCGEN: %s INF error - incorrect %s line\r\n"), keyword, KEYWORD_SHARENAME );
  1172. continue;
  1173. }
  1174. #ifdef UNICODE
  1175. netStat = NetShareDel( NULL, ShareName, 0 );
  1176. #else // UNICODE
  1177. WCHAR ShareNameW[ SBUF_SIZE ];
  1178. mbstowcs( ShareNameW, ShareName, lstrlen(ShareName));
  1179. netStat = NetShareDel( NULL, ShareNameW, 0 );
  1180. #endif // UNICODE
  1181. if ( netStat != NERR_Success )
  1182. {
  1183. log( TEXT("OCGEN: Failed to remove %s share. Error 0x%08x\r\n"), ShareName, netStat );
  1184. continue;
  1185. }
  1186. log( TEXT("OCGEN: %s share removed successfully.\r\n"), ShareName );
  1187. }
  1188. return TRUE;
  1189. }
  1190. DWORD
  1191. RunExternalProgram(
  1192. PPER_COMPONENT_DATA cd,
  1193. LPCTSTR component,
  1194. DWORD state)
  1195. {
  1196. INFCONTEXT ic;
  1197. TCHAR sname[S_SIZE];
  1198. DWORD section;
  1199. TCHAR *keyword;
  1200. keyword = KEYWORD_RUN;
  1201. for (section = 1;
  1202. EnumSections(cd->hinf, component, keyword, section, &ic, sname);
  1203. section++)
  1204. {
  1205. INFCONTEXT sic;
  1206. TCHAR CommandLine[ SBUF_SIZE ];
  1207. CHAR szTickCount[ SBUF_SIZE ];
  1208. ULONG TickCount;
  1209. BOOL b;
  1210. STARTUPINFO startupinfo;
  1211. PROCESS_INFORMATION process_information;
  1212. DWORD dwErr;
  1213. if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_COMMANDLINE , &sic))
  1214. {
  1215. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_COMMANDLINE );
  1216. continue;
  1217. }
  1218. if (!SetupGetStringField(&sic, 1, CommandLine, SBUF_SIZE, NULL))
  1219. {
  1220. log( TEXT("OCGEN: %s INF error - incorrect %s line\r\n"), keyword, KEYWORD_COMMANDLINE );
  1221. continue;
  1222. }
  1223. if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_TICKCOUNT, &sic))
  1224. {
  1225. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_TICKCOUNT );
  1226. continue;
  1227. }
  1228. if (!SetupGetStringFieldA(&sic, 1, szTickCount, SBUF_SIZE, NULL))
  1229. {
  1230. log( TEXT("OCGEN: %s INF error - incorrect %s line\r\n"), keyword, KEYWORD_TICKCOUNT );
  1231. continue;
  1232. }
  1233. TickCount = atoi( szTickCount );
  1234. ZeroMemory( &startupinfo, sizeof(startupinfo) );
  1235. startupinfo.cb = sizeof(startupinfo);
  1236. startupinfo.dwFlags = STARTF_USESHOWWINDOW;
  1237. startupinfo.wShowWindow = SW_HIDE | SW_SHOWMINNOACTIVE;
  1238. b = CreateProcess( NULL,
  1239. CommandLine,
  1240. NULL,
  1241. NULL,
  1242. FALSE,
  1243. CREATE_DEFAULT_ERROR_MODE,
  1244. NULL,
  1245. NULL,
  1246. &startupinfo,
  1247. &process_information );
  1248. if ( !b )
  1249. {
  1250. log( TEXT("OCGEN: failed to spawn %s process.\r\n"), CommandLine );
  1251. continue;
  1252. }
  1253. dwErr = WaitForSingleObject( process_information.hProcess, TickCount * 1000 );
  1254. if ( dwErr != NO_ERROR )
  1255. {
  1256. log( TEXT("OCGEN: WaitForSingleObject() failed. Error 0x%08x\r\n"), dwErr );
  1257. TerminateProcess( process_information.hProcess, -1 );
  1258. CloseHandle( process_information.hProcess );
  1259. CloseHandle( process_information.hThread );
  1260. continue;
  1261. }
  1262. CloseHandle( process_information.hProcess );
  1263. CloseHandle( process_information.hThread );
  1264. log( TEXT("OCGEN: %s successfully completed within %u seconds.\r\n"), CommandLine, TickCount );
  1265. }
  1266. return TRUE;
  1267. }