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.

627 lines
15 KiB

  1. #include <pch.h>
  2. #pragma hdrstop
  3. #include "comp.h"
  4. #include "nccom.h"
  5. #include "ncperms.h"
  6. #include "ncreg.h"
  7. #include "ncsetup.h"
  8. #include "util.h"
  9. VOID
  10. CreateInstanceKeyPath (
  11. NETCLASS Class,
  12. const GUID& InstanceGuid,
  13. PWSTR pszPath)
  14. {
  15. PCWSTR pszNetworkSubtreePath;
  16. Assert (pszPath);
  17. pszNetworkSubtreePath = MAP_NETCLASS_TO_NETWORK_SUBTREE[Class];
  18. AssertSz (pszNetworkSubtreePath,
  19. "This class does not use the network subtree.");
  20. wcscpy (pszPath, pszNetworkSubtreePath);
  21. wcscat (pszPath, L"\\");
  22. INT cch = StringFromGUID2 (
  23. InstanceGuid,
  24. pszPath + wcslen(pszPath),
  25. c_cchGuidWithTerm);
  26. Assert (c_cchGuidWithTerm == cch);
  27. }
  28. HRESULT
  29. HrOpenDeviceInfo (
  30. IN NETCLASS Class,
  31. IN PCWSTR pszPnpId,
  32. OUT HDEVINFO* phdiOut,
  33. OUT SP_DEVINFO_DATA* pdeidOut)
  34. {
  35. HRESULT hr;
  36. Assert (FIsEnumerated(Class));
  37. Assert (pszPnpId && *pszPnpId);
  38. Assert (phdiOut);
  39. Assert (pdeidOut);
  40. hr = HrSetupDiCreateDeviceInfoList (
  41. NULL,
  42. NULL,
  43. phdiOut);
  44. if (S_OK == hr)
  45. {
  46. hr = HrSetupDiOpenDeviceInfo (
  47. *phdiOut,
  48. pszPnpId,
  49. NULL,
  50. 0,
  51. pdeidOut);
  52. // On failure, cleanup the hdevinfo.
  53. //
  54. if (S_OK != hr)
  55. {
  56. SetupDiDestroyDeviceInfoList (*phdiOut);
  57. *phdiOut = NULL;
  58. }
  59. }
  60. TraceHr (ttidError, FAL, hr, SPAPI_E_NO_SUCH_DEVINST == hr,
  61. "HrOpenDeviceInfo (%S)", pszPnpId);
  62. return hr;
  63. }
  64. HRESULT
  65. HrOpenComponentInstanceKey (
  66. IN NETCLASS Class,
  67. IN const GUID& InstanceGuid, OPTIONAL
  68. IN PCWSTR pszPnpId, OPTIONAL
  69. IN REGSAM samDesired,
  70. OUT HKEY* phkey,
  71. OUT HDEVINFO* phdiOut OPTIONAL,
  72. OUT SP_DEVINFO_DATA* pdeidOut OPTIONAL)
  73. {
  74. HRESULT hr;
  75. WCHAR szInstanceKeyPath [_MAX_PATH];
  76. Assert (FIsValidNetClass(Class));
  77. Assert (FImplies(FIsConsideredNetClass(Class), pszPnpId && *pszPnpId));
  78. Assert (phkey);
  79. Assert ((phdiOut && pdeidOut) || (!phdiOut && !pdeidOut));
  80. *phkey = NULL;
  81. if (phdiOut)
  82. {
  83. *phdiOut = NULL;
  84. }
  85. // Non-enumerated components have there instance key under the Network
  86. // tree.
  87. //
  88. if (!FIsEnumerated (Class))
  89. {
  90. CreateInstanceKeyPath(Class, InstanceGuid, szInstanceKeyPath);
  91. hr = HrRegOpenKeyEx (
  92. HKEY_LOCAL_MACHINE,
  93. szInstanceKeyPath,
  94. samDesired,
  95. phkey);
  96. TraceHr (ttidError, FAL, hr, FALSE, "HrOpenInstanceKey (%S)",
  97. szInstanceKeyPath);
  98. }
  99. // For enumerated components, we get the instance key from PnP.
  100. //
  101. else
  102. {
  103. Assert (pszPnpId);
  104. HDEVINFO hdi;
  105. SP_DEVINFO_DATA deid;
  106. SP_DEVINFO_DATA* pdeid;
  107. pdeid = (pdeidOut) ? pdeidOut : &deid;
  108. hr = HrOpenDeviceInfo (Class, pszPnpId, &hdi, pdeid);
  109. if (S_OK == hr)
  110. {
  111. hr = HrSetupDiOpenDevRegKey (
  112. hdi,
  113. pdeid,
  114. DICS_FLAG_GLOBAL,
  115. 0,
  116. DIREG_DRV,
  117. samDesired,
  118. phkey);
  119. if (S_OK == hr)
  120. {
  121. if (phdiOut)
  122. {
  123. *phdiOut = hdi;
  124. }
  125. }
  126. // On error, or if the caller doesn't want the HDEVINFO, free it.
  127. //
  128. if (!phdiOut || (S_OK != hr))
  129. {
  130. SetupDiDestroyDeviceInfoList (hdi);
  131. }
  132. }
  133. else if ((SPAPI_E_NO_SUCH_DEVINST == hr) && (KEY_READ == samDesired))
  134. {
  135. // The instance key may not exist for the case when the
  136. // class installer is called to remove an enumerated
  137. // component and then notifies us to remove its bindings.
  138. // For this case, the class installer has created a
  139. // temporary key under the Network subtree that we can use
  140. // to read a limited set of the data (namely LowerRange and
  141. // UpperRange) we'll need to finish off the removal.
  142. //
  143. // We only do this for KEY_READ since there is no point in
  144. // allowing anyone else to write to this key. This prevents
  145. // HrCreateLinkageKey in particular from trying to write
  146. // to this key.
  147. //
  148. wcscpy (szInstanceKeyPath,
  149. c_szTempNetcfgStorageForUninstalledEnumeratedComponent);
  150. INT cch = StringFromGUID2 (
  151. InstanceGuid,
  152. szInstanceKeyPath + wcslen(szInstanceKeyPath),
  153. c_cchGuidWithTerm);
  154. Assert (c_cchGuidWithTerm == cch);
  155. hr = HrRegOpenKeyEx (
  156. HKEY_LOCAL_MACHINE,
  157. szInstanceKeyPath,
  158. KEY_READ,
  159. phkey);
  160. if (S_OK != hr)
  161. {
  162. hr = SPAPI_E_NO_SUCH_DEVINST;
  163. }
  164. }
  165. TraceHr (ttidError, FAL, hr,
  166. (SPAPI_E_NO_SUCH_DEVINST == hr),
  167. "HrOpenInstanceKey (%S)", pszPnpId);
  168. }
  169. return hr;
  170. }
  171. HRESULT
  172. HrOpenNetworkKey (
  173. IN REGSAM samDesired,
  174. OUT HKEY* phkey)
  175. {
  176. HRESULT hr;
  177. hr = HrRegOpenKeyEx (
  178. HKEY_LOCAL_MACHINE,
  179. L"System\\CurrentControlSet\\Control\\Network",
  180. samDesired,
  181. phkey);
  182. TraceHr (ttidError, FAL, hr, FALSE, "HrOpenNetworkKey");
  183. return hr;
  184. }
  185. HRESULT
  186. HrRegCreateKeyWithWorldAccess (
  187. HKEY hkey,
  188. PCWSTR pszSubkey,
  189. DWORD dwOptions,
  190. REGSAM samDesired,
  191. PHKEY phkey,
  192. LPDWORD pdwDisposition)
  193. {
  194. HRESULT hr;
  195. SECURITY_ATTRIBUTES sa = {0};
  196. PSECURITY_DESCRIPTOR pSd;
  197. // Create the correct descriptor. If this fails, we'll still
  198. // create the key, it's just that if a service running as
  199. // localsystem is creating this key, and a user process tries
  200. // to open it, it will fail.
  201. //
  202. hr = HrAllocateSecurityDescriptorAllowAccessToWorld (&pSd);
  203. if (S_OK == hr)
  204. {
  205. sa.nLength = sizeof(sa);
  206. sa.lpSecurityDescriptor = pSd;
  207. sa.bInheritHandle = FALSE;
  208. }
  209. else
  210. {
  211. Assert (!pSd);
  212. TraceHr (ttidError, FAL, hr, FALSE,
  213. "HrAllocateSecurityDescriptorAllowAccessToWorld "
  214. "failed in HrRegCreateKeyWithWorldAccess");
  215. }
  216. hr = HrRegCreateKeyEx (
  217. hkey,
  218. pszSubkey,
  219. dwOptions,
  220. samDesired,
  221. (pSd) ? &sa : NULL,
  222. phkey,
  223. pdwDisposition);
  224. MemFree (pSd);
  225. TraceHr (ttidError, FAL, hr, FALSE, "HrRegCreateKeyWithWorldAccess");
  226. return hr;
  227. }
  228. PWSTR
  229. GetNextStringToken (
  230. IN OUT PWSTR pszString,
  231. IN PCWSTR pszDelims,
  232. OUT PWSTR* ppszNextToken)
  233. {
  234. const WCHAR* pchDelim;
  235. PWSTR pszToken;
  236. Assert (pszDelims);
  237. Assert (ppszNextToken);
  238. // If pszString is NULL, continue with the previous string.
  239. //
  240. if (!pszString)
  241. {
  242. pszString = *ppszNextToken;
  243. Assert (pszString);
  244. }
  245. // Find the beginning of the token by skipping over the leading
  246. // delimiters. Note that there is no token if and only if this loop
  247. // sets pszString to point to the terminating NULL.
  248. //
  249. while (*pszString)
  250. {
  251. pchDelim = pszDelims;
  252. while (*pchDelim && (*pchDelim != *pszString))
  253. {
  254. pchDelim++;
  255. }
  256. if (!*pchDelim)
  257. {
  258. // Current string character is not a delimiter, so it must
  259. // be part of the token. Break the loop and go find the
  260. // whole token.
  261. //
  262. break;
  263. }
  264. pszString++;
  265. }
  266. pszToken = pszString;
  267. // Find the end of the token. If it is not the end of the string,
  268. // put a NULL there.
  269. //
  270. while (*pszString)
  271. {
  272. pchDelim = pszDelims;
  273. while (*pchDelim && (*pchDelim != *pszString))
  274. {
  275. pchDelim++;
  276. }
  277. if (*pchDelim)
  278. {
  279. // Found a delimiter so this ends the token. Advance
  280. // pszString so that we'll set *ppszNextToken for next time.
  281. //
  282. *pszString = 0;
  283. pszString++;
  284. break;
  285. }
  286. pszString++;
  287. }
  288. // Remember where we left off for the next token.
  289. //
  290. *ppszNextToken = pszString;
  291. // Return the token if we found it.
  292. //
  293. if (pszToken == pszString)
  294. {
  295. return NULL;
  296. }
  297. else
  298. {
  299. return pszToken;
  300. }
  301. }
  302. #define GetNextCommaSeparatedToken(pStart, pEnd, cch) \
  303. pStart = pEnd; \
  304. while (*pStart && (*pStart == L' ' || *pStart == L',')) \
  305. { \
  306. pStart++; \
  307. } \
  308. \
  309. pEnd = pStart; \
  310. while (*pEnd && *pEnd != L' ' && *pEnd != L',') \
  311. { \
  312. pEnd++; \
  313. } \
  314. \
  315. cch = pEnd - pStart;
  316. BOOL
  317. FSubstringMatch (
  318. PCTSTR pStr1,
  319. PCTSTR pStr2,
  320. const WCHAR** ppStart,
  321. ULONG* pcch)
  322. {
  323. const WCHAR* p1Start;
  324. const WCHAR* p1End;
  325. const WCHAR* p2Start;
  326. const WCHAR* p2End;
  327. ULONG cch1;
  328. ULONG cch2;
  329. if (ppStart)
  330. {
  331. *ppStart = NULL;
  332. }
  333. if (pcch)
  334. {
  335. *pcch = NULL;
  336. }
  337. p1End = pStr1;
  338. while (1)
  339. {
  340. GetNextCommaSeparatedToken(p1Start, p1End, cch1);
  341. if (!cch1)
  342. {
  343. break;
  344. }
  345. p2End = pStr2;
  346. while (1)
  347. {
  348. GetNextCommaSeparatedToken(p2Start, p2End, cch2);
  349. if (!cch2)
  350. {
  351. break;
  352. }
  353. if (cch1 == cch2)
  354. {
  355. if (0 == memcmp(p1Start, p2Start, cch1 * sizeof(WCHAR)))
  356. {
  357. if (ppStart)
  358. {
  359. *ppStart = p1Start;
  360. }
  361. if (pcch)
  362. {
  363. *pcch = cch1;
  364. }
  365. return TRUE;
  366. }
  367. }
  368. }
  369. }
  370. return FALSE;
  371. }
  372. VOID
  373. SignalNetworkProviderLoaded (
  374. VOID)
  375. {
  376. HANDLE Event;
  377. UNICODE_STRING EventName;
  378. OBJECT_ATTRIBUTES EventAttr;
  379. NTSTATUS Status;
  380. RtlInitUnicodeString (
  381. &EventName,
  382. L"\\Security\\NetworkProviderLoad");
  383. InitializeObjectAttributes (
  384. &EventAttr,
  385. &EventName,
  386. OBJ_CASE_INSENSITIVE,
  387. NULL, NULL);
  388. Status = NtOpenEvent (
  389. &Event,
  390. EVENT_QUERY_STATE | EVENT_MODIFY_STATE | SYNCHRONIZE,
  391. &EventAttr);
  392. if (NT_SUCCESS(Status))
  393. {
  394. SetEvent (Event);
  395. CloseHandle (Event);
  396. }
  397. else
  398. {
  399. ULONG Win32Error;
  400. Win32Error = RtlNtStatusToDosError(Status);
  401. SetLastError(Win32Error);
  402. TraceHr (ttidError, FAL, HrFromLastWin32Error(), FALSE,
  403. "SignalNetworkProviderLoaded");
  404. }
  405. }
  406. BOOL
  407. CDynamicBuffer::FGrowBuffer (
  408. ULONG cbGrow)
  409. {
  410. PBYTE pbNew;
  411. // If it hasn't been set, use a default of 4096.
  412. if (!m_cbGranularity)
  413. {
  414. m_cbGranularity = 4096;
  415. }
  416. if (cbGrow % m_cbGranularity)
  417. {
  418. cbGrow = (cbGrow + m_cbGranularity) - (cbGrow % m_cbGranularity);
  419. }
  420. pbNew = (PBYTE)MemAlloc (m_cbAllocated + cbGrow);
  421. if (pbNew)
  422. {
  423. #ifdef ENABLETRACE
  424. if (m_pbBuffer)
  425. {
  426. TraceTag (ttidDefault, "Dynamic buffer grown. New size = %d.",
  427. m_cbAllocated + cbGrow);
  428. }
  429. #endif
  430. CopyMemory (pbNew, m_pbBuffer, m_cbConsumed);
  431. MemFree (m_pbBuffer);
  432. m_pbBuffer = pbNew;
  433. m_cbAllocated += cbGrow;
  434. }
  435. return !!pbNew;
  436. }
  437. HRESULT
  438. CDynamicBuffer::HrReserveBytes (
  439. ULONG cbReserve)
  440. {
  441. if (cbReserve > m_cbAllocated)
  442. {
  443. return (FGrowBuffer(cbReserve)) ? S_OK : E_OUTOFMEMORY;
  444. }
  445. return S_OK;
  446. }
  447. HRESULT
  448. CDynamicBuffer::HrCopyBytes (
  449. const BYTE* pbSrc,
  450. ULONG cbSrc)
  451. {
  452. Assert (pbSrc);
  453. Assert (m_cbAllocated >= m_cbConsumed);
  454. if (cbSrc > m_cbAllocated - m_cbConsumed)
  455. {
  456. if (!FGrowBuffer (cbSrc))
  457. {
  458. return E_OUTOFMEMORY;
  459. }
  460. }
  461. CopyMemory (m_pbBuffer + m_cbConsumed, pbSrc, cbSrc);
  462. m_cbConsumed += cbSrc;
  463. return S_OK;
  464. }
  465. HRESULT
  466. CDynamicBuffer::HrCopyString (
  467. PCWSTR pszSrc)
  468. {
  469. ULONG cbSrc;
  470. cbSrc = CbOfSzAndTermSafe(pszSrc);
  471. return HrCopyBytes ((const BYTE*)pszSrc, cbSrc);
  472. }
  473. BOOL
  474. FIsFilterDevice (HDEVINFO hdi, PSP_DEVINFO_DATA pdeid)
  475. {
  476. WCHAR szFilterInfId[_MAX_PATH];
  477. BOOL fIsFilterDevice = FALSE;
  478. HKEY hkeyInstance;
  479. HRESULT hr;
  480. // Open the device's driver key.
  481. //
  482. hr = HrSetupDiOpenDevRegKey (
  483. hdi, pdeid,
  484. DICS_FLAG_GLOBAL, 0, DIREG_DRV,
  485. KEY_READ, &hkeyInstance);
  486. if (S_OK == hr)
  487. {
  488. // Get the filterinfid value. If present, then
  489. // this device is a filter device.
  490. //
  491. DWORD cbFilterInfId = sizeof(szFilterInfId);
  492. hr = HrRegQuerySzBuffer (
  493. hkeyInstance,
  494. L"FilterInfId",
  495. szFilterInfId,
  496. &cbFilterInfId);
  497. if (S_OK == hr)
  498. {
  499. fIsFilterDevice = TRUE;
  500. }
  501. RegCloseKey (hkeyInstance);
  502. }
  503. return fIsFilterDevice;
  504. }
  505. VOID
  506. AddOrRemoveDontExposeLowerCharacteristicIfNeeded (
  507. IN OUT CComponent* pComponent)
  508. {
  509. ASSERT (pComponent);
  510. // Special case: NCF_DONTEXPOSELOWER
  511. // SPX has erroneously set this characteristic. It's not really
  512. // needed as nothing binds with SPX. Having it set means that
  513. // two components above IPX have this characteristic set. (NWNB
  514. // is the other. The code to generate bindpaths by recursing
  515. // the stack table is only setup to handle at most one component
  516. // with this characteristic per pass. Turning it off for SPX
  517. // solves this in the simplest way.
  518. //
  519. // Furthermore, enforce that only IPX and NWNB have this
  520. // characteristic set..
  521. //
  522. //
  523. if ((0 == wcscmp(L"ms_nwnb", pComponent->m_pszInfId)) ||
  524. (0 == wcscmp(L"ms_nwipx", pComponent->m_pszInfId)))
  525. {
  526. pComponent->m_dwCharacter |= NCF_DONTEXPOSELOWER;
  527. }
  528. else
  529. {
  530. pComponent->m_dwCharacter &= ~NCF_DONTEXPOSELOWER;
  531. }
  532. // End Special case
  533. }