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.

453 lines
11 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. ocstate.c
  5. Abstract:
  6. Routines to remember and restore the install state of subcomponents.
  7. Author:
  8. Ted Miller (tedm) 17-Oct-1996
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. typedef struct _I_S_PARAMS {
  14. HKEY hKey;
  15. BOOL Set;
  16. BOOL AnyError;
  17. BOOL Simple;
  18. POC_MANAGER OcManager;
  19. } I_S_PARAMS, *PI_S_PARAMS;
  20. BOOL
  21. pOcPersistantInstallStatesWorker(
  22. IN POC_MANAGER OcManager,
  23. IN BOOL Set,
  24. IN LONG ComponentStringId
  25. );
  26. BOOL
  27. pOcInitInstallStatesStringTableCB(
  28. IN PVOID StringTable,
  29. IN LONG StringId,
  30. IN PCTSTR String,
  31. IN POPTIONAL_COMPONENT Oc,
  32. IN UINT OcStructSize,
  33. IN PI_S_PARAMS Params
  34. );
  35. BOOL
  36. pOcFetchInstallStates(
  37. IN POC_MANAGER OcManager
  38. )
  39. /*++
  40. Routine Description:
  41. This routine retreives stored installation state for all leaf child
  42. subcomponents, from the registry. It does NOT set or manipulate parent
  43. selection states.
  44. Both the selection state and original selection state memebers of the
  45. optional component structures are set (to the same value) by this routine.
  46. Arguments:
  47. OcManager - supplies OC Manager context info.
  48. Return Value:
  49. Boolean value indicating outcome. If FALSE then some catastrophic
  50. registry error occurred.
  51. --*/
  52. {
  53. return(pOcPersistantInstallStatesWorker(OcManager,FALSE,-1));
  54. }
  55. BOOL
  56. pOcRememberInstallStates(
  57. IN POC_MANAGER OcManager
  58. )
  59. /*++
  60. Routine Description:
  61. This routine stores installation state for all leaf child
  62. subcomponents, into the registry. It does NOT set or manipulate parent
  63. selection states.
  64. The current selection state is stored, and then the original state is
  65. reset to the current state.
  66. Arguments:
  67. OcManager - supplies OC Manager context info.
  68. Return Value:
  69. Boolean value indicating outcome. If FALSE then some catastrophic
  70. registry error occurred.
  71. --*/
  72. {
  73. return(pOcPersistantInstallStatesWorker(OcManager,TRUE,-1));
  74. }
  75. BOOL
  76. pOcSetOneInstallState(
  77. IN POC_MANAGER OcManager,
  78. IN LONG StringId
  79. )
  80. /*++
  81. Routine Description:
  82. This routine stores installation state for one single leaf child
  83. subcomponent, into the registry.
  84. The current selection state is stored. The original selection state
  85. is not manipulated.
  86. Arguments:
  87. OcManager - supplies OC Manager context info.
  88. Return Value:
  89. Boolean value indicating outcome. If FALSE then some catastrophic
  90. registry error occurred.
  91. --*/
  92. {
  93. return(pOcPersistantInstallStatesWorker(OcManager,TRUE,StringId));
  94. }
  95. BOOL
  96. pOcPersistantInstallStatesWorker(
  97. IN POC_MANAGER OcManager,
  98. IN BOOL Set,
  99. IN LONG ComponentStringId
  100. )
  101. /*++
  102. Routine Description:
  103. Worker routine for fetching and remembering installation states.
  104. If opens/creates the key used in the registry for persistent state info,
  105. the enumerates the component string table to examine each subcomponent
  106. and either fetch or set the install state.
  107. Arguments:
  108. OcManager - supplies OC Manager context info.
  109. Set - if 0 then query state from the registry and store in the
  110. OPTIONAL_COMPONENT structures. If non-0 then set state into registry.
  111. If 0 then query. Component DLLs will be sent OC_DETECT_INITIAL_STATE
  112. notifications.
  113. Return Value:
  114. Boolean value indicating outcome. If FALSE then some catastrophic
  115. registry error occurred.
  116. --*/
  117. {
  118. OPTIONAL_COMPONENT Oc;
  119. LONG l;
  120. DWORD Disposition;
  121. I_S_PARAMS Params;
  122. l = RegCreateKeyEx(
  123. HKEY_LOCAL_MACHINE,
  124. szSubcompList,
  125. 0,
  126. NULL,
  127. REG_OPTION_NON_VOLATILE,
  128. (Set || (OcManager->InternalFlags & OCMFLAG_KILLSUBCOMPS)) ? KEY_SET_VALUE : KEY_QUERY_VALUE,
  129. NULL,
  130. &Params.hKey,
  131. &Disposition
  132. );
  133. if(l != NO_ERROR) {
  134. _LogError(
  135. OcManager,
  136. Set ? OcErrLevError : OcErrLevFatal,
  137. MSG_OC_CREATE_KEY_FAILED,
  138. szSubcompList,
  139. l
  140. );
  141. return(FALSE);
  142. }
  143. Params.Set = Set;
  144. Params.AnyError = FALSE;
  145. Params.OcManager = OcManager;
  146. if(ComponentStringId == -1) {
  147. //
  148. // Enumerate whole table and operate on each leaf node.
  149. //
  150. Params.Simple = FALSE;
  151. pSetupStringTableEnum(
  152. OcManager->ComponentStringTable,
  153. &Oc,
  154. sizeof(OPTIONAL_COMPONENT),
  155. (PSTRTAB_ENUM_ROUTINE)pOcInitInstallStatesStringTableCB,
  156. (LPARAM)&Params
  157. );
  158. } else {
  159. //
  160. // Operate on one single subcomponent.
  161. //
  162. Params.Simple = TRUE;
  163. if (!pOcComponentWasRemoved(OcManager, ComponentStringId)) {
  164. pSetupStringTableGetExtraData(
  165. OcManager->ComponentStringTable,
  166. ComponentStringId,
  167. &Oc,
  168. sizeof(OPTIONAL_COMPONENT)
  169. );
  170. pOcInitInstallStatesStringTableCB(
  171. OcManager->ComponentStringTable,
  172. ComponentStringId,
  173. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentStringId),
  174. &Oc,
  175. sizeof(OPTIONAL_COMPONENT),
  176. &Params
  177. );
  178. }
  179. }
  180. RegCloseKey(Params.hKey);
  181. return(!Params.AnyError);
  182. }
  183. BOOL
  184. pOcInitInstallStatesStringTableCB(
  185. IN PVOID StringTable,
  186. IN LONG StringId,
  187. IN PCTSTR String,
  188. IN POPTIONAL_COMPONENT Oc,
  189. IN UINT OcStructSize,
  190. IN PI_S_PARAMS Params
  191. )
  192. {
  193. LONG l;
  194. DWORD Type;
  195. DWORD Data;
  196. DWORD Size;
  197. SubComponentState s;
  198. //
  199. // If this is not a leaf/child component, ignore it.
  200. //
  201. if(Oc->FirstChildStringId == -1) {
  202. if(Params->Set) {
  203. Data = (Oc->SelectionState == SELSTATE_NO) ? 0 : 1;
  204. if( ((Params->OcManager)->SetupMode & SETUPMODE_PRIVATE_MASK) == SETUPMODE_REMOVEALL ) {
  205. RegDeleteValue(Params->hKey,String);
  206. } else {
  207. l = RegSetValueEx(Params->hKey,String,0,REG_DWORD,(CONST BYTE *)&Data,sizeof(DWORD));
  208. if(l != NO_ERROR) {
  209. Params->AnyError = TRUE;
  210. _LogError(
  211. Params->OcManager,
  212. OcErrLevError,
  213. MSG_OC_CANT_REMEMBER_STATE,
  214. Oc->Description,
  215. l
  216. );
  217. }
  218. }
  219. } else {
  220. // kill the entry from the registry before starting, if indicated
  221. if (Params->OcManager->InternalFlags & OCMFLAG_KILLSUBCOMPS)
  222. l = RegDeleteValue(Params->hKey,String);
  223. // Check the registery and see if we have dealt with this component before
  224. // Data should contain 0/1 depending on the current installed state
  225. //
  226. // If the entry does not exist the data type/size is not valid
  227. // then we don't have Prior knowlege of component.
  228. //
  229. // also check the inf settting for installation state
  230. Size = sizeof(DWORD);
  231. l = RegQueryValueEx(Params->hKey,String,NULL,&Type,(LPBYTE)&Data,&Size);
  232. switch (Oc->InstalledState)
  233. {
  234. case INSTSTATE_YES:
  235. Data = 1;
  236. break;
  237. case INSTSTATE_NO:
  238. Data = 0;
  239. break;
  240. }
  241. if((l != NO_ERROR) || (Size != sizeof(DWORD)) || ((Type != REG_DWORD) && (Type != REG_BINARY))) {
  242. // Nope, never seen it, Set Data to Uninstalled
  243. // and flag this item as new
  244. Data = 0;
  245. Oc->InternalFlags |= OCFLAG_NEWITEM;
  246. } else {
  247. // have seen it before, Data contains it's current install state
  248. // Flag this component that it had an initial install state
  249. Oc->InternalFlags |= OCFLAG_ANYORIGINALLYON;
  250. }
  251. //
  252. // Now call out to the component dll to ask whether it wants to
  253. // override the value we decided on.
  254. //
  255. s = OcInterfaceQueryState(
  256. Params->OcManager,
  257. pOcGetTopLevelComponent(Params->OcManager,StringId),
  258. String,
  259. OCSELSTATETYPE_ORIGINAL
  260. );
  261. switch(s) {
  262. case SubcompUseOcManagerDefault:
  263. Oc->SelectionState = Data ? SELSTATE_YES : SELSTATE_NO;
  264. break;
  265. case SubcompOn:
  266. Oc->SelectionState = SELSTATE_YES;
  267. Oc->InternalFlags |= OCFLAG_ANYORIGINALLYON;
  268. break;
  269. case SubcompOff:
  270. Oc->SelectionState = SELSTATE_NO;
  271. Oc->InternalFlags |= OCFLAG_ANYORIGINALLYOFF;
  272. break;
  273. }
  274. }
  275. pSetupStringTableSetExtraData(StringTable,StringId,Oc,OcStructSize);
  276. if(!Params->Simple) {
  277. Oc->OriginalSelectionState = Oc->SelectionState;
  278. pSetupStringTableSetExtraData(StringTable,StringId,Oc,OcStructSize);
  279. pOcUpdateParentSelectionStates(Params->OcManager,NULL,StringId);
  280. }
  281. }
  282. return(TRUE);
  283. }
  284. /*
  285. * this function is exported to allow external code to
  286. * access the installation states
  287. */
  288. UINT
  289. OcComponentState(
  290. LPCTSTR component,
  291. UINT operation,
  292. DWORD *val
  293. )
  294. {
  295. HKEY hkey;
  296. LONG rc;
  297. DWORD dw;
  298. DWORD size;
  299. sapiAssert(val);
  300. rc = RegCreateKeyEx(
  301. HKEY_LOCAL_MACHINE,
  302. szSubcompList,
  303. 0,
  304. NULL,
  305. REG_OPTION_NON_VOLATILE,
  306. (operation == infQuery) ? KEY_QUERY_VALUE : KEY_SET_VALUE,
  307. NULL,
  308. &hkey,
  309. &dw
  310. );
  311. if (rc != ERROR_SUCCESS)
  312. return rc;
  313. switch (operation) {
  314. case infQuery:
  315. rc = RegQueryValueEx(hkey, component, NULL, &dw, (LPBYTE)val, &size);
  316. if (rc == ERROR_FILE_NOT_FOUND) {
  317. *val = 0;
  318. rc = ERROR_SUCCESS;
  319. }
  320. break;
  321. case infSet:
  322. if (*val == SELSTATE_NO || *val == SELSTATE_YES) {
  323. dw = (*val == SELSTATE_NO) ? 0 : 1;
  324. rc = RegSetValueEx(hkey, component, 0, REG_DWORD, (CONST BYTE *)&dw, sizeof(DWORD));
  325. break;
  326. }
  327. // pass through
  328. default:
  329. rc = ERROR_INVALID_PARAMETER;
  330. break;
  331. }
  332. RegCloseKey(hkey);
  333. *val = (*val == 0) ? SELSTATE_NO : SELSTATE_YES;
  334. return rc;
  335. }