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.

979 lines
24 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. components.c
  5. Abstract:
  6. Implements a set of APIs for the purposes of allowing the application layer to select
  7. module functionality.
  8. Author:
  9. Jim Schmidt (jimschm) 07-Aug-2000
  10. Revision History:
  11. <alias> <date> <comments>
  12. --*/
  13. //
  14. // Includes
  15. //
  16. #include "pch.h"
  17. #include "ism.h"
  18. #include "ismp.h"
  19. #define DBG_COMP "Comp"
  20. //
  21. // Strings
  22. //
  23. #define S_COMPONENT_ROOT TEXT("Components")
  24. #define S_USER_SUPPLIED TEXT("User")
  25. #define S_MODULE_SUPPLIED TEXT("Module")
  26. //
  27. // Constants
  28. //
  29. #define MAX_COMPONENT_SPEC 127
  30. #define MAX_COMPONENT_SPEC_PLUS_NUL (MAX_COMPONENT_SPEC+1)
  31. #define MAX_CONTROLLED_NODE_SIZE (MAX_COMPONENT_SPEC_PLUS_NUL + \
  32. ARRAYSIZE(S_COMPONENT_ROOT) + \
  33. ARRAYSIZE(S_MODULE_SUPPLIED) + 16)
  34. #define MEMDB_FLAG_PREFERRED 1
  35. #define MEMDB_FLAG_SELECTED 1
  36. //
  37. // Macros
  38. //
  39. // none
  40. //
  41. // Types
  42. //
  43. typedef enum {
  44. CES_DONE = 0,
  45. CES_FIRST_COMPONENT,
  46. CES_NEXT_COMPONENT,
  47. CES_FIRST_ALIAS,
  48. CES_NEXT_ALIAS,
  49. CES_CHECK_ALIAS_FLAGS
  50. } COMPONENTENUMSTATE;
  51. typedef struct {
  52. MEMDB_ENUM ComponentEnumStruct;
  53. MEMDB_ENUM AliasEnumStruct;
  54. BOOL EnumAliases;
  55. UINT GroupIdFilter;
  56. BOOL EnumEnabled;
  57. BOOL EnumDisabled;
  58. BOOL EnumPreferredOnly;
  59. BOOL EnumNonPreferredOnly;
  60. COMPONENTENUMSTATE State;
  61. } COMPONENTENUM_HANDLE, *PCOMPONENTENUM_HANDLE;
  62. //
  63. // Globals
  64. //
  65. // none
  66. //
  67. // Macro expansion list
  68. //
  69. // none
  70. //
  71. // Private function prototypes
  72. //
  73. // none
  74. //
  75. // Macro expansion definition
  76. //
  77. // none
  78. //
  79. // Code
  80. //
  81. BOOL
  82. pCheckCompChar (
  83. IN CHARTYPE Char,
  84. IN BOOL CheckDecoration
  85. )
  86. {
  87. //
  88. // Process decoration chars
  89. //
  90. if (Char == TEXT('$') || Char == TEXT('@') || Char == TEXT('~') || Char == TEXT('#')) {
  91. return CheckDecoration;
  92. }
  93. if (CheckDecoration) {
  94. return FALSE;
  95. }
  96. //
  97. // Block illegal chars
  98. //
  99. if (Char == TEXT('\"') || Char == TEXT('*') || Char == TEXT('?') || Char== TEXT('\\') ||
  100. Char == TEXT('%') || Char == TEXT(';')
  101. ) {
  102. return FALSE;
  103. }
  104. //
  105. // Make sure char is printable
  106. //
  107. if (Char < 33 || Char > 126) {
  108. return FALSE;
  109. }
  110. return TRUE;
  111. }
  112. BOOL
  113. pCheckComponentName (
  114. IN PCTSTR ComponentString
  115. )
  116. {
  117. BOOL result = FALSE;
  118. PCTSTR end;
  119. PCTSTR begin;
  120. //
  121. // Check for a non-empty spec
  122. //
  123. if (ComponentString && ComponentString[0]) {
  124. //
  125. // Allow for decoration
  126. //
  127. end = ComponentString;
  128. while (pCheckCompChar ((CHARTYPE) _tcsnextc (end), TRUE)) {
  129. end = _tcsinc (end);
  130. }
  131. //
  132. // Now enforce the name character set: non-decorated characters and no
  133. // more than MAX_COMPONENT_SPEC characters. Allow spaces in the middle.
  134. //
  135. begin = end;
  136. while (*end) {
  137. if (!pCheckCompChar ((CHARTYPE) _tcsnextc (end), FALSE)) {
  138. if (_tcsnextc (end) == TEXT(' ')) {
  139. if (!end[1] || end == begin) {
  140. break;
  141. }
  142. } else {
  143. break;
  144. }
  145. }
  146. end = _tcsinc (end);
  147. }
  148. if (!(*end) && *begin) {
  149. if (end - ComponentString <= MAX_COMPONENT_SPEC) {
  150. result = TRUE;
  151. }
  152. }
  153. }
  154. if (!result) {
  155. SetLastError (ERROR_INVALID_PARAMETER);
  156. DEBUGMSG ((DBG_ERROR, "%s is not a valid component name", ComponentString));
  157. }
  158. return result;
  159. }
  160. BOOL
  161. pFindComponent (
  162. IN PCTSTR LocalizedAlias,
  163. IN UINT ComponentGroupId,
  164. OUT PCTSTR *ComponentKey, OPTIONAL
  165. OUT PCTSTR *AliasKey OPTIONAL
  166. )
  167. {
  168. MEMDB_ENUM component;
  169. PCTSTR memdbNode = NULL;
  170. PCTSTR encodedUserAlias;
  171. PCTSTR encodedModuleAlias;
  172. TCHAR number[32];
  173. BOOL result = FALSE;
  174. //
  175. // Find the component based on the localized alias
  176. //
  177. wsprintf (number, TEXT("\\%s\\%04u"), S_USER_SUPPLIED, ComponentGroupId);
  178. encodedUserAlias = JoinPaths (number, LocalizedAlias);
  179. wsprintf (number, TEXT("\\%s\\%04u"), S_MODULE_SUPPLIED, ComponentGroupId);
  180. encodedModuleAlias = JoinPaths (number, LocalizedAlias);
  181. if (MemDbEnumFirst (
  182. &component,
  183. S_COMPONENT_ROOT TEXT("\\*"),
  184. ENUMFLAG_ALL,
  185. 1,
  186. 1
  187. )) {
  188. do {
  189. memdbNode = JoinText (component.FullKeyName, encodedModuleAlias);
  190. if (MemDbTestKey (memdbNode)) {
  191. break;
  192. }
  193. FreeText (memdbNode);
  194. memdbNode = NULL;
  195. memdbNode = JoinText (component.FullKeyName, encodedUserAlias);
  196. if (MemDbTestKey (memdbNode)) {
  197. break;
  198. }
  199. FreeText (memdbNode);
  200. memdbNode = NULL;
  201. } while (MemDbEnumNext (&component));
  202. }
  203. if (memdbNode) {
  204. if (ComponentKey) {
  205. *ComponentKey = DuplicateText (component.FullKeyName);
  206. }
  207. if (AliasKey) {
  208. *AliasKey = memdbNode;
  209. memdbNode = NULL;
  210. }
  211. MemDbAbortEnum (&component);
  212. result = TRUE;
  213. }
  214. FreeText (memdbNode);
  215. INVALID_POINTER (memdbNode);
  216. FreePathString (encodedUserAlias);
  217. INVALID_POINTER (encodedUserAlias);
  218. FreePathString (encodedModuleAlias);
  219. INVALID_POINTER (encodedModuleAlias);
  220. return result;
  221. }
  222. BOOL
  223. WINAPI
  224. IsmSelectPreferredAlias (
  225. IN PCTSTR ComponentString,
  226. IN PCTSTR LocalizedAlias, OPTIONAL
  227. IN UINT ComponentGroupId OPTIONAL
  228. )
  229. /*++
  230. Routine Description:
  231. IsmSelectPreferredAlias marks a specific alias as the "preferred" one, so
  232. that the UI knows what to display. If LocalizedAlias is not specified, none
  233. of the aliases are preferred.
  234. A component can have only one preferred localized alias. If another alias is
  235. selected as preferred, it will be deselected automatically.
  236. Arguments:
  237. ComponentString - Specifies the non-displayed component identifier
  238. LocalizedAlias - Specifies the displayable string to mark as "preferred,"
  239. or NULL to remove the preferred flag from the component.
  240. ComponentGroupId - Specifies the group ID for LocalizedAlias. Required if
  241. LocalizedAlias is not NULL.
  242. Return Value:
  243. TRUE if selection (or deselection) succeeded, FALSE if LocalizedAlias does
  244. not exist.
  245. --*/
  246. {
  247. MEMDB_ENUM e;
  248. TCHAR number[32];
  249. PCTSTR memdbNode = NULL;
  250. PCTSTR baseOfPattern;
  251. PCTSTR enumPattern;
  252. PCTSTR groupedAlias;
  253. BOOL result;
  254. if (!ComponentString || (LocalizedAlias && !ComponentGroupId)) {
  255. MYASSERT (FALSE);
  256. SetLastError (ERROR_INVALID_PARAMETER);
  257. return FALSE;
  258. }
  259. result = (LocalizedAlias == NULL);
  260. //
  261. // Build enumeration string Components\<component>\*
  262. //
  263. baseOfPattern = JoinPaths (S_COMPONENT_ROOT, ComponentString);
  264. enumPattern = JoinPaths (baseOfPattern, TEXT("*"));
  265. FreePathString (baseOfPattern);
  266. INVALID_POINTER (baseOfPattern);
  267. if (LocalizedAlias) {
  268. wsprintf (number, TEXT("%04u"), ComponentGroupId);
  269. groupedAlias = JoinPaths (number, LocalizedAlias);
  270. } else {
  271. groupedAlias = NULL;
  272. }
  273. if (MemDbEnumFirst (
  274. &e,
  275. enumPattern,
  276. ENUMFLAG_NORMAL,
  277. 3,
  278. ENUMLEVEL_ALLLEVELS
  279. )) {
  280. do {
  281. if (groupedAlias && StringIMatch (e.KeyName, groupedAlias)) {
  282. MemDbSetFlags (e.FullKeyName, MEMDB_FLAG_PREFERRED, MEMDB_FLAG_PREFERRED);
  283. result = TRUE;
  284. } else {
  285. MemDbSetFlags (e.FullKeyName, 0, MEMDB_FLAG_PREFERRED);
  286. }
  287. } while (MemDbEnumNext (&e));
  288. }
  289. FreePathString (enumPattern);
  290. INVALID_POINTER (enumPattern);
  291. FreePathString (groupedAlias);
  292. INVALID_POINTER (groupedAlias);
  293. return result;
  294. }
  295. BOOL
  296. WINAPI
  297. IsmAddComponentAlias (
  298. IN PCTSTR ComponentString, OPTIONAL
  299. IN UINT MasterGroup,
  300. IN PCTSTR LocalizedAlias,
  301. IN UINT ComponentGroupId,
  302. IN BOOL UserSupplied
  303. )
  304. /*++
  305. Routine Description:
  306. IsmAddComponentAlias associates a display string (LocalizedAlias) with a
  307. logical component tag (ComponentString).
  308. Arguments:
  309. ComponentString - Specifies the identifier of the component. This
  310. identifier is not used for display purposes.
  311. MasterGroup - Specifies a MASTERGROUP_xxx constant, which organizes
  312. the components into major groups such as system settings
  313. and app settings (to simplify selection).
  314. LocalizedAliais - The displayable text. It is a localized component name,
  315. a path, a file, etc.
  316. ComponentGroupId - An arbitrary numeric ID defined outside of the ISM. This
  317. ID is used to implement requirements specific to the app
  318. layer. It allows for arbitrary idenfication and grouping.
  319. UserSupplied - Specifies TRUE if the end-user supplied this info, FALSE
  320. if it is built into the migration package.
  321. Return Value:
  322. A flag indicating success or failure.
  323. --*/
  324. {
  325. PCTSTR memdbNode;
  326. TCHAR workNode[MAX_CONTROLLED_NODE_SIZE];
  327. static UINT sequencer = 0;
  328. TCHAR madeUpComponent[MAX_COMPONENT_SPEC_PLUS_NUL];
  329. BOOL b;
  330. BOOL newComponent = FALSE;
  331. //
  332. // Components are kept in memdb in the form of
  333. //
  334. // Component\<Module|User>\<GroupId>\<LocalizedAlias> = <preferred flag>
  335. //
  336. // <GroupId> is stored as a 4 digit number (such as 0001)
  337. //
  338. // Component\<Module|User> = <enable/disable>,<master group>
  339. //
  340. //
  341. // Validate arguments
  342. //
  343. if (ComponentGroupId > 9999) {
  344. SetLastError (ERROR_INVALID_PARAMETER);
  345. return FALSE;
  346. }
  347. if (!ComponentString || !ComponentString[0]) {
  348. wsprintf (madeUpComponent, TEXT("Component %u"), ++sequencer);
  349. ComponentString = madeUpComponent;
  350. } else if (!pCheckComponentName (ComponentString)) {
  351. return FALSE;
  352. }
  353. if (!MasterGroup || MasterGroup >= MASTERGROUP_ALL) {
  354. SetLastError (ERROR_INVALID_PARAMETER);
  355. DEBUGMSG ((DBG_ERROR, "MasterGroup is invalid"));
  356. return FALSE;
  357. }
  358. //
  359. // See if the component already exists
  360. //
  361. // This is safe since ComponentString was already checked for length by pCheckComponentName
  362. wsprintf (workNode, TEXT("%s\\%s"), S_COMPONENT_ROOT, ComponentString);
  363. if (pFindComponent (LocalizedAlias, ComponentGroupId, &memdbNode, NULL)) {
  364. if (StringIMatch (workNode, memdbNode)) {
  365. DEBUGMSG ((DBG_VERBOSE, "Alias %s already exists; not adding it again", LocalizedAlias));
  366. } else {
  367. DEBUGMSG ((
  368. DBG_WARNING,
  369. "Alias %s is in use by component %s; not adding it again",
  370. LocalizedAlias,
  371. _tcschr (memdbNode, TEXT('\\')) + 1
  372. ));
  373. }
  374. FreeText (memdbNode);
  375. return FALSE;
  376. }
  377. //
  378. // Create the component if it doesn't exist, and then add the alias
  379. //
  380. if (!MemDbTestKey (workNode)) {
  381. if (!MemDbSetValueAndFlags (workNode, MasterGroup, MEMDB_FLAG_SELECTED, MEMDB_FLAG_SELECTED)) {
  382. EngineError ();
  383. return FALSE;
  384. }
  385. newComponent = TRUE;
  386. }
  387. // This is safe since ComponentString was already checked for length by pCheckComponentName
  388. wsprintf (
  389. workNode,
  390. TEXT("%s\\%s\\%s\\%04u"),
  391. S_COMPONENT_ROOT,
  392. ComponentString,
  393. UserSupplied ? S_USER_SUPPLIED : S_MODULE_SUPPLIED,
  394. ComponentGroupId
  395. );
  396. memdbNode = JoinPaths (workNode, LocalizedAlias);
  397. if (newComponent) {
  398. b = MemDbSetFlags (memdbNode, MEMDB_FLAG_PREFERRED, MEMDB_FLAG_PREFERRED);
  399. } else {
  400. b = MemDbSetKey (memdbNode);
  401. }
  402. FreePathString (memdbNode);
  403. if (!b) {
  404. EngineError ();
  405. return FALSE;
  406. }
  407. return TRUE;
  408. }
  409. BOOL
  410. WINAPI
  411. IsmSelectComponent (
  412. IN PCTSTR ComponentOrAlias,
  413. IN UINT ComponentGroupId, OPTIONAL
  414. IN BOOL Enable
  415. )
  416. {
  417. PCTSTR memdbNode = NULL;
  418. UINT flags;
  419. BOOL b;
  420. if (ComponentGroupId > 9999) {
  421. SetLastError (ERROR_INVALID_PARAMETER);
  422. DEBUGMSG ((DBG_ERROR, "Invalid component group"));
  423. return FALSE;
  424. }
  425. if (!ComponentOrAlias || !ComponentOrAlias[0]) {
  426. SetLastError (ERROR_INVALID_PARAMETER);
  427. DEBUGMSG ((DBG_ERROR, "Invalid localized alias"));
  428. return FALSE;
  429. }
  430. if (!ComponentGroupId) {
  431. if (!pCheckComponentName (ComponentOrAlias)) {
  432. return FALSE;
  433. }
  434. memdbNode = JoinText (S_COMPONENT_ROOT TEXT("\\"), ComponentOrAlias);
  435. if (!MemDbTestKey (memdbNode)) {
  436. FreeText (memdbNode);
  437. return FALSE;
  438. }
  439. } else {
  440. if (!pFindComponent (ComponentOrAlias, ComponentGroupId, &memdbNode, NULL)) {
  441. SetLastError (ERROR_NO_SUCH_ALIAS);
  442. return FALSE;
  443. }
  444. }
  445. flags = Enable ? MEMDB_FLAG_SELECTED : 0;
  446. b = MemDbSetFlags (memdbNode, flags, MEMDB_FLAG_SELECTED);
  447. FreeText (memdbNode);
  448. if (!b) {
  449. EngineError ();
  450. return FALSE;
  451. }
  452. return TRUE;
  453. }
  454. BOOL
  455. pEnumWorker (
  456. IN OUT PMIG_COMPONENT_ENUM EnumPtr,
  457. IN OUT PCOMPONENTENUM_HANDLE Handle
  458. )
  459. {
  460. BOOL result = FALSE;
  461. PCTSTR pattern;
  462. PCTSTR p;
  463. BOOL enabled;
  464. while (Handle->State != CES_DONE) {
  465. switch (Handle->State) {
  466. case CES_FIRST_COMPONENT:
  467. if (!MemDbEnumFirst (
  468. &Handle->ComponentEnumStruct,
  469. S_COMPONENT_ROOT TEXT("\\*"),
  470. ENUMFLAG_ALL,
  471. 1,
  472. 1
  473. )) {
  474. Handle->State = CES_DONE;
  475. } else {
  476. if (Handle->EnumAliases) {
  477. Handle->State = CES_FIRST_ALIAS;
  478. } else {
  479. Handle->State = CES_NEXT_COMPONENT;
  480. result = TRUE;
  481. }
  482. }
  483. break;
  484. case CES_FIRST_ALIAS:
  485. enabled = ((Handle->ComponentEnumStruct.Flags & MEMDB_FLAG_SELECTED) != 0);
  486. if ((!Handle->EnumEnabled && enabled) ||
  487. (!Handle->EnumDisabled && !enabled)
  488. ) {
  489. Handle->State = CES_NEXT_COMPONENT;
  490. continue;
  491. }
  492. EnumPtr->Instance = 0;
  493. pattern = JoinPaths (Handle->ComponentEnumStruct.FullKeyName, TEXT("*"));
  494. if (!MemDbEnumFirst (
  495. &Handle->AliasEnumStruct,
  496. pattern,
  497. ENUMFLAG_NORMAL,
  498. 4,
  499. ENUMLEVEL_ALLLEVELS
  500. )) {
  501. Handle->State = CES_NEXT_COMPONENT;
  502. } else {
  503. Handle->State = CES_CHECK_ALIAS_FLAGS;
  504. }
  505. FreePathString (pattern);
  506. break;
  507. case CES_NEXT_ALIAS:
  508. if (EnumPtr->SkipToNextComponent) {
  509. MemDbAbortEnum (&Handle->AliasEnumStruct);
  510. Handle->State = CES_NEXT_COMPONENT;
  511. EnumPtr->SkipToNextComponent = FALSE;
  512. break;
  513. }
  514. if (!MemDbEnumNext (&Handle->AliasEnumStruct)) {
  515. Handle->State = CES_NEXT_COMPONENT;
  516. } else {
  517. Handle->State = CES_CHECK_ALIAS_FLAGS;
  518. }
  519. break;
  520. case CES_CHECK_ALIAS_FLAGS:
  521. EnumPtr->Preferred = ((Handle->AliasEnumStruct.Flags & MEMDB_FLAG_PREFERRED) != 0);
  522. Handle->State = CES_NEXT_ALIAS;
  523. if (Handle->EnumPreferredOnly) {
  524. result = EnumPtr->Preferred;
  525. } else if (Handle->EnumNonPreferredOnly) {
  526. result = !EnumPtr->Preferred;
  527. } else {
  528. result = TRUE;
  529. }
  530. break;
  531. case CES_NEXT_COMPONENT:
  532. if (!MemDbEnumNext (&Handle->ComponentEnumStruct)) {
  533. Handle->State = CES_DONE;
  534. } else {
  535. if (Handle->EnumAliases) {
  536. Handle->State = CES_FIRST_ALIAS;
  537. } else {
  538. Handle->State = CES_NEXT_COMPONENT;
  539. result = TRUE;
  540. }
  541. }
  542. break;
  543. default:
  544. Handle->State = CES_DONE;
  545. break;
  546. }
  547. if (result) {
  548. //
  549. // Fill in all of the caller enum struct fields
  550. //
  551. EnumPtr->SkipToNextComponent = FALSE;
  552. EnumPtr->ComponentString = Handle->ComponentEnumStruct.KeyName;
  553. EnumPtr->Enabled = ((Handle->ComponentEnumStruct.Flags & MEMDB_FLAG_SELECTED) != 0);
  554. EnumPtr->MasterGroup = Handle->ComponentEnumStruct.Value;
  555. if (Handle->EnumAliases) {
  556. p = _tcschr (Handle->AliasEnumStruct.FullKeyName, TEXT('\\'));
  557. MYASSERT (p);
  558. if (p) {
  559. p = _tcschr (p + 1, TEXT('\\'));
  560. MYASSERT (p);
  561. }
  562. if (p) {
  563. p++;
  564. if (_totlower (p[0]) == TEXT('u')) {
  565. EnumPtr->UserSupplied = TRUE;
  566. } else {
  567. EnumPtr->UserSupplied = FALSE;
  568. }
  569. p = _tcschr (p, TEXT('\\'));
  570. MYASSERT (p);
  571. }
  572. if (p) {
  573. p++;
  574. EnumPtr->GroupId = _tcstoul (p, (PTSTR *) (&p), 10);
  575. MYASSERT (p && p[0] == TEXT('\\'));
  576. }
  577. if (p) {
  578. EnumPtr->LocalizedAlias = p + 1;
  579. }
  580. //
  581. // If group ID filter was specified, loop until a match is found
  582. //
  583. if (Handle->GroupIdFilter && Handle->GroupIdFilter != EnumPtr->GroupId) {
  584. result = FALSE;
  585. continue;
  586. }
  587. } else {
  588. EnumPtr->Preferred = FALSE;
  589. EnumPtr->UserSupplied = FALSE;
  590. EnumPtr->GroupId = 0;
  591. EnumPtr->LocalizedAlias = NULL;
  592. }
  593. EnumPtr->Instance++;
  594. break;
  595. }
  596. }
  597. if (!result) {
  598. IsmAbortComponentEnum (EnumPtr);
  599. }
  600. return result;
  601. }
  602. BOOL
  603. WINAPI
  604. IsmEnumFirstComponent (
  605. OUT PMIG_COMPONENT_ENUM EnumPtr,
  606. IN DWORD Flags,
  607. IN UINT GroupIdFilter OPTIONAL
  608. )
  609. {
  610. PCOMPONENTENUM_HANDLE handle;
  611. ZeroMemory (EnumPtr, sizeof (MIG_COMPONENT_ENUM));
  612. if (Flags & (COMPONENTENUM_PREFERRED_ONLY|COMPONENTENUM_NON_PREFERRED_ONLY)) {
  613. if (!(Flags & COMPONENTENUM_ALIASES)) {
  614. SetLastError (ERROR_INVALID_PARAMETER);
  615. return FALSE;
  616. }
  617. if ((Flags & (COMPONENTENUM_PREFERRED_ONLY|COMPONENTENUM_NON_PREFERRED_ONLY)) ==
  618. (COMPONENTENUM_PREFERRED_ONLY|COMPONENTENUM_NON_PREFERRED_ONLY)
  619. ) {
  620. SetLastError (ERROR_INVALID_PARAMETER);
  621. return FALSE;
  622. }
  623. }
  624. EnumPtr->Handle = MemAllocUninit (sizeof (COMPONENTENUM_HANDLE));
  625. handle = (PCOMPONENTENUM_HANDLE) EnumPtr->Handle;
  626. handle->EnumAliases = Flags & COMPONENTENUM_ALIASES ? TRUE : FALSE;
  627. handle->EnumEnabled = Flags & COMPONENTENUM_ENABLED ? TRUE : FALSE;
  628. handle->EnumDisabled = Flags & COMPONENTENUM_DISABLED ? TRUE : FALSE;
  629. handle->GroupIdFilter = GroupIdFilter;
  630. handle->EnumPreferredOnly = Flags & COMPONENTENUM_PREFERRED_ONLY;
  631. handle->EnumNonPreferredOnly = Flags & COMPONENTENUM_NON_PREFERRED_ONLY;
  632. handle->State = CES_FIRST_COMPONENT;
  633. return pEnumWorker (EnumPtr, handle);
  634. }
  635. BOOL
  636. WINAPI
  637. IsmEnumNextComponent (
  638. IN OUT PMIG_COMPONENT_ENUM EnumPtr
  639. )
  640. {
  641. PCOMPONENTENUM_HANDLE handle;
  642. handle = (PCOMPONENTENUM_HANDLE) EnumPtr->Handle;
  643. return pEnumWorker (EnumPtr, handle);
  644. }
  645. VOID
  646. WINAPI
  647. IsmAbortComponentEnum (
  648. IN PMIG_COMPONENT_ENUM EnumPtr ZEROED
  649. )
  650. {
  651. PCOMPONENTENUM_HANDLE handle;
  652. handle = (PCOMPONENTENUM_HANDLE) EnumPtr->Handle;
  653. if (handle) {
  654. if (handle->State == CES_NEXT_COMPONENT) {
  655. MemDbAbortEnum (&handle->ComponentEnumStruct);
  656. }
  657. if (handle->EnumAliases) {
  658. if (handle->State == CES_NEXT_ALIAS) {
  659. MemDbAbortEnum (&handle->AliasEnumStruct);
  660. }
  661. }
  662. FreeAlloc (handle);
  663. }
  664. ZeroMemory (EnumPtr, sizeof (MIG_COMPONENT_ENUM));
  665. }
  666. VOID
  667. WINAPI
  668. IsmRemoveAllUserSuppliedComponents (
  669. VOID
  670. )
  671. {
  672. MEMDB_ENUM e;
  673. MULTISZ_ENUM listEnum;
  674. GROWBUFFER list = INIT_GROWBUFFER;
  675. //
  676. // Collect all the components that have user-supplied aliases. Then after
  677. // enum completes, delete them. We don't delete during the enum because it
  678. // is never a good idea to delete the item just enumerated, and then try
  679. // to continue enumerating.
  680. //
  681. if (MemDbEnumFirst (
  682. &e,
  683. S_COMPONENT_ROOT TEXT("\\*\\") S_USER_SUPPLIED TEXT("\\*"),
  684. ENUMFLAG_ALL,
  685. 2,
  686. 2
  687. )) {
  688. do {
  689. GbMultiSzAppend (&list, e.FullKeyName);
  690. } while (MemDbEnumNext (&e));
  691. }
  692. if (EnumFirstMultiSz (&listEnum, (PCTSTR) list.Buf)) {
  693. do {
  694. MemDbDeleteTree (listEnum.CurrentString);
  695. } while (EnumNextMultiSz (&listEnum));
  696. }
  697. GbFree (&list);
  698. }
  699. BOOL
  700. WINAPI
  701. IsmSelectMasterGroup (
  702. IN UINT MasterGroup,
  703. IN BOOL Enable
  704. )
  705. {
  706. MEMDB_ENUM e;
  707. UINT flags;
  708. if (MasterGroup > MASTERGROUP_ALL) {
  709. SetLastError (ERROR_INVALID_PARAMETER);
  710. DEBUGMSG ((DBG_ERROR, "Can't select invalid MasterGroup"));
  711. return FALSE;
  712. }
  713. //
  714. // Enumerate all components and mark them enabled or disabled
  715. // depending on the master group
  716. //
  717. if (MemDbEnumFirst (
  718. &e,
  719. S_COMPONENT_ROOT TEXT("\\*"),
  720. ENUMFLAG_NORMAL,
  721. 1,
  722. 1
  723. )) {
  724. do {
  725. if (MasterGroup == MASTERGROUP_ALL ||
  726. MasterGroup == e.Value
  727. ) {
  728. flags = Enable ? MEMDB_FLAG_SELECTED : 0;
  729. } else {
  730. flags = 0;
  731. }
  732. if (!MemDbSetFlags (e.FullKeyName, flags, MEMDB_FLAG_SELECTED)) {
  733. EngineError ();
  734. MemDbAbortEnum (&e);
  735. return FALSE;
  736. }
  737. } while (MemDbEnumNext (&e));
  738. }
  739. return TRUE;
  740. }
  741. BOOL
  742. WINAPI
  743. IsmIsComponentSelected (
  744. IN PCTSTR ComponentOrAlias,
  745. IN UINT ComponentGroupId OPTIONAL
  746. )
  747. {
  748. UINT flags = 0;
  749. TCHAR memdbNode[MAX_CONTROLLED_NODE_SIZE];
  750. PCTSTR componentNode;
  751. if (!ComponentGroupId) {
  752. if (!pCheckComponentName (ComponentOrAlias)) {
  753. return FALSE;
  754. }
  755. // This is safe since ComponentOrAlias was already checked for length by pCheckComponentName
  756. wsprintf (memdbNode, TEXT("%s\\%s"), S_COMPONENT_ROOT, ComponentOrAlias);
  757. MemDbGetFlags (memdbNode, &flags);
  758. } else {
  759. if (pFindComponent (ComponentOrAlias, ComponentGroupId, &componentNode, NULL)) {
  760. MemDbGetFlags (componentNode, &flags);
  761. FreeText (componentNode);
  762. }
  763. }
  764. return (flags & MEMDB_FLAG_SELECTED) != 0;
  765. }