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.

716 lines
18 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: P E R S I S T . C P P
  7. //
  8. // Contents: Module repsonsible for persistence of the network
  9. // configuration information.
  10. //
  11. // Notes:
  12. //
  13. // Author: shaunco 15 Jan 1999
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.h>
  17. #pragma hdrstop
  18. #include "persist.h"
  19. #include "ncreg.h"
  20. #if defined (_X86_)
  21. inline BOOL IsRunningOnWow64()
  22. {
  23. static DWORD dwCachedWow64 = DWORD_MAX;
  24. if (DWORD_MAX == dwCachedWow64)
  25. {
  26. BOOL fTempWow64;
  27. if (IsWow64Process(GetCurrentProcess(), &fTempWow64))
  28. {
  29. dwCachedWow64 = fTempWow64;
  30. }
  31. else
  32. {
  33. AssertSz(FALSE, "Could not determine whether this is a WOW64 process.");
  34. return FALSE;
  35. }
  36. }
  37. return dwCachedWow64;
  38. }
  39. inline size_t ALIGNUP(size_t nSize)
  40. {
  41. // If we are a 32-bit app running on a 64-bit O/S we need to use 64-bit alignment when reading or writing from the registry.
  42. if (IsRunningOnWow64())
  43. {
  44. return ((nSize + (sizeof(DWORD64) - 1)) & ~(sizeof(DWORD64) - 1));
  45. }
  46. else
  47. {
  48. return nSize;
  49. }
  50. }
  51. #elif defined (_WIN64)
  52. #define ALIGNUP(x) ((x + (sizeof(PVOID) - 1)) & ~(sizeof(PVOID) - 1))
  53. #else
  54. #error Please define an ALIGNUP implementation for this architecture.
  55. #endif
  56. #define alignedsizeof(x) ALIGNUP(sizeof(x))
  57. const DWORD CURRENT_VERSION = 0;
  58. HRESULT
  59. HrLoadNetworkConfigurationFromBuffer (
  60. IN const BYTE* pbBuf,
  61. IN ULONG cbBuf,
  62. OUT CNetConfig* pNetConfig)
  63. {
  64. HRESULT hr;
  65. DWORD dwVersion;
  66. ULONG cComponents;
  67. ULONG cStackEntries;
  68. ULONG cBindPaths;
  69. ULONG unUpperIndex;
  70. ULONG unLowerIndex;
  71. ULONG unComponentIndex;
  72. BOOL fRefByUser;
  73. BASIC_COMPONENT_DATA Data;
  74. CComponentList* pComponents;
  75. CComponent* pComponent;
  76. CStackEntry StackEntry;
  77. CBindPath BindPath;
  78. PCWSTR pszString;
  79. // We should be starting clean.
  80. //
  81. Assert (pNetConfig->Core.FIsEmpty());
  82. hr = S_OK;
  83. // Load the version marker.
  84. //
  85. dwVersion = *(DWORD32*)pbBuf;
  86. pbBuf += alignedsizeof(DWORD32);
  87. if (dwVersion > CURRENT_VERSION)
  88. {
  89. hr = E_UNEXPECTED;
  90. goto finished;
  91. }
  92. // Load the component list.
  93. //
  94. cComponents = *(ULONG32*)pbBuf;
  95. pbBuf += alignedsizeof(ULONG32);
  96. while (cComponents--)
  97. {
  98. ZeroMemory (&Data, sizeof(Data));
  99. Data.InstanceGuid = *(GUID*)pbBuf;
  100. pbBuf += alignedsizeof(GUID);
  101. Data.Class = *(NETCLASS*)pbBuf;
  102. pbBuf += alignedsizeof(NETCLASS);
  103. Data.dwCharacter = *(DWORD32*)pbBuf;
  104. pbBuf += alignedsizeof(DWORD32);
  105. Data.pszInfId = (PCWSTR)pbBuf;
  106. Assert (*Data.pszInfId);
  107. pbBuf += ALIGNUP(CbOfSzAndTerm (Data.pszInfId));
  108. pszString = (PCWSTR)pbBuf;
  109. pbBuf += ALIGNUP(CbOfSzAndTerm (pszString));
  110. if (*pszString)
  111. {
  112. Data.pszPnpId = pszString;
  113. }
  114. hr = CComponent::HrCreateInstance (
  115. &Data,
  116. CCI_DEFAULT,
  117. NULL,
  118. &pComponent);
  119. if (S_OK == hr)
  120. {
  121. hr = pNetConfig->Core.Components.HrInsertComponent (
  122. pComponent, INS_ASSERT_IF_DUP | INS_NON_SORTED);
  123. }
  124. if (S_OK != hr)
  125. {
  126. goto finished;
  127. }
  128. }
  129. // Load the stack table.
  130. //
  131. pComponents = &pNetConfig->Core.Components;
  132. pNetConfig->Core.StackTable.m_fWanAdaptersFirst = *(ULONG32*)pbBuf;
  133. pbBuf += alignedsizeof(ULONG32);
  134. cStackEntries = *(ULONG32*)pbBuf;
  135. pbBuf += alignedsizeof(ULONG32);
  136. while (cStackEntries--)
  137. {
  138. ZeroMemory (&StackEntry, sizeof(StackEntry));
  139. unUpperIndex = *(ULONG32*)pbBuf;
  140. pbBuf += alignedsizeof(ULONG32);
  141. unLowerIndex = *(ULONG32*)pbBuf;
  142. pbBuf += alignedsizeof(ULONG32);
  143. StackEntry.pUpper = pComponents->PGetComponentAtIndex (
  144. unUpperIndex);
  145. StackEntry.pLower = pComponents->PGetComponentAtIndex (
  146. unLowerIndex);
  147. // Insert in the order we persisted. If we used ISE_SORT here, we'd
  148. // blow away whatever bind order we saved.
  149. //
  150. hr = pNetConfig->Core.StackTable.HrInsertStackEntry (
  151. &StackEntry, INS_NON_SORTED);
  152. if (S_OK != hr)
  153. {
  154. goto finished;
  155. }
  156. }
  157. // Load the disabled bindpaths.
  158. //
  159. cBindPaths = *(ULONG32*)pbBuf;
  160. pbBuf += alignedsizeof(ULONG32);
  161. while (cBindPaths--)
  162. {
  163. cComponents = *(ULONG32*)pbBuf;
  164. pbBuf += alignedsizeof(ULONG32);
  165. BindPath.Clear();
  166. while (cComponents--)
  167. {
  168. unComponentIndex = *(ULONG32*)pbBuf;
  169. pbBuf += alignedsizeof(ULONG32);
  170. pComponent = pComponents->PGetComponentAtIndex (unComponentIndex);
  171. Assert (pComponent);
  172. hr = BindPath.HrAppendComponent (pComponent);
  173. if (S_OK != hr)
  174. {
  175. goto finished;
  176. }
  177. }
  178. hr = pNetConfig->Core.DisabledBindings.HrAddBindPath (
  179. &BindPath, INS_ASSERT_IF_DUP | INS_APPEND);
  180. if (S_OK != hr)
  181. {
  182. goto finished;
  183. }
  184. }
  185. // Load the component references.
  186. //
  187. cComponents = *(ULONG32*)pbBuf;
  188. pbBuf += alignedsizeof(ULONG32);
  189. while (cComponents--)
  190. {
  191. unComponentIndex = *(ULONG32*)pbBuf;
  192. pbBuf += alignedsizeof(ULONG32);
  193. pComponent = pComponents->PGetComponentAtIndex (unComponentIndex);
  194. Assert (pComponent);
  195. fRefByUser = *(ULONG32*)pbBuf;
  196. pbBuf += alignedsizeof(ULONG32);
  197. if (fRefByUser)
  198. {
  199. hr = pComponent->Refs.HrAddReferenceByUser ();
  200. if (S_OK != hr)
  201. {
  202. goto finished;
  203. }
  204. }
  205. // Load the count of components that reference this component.
  206. //
  207. ULONG CountRefdBy = *(ULONG32*)pbBuf;
  208. pbBuf += alignedsizeof(ULONG32);
  209. // Load the indicies of the components that reference this component.
  210. //
  211. for (UINT i = 0; i < CountRefdBy; i++)
  212. {
  213. unComponentIndex = *(ULONG32*)pbBuf;
  214. pbBuf += alignedsizeof(ULONG32);
  215. CComponent* pRefdBy;
  216. pRefdBy = pComponents->PGetComponentAtIndex (unComponentIndex);
  217. Assert (pRefdBy);
  218. hr = pComponent->Refs.HrAddReferenceByComponent (pRefdBy);
  219. if (S_OK != hr)
  220. {
  221. goto finished;
  222. }
  223. }
  224. // Load the count of strings that represent external software
  225. // that reference this component.
  226. //
  227. CountRefdBy = *(ULONG32*)pbBuf;
  228. pbBuf += alignedsizeof(ULONG32);
  229. // Load the strings that represent external software that
  230. // references this component.
  231. //
  232. for (i = 0; i < CountRefdBy; i++)
  233. {
  234. pszString = (PCWSTR)pbBuf;
  235. pbBuf += ALIGNUP(CbOfSzAndTerm (pszString));
  236. hr = pComponent->Refs.HrAddReferenceBySoftware (pszString);
  237. if (S_OK != hr)
  238. {
  239. goto finished;
  240. }
  241. }
  242. }
  243. finished:
  244. if (S_OK != hr)
  245. {
  246. pNetConfig->Core.DisabledBindings.Clear ();
  247. pNetConfig->Core.StackTable.Clear ();
  248. FreeCollectionAndItem (pNetConfig->Core.Components);
  249. }
  250. return hr;
  251. }
  252. HRESULT
  253. HrLoadNetworkConfigurationFromRegistry (
  254. IN REGSAM samDesired,
  255. OUT CNetConfig* pNetConfig)
  256. {
  257. HRESULT hr;
  258. HKEY hkeyNetwork;
  259. Assert ((KEY_READ == samDesired) || (KEY_WRITE == samDesired));
  260. hr = HrOpenNetworkKey (KEY_READ, &hkeyNetwork);
  261. if (S_OK == hr)
  262. {
  263. BYTE* pbBuf;
  264. ULONG cbBuf;
  265. hr = HrRegQueryBinaryWithAlloc (
  266. hkeyNetwork,
  267. L"Config",
  268. &pbBuf, &cbBuf);
  269. // If we read the config binary, use it to initialize pNetConfig.
  270. //
  271. if (S_OK == hr)
  272. {
  273. hr = HrLoadNetworkConfigurationFromBuffer (pbBuf, cbBuf,
  274. pNetConfig);
  275. if (S_OK == hr)
  276. {
  277. pNetConfig->Core.DbgVerifyData ();
  278. }
  279. MemFree (pbBuf);
  280. }
  281. // Otherwise, if we couldn't read the config binary, we'll have
  282. // to construct what we can by grovelling the registry.
  283. //
  284. else
  285. {
  286. hr = HrLoadNetworkConfigurationFromLegacy (pNetConfig);
  287. if (S_OK == hr)
  288. {
  289. hr = HrSaveNetworkConfigurationToRegistry (pNetConfig);
  290. }
  291. }
  292. RegCloseKey (hkeyNetwork);
  293. }
  294. TraceHr (ttidError, FAL, hr, FALSE, "HrLoadNetworkConfigurationFromRegistry");
  295. return hr;
  296. }
  297. ULONG
  298. CountComponentsReferencedByOthers (
  299. IN CNetConfig* pNetConfig)
  300. {
  301. ULONG cComponents;
  302. CComponentList::iterator iter;
  303. CComponent* pComponent;
  304. cComponents = 0;
  305. for (iter = pNetConfig->Core.Components.begin();
  306. iter != pNetConfig->Core.Components.end();
  307. iter++)
  308. {
  309. pComponent = *iter;
  310. Assert (pComponent);
  311. if (pComponent->Refs.FIsReferencedByOthers ())
  312. {
  313. cComponents++;
  314. }
  315. }
  316. return cComponents;
  317. }
  318. HRESULT
  319. HrSaveNetworkConfigurationToBuffer (
  320. IN CNetConfig* pNetConfig,
  321. IN BYTE* pbBuf,
  322. IN OUT ULONG* pcbBuf)
  323. {
  324. HRESULT hr;
  325. ULONG cbBuf;
  326. ULONG cbBufIn;
  327. ULONG unIndex;
  328. ULONG Count;
  329. CComponentList* pComponents;
  330. CComponent* pComponent;
  331. CStackEntry* pStackEntry;
  332. CBindPath* pBindPath;
  333. PCWSTR pszString;
  334. Assert (pNetConfig);
  335. pNetConfig->Core.DbgVerifyData ();
  336. Assert (pcbBuf);
  337. cbBufIn = *pcbBuf;
  338. cbBuf = 0;
  339. pComponents = &pNetConfig->Core.Components;
  340. // Save the version number.
  341. //
  342. cbBuf += alignedsizeof(DWORD32);
  343. if (pbBuf && (cbBuf <= cbBufIn))
  344. {
  345. *(DWORD32*)pbBuf = CURRENT_VERSION;
  346. pbBuf += alignedsizeof(DWORD32);
  347. }
  348. // Save the component list.
  349. //
  350. Count = pComponents->Count();
  351. cbBuf += alignedsizeof(ULONG32);
  352. if (pbBuf && (cbBuf <= cbBufIn))
  353. {
  354. *(ULONG32*)pbBuf = Count;
  355. pbBuf += alignedsizeof(ULONG32);
  356. }
  357. for (unIndex = 0; unIndex < Count; unIndex++)
  358. {
  359. pComponent = pComponents->PGetComponentAtIndex (unIndex);
  360. Assert (pComponent);
  361. pszString = (pComponent->m_pszPnpId) ? pComponent->m_pszPnpId : L"";
  362. ULONG cbInfIdUnpad = CbOfSzAndTerm (pComponent->m_pszInfId);
  363. ULONG cbPnpIdUnpad = CbOfSzAndTerm (pszString);
  364. ULONG cbInfId = ALIGNUP(cbInfIdUnpad);
  365. ULONG cbPnpId = ALIGNUP(cbPnpIdUnpad);
  366. cbBuf += alignedsizeof(GUID) + alignedsizeof(NETCLASS) + alignedsizeof(DWORD32) +
  367. cbInfId +
  368. cbPnpId;
  369. if (pbBuf && (cbBuf <= cbBufIn))
  370. {
  371. *(GUID*)pbBuf = pComponent->m_InstanceGuid;
  372. pbBuf += alignedsizeof(GUID);
  373. *(NETCLASS*)pbBuf = pComponent->Class();
  374. pbBuf += alignedsizeof(NETCLASS);
  375. *(DWORD32*)pbBuf = pComponent->m_dwCharacter;
  376. pbBuf += alignedsizeof(DWORD32);
  377. CopyMemory(pbBuf, pComponent->m_pszInfId, cbInfIdUnpad);
  378. pbBuf += cbInfId;
  379. CopyMemory(pbBuf, pszString, cbPnpIdUnpad);
  380. pbBuf += cbPnpId;
  381. }
  382. }
  383. // Save the stack table.
  384. //
  385. cbBuf += alignedsizeof(ULONG32);
  386. if (pbBuf && (cbBuf <= cbBufIn))
  387. {
  388. *(ULONG32*)pbBuf = pNetConfig->Core.StackTable.m_fWanAdaptersFirst;
  389. pbBuf += alignedsizeof(ULONG32);
  390. }
  391. Count = pNetConfig->Core.StackTable.CountEntries();
  392. cbBuf += alignedsizeof(ULONG32);
  393. if (pbBuf && (cbBuf <= cbBufIn))
  394. {
  395. *(ULONG32*)pbBuf = Count;
  396. pbBuf += alignedsizeof(ULONG32);
  397. }
  398. for (pStackEntry = pNetConfig->Core.StackTable.begin();
  399. pStackEntry != pNetConfig->Core.StackTable.end();
  400. pStackEntry++)
  401. {
  402. cbBuf += alignedsizeof(ULONG32) + alignedsizeof(ULONG32);
  403. if (pbBuf && (cbBuf <= cbBufIn))
  404. {
  405. *(ULONG32*)pbBuf = pComponents->UnGetIndexOfComponent (pStackEntry->pUpper);
  406. pbBuf += alignedsizeof(ULONG32);
  407. *(ULONG32*)pbBuf = pComponents->UnGetIndexOfComponent (pStackEntry->pLower);
  408. pbBuf += alignedsizeof(ULONG32);
  409. }
  410. }
  411. // Save the disabled bindpaths.
  412. //
  413. Count = pNetConfig->Core.DisabledBindings.CountBindPaths();
  414. cbBuf += alignedsizeof(ULONG32);
  415. if (pbBuf && (cbBuf <= cbBufIn))
  416. {
  417. *(ULONG32*)pbBuf = Count;
  418. pbBuf += alignedsizeof(ULONG32);
  419. }
  420. for (pBindPath = pNetConfig->Core.DisabledBindings.begin();
  421. pBindPath != pNetConfig->Core.DisabledBindings.end();
  422. pBindPath++)
  423. {
  424. Count = pBindPath->CountComponents();
  425. cbBuf += alignedsizeof(ULONG32) + (Count * alignedsizeof(ULONG32));
  426. if (pbBuf && (cbBuf <= cbBufIn))
  427. {
  428. *(ULONG32*)pbBuf = Count;
  429. pbBuf += alignedsizeof(ULONG32);
  430. CBindPath::iterator iter;
  431. for (iter = pBindPath->begin();
  432. iter != pBindPath->end();
  433. iter++)
  434. {
  435. pComponent = *iter;
  436. *(ULONG32*)pbBuf = pComponents->UnGetIndexOfComponent (pComponent);
  437. pbBuf += alignedsizeof(ULONG32);
  438. }
  439. }
  440. }
  441. // Save the component references.
  442. //
  443. Count = CountComponentsReferencedByOthers (pNetConfig);
  444. cbBuf += alignedsizeof(ULONG32);
  445. if (pbBuf && (cbBuf <= cbBufIn))
  446. {
  447. *(ULONG32*)pbBuf = Count;
  448. pbBuf += alignedsizeof(ULONG32);
  449. }
  450. for (unIndex = 0; unIndex < pComponents->Count(); unIndex++)
  451. {
  452. pComponent = pComponents->PGetComponentAtIndex (unIndex);
  453. Assert (pComponent);
  454. if (!pComponent->Refs.FIsReferencedByOthers ())
  455. {
  456. continue;
  457. }
  458. // Index of component with the references.
  459. //
  460. cbBuf += alignedsizeof(ULONG32);
  461. if (pbBuf && (cbBuf <= cbBufIn))
  462. {
  463. *(ULONG32*)pbBuf = unIndex;
  464. pbBuf += alignedsizeof(ULONG32);
  465. }
  466. // Save whether the component is refernced by the user or not.
  467. //
  468. cbBuf += alignedsizeof(ULONG32);
  469. if (pbBuf && (cbBuf <= cbBufIn))
  470. {
  471. *(ULONG32*)pbBuf = pComponent->Refs.FIsReferencedByUser() ? 1 : 0;
  472. pbBuf += alignedsizeof(ULONG32);
  473. }
  474. // Save the count of components that reference this component.
  475. //
  476. ULONG CountRefdBy = pComponent->Refs.CountComponentsReferencedBy ();
  477. cbBuf += alignedsizeof(ULONG32);
  478. if (pbBuf && (cbBuf <= cbBufIn))
  479. {
  480. *(ULONG32*)pbBuf = CountRefdBy;
  481. pbBuf += alignedsizeof(ULONG32);
  482. }
  483. // Save the indicies of the components that reference this component.
  484. //
  485. for (UINT i = 0; i < CountRefdBy; i++)
  486. {
  487. CComponent* pRefdBy;
  488. pRefdBy = pComponent->Refs.PComponentReferencedByAtIndex(i);
  489. Assert (pRefdBy);
  490. cbBuf += alignedsizeof(ULONG32);
  491. if (pbBuf && (cbBuf <= cbBufIn))
  492. {
  493. *(ULONG32*)pbBuf = pComponents->UnGetIndexOfComponent (pRefdBy);
  494. pbBuf += alignedsizeof(ULONG32);
  495. }
  496. }
  497. // Save the count of strings that represent external software
  498. // that reference this component.
  499. //
  500. CountRefdBy = pComponent->Refs.CountSoftwareReferencedBy ();
  501. cbBuf += alignedsizeof(ULONG32);
  502. if (pbBuf && (cbBuf <= cbBufIn))
  503. {
  504. *(ULONG32*)pbBuf = CountRefdBy;
  505. pbBuf += alignedsizeof(ULONG32);
  506. }
  507. // Save the strings that represent external software that
  508. // reference this component.
  509. //
  510. for (i = 0; i < CountRefdBy; i++)
  511. {
  512. const CWideString* pStr;
  513. pStr = pComponent->Refs.PSoftwareReferencedByAtIndex(i);
  514. Assert (pStr);
  515. ULONG cb = (pStr->length() + 1) * sizeof(WCHAR);
  516. cbBuf += ALIGNUP(cb);
  517. if (pbBuf && (cbBuf <= cbBufIn))
  518. {
  519. CopyMemory (pbBuf, pStr->c_str(), cb);
  520. pbBuf += ALIGNUP(cb);
  521. }
  522. }
  523. }
  524. *pcbBuf = cbBuf;
  525. if (cbBuf <= cbBufIn)
  526. {
  527. hr = S_OK;
  528. }
  529. else
  530. {
  531. hr = (pbBuf) ? HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) : S_OK;
  532. }
  533. TraceHr (ttidError, FAL, hr, FALSE, "HrSaveNetworkConfigurationToBuffer");
  534. return hr;
  535. }
  536. HRESULT
  537. HrSaveNetworkConfigurationToBufferWithAlloc (
  538. IN CNetConfig* pNetConfig,
  539. OUT BYTE** ppbBuf,
  540. OUT ULONG* pcbBuf)
  541. {
  542. HRESULT hr;
  543. Assert (pNetConfig);
  544. Assert (ppbBuf);
  545. Assert (pcbBuf);
  546. *ppbBuf = NULL;
  547. *pcbBuf = 0;
  548. ULONG cbBuf;
  549. hr = HrSaveNetworkConfigurationToBuffer (pNetConfig, NULL, &cbBuf);
  550. if (S_OK == hr)
  551. {
  552. hr = E_OUTOFMEMORY;
  553. *ppbBuf = (BYTE*)MemAlloc (cbBuf);
  554. if (*ppbBuf)
  555. {
  556. hr = HrSaveNetworkConfigurationToBuffer (
  557. pNetConfig, *ppbBuf, &cbBuf);
  558. if (S_OK == hr)
  559. {
  560. *pcbBuf = cbBuf;
  561. }
  562. }
  563. }
  564. TraceHr (ttidError, FAL, hr, FALSE, "HrSaveNetworkConfigurationToBufferWithAlloc");
  565. return hr;
  566. }
  567. HRESULT
  568. HrSaveNetworkConfigurationToRegistry (
  569. IN CNetConfig* pNetConfig)
  570. {
  571. HRESULT hr;
  572. HKEY hkeyNetwork;
  573. Assert (pNetConfig);
  574. pNetConfig->Core.DbgVerifyData ();
  575. hr = HrOpenNetworkKey (KEY_WRITE, &hkeyNetwork);
  576. if (S_OK == hr)
  577. {
  578. BYTE* pbBuf;
  579. ULONG cbBuf;
  580. hr = HrSaveNetworkConfigurationToBufferWithAlloc (
  581. pNetConfig, &pbBuf, &cbBuf);
  582. if (S_OK == hr)
  583. {
  584. hr = HrRegSetBinary (hkeyNetwork, L"Config", pbBuf, cbBuf);
  585. MemFree (pbBuf);
  586. // Permission from the Perf team to call this. We need to ensure
  587. // that the configuration we just wrote will be available on
  588. // next boot in the case that we crash.
  589. //
  590. RegFlushKey (hkeyNetwork);
  591. }
  592. RegCloseKey (hkeyNetwork);
  593. }
  594. TraceHr (ttidError, FAL, hr, FALSE, "HrSaveNetworkConfigurationToRegistry");
  595. return hr;
  596. }