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.

2228 lines
53 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. routing\netsh\shell\reghlp.c
  5. Abstract:
  6. To get information about helper DLLs from registry.
  7. Revision History:
  8. Anand Mahalingam 7/06/98 Created
  9. Dave Thaler 11/13/98 Revised
  10. --*/
  11. #include "precomp.h"
  12. #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
  13. #define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
  14. #define DLL_INIT_FN "InitHelperDll"
  15. #define DLL_INIT_FN_NAME L"InitHelperDll"
  16. #define REG_KEY_NETSH_HELPER L"SOFTWARE\\Microsoft\\NetSh"
  17. PNS_HELPER_TABLE_ENTRY g_CurrentHelper = NULL;
  18. PCNS_CONTEXT_ATTRIBUTES g_CurrentContext = NULL;
  19. /* fa85c48a-68d7-4a8c-891c-2360edc4d78 */
  20. #define NETSH_NULL_GUID \
  21. { 0xfa85c48a, 0x68d7, 0x4a8c, {0x89, 0x1c, 0x23, 0x60, 0xed, 0xc4, 0xd7, 0x8} };
  22. static const GUID g_NetshGuid = NETSH_ROOT_GUID;
  23. static const GUID g_NullGuid = NETSH_NULL_GUID;
  24. //
  25. // Initialize helper Table
  26. //
  27. PNS_HELPER_TABLE_ENTRY g_HelperTable;
  28. DWORD g_dwNumHelpers = 0;
  29. PNS_DLL_TABLE_ENTRY g_DllTable;
  30. DWORD g_dwNumDlls = 0;
  31. // This variable maintains the index of the Dll currently being called out to.
  32. DWORD g_dwDllIndex;
  33. DWORD WINAPI
  34. RegisterContext(
  35. IN CONST NS_CONTEXT_ATTRIBUTES *pChildContext
  36. );
  37. DWORD
  38. FindHelper(
  39. IN CONST GUID *pguidHelper,
  40. OUT PDWORD pdwIndex
  41. );
  42. DWORD
  43. GenericDeleteContext(
  44. IN PNS_HELPER_TABLE_ENTRY pParentHelper,
  45. IN DWORD dwContextIdx
  46. );
  47. DWORD
  48. CommitSubContexts(
  49. IN PNS_HELPER_TABLE_ENTRY pHelper,
  50. IN DWORD dwAction
  51. );
  52. DWORD
  53. WINAPI
  54. InitHelperDll(
  55. IN DWORD dwNetshVersion,
  56. OUT PVOID pReserved
  57. );
  58. DWORD
  59. UninstallDll(
  60. IN LPCWSTR pwszConfigDll,
  61. IN BOOL fDeleteFromRegistry
  62. );
  63. //
  64. // Local copy of the commit state.
  65. //
  66. BOOL g_bCommit = TRUE;
  67. int __cdecl
  68. ContextCmp(
  69. const void *a,
  70. const void *b
  71. )
  72. {
  73. PCNS_CONTEXT_ATTRIBUTES pCA = (PCNS_CONTEXT_ATTRIBUTES)a;
  74. PCNS_CONTEXT_ATTRIBUTES pCB = (PCNS_CONTEXT_ATTRIBUTES)b;
  75. ULONG ulPriA = (pCA->dwFlags & CMD_FLAG_PRIORITY)? pCA->ulPriority : DEFAULT_CONTEXT_PRIORITY;
  76. ULONG ulPriB = (pCB->dwFlags & CMD_FLAG_PRIORITY)? pCB->ulPriority : DEFAULT_CONTEXT_PRIORITY;
  77. return ulPriA - ulPriB;
  78. }
  79. DWORD
  80. DumpContext(
  81. IN PCNS_CONTEXT_ATTRIBUTES pContext,
  82. IN LPWSTR *ppwcArguments,
  83. IN DWORD dwArgCount,
  84. IN LPCVOID pvData
  85. )
  86. {
  87. DWORD dwErr = NO_ERROR;
  88. PNS_HELPER_TABLE_ENTRY pChildHelper;
  89. do {
  90. if (pContext->pfnDumpFn)
  91. {
  92. dwErr = pContext->pfnDumpFn( g_pwszRouterName,
  93. ppwcArguments,
  94. dwArgCount,
  95. pvData );
  96. if (dwErr)
  97. {
  98. break;
  99. }
  100. }
  101. // Dump child contexts (even if parent didn't have a dump function)
  102. dwErr = GetHelperEntry(&pContext->guidHelper, &pChildHelper);
  103. if (dwErr)
  104. {
  105. break;
  106. }
  107. dwErr = DumpSubContexts(pChildHelper,
  108. ppwcArguments, dwArgCount, pvData);
  109. if (dwErr)
  110. {
  111. break;
  112. }
  113. } while (FALSE);
  114. return NO_ERROR;
  115. }
  116. DWORD
  117. DumpSubContexts(
  118. IN PNS_HELPER_TABLE_ENTRY pHelper,
  119. IN LPWSTR *ppwcArguments,
  120. IN DWORD dwArgCount,
  121. IN LPCVOID pvData
  122. )
  123. {
  124. DWORD i, dwSize,
  125. dwErr = NO_ERROR;
  126. PCNS_CONTEXT_ATTRIBUTES pSubContext;
  127. PBYTE pSubContextTable;
  128. // Copy contexts for sorting
  129. dwSize =pHelper->ulNumSubContexts * pHelper->ulSubContextSize;
  130. pSubContextTable = MALLOC( dwSize );
  131. if (!pSubContextTable)
  132. {
  133. return ERROR_NOT_ENOUGH_MEMORY;
  134. }
  135. memcpy(pSubContextTable, pHelper->pSubContextTable, dwSize );
  136. // Sort copy of contexts by priority
  137. qsort(pSubContextTable,
  138. pHelper->ulNumSubContexts,
  139. pHelper->ulSubContextSize,
  140. ContextCmp);
  141. for (i = 0; i < pHelper->ulNumSubContexts; i++)
  142. {
  143. pSubContext = (PCNS_CONTEXT_ATTRIBUTES)
  144. (pSubContextTable + i*pHelper->ulSubContextSize);
  145. dwErr = DumpContext( pSubContext,
  146. ppwcArguments, dwArgCount, pvData );
  147. if (dwErr)
  148. {
  149. break;
  150. }
  151. }
  152. // Free contexts for sorting
  153. FREE(pSubContextTable);
  154. return dwErr;
  155. }
  156. DWORD
  157. CommitContext(
  158. IN PCNS_CONTEXT_ATTRIBUTES pContext,
  159. IN DWORD dwAction
  160. )
  161. {
  162. DWORD dwErr = NO_ERROR;
  163. PNS_HELPER_TABLE_ENTRY pChildHelper;
  164. do {
  165. if (pContext->pfnCommitFn)
  166. {
  167. // No need to call connect since you cannot change machines in
  168. // offline mode
  169. dwErr = pContext->pfnCommitFn(dwAction);
  170. if (dwErr)
  171. {
  172. break;
  173. }
  174. }
  175. // Commit child contexts (even if parent didn't have a commit function)
  176. dwErr = GetHelperEntry(&pContext->guidHelper, &pChildHelper);
  177. if (dwErr)
  178. {
  179. break;
  180. }
  181. dwErr = CommitSubContexts(pChildHelper, dwAction);
  182. if (dwErr)
  183. {
  184. break;
  185. }
  186. } while (FALSE);
  187. return NO_ERROR;
  188. }
  189. DWORD
  190. CommitSubContexts(
  191. IN PNS_HELPER_TABLE_ENTRY pHelper,
  192. IN DWORD dwAction
  193. )
  194. {
  195. DWORD i, dwSize,
  196. dwErr = NO_ERROR;
  197. PCNS_CONTEXT_ATTRIBUTES pSubContext;
  198. PBYTE pSubContextTable;
  199. // Copy contexts for sorting
  200. dwSize =pHelper->ulNumSubContexts * pHelper->ulSubContextSize;
  201. pSubContextTable = MALLOC( dwSize );
  202. if (!pSubContextTable)
  203. {
  204. return ERROR_NOT_ENOUGH_MEMORY;
  205. }
  206. memcpy(pSubContextTable, pHelper->pSubContextTable, dwSize );
  207. // Sort copy of contexts by priority
  208. qsort(pSubContextTable,
  209. pHelper->ulNumSubContexts,
  210. pHelper->ulSubContextSize,
  211. ContextCmp);
  212. for (i = 0; i < pHelper->ulNumSubContexts; i++)
  213. {
  214. pSubContext = (PCNS_CONTEXT_ATTRIBUTES)
  215. (pSubContextTable + i*pHelper->ulSubContextSize);
  216. dwErr = CommitContext(pSubContext, dwAction);
  217. if (dwErr)
  218. {
  219. break;
  220. }
  221. }
  222. // Free contexts for sorting
  223. FREE(pSubContextTable);
  224. return dwErr;
  225. }
  226. DWORD
  227. CallCommit(
  228. IN DWORD dwAction,
  229. OUT BOOL *pbCommit
  230. )
  231. /*++
  232. Routine Description:
  233. Calls commit for all the transports.
  234. Arguments:
  235. dwAction - What to do. Could be one of COMMIT, UNCOMMIT, FLUSH,
  236. COMMIT_STATE
  237. pbCommit - The current commit state.
  238. Return Value:
  239. NO_ERROR
  240. --*/
  241. {
  242. DWORD i, dwErr;
  243. PHELPER_ENTRY_FN pfnEntry;
  244. PCNS_CONTEXT_ATTRIBUTES pContext, pSubContext;
  245. PNS_HELPER_TABLE_ENTRY pHelper;
  246. switch (dwAction)
  247. {
  248. case NETSH_COMMIT_STATE :
  249. *pbCommit = g_bCommit;
  250. return NO_ERROR;
  251. case NETSH_COMMIT :
  252. g_bCommit = TRUE;
  253. break;
  254. case NETSH_UNCOMMIT :
  255. g_bCommit = FALSE;
  256. default :
  257. break;
  258. }
  259. //
  260. // Call commit for each sub context
  261. //
  262. dwErr = GetRootContext( &pContext, &pHelper );
  263. if (dwErr)
  264. {
  265. return dwErr;
  266. }
  267. dwErr = CommitContext( pContext, dwAction );
  268. if (dwErr isnot NO_ERROR)
  269. {
  270. PrintMessageFromModule(g_hModule, MSG_COMMIT_ERROR,
  271. pContext->pwszContext);
  272. dwErr = ERROR_SUPPRESS_OUTPUT;
  273. }
  274. return dwErr;
  275. }
  276. DWORD
  277. FindHelper(
  278. IN CONST GUID *pguidHelper,
  279. OUT PDWORD pdwIndex
  280. )
  281. {
  282. DWORD i;
  283. for (i=0; i<g_dwNumHelpers; i++)
  284. {
  285. if (!memcmp(pguidHelper, &g_HelperTable[i].nha.guidHelper, sizeof(GUID)))
  286. {
  287. *pdwIndex = i;
  288. return NO_ERROR;
  289. }
  290. }
  291. return ERROR_NOT_FOUND;
  292. }
  293. DWORD
  294. AddHelper(
  295. IN CONST GUID *pguidParent,
  296. IN CONST NS_HELPER_ATTRIBUTES *pAttributes
  297. )
  298. {
  299. PNS_HELPER_TABLE_ENTRY phtTmp;
  300. //
  301. // Need to add entries in the helper table
  302. //
  303. phtTmp = MALLOC((g_dwNumHelpers + 1) * sizeof(NS_HELPER_TABLE_ENTRY));
  304. if (phtTmp is NULL)
  305. {
  306. return ERROR_NOT_ENOUGH_MEMORY;
  307. }
  308. CopyMemory(phtTmp, g_HelperTable,
  309. g_dwNumHelpers * sizeof(NS_HELPER_TABLE_ENTRY));
  310. CopyMemory(&phtTmp[g_dwNumHelpers],
  311. pAttributes,
  312. sizeof(NS_HELPER_ATTRIBUTES));
  313. CopyMemory(&phtTmp[g_dwNumHelpers].guidParent, pguidParent, sizeof(GUID));
  314. phtTmp[g_dwNumHelpers].dwDllIndex = g_dwDllIndex;
  315. phtTmp[g_dwNumHelpers].bStarted = FALSE;
  316. phtTmp[g_dwNumHelpers].ulSubContextSize = sizeof(NS_CONTEXT_ATTRIBUTES);
  317. phtTmp[g_dwNumHelpers].ulNumSubContexts = 0;
  318. phtTmp[g_dwNumHelpers].pSubContextTable = (UINT_PTR)NULL;
  319. g_dwNumHelpers ++;
  320. FREE(g_HelperTable);
  321. g_HelperTable = phtTmp;
  322. return ERROR_SUCCESS;
  323. }
  324. DWORD
  325. WINAPI
  326. GenericDeregisterAllContexts(
  327. IN CONST GUID *pguidChild
  328. )
  329. /*++
  330. Description:
  331. Remove all contexts registered by a given helper
  332. --*/
  333. {
  334. DWORD j, dwErr;
  335. PNS_HELPER_TABLE_ENTRY pChildHelper, pParentHelper;
  336. PCNS_CONTEXT_ATTRIBUTES pSubContext;
  337. dwErr = GetHelperEntry(pguidChild, &pChildHelper);
  338. if (dwErr)
  339. {
  340. return dwErr;
  341. }
  342. dwErr = GetHelperEntry(&pChildHelper->guidParent, &pParentHelper);
  343. if (dwErr)
  344. {
  345. return dwErr;
  346. }
  347. for (j=0; j<pParentHelper->ulNumSubContexts; j++)
  348. {
  349. pSubContext = (PCNS_CONTEXT_ATTRIBUTES)
  350. (pParentHelper->pSubContextTable + j*pParentHelper->ulSubContextSize);
  351. if (!memcmp( &pSubContext->guidHelper, pguidChild, sizeof(GUID) ))
  352. {
  353. GenericDeleteContext(pParentHelper, j);
  354. j--;
  355. }
  356. }
  357. return dwErr;
  358. }
  359. DWORD
  360. DeleteHelper(
  361. IN DWORD dwHelperIdx
  362. )
  363. {
  364. DWORD j, dwErr, dwParentIndex;
  365. PNS_HELPER_TABLE_ENTRY phtTmp = NULL;
  366. // Tell parent helper to
  367. // uninstall all contexts for this helper
  368. dwErr = FindHelper(&g_HelperTable[dwHelperIdx].guidParent, &dwParentIndex);
  369. if (dwErr is NO_ERROR)
  370. {
  371. GenericDeregisterAllContexts(&g_HelperTable[dwHelperIdx].nha.guidHelper);
  372. }
  373. phtTmp = MALLOC((g_dwNumHelpers - 1) * sizeof(NS_HELPER_TABLE_ENTRY));
  374. if (phtTmp is NULL)
  375. {
  376. return ERROR_NOT_ENOUGH_MEMORY;
  377. }
  378. CopyMemory(phtTmp,
  379. g_HelperTable,
  380. dwHelperIdx * sizeof(NS_HELPER_TABLE_ENTRY));
  381. CopyMemory(phtTmp + dwHelperIdx,
  382. g_HelperTable + dwHelperIdx + 1,
  383. (g_dwNumHelpers - 1 - dwHelperIdx)
  384. * sizeof(NS_HELPER_TABLE_ENTRY));
  385. g_dwNumHelpers --;
  386. FREE(g_HelperTable);
  387. g_HelperTable = phtTmp;
  388. return ERROR_SUCCESS;
  389. }
  390. DWORD
  391. GetHelperEntry(
  392. IN CONST GUID *pGuid,
  393. OUT PNS_HELPER_TABLE_ENTRY *ppHelper
  394. )
  395. {
  396. DWORD i, dwErr;
  397. dwErr = FindHelper(pGuid, &i);
  398. if (dwErr is NO_ERROR)
  399. {
  400. *ppHelper = &g_HelperTable[i];
  401. }
  402. return dwErr;
  403. }
  404. DWORD
  405. GetDllEntry(
  406. IN DWORD dwDllIndex,
  407. OUT PNS_DLL_TABLE_ENTRY *ppDll
  408. )
  409. {
  410. *ppDll = &g_DllTable[ dwDllIndex ];
  411. return NO_ERROR;
  412. }
  413. DWORD
  414. RegisterHelper(
  415. IN CONST GUID *pguidParent,
  416. IN CONST NS_HELPER_ATTRIBUTES *pAttributes
  417. )
  418. {
  419. DWORD i, dwErr;
  420. dwErr = FindHelper(&pAttributes->guidHelper, &i);
  421. if (dwErr is NO_ERROR)
  422. {
  423. return ERROR_HELPER_ALREADY_REGISTERED;
  424. }
  425. //if pguidParent is NULL, the caller means the parent is netsh (g_NetshGuid)
  426. if (!pguidParent)
  427. {
  428. pguidParent = &g_NetshGuid;
  429. }
  430. // Make sure we don't cause a recursive registration.
  431. if (IsEqualGUID(&pAttributes->guidHelper, pguidParent))
  432. {
  433. if (! (IsEqualGUID(&pAttributes->guidHelper, &g_NullGuid) &&
  434. IsEqualGUID(pguidParent, &g_NullGuid) ) )
  435. {
  436. ASSERT(FALSE);
  437. return ERROR_INVALID_PARAMETER;
  438. }
  439. }
  440. return AddHelper(pguidParent, pAttributes);
  441. }
  442. VOID
  443. ConvertGuidToString(
  444. IN CONST GUID *pGuid,
  445. OUT LPWSTR pwszBuffer
  446. )
  447. {
  448. wsprintf(pwszBuffer, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
  449. pGuid->Data1, pGuid->Data2, pGuid->Data3,
  450. pGuid->Data4[0], pGuid->Data4[1],
  451. pGuid->Data4[2], pGuid->Data4[3],
  452. pGuid->Data4[4], pGuid->Data4[5],
  453. pGuid->Data4[6], pGuid->Data4[7]);
  454. }
  455. DWORD
  456. ConvertStringToGuid(
  457. IN LPCWSTR pwszGuid,
  458. IN USHORT usStringLen,
  459. OUT GUID *pGuid
  460. )
  461. {
  462. UNICODE_STRING Temp;
  463. Temp.Length = Temp.MaximumLength = usStringLen;
  464. Temp.Buffer = (LPWSTR)pwszGuid;
  465. if(RtlGUIDFromString(&Temp, pGuid) isnot STATUS_SUCCESS)
  466. {
  467. return ERROR_INVALID_PARAMETER;
  468. }
  469. return NO_ERROR;
  470. }
  471. DWORD
  472. LoadDll(
  473. DWORD dwIdx
  474. )
  475. {
  476. HANDLE hDll;
  477. DWORD dwErr;
  478. PNS_DLL_INIT_FN pfnLoadFn;
  479. NS_DLL_ATTRIBUTES DllTable;
  480. g_dwDllIndex = dwIdx;
  481. //
  482. // Try to load DLL into memory.
  483. //
  484. if (dwIdx is 0)
  485. {
  486. // Netsh internal helper
  487. hDll = g_hModule;
  488. pfnLoadFn = InitHelperDll;
  489. }
  490. else
  491. {
  492. hDll = LoadLibraryW(g_DllTable[dwIdx].pwszDLLName);
  493. if (hDll is NULL)
  494. {
  495. PrintMessageFromModule( g_hModule,
  496. MSG_DLL_LOAD_FAILED,
  497. g_DllTable[dwIdx].pwszDLLName );
  498. return ERROR_SUPPRESS_OUTPUT;
  499. }
  500. pfnLoadFn = (PNS_DLL_INIT_FN) GetProcAddress(hDll, DLL_INIT_FN);
  501. }
  502. if (!pfnLoadFn)
  503. {
  504. PrintMessageFromModule( g_hModule,
  505. EMSG_DLL_FN_NOT_FOUND,
  506. DLL_INIT_FN_NAME,
  507. g_DllTable[dwIdx].pwszDLLName );
  508. FreeLibrary(hDll);
  509. g_DllTable[dwIdx].hDll = NULL;
  510. return ERROR_SUPPRESS_OUTPUT;
  511. }
  512. g_DllTable[dwIdx].hDll = hDll;
  513. memset(&DllTable, 0, sizeof(DllTable));
  514. dwErr = (pfnLoadFn)( NETSH_VERSION_50, &DllTable );
  515. if (dwErr == NO_ERROR)
  516. {
  517. g_DllTable[dwIdx].bLoaded = TRUE;
  518. g_DllTable[dwIdx].pfnStopFn = DllTable.pfnStopFn;
  519. }
  520. else
  521. {
  522. PrintMessageFromModule( g_hModule,
  523. MSG_DLL_START_FAILED,
  524. DLL_INIT_FN_NAME,
  525. g_DllTable[dwIdx].pwszDLLName,
  526. dwErr );
  527. UninstallDll(g_DllTable[dwIdx].pwszDLLName, FALSE);
  528. }
  529. return NO_ERROR;
  530. }
  531. VOID
  532. StartNewHelpers()
  533. /*++
  534. Description:
  535. Recursively start all unstarted helpers whose parent (if any)
  536. is started.
  537. --*/
  538. {
  539. BOOL bFound = FALSE;
  540. DWORD i, dwParentIndex, dwErr, dwVersion;
  541. // Mark root as started
  542. g_HelperTable[0].bStarted = TRUE;
  543. // Repeat until we couldn't find any helper to start
  544. do {
  545. bFound = FALSE;
  546. // Look for a startable helper
  547. for (i=0; i<g_dwNumHelpers; i++)
  548. {
  549. if (g_HelperTable[i].bStarted)
  550. continue;
  551. dwErr = FindHelper(&g_HelperTable[i].guidParent, &dwParentIndex);
  552. if (dwErr isnot NO_ERROR)
  553. {
  554. continue;
  555. }
  556. if (!g_HelperTable[dwParentIndex].bStarted)
  557. {
  558. continue;
  559. }
  560. dwVersion = NETSH_VERSION_50;
  561. bFound = TRUE;
  562. break;
  563. }
  564. if (bFound)
  565. {
  566. g_HelperTable[i].bStarted = TRUE;
  567. if (g_HelperTable[i].nha.pfnStart)
  568. {
  569. g_HelperTable[i].nha.pfnStart( &g_HelperTable[i].guidParent,
  570. dwVersion );
  571. }
  572. }
  573. } while (bFound);
  574. }
  575. DWORD
  576. AddDllEntry(
  577. LPCWSTR pwszValueName,
  578. LPCWSTR pwszConfigDll
  579. )
  580. {
  581. PNS_DLL_TABLE_ENTRY phtTmp = NULL;
  582. //
  583. // Need to add entry in the dll table
  584. //
  585. phtTmp = MALLOC((g_dwNumDlls + 1) * sizeof(NS_DLL_TABLE_ENTRY));
  586. if (phtTmp is NULL)
  587. {
  588. return ERROR_NOT_ENOUGH_MEMORY;
  589. }
  590. CopyMemory(phtTmp, g_DllTable,
  591. g_dwNumDlls * sizeof(NS_DLL_TABLE_ENTRY));
  592. ZeroMemory(&phtTmp[g_dwNumDlls], sizeof(NS_DLL_TABLE_ENTRY));
  593. phtTmp[g_dwNumDlls].pwszValueName = MALLOC( (wcslen(pwszValueName) + 1)
  594. * sizeof(WCHAR));
  595. if (!phtTmp[g_dwNumDlls].pwszValueName)
  596. {
  597. return ERROR_NOT_ENOUGH_MEMORY;
  598. }
  599. wcscpy(phtTmp[g_dwNumDlls].pwszValueName, pwszValueName);
  600. phtTmp[g_dwNumDlls].pwszDLLName = MALLOC( (wcslen(pwszConfigDll) + 1)
  601. * sizeof(WCHAR));
  602. if (!phtTmp[g_dwNumDlls].pwszDLLName)
  603. {
  604. return ERROR_NOT_ENOUGH_MEMORY;
  605. }
  606. wcscpy(phtTmp[g_dwNumDlls].pwszDLLName, pwszConfigDll);
  607. _wcsupr(phtTmp[g_dwNumDlls].pwszDLLName);
  608. g_dwNumDlls ++;
  609. FREE(g_DllTable);
  610. g_DllTable = phtTmp;
  611. return LoadDll(g_dwNumDlls - 1);
  612. }
  613. DWORD
  614. InstallDll(
  615. IN LPCWSTR pwszConfigDll
  616. )
  617. /*++
  618. Called by: HandleAddHelper()
  619. --*/
  620. {
  621. DWORD i, dwErr;
  622. HKEY hBaseKey;
  623. DWORD dwResult = ERROR_SUCCESS;
  624. BOOL bFound = FALSE;
  625. WCHAR wcszKeyName[80];
  626. LPWSTR p, q;
  627. LPWSTR pwszConfigDllCopy;
  628. //
  629. // Check to see if the DLL is already present.
  630. //
  631. for (i = 0; i < g_dwNumDlls; i++)
  632. {
  633. if (_wcsicmp(g_DllTable[i].pwszDLLName, pwszConfigDll) == 0)
  634. {
  635. bFound = TRUE;
  636. break;
  637. }
  638. }
  639. do
  640. {
  641. if (bFound)
  642. break;
  643. //
  644. // Add the key to the registry
  645. //
  646. //
  647. // Create Base Key. If it already exists, fine.
  648. //
  649. dwResult = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
  650. REG_KEY_NETSH_HELPER,
  651. 0,
  652. L"STRING",
  653. REG_OPTION_NON_VOLATILE,
  654. KEY_ALL_ACCESS,
  655. NULL,
  656. &hBaseKey,
  657. NULL);
  658. if(dwResult != ERROR_SUCCESS)
  659. {
  660. break;
  661. }
  662. //
  663. // Add key for the Dll
  664. //
  665. pwszConfigDllCopy = _wcsdup(pwszConfigDll);
  666. if (!pwszConfigDllCopy)
  667. {
  668. return ERROR_NOT_ENOUGH_MEMORY;
  669. }
  670. p = pwszConfigDllCopy;
  671. if ((q = wcsrchr(pwszConfigDllCopy, L'/')) isnot NULL)
  672. {
  673. p = q+1;
  674. }
  675. else if ((q = wcsrchr(pwszConfigDllCopy, L'\\')) isnot NULL)
  676. {
  677. p = q+1;
  678. }
  679. wcscpy(wcszKeyName, p);
  680. if ((p = wcsrchr(wcszKeyName, L'.')) isnot NULL)
  681. {
  682. *p = L'\0';
  683. }
  684. dwResult = RegSetValueExW(hBaseKey,
  685. wcszKeyName,
  686. 0,
  687. REG_SZ,
  688. (PBYTE) pwszConfigDllCopy,
  689. (wcslen(pwszConfigDllCopy) + 1) * sizeof(WCHAR));
  690. RegCloseKey(hBaseKey);
  691. free(pwszConfigDllCopy);
  692. } while (FALSE);
  693. if (dwResult != ERROR_SUCCESS)
  694. {
  695. //
  696. // Could not install key successfully
  697. //
  698. PrintMessageFromModule(g_hModule, EMSG_INSTALL_KEY_FAILED, pwszConfigDll);
  699. return dwResult;
  700. }
  701. dwErr = AddDllEntry(wcszKeyName, pwszConfigDll);
  702. StartNewHelpers();
  703. return dwErr;
  704. }
  705. DWORD
  706. UninstallDll(
  707. IN LPCWSTR pwszConfigDll,
  708. IN BOOL fDeleteFromRegistry
  709. )
  710. {
  711. DWORD i, j;
  712. HKEY hBaseKey;
  713. DWORD dwResult = ERROR_SUCCESS;
  714. BOOL bFound = FALSE;
  715. PNS_DLL_TABLE_ENTRY phtTmp = NULL;
  716. //
  717. // Check to see if the DLL is present.
  718. //
  719. for (i = 0; i < g_dwNumDlls; i++)
  720. {
  721. if (_wcsicmp(g_DllTable[i].pwszDLLName, pwszConfigDll) == 0)
  722. {
  723. bFound = TRUE;
  724. break;
  725. }
  726. }
  727. if (!bFound)
  728. {
  729. //
  730. // DLL to be uninstalled not found.
  731. //
  732. return ERROR_NOT_FOUND;
  733. }
  734. // Uninstall all helpers for this DLL
  735. for (j=0; j<g_dwNumHelpers; j++)
  736. {
  737. if (g_HelperTable[j].dwDllIndex is i)
  738. {
  739. DeleteHelper(j);
  740. j--;
  741. }
  742. }
  743. do
  744. {
  745. if (fDeleteFromRegistry)
  746. {
  747. //
  748. // Delete the key from registry
  749. //
  750. //
  751. // Open Base Key.
  752. //
  753. dwResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  754. REG_KEY_NETSH_HELPER,
  755. 0,
  756. KEY_ALL_ACCESS,
  757. &hBaseKey);
  758. if(dwResult != ERROR_SUCCESS)
  759. {
  760. break;
  761. }
  762. //
  763. // Delete key for the Dll
  764. //
  765. dwResult = RegDeleteValueW(hBaseKey,
  766. g_DllTable[i].pwszValueName);
  767. RegCloseKey(hBaseKey);
  768. }
  769. } while (FALSE);
  770. if (dwResult != ERROR_SUCCESS)
  771. {
  772. //
  773. // Could not uninstall key successfully
  774. //
  775. PrintMessageFromModule(g_hModule,
  776. EMSG_UNINSTALL_KEY_FAILED,
  777. pwszConfigDll);
  778. return dwResult;
  779. }
  780. //
  781. // Key succesfully deleted from registry. If a DLL table is currently
  782. // available, then reflect changes in it too.
  783. //
  784. FREE( g_DllTable[i].pwszDLLName );
  785. g_DllTable[i].pwszDLLName = NULL;
  786. FREE( g_DllTable[i].pwszValueName );
  787. g_DllTable[i].pwszValueName = NULL;
  788. phtTmp = MALLOC((g_dwNumDlls - 1) * sizeof(NS_DLL_TABLE_ENTRY));
  789. if (phtTmp is NULL)
  790. {
  791. return ERROR_NOT_ENOUGH_MEMORY;
  792. }
  793. CopyMemory(phtTmp,
  794. g_DllTable,
  795. i * sizeof(NS_DLL_TABLE_ENTRY));
  796. CopyMemory(phtTmp + i,
  797. g_DllTable + i + 1,
  798. (g_dwNumDlls - 1 - i) * sizeof(NS_DLL_TABLE_ENTRY));
  799. g_dwNumDlls --;
  800. // Update the DLL index in all helpers
  801. for (j=0; j<g_dwNumHelpers; j++)
  802. {
  803. if (g_HelperTable[j].dwDllIndex > i)
  804. {
  805. g_HelperTable[j].dwDllIndex--;
  806. }
  807. }
  808. //
  809. // Unload the dll if it was loaded
  810. //
  811. if (g_DllTable[i].bLoaded)
  812. {
  813. #if 0
  814. if (pHelperTable[i].pfnUnInitFn)
  815. (pHelperTable[i].pfnUnInitFn)(0);
  816. #endif
  817. FreeLibrary(g_DllTable[i].hDll);
  818. }
  819. FREE(g_DllTable);
  820. g_DllTable = phtTmp;
  821. return ERROR_SUCCESS;
  822. }
  823. VOID
  824. LoadDllInfoFromRegistry(
  825. VOID
  826. )
  827. /*++
  828. Routine Description:
  829. Loads information about the helper DLLs from the registry.
  830. Arguments:
  831. Return Value:
  832. --*/
  833. {
  834. DWORD dwResult, i, dwMaxValueLen, dwValueLen;
  835. DWORD dwMaxValueNameLen, dwValueNameLen;
  836. DWORD dwSize,dwType,dwNumDlls;
  837. FILETIME ftLastTime;
  838. HKEY hkeyDlls = NULL;
  839. LPWSTR pwValue = NULL;
  840. LPWSTR pwValueName = NULL;
  841. do {
  842. //
  843. // Open Base Key
  844. //
  845. dwResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  846. REG_KEY_NETSH_HELPER,
  847. 0,
  848. KEY_READ,
  849. &hkeyDlls);
  850. if(dwResult != NO_ERROR)
  851. {
  852. break;
  853. }
  854. //
  855. // Get Number of DLLs
  856. //
  857. dwResult = RegQueryInfoKey(hkeyDlls,
  858. NULL,
  859. NULL,
  860. NULL,
  861. NULL,
  862. NULL,
  863. NULL,
  864. &dwNumDlls,
  865. &dwMaxValueNameLen,
  866. &dwMaxValueLen,
  867. NULL,
  868. NULL);
  869. if(dwResult != NO_ERROR)
  870. {
  871. break;
  872. }
  873. if(dwNumDlls == 0)
  874. {
  875. //
  876. // Nothing registered
  877. //
  878. break;
  879. }
  880. //
  881. // Key len is in WCHARS
  882. //
  883. dwSize = dwMaxValueNameLen + 1;
  884. pwValueName = HeapAlloc(GetProcessHeap(),
  885. HEAP_ZERO_MEMORY,
  886. dwSize * sizeof(WCHAR));
  887. if(pwValueName is NULL)
  888. {
  889. PrintMessageFromModule(g_hModule, MSG_NOT_ENOUGH_MEMORY);
  890. break;
  891. }
  892. dwSize = dwMaxValueLen + 1;
  893. pwValue = HeapAlloc(GetProcessHeap(),
  894. HEAP_ZERO_MEMORY,
  895. dwSize);
  896. if(pwValue is NULL)
  897. {
  898. FREE(pwValueName);
  899. PrintMessageFromModule(g_hModule, MSG_NOT_ENOUGH_MEMORY);
  900. break;
  901. }
  902. for(i = 0; i < dwNumDlls; i++)
  903. {
  904. dwValueLen = dwMaxValueLen + 1;
  905. dwValueNameLen = dwMaxValueNameLen + 1;
  906. dwResult = RegEnumValueW(hkeyDlls,
  907. i,
  908. pwValueName,
  909. &dwValueNameLen,
  910. NULL,
  911. NULL,
  912. (PBYTE)pwValue,
  913. &dwValueLen);
  914. if(dwResult isnot NO_ERROR)
  915. {
  916. if(dwResult is ERROR_NO_MORE_ITEMS)
  917. {
  918. //
  919. // Done
  920. //
  921. break;
  922. }
  923. continue;
  924. }
  925. dwResult = AddDllEntry(pwValueName, pwValue);
  926. }
  927. } while (FALSE);
  928. if (hkeyDlls)
  929. {
  930. RegCloseKey(hkeyDlls);
  931. }
  932. if (pwValueName)
  933. {
  934. FREE(pwValueName);
  935. }
  936. if (pwValue)
  937. {
  938. FREE(pwValue);
  939. }
  940. StartNewHelpers();
  941. return;
  942. }
  943. DWORD
  944. GetContextEntry(
  945. IN PNS_HELPER_TABLE_ENTRY pHelper,
  946. IN LPCWSTR pwszContext,
  947. OUT PCNS_CONTEXT_ATTRIBUTES *ppContext
  948. )
  949. {
  950. DWORD k;
  951. PCNS_CONTEXT_ATTRIBUTES pSubContext;
  952. for ( k = 0 ; k < pHelper->ulNumSubContexts ; k++)
  953. {
  954. pSubContext = (PCNS_CONTEXT_ATTRIBUTES)
  955. (pHelper->pSubContextTable + k*pHelper->ulSubContextSize);
  956. if (MatchToken(pwszContext, pSubContext->pwszContext))
  957. {
  958. *ppContext = (PCNS_CONTEXT_ATTRIBUTES)pSubContext;
  959. return NO_ERROR;
  960. }
  961. }
  962. return ERROR_NOT_FOUND;
  963. }
  964. DWORD
  965. FreeHelpers(
  966. VOID
  967. )
  968. {
  969. DWORD i;
  970. for (i = 0; i < g_dwNumHelpers; i++)
  971. {
  972. if (g_HelperTable[i].nha.pfnStop)
  973. (g_HelperTable[i].nha.pfnStop)(0);
  974. }
  975. FREE(g_HelperTable);
  976. return NO_ERROR;
  977. }
  978. DWORD
  979. FreeDlls(
  980. VOID
  981. )
  982. {
  983. DWORD i;
  984. for (i = 0; i < g_dwNumDlls; i++)
  985. {
  986. if (g_DllTable[i].bLoaded)
  987. {
  988. FreeLibrary(g_DllTable[i].hDll);
  989. }
  990. }
  991. FREE(g_DllTable);
  992. return NO_ERROR;
  993. }
  994. DWORD
  995. ShowHelpers(
  996. PNS_HELPER_TABLE_ENTRY pHelper,
  997. DWORD dwLevel
  998. )
  999. {
  1000. DWORD i, dwDllIndex, dwErr = NO_ERROR, j;
  1001. WCHAR rgwcHelperGuid[MAX_NAME_LEN];
  1002. PCNS_CONTEXT_ATTRIBUTES pSubContext;
  1003. PNS_HELPER_TABLE_ENTRY pChildHelper;
  1004. for (i = 0; i < pHelper->ulNumSubContexts; i++)
  1005. {
  1006. pSubContext = (PCNS_CONTEXT_ATTRIBUTES)
  1007. (pHelper->pSubContextTable + i*pHelper->ulSubContextSize);
  1008. dwErr = GetHelperEntry( &pSubContext->guidHelper, &pChildHelper );
  1009. if (dwErr)
  1010. {
  1011. return dwErr;
  1012. }
  1013. ConvertGuidToString(&pSubContext->guidHelper,
  1014. rgwcHelperGuid);
  1015. dwDllIndex = pChildHelper->dwDllIndex;
  1016. PrintMessageFromModule( g_hModule,
  1017. MSG_SHOW_HELPER_INFO,
  1018. rgwcHelperGuid,
  1019. g_DllTable[dwDllIndex].pwszDLLName );
  1020. for (j=0; j<dwLevel; j++)
  1021. {
  1022. PrintMessageFromModule(g_hModule, MSG_SHOW_HELPER_INFO1);
  1023. }
  1024. PrintMessageFromModule( g_hModule,
  1025. MSG_SHOW_HELPER_INFO2,
  1026. pSubContext->pwszContext );
  1027. dwErr = ShowHelpers( pChildHelper, dwLevel+1 );
  1028. }
  1029. return dwErr;
  1030. }
  1031. DWORD
  1032. HandleShowHelper(
  1033. LPCWSTR pwszMachine,
  1034. LPWSTR *ppwcArguments,
  1035. DWORD dwCurrentIndex,
  1036. DWORD dwArgCount,
  1037. DWORD dwFlags,
  1038. PVOID pvData,
  1039. BOOL *pbDone
  1040. )
  1041. /*++
  1042. Routine Description:
  1043. Arguments:
  1044. None
  1045. Return Value:
  1046. None
  1047. --*/
  1048. {
  1049. DWORD i, dwHelperIdx, dwDllIndex, dwErr = NO_ERROR;
  1050. WCHAR rgwcHelperGuid[MAX_NAME_LEN];
  1051. PNS_HELPER_TABLE_ENTRY pHelper = g_CurrentHelper;
  1052. PCNS_CONTEXT_ATTRIBUTES pContext;
  1053. WCHAR rgwcParentGuid[MAX_NAME_LEN];
  1054. BOOL bFound;
  1055. dwErr = GetRootContext(&pContext, &pHelper);
  1056. if (dwErr isnot NO_ERROR)
  1057. {
  1058. return dwErr;
  1059. }
  1060. PrintMessageFromModule(g_hModule, MSG_SHOW_HELPER_HDR);
  1061. ShowHelpers(pHelper, 0);
  1062. // Show orphaned DLLs
  1063. for (bFound=FALSE,i=0; i<g_dwNumDlls; i++)
  1064. {
  1065. if (!g_DllTable[i].bLoaded)
  1066. {
  1067. if (!bFound)
  1068. {
  1069. PrintMessageFromModule( g_hModule, MSG_SHOW_HELPER_DLL_HDR );
  1070. bFound = TRUE;
  1071. }
  1072. PrintMessage( L"%1!s!\n", g_DllTable[i].pwszDLLName );
  1073. }
  1074. }
  1075. // Show orphaned helpers
  1076. for (bFound=FALSE,i=0; i<g_dwNumHelpers; i++)
  1077. {
  1078. if (!g_HelperTable[i].bStarted)
  1079. {
  1080. ConvertGuidToString(&g_HelperTable[i].nha.guidHelper,
  1081. rgwcHelperGuid);
  1082. ConvertGuidToString(&g_HelperTable[i].guidParent,
  1083. rgwcParentGuid);
  1084. if (!bFound)
  1085. {
  1086. PrintMessageFromModule( g_hModule, MSG_SHOW_HELPER_ORPHAN_HDR );
  1087. bFound = TRUE;
  1088. }
  1089. PrintMessageFromModule(g_hModule,
  1090. MSG_SHOW_HELPER_ORPHAN_INFO,
  1091. rgwcHelperGuid,
  1092. g_DllTable[g_HelperTable[i].dwDllIndex].pwszDLLName,
  1093. rgwcParentGuid);
  1094. }
  1095. }
  1096. return NO_ERROR;
  1097. }
  1098. DWORD
  1099. HandleAddHelper(
  1100. LPCWSTR pwszMachine,
  1101. LPWSTR *ppwcArguments,
  1102. DWORD dwCurrentIndex,
  1103. DWORD dwArgCount,
  1104. DWORD dwFlags,
  1105. PVOID pvData,
  1106. BOOL *pbDone
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. Installs a helper under the shell
  1111. Arguments:
  1112. Return Value:
  1113. NO_ERROR
  1114. --*/
  1115. {
  1116. DWORD dwErr;
  1117. if (dwArgCount-dwCurrentIndex != 1
  1118. || IsHelpToken(ppwcArguments[dwCurrentIndex]))
  1119. {
  1120. //
  1121. // Install requires only the dll name
  1122. //
  1123. return ERROR_INVALID_SYNTAX;
  1124. }
  1125. #if 0
  1126. if(IsReservedKeyWord(ppwcArguments[dwCurrentIndex]))
  1127. {
  1128. PrintMessageFromModule(g_hModule, EMSG_RSVD_KEYWORD,
  1129. ppwcArguments[dwCurrentIndex]);
  1130. return ERROR_INVALID_PARAMETER;
  1131. }
  1132. #endif
  1133. dwErr = InstallDll(ppwcArguments[dwCurrentIndex]);
  1134. if (dwErr is ERROR_NOT_ENOUGH_MEMORY)
  1135. {
  1136. PrintMessageFromModule(g_hModule, MSG_NOT_ENOUGH_MEMORY);
  1137. dwErr = ERROR_SUPPRESS_OUTPUT;
  1138. }
  1139. if (dwErr is ERROR_SUCCESS)
  1140. {
  1141. dwErr = ERROR_OKAY;
  1142. }
  1143. return dwErr;
  1144. }
  1145. DWORD
  1146. HandleDelHelper(
  1147. LPCWSTR pwszMachine,
  1148. LPWSTR *ppwcArguments,
  1149. DWORD dwCurrentIndex,
  1150. DWORD dwArgCount,
  1151. DWORD dwFlags,
  1152. PVOID pvData,
  1153. BOOL *pbDone
  1154. )
  1155. /*++
  1156. Routine Description:
  1157. Removes a helper from under the Shell
  1158. Arguments:
  1159. Return Value:
  1160. NO_ERROR
  1161. --*/
  1162. {
  1163. DWORD dwErr;
  1164. if (dwArgCount-dwCurrentIndex != 1)
  1165. {
  1166. //
  1167. // Uninstall requires name of helper
  1168. //
  1169. return ERROR_INVALID_SYNTAX;
  1170. }
  1171. dwErr = UninstallDll(ppwcArguments[dwCurrentIndex], TRUE);
  1172. if (dwErr is ERROR_NOT_ENOUGH_MEMORY)
  1173. {
  1174. PrintMessageFromModule(g_hModule, MSG_NOT_ENOUGH_MEMORY);
  1175. }
  1176. if (dwErr is ERROR_SUCCESS)
  1177. {
  1178. dwErr = ERROR_OKAY;
  1179. }
  1180. return dwErr;
  1181. }
  1182. DWORD
  1183. GenericDeleteContext(
  1184. IN PNS_HELPER_TABLE_ENTRY pParentHelper,
  1185. IN DWORD dwContextIdx
  1186. )
  1187. {
  1188. DWORD dwResult = ERROR_SUCCESS;
  1189. PBYTE phtTmp = NULL;
  1190. phtTmp = MALLOC((pParentHelper->ulNumSubContexts - 1)
  1191. * pParentHelper->ulSubContextSize);
  1192. if (phtTmp is NULL)
  1193. {
  1194. return ERROR_NOT_ENOUGH_MEMORY;
  1195. }
  1196. CopyMemory(phtTmp,
  1197. pParentHelper->pSubContextTable,
  1198. dwContextIdx * pParentHelper->ulSubContextSize);
  1199. CopyMemory(phtTmp + dwContextIdx * pParentHelper->ulSubContextSize,
  1200. pParentHelper->pSubContextTable + (dwContextIdx + 1) * pParentHelper->ulSubContextSize,
  1201. (pParentHelper->ulNumSubContexts - 1 - dwContextIdx)
  1202. * pParentHelper->ulSubContextSize);
  1203. pParentHelper->ulNumSubContexts --;
  1204. FREE(pParentHelper->pSubContextTable);
  1205. pParentHelper->pSubContextTable = phtTmp;
  1206. return ERROR_SUCCESS;
  1207. }
  1208. DWORD
  1209. GenericFindContext(
  1210. IN PNS_HELPER_TABLE_ENTRY pParentHelper,
  1211. IN LPCWSTR pwszContext,
  1212. OUT PDWORD pdwIndex
  1213. )
  1214. {
  1215. DWORD i;
  1216. PCNS_CONTEXT_ATTRIBUTES pSubContext;
  1217. for (i=0; i<pParentHelper->ulNumSubContexts; i++)
  1218. {
  1219. pSubContext = (PCNS_CONTEXT_ATTRIBUTES)
  1220. (pParentHelper->pSubContextTable + i*pParentHelper->ulSubContextSize);
  1221. if (!_wcsicmp(pwszContext, pSubContext->pwszContext))
  1222. {
  1223. *pdwIndex = i;
  1224. return NO_ERROR;
  1225. }
  1226. }
  1227. return ERROR_NOT_FOUND;
  1228. }
  1229. DWORD
  1230. GenericAddContext(
  1231. IN PNS_HELPER_TABLE_ENTRY pParentHelper,
  1232. IN PCNS_CONTEXT_ATTRIBUTES pChildContext
  1233. )
  1234. {
  1235. PBYTE phtTmp;
  1236. DWORD i;
  1237. PCNS_CONTEXT_ATTRIBUTES pSubContext;
  1238. // Find where in the table the new entry should go
  1239. for (i=0; i<pParentHelper->ulNumSubContexts; i++)
  1240. {
  1241. pSubContext = (PCNS_CONTEXT_ATTRIBUTES)
  1242. (pParentHelper->pSubContextTable + i*pParentHelper->ulSubContextSize);
  1243. if (_wcsicmp(pChildContext->pwszContext, pSubContext->pwszContext) < 0)
  1244. {
  1245. break;
  1246. }
  1247. }
  1248. //
  1249. // Need to add entries in the context table
  1250. //
  1251. phtTmp = MALLOC((pParentHelper->ulNumSubContexts + 1) *
  1252. pParentHelper->ulSubContextSize );
  1253. if (phtTmp is NULL)
  1254. {
  1255. return ERROR_NOT_ENOUGH_MEMORY;
  1256. }
  1257. // Copy all contexts which come before the new one
  1258. if (i > 0)
  1259. {
  1260. CopyMemory(phtTmp, pParentHelper->pSubContextTable,
  1261. i * pParentHelper->ulSubContextSize);
  1262. }
  1263. CopyMemory(phtTmp + i*pParentHelper->ulSubContextSize,
  1264. pChildContext, pParentHelper->ulSubContextSize);
  1265. // Copy any contexts which come after the new one
  1266. if (i < pParentHelper->ulNumSubContexts)
  1267. {
  1268. CopyMemory(phtTmp + (i+1)*pParentHelper->ulSubContextSize,
  1269. pParentHelper->pSubContextTable + i*pParentHelper->ulSubContextSize,
  1270. (pParentHelper->ulNumSubContexts - i)
  1271. * pParentHelper->ulSubContextSize);
  1272. }
  1273. (pParentHelper->ulNumSubContexts) ++;
  1274. FREE(pParentHelper->pSubContextTable);
  1275. pParentHelper->pSubContextTable = phtTmp;
  1276. return ERROR_SUCCESS;
  1277. }
  1278. DWORD WINAPI
  1279. RegisterContext(
  1280. IN CONST NS_CONTEXT_ATTRIBUTES *pChildContext
  1281. )
  1282. {
  1283. DWORD dwErr, i;
  1284. PNS_HELPER_TABLE_ENTRY pParentHelper;
  1285. CONST GUID *pguidParent;
  1286. ULONG nGroups, nSubGroups;
  1287. if (!pChildContext)
  1288. {
  1289. return ERROR_INVALID_PARAMETER;
  1290. }
  1291. if ( (!pChildContext->pwszContext) ||
  1292. (wcslen(pChildContext->pwszContext) == 0) ||
  1293. (wcschr(pChildContext->pwszContext, L' ') != 0) ||
  1294. (wcschr(pChildContext->pwszContext, L'=') != 0) )
  1295. {
  1296. return ERROR_INVALID_PARAMETER;
  1297. }
  1298. for (nGroups = 0; nGroups < pChildContext->ulNumTopCmds; nGroups++)
  1299. {
  1300. CMD_ENTRY *cmd = &((*pChildContext->pTopCmds)[nGroups]);
  1301. if ( (!cmd->pwszCmdToken) ||
  1302. (wcslen(cmd->pwszCmdToken) == 0) ||
  1303. (wcschr(cmd->pwszCmdToken, L' ') != 0) ||
  1304. (wcschr(cmd->pwszCmdToken, L'=') != 0) )
  1305. {
  1306. PrintMessageFromModule(g_hModule, MSG_INVALID_TOPLEVEL_CMD, cmd->pwszCmdToken);
  1307. ASSERT(FALSE);
  1308. }
  1309. }
  1310. for (nGroups = 0; nGroups < pChildContext->ulNumGroups; nGroups++)
  1311. {
  1312. CMD_GROUP_ENTRY *grpCmd = &((*pChildContext->pCmdGroups)[nGroups]);
  1313. if ( (!grpCmd->pwszCmdGroupToken) ||
  1314. (wcslen(grpCmd->pwszCmdGroupToken) == 0) ||
  1315. (wcschr(grpCmd->pwszCmdGroupToken, L' ') != 0) ||
  1316. (wcschr(grpCmd->pwszCmdGroupToken, L'=') != 0) )
  1317. {
  1318. PrintMessageFromModule(g_hModule, MSG_INVALID_CMD_GROUP, grpCmd->pwszCmdGroupToken);
  1319. ASSERT(FALSE);
  1320. }
  1321. for (nSubGroups = 0; nSubGroups < grpCmd->ulCmdGroupSize; nSubGroups++)
  1322. {
  1323. CMD_ENTRY *cmd = &((grpCmd->pCmdGroup)[nSubGroups]);
  1324. if ( (!cmd->pwszCmdToken) ||
  1325. (wcslen(cmd->pwszCmdToken) == 0) ||
  1326. (wcschr(cmd->pwszCmdToken, L' ') != 0) ||
  1327. (wcschr(cmd->pwszCmdToken, L'=') != 0) )
  1328. {
  1329. PrintMessageFromModule(g_hModule, MSG_INVALID_CMD, cmd->pwszCmdToken);
  1330. ASSERT(FALSE);
  1331. }
  1332. }
  1333. }
  1334. // Get parent guid from child guid
  1335. dwErr = FindHelper( &pChildContext->guidHelper, &i );
  1336. if (dwErr)
  1337. {
  1338. return dwErr;
  1339. }
  1340. pguidParent = &g_HelperTable[i].guidParent;
  1341. dwErr = GetHelperEntry( pguidParent, &pParentHelper );
  1342. if (dwErr)
  1343. {
  1344. return dwErr;
  1345. }
  1346. dwErr = GenericFindContext(pParentHelper, pChildContext->pwszContext, &i);
  1347. if (dwErr is NO_ERROR)
  1348. {
  1349. CopyMemory( pParentHelper->pSubContextTable + i*pParentHelper->ulSubContextSize,
  1350. pChildContext,
  1351. pParentHelper->ulSubContextSize );
  1352. return NO_ERROR;
  1353. }
  1354. return GenericAddContext( pParentHelper, pChildContext );
  1355. }
  1356. DWORD
  1357. WINAPI
  1358. GetHostMachineInfo(
  1359. IN OUT UINT *puiCIMOSType, // WMI: Win32_OperatingSystem OSType
  1360. IN OUT UINT *puiCIMOSProductSuite, // WMI: Win32_OperatingSystem OSProductSuite
  1361. IN OUT LPWSTR pszCIMOSVersion, // WMI: Win32_OperatingSystem Version
  1362. IN OUT LPWSTR pszCIMOSBuildNumber, // WMI: Win32_OperatingSystem BuildNumber
  1363. IN OUT LPWSTR pszCIMServicePackMajorVersion, // WMI: Win32_OperatingSystem ServicePackMajorVersion
  1364. IN OUT LPWSTR pszCIMServicePackMinorVersion, // WMI: Win32_OperatingSystem ServicePackMinorVersion
  1365. IN OUT UINT *puiCIMProcessorArchitecture) // WMI: Win32_Processor Architecture
  1366. {
  1367. if (!g_CIMSucceeded)
  1368. return ERROR_HOST_UNREACHABLE;
  1369. if (puiCIMOSType)
  1370. *puiCIMOSType = g_CIMOSType;
  1371. if (puiCIMOSProductSuite)
  1372. *puiCIMOSProductSuite = g_CIMOSProductSuite;
  1373. if (puiCIMProcessorArchitecture)
  1374. *puiCIMProcessorArchitecture = g_CIMProcessorArchitecture;
  1375. if (pszCIMOSVersion)
  1376. wcsncpy(pszCIMOSVersion, g_CIMOSVersion, MAX_PATH);
  1377. if (pszCIMOSBuildNumber)
  1378. wcsncpy(pszCIMOSBuildNumber, g_CIMOSBuildNumber, MAX_PATH);
  1379. if (pszCIMServicePackMajorVersion)
  1380. wcsncpy(pszCIMServicePackMajorVersion, g_CIMServicePackMajorVersion, MAX_PATH);
  1381. if (pszCIMServicePackMinorVersion)
  1382. wcsncpy(pszCIMServicePackMinorVersion, g_CIMServicePackMinorVersion, MAX_PATH);
  1383. return NO_ERROR;
  1384. }
  1385. BOOL VerifyOsVersion(IN PNS_OSVERSIONCHECK pfnVersionCheck)
  1386. {
  1387. DWORD dwRetVal;
  1388. if (!pfnVersionCheck)
  1389. {
  1390. return TRUE;
  1391. }
  1392. else
  1393. {
  1394. if (g_CIMSucceeded)
  1395. {
  1396. dwRetVal = pfnVersionCheck(
  1397. g_CIMOSType,
  1398. g_CIMOSProductSuite,
  1399. g_CIMOSVersion,
  1400. g_CIMOSBuildNumber,
  1401. g_CIMServicePackMajorVersion,
  1402. g_CIMServicePackMinorVersion,
  1403. g_CIMProcessorArchitecture,
  1404. 0);
  1405. return dwRetVal;
  1406. }
  1407. else
  1408. {
  1409. return FALSE;
  1410. }
  1411. }
  1412. }
  1413. DWORD WINAPI
  1414. GenericMonitor(
  1415. IN const NS_CONTEXT_ATTRIBUTES *pGenericContext,
  1416. IN LPCWSTR pwszMachine,
  1417. IN OUT LPWSTR *ppwcArguments,
  1418. IN DWORD dwArgCount,
  1419. IN DWORD dwFlags,
  1420. IN LPCVOID pvData,
  1421. OUT LPWSTR pwcNewContext
  1422. )
  1423. {
  1424. DWORD dwErr = NO_ERROR, dwIndex, i, j;
  1425. BOOL bFound = FALSE;
  1426. DWORD dwNumMatched;
  1427. DWORD dwCmdHelpToken;
  1428. LPCWSTR pwszCmdToken;
  1429. PNS_DLL_TABLE_ENTRY pDll;
  1430. PNS_HELPER_TABLE_ENTRY pHelper;
  1431. PCNS_CONTEXT_ATTRIBUTES pSubContext;
  1432. PCNS_CONTEXT_ATTRIBUTES pContext = pGenericContext;
  1433. GetHelperEntry( &pContext->guidHelper, &pHelper);
  1434. GetDllEntry( pHelper->dwDllIndex, &pDll);
  1435. g_CurrentContext = pContext;
  1436. g_CurrentHelper = pHelper;
  1437. if (pContext->pfnConnectFn)
  1438. {
  1439. dwErr = pContext->pfnConnectFn(pwszMachine);
  1440. if (dwErr)
  1441. {
  1442. return dwErr;
  1443. }
  1444. }
  1445. //
  1446. // See if command is a context switch.
  1447. //
  1448. if (dwArgCount is 1)
  1449. {
  1450. UpdateNewContext(pwcNewContext,
  1451. pContext->pwszContext,
  1452. dwArgCount);
  1453. return ERROR_CONTEXT_SWITCH;
  1454. }
  1455. //
  1456. // See if the command is a ubiquitous command
  1457. //
  1458. for (i=0; i<g_ulNumUbiqCmds; i++)
  1459. {
  1460. if (g_UbiqCmds[i].dwFlags & ~dwFlags)
  1461. {
  1462. continue;
  1463. }
  1464. if (MatchToken(ppwcArguments[1],
  1465. g_UbiqCmds[i].pwszCmdToken))
  1466. {
  1467. if (!VerifyOsVersion(g_UbiqCmds[i].pOsVersionCheck))
  1468. {
  1469. continue;
  1470. }
  1471. dwErr = GetHelperEntry( &g_NetshGuid, &pHelper );
  1472. GetDllEntry( pHelper->dwDllIndex, &pDll);
  1473. return ExecuteHandler( pDll->hDll,
  1474. &g_UbiqCmds[i],
  1475. ppwcArguments,
  1476. 2,
  1477. dwArgCount,
  1478. dwFlags,
  1479. pvData,
  1480. NULL,
  1481. &g_bDone );
  1482. }
  1483. }
  1484. //
  1485. // See if the command is a top level (non group) command
  1486. //
  1487. for(i = 0; i < pContext->ulNumTopCmds; i++)
  1488. {
  1489. if ((*pContext->pTopCmds)[i].dwFlags & ~dwFlags)
  1490. {
  1491. continue;
  1492. }
  1493. if (MatchToken(ppwcArguments[1],
  1494. (*pContext->pTopCmds)[i].pwszCmdToken))
  1495. {
  1496. if (!VerifyOsVersion( (*pContext->pTopCmds)[i].pOsVersionCheck) )
  1497. {
  1498. continue;
  1499. }
  1500. return ExecuteHandler( pDll->hDll,
  1501. &(*pContext->pTopCmds)[i],
  1502. ppwcArguments,
  1503. 2,
  1504. dwArgCount,
  1505. dwFlags,
  1506. pvData,
  1507. NULL,
  1508. &g_bDone );
  1509. }
  1510. }
  1511. //
  1512. // Check to see if it is meant for one of the
  1513. // helpers under it.
  1514. //
  1515. for (i=0; i<pHelper->ulNumSubContexts; i++)
  1516. {
  1517. pSubContext = (PCNS_CONTEXT_ATTRIBUTES)
  1518. (pHelper->pSubContextTable + i*pHelper->ulSubContextSize);
  1519. if (pSubContext->dwFlags & ~dwFlags)
  1520. {
  1521. continue;
  1522. }
  1523. if (!VerifyOsVersion(pSubContext->pfnOsVersionCheck))
  1524. {
  1525. continue;
  1526. }
  1527. if (MatchToken( ppwcArguments[1],
  1528. pSubContext->pwszContext))
  1529. {
  1530. dwIndex = i;
  1531. bFound = TRUE;
  1532. break;
  1533. }
  1534. }
  1535. if (bFound)
  1536. {
  1537. PNS_PRIV_CONTEXT_ATTRIBUTES pNsPrivContextAttributes;
  1538. PNS_PRIV_CONTEXT_ATTRIBUTES pNsPrivSubContextAttributes;
  1539. //
  1540. // Intended for one of the helpers under this one
  1541. // Pass on the command to the helper
  1542. //
  1543. UpdateNewContext(pwcNewContext,
  1544. pSubContext->pwszContext,
  1545. dwArgCount - 1);
  1546. //
  1547. // Call entry point of the helper.
  1548. //
  1549. pNsPrivContextAttributes = pContext->pReserved;
  1550. pNsPrivSubContextAttributes = pSubContext->pReserved;
  1551. if ( (pNsPrivContextAttributes) && (pNsPrivContextAttributes->pfnSubEntryFn) )
  1552. {
  1553. dwErr = (*pNsPrivContextAttributes->pfnSubEntryFn)(
  1554. pSubContext,
  1555. pwszMachine,
  1556. ppwcArguments + 1,
  1557. dwArgCount - 1,
  1558. dwFlags,
  1559. NULL,
  1560. pwcNewContext);
  1561. }
  1562. else
  1563. {
  1564. if ( (!pNsPrivSubContextAttributes) || (!pNsPrivSubContextAttributes->pfnEntryFn) )
  1565. {
  1566. dwErr = GenericMonitor( pSubContext,
  1567. pwszMachine,
  1568. ppwcArguments + 1,
  1569. dwArgCount - 1,
  1570. dwFlags,
  1571. NULL,
  1572. pwcNewContext);
  1573. }
  1574. else
  1575. {
  1576. dwErr = (pNsPrivSubContextAttributes->pfnEntryFn)(
  1577. pwszMachine,
  1578. ppwcArguments + 1,
  1579. dwArgCount - 1,
  1580. dwFlags,
  1581. NULL,
  1582. pwcNewContext);
  1583. }
  1584. }
  1585. return dwErr;
  1586. }
  1587. //
  1588. // It is a command group
  1589. //
  1590. bFound = FALSE;
  1591. for(i = 0; i < pContext->ulNumGroups; i++)
  1592. {
  1593. if ((*pContext->pCmdGroups)[i].dwFlags & ~dwFlags)
  1594. {
  1595. continue;
  1596. }
  1597. if (MatchToken(ppwcArguments[1],
  1598. (*pContext->pCmdGroups)[i].pwszCmdGroupToken))
  1599. {
  1600. LPCWSTR pwszCmdGroupToken = (*pContext->pCmdGroups)[i].pwszCmdGroupToken;
  1601. if (!VerifyOsVersion((*pContext->pCmdGroups)[i].pOsVersionCheck))
  1602. {
  1603. continue;
  1604. }
  1605. // See if it's a request for help
  1606. if ((dwArgCount<3) || IsHelpToken(ppwcArguments[2]))
  1607. {
  1608. return DisplayContextHelp(
  1609. pContext,
  1610. CMD_FLAG_PRIVATE,
  1611. dwFlags,
  1612. dwArgCount-2+1,
  1613. (*pContext->pCmdGroups)[i].pwszCmdGroupToken );
  1614. }
  1615. //
  1616. // Command matched entry i, so look at the table of sub commands
  1617. // for this command
  1618. //
  1619. for (j = 0; j < (*pContext->pCmdGroups)[i].ulCmdGroupSize; j++)
  1620. {
  1621. if ((*pContext->pCmdGroups)[i].pCmdGroup[j].dwFlags & ~dwFlags)
  1622. {
  1623. continue;
  1624. }
  1625. if (MatchCmdLine(ppwcArguments + 2,
  1626. dwArgCount - 1,
  1627. (*pContext->pCmdGroups)[i].pCmdGroup[j].pwszCmdToken,
  1628. &dwNumMatched))
  1629. {
  1630. if (!VerifyOsVersion((*pContext->pCmdGroups)[i].pCmdGroup[j].pOsVersionCheck))
  1631. {
  1632. continue;
  1633. }
  1634. return ExecuteHandler( pDll->hDll,
  1635. &(*pContext->pCmdGroups)[i].pCmdGroup[j],
  1636. ppwcArguments,
  1637. dwNumMatched + 2,
  1638. dwArgCount,
  1639. dwFlags,
  1640. pvData,
  1641. pwszCmdGroupToken, // the command group name
  1642. &g_bDone );
  1643. }
  1644. }
  1645. return ERROR_CMD_NOT_FOUND;
  1646. }
  1647. }
  1648. return ERROR_CMD_NOT_FOUND;
  1649. }
  1650. DWORD
  1651. WINAPI
  1652. NetshStartHelper(
  1653. IN CONST GUID *pguidParent,
  1654. IN DWORD dwVersion
  1655. )
  1656. {
  1657. DWORD dwErr;
  1658. NS_CONTEXT_ATTRIBUTES attMyAttributes;
  1659. // ParentVersion = dwVersion;
  1660. ZeroMemory(&attMyAttributes, sizeof(attMyAttributes));
  1661. attMyAttributes.pwszContext = L"netsh";
  1662. attMyAttributes.guidHelper = g_NetshGuid;
  1663. attMyAttributes.dwVersion = 1;
  1664. attMyAttributes.dwFlags = 0;
  1665. attMyAttributes.ulNumTopCmds = g_ulNumShellCmds;
  1666. attMyAttributes.pTopCmds = (CMD_ENTRY (*)[])&g_ShellCmds;
  1667. attMyAttributes.ulNumGroups = g_ulNumGroups;
  1668. attMyAttributes.pCmdGroups = (CMD_GROUP_ENTRY (*)[])&g_ShellCmdGroups;
  1669. dwErr = RegisterContext( &attMyAttributes );
  1670. return dwErr;
  1671. }
  1672. DWORD
  1673. WINAPI
  1674. InitHelperDll(
  1675. IN DWORD dwNetshVersion,
  1676. OUT PVOID pReserved
  1677. )
  1678. {
  1679. NS_HELPER_ATTRIBUTES attMyAttributes;
  1680. ZeroMemory( &attMyAttributes, sizeof(attMyAttributes) );
  1681. attMyAttributes.guidHelper = g_NullGuid;
  1682. attMyAttributes.dwVersion = 1;
  1683. RegisterHelper( &g_NullGuid, &attMyAttributes );
  1684. attMyAttributes.guidHelper = g_NetshGuid;
  1685. attMyAttributes.dwVersion = 1;
  1686. attMyAttributes.pfnStart = NetshStartHelper;
  1687. RegisterHelper( &g_NullGuid, &attMyAttributes );
  1688. return NO_ERROR;
  1689. }
  1690. DWORD
  1691. GetRootContext(
  1692. OUT PCNS_CONTEXT_ATTRIBUTES *ppContext,
  1693. OUT PNS_HELPER_TABLE_ENTRY *ppHelper
  1694. )
  1695. {
  1696. PCNS_CONTEXT_ATTRIBUTES pContext;
  1697. DWORD dwErr, k;
  1698. PNS_HELPER_TABLE_ENTRY pNull;
  1699. dwErr = GetHelperEntry( &g_NetshGuid, ppHelper );
  1700. dwErr = GetHelperEntry( &g_NullGuid, &pNull );
  1701. for ( k = 0 ; k < pNull->ulNumSubContexts ; k++)
  1702. {
  1703. pContext = (PCNS_CONTEXT_ATTRIBUTES)
  1704. (pNull->pSubContextTable + k*pNull->ulSubContextSize);
  1705. if (memcmp( &g_NetshGuid, &pContext->guidHelper, sizeof(GUID) ))
  1706. {
  1707. continue;
  1708. }
  1709. *ppContext = pContext;
  1710. return NO_ERROR;
  1711. }
  1712. return dwErr;
  1713. }
  1714. DWORD
  1715. GetParentContext(
  1716. IN PCNS_CONTEXT_ATTRIBUTES pChildContext,
  1717. OUT PCNS_CONTEXT_ATTRIBUTES *ppParentContext
  1718. )
  1719. {
  1720. DWORD dwErr, k;
  1721. PNS_HELPER_TABLE_ENTRY pChild, pParent, pGrandParent;
  1722. PCNS_CONTEXT_ATTRIBUTES pParentContext;
  1723. // For now, just pick the first context in the parent helper
  1724. // To do this, we need to look through the grandparent's subcontexts
  1725. dwErr = GetHelperEntry( &pChildContext->guidHelper, &pChild );
  1726. if (dwErr)
  1727. {
  1728. return dwErr;
  1729. }
  1730. dwErr = GetHelperEntry( &pChild->guidParent, &pParent );
  1731. if (dwErr)
  1732. {
  1733. return dwErr;
  1734. }
  1735. dwErr = GetHelperEntry( &pParent->guidParent, &pGrandParent );
  1736. if (dwErr)
  1737. {
  1738. return dwErr;
  1739. }
  1740. for ( k = 0 ; k < pGrandParent->ulNumSubContexts ; k++)
  1741. {
  1742. pParentContext = (PCNS_CONTEXT_ATTRIBUTES)
  1743. (pGrandParent->pSubContextTable + k*pGrandParent->ulSubContextSize);
  1744. if (memcmp( &pChild->guidParent,
  1745. &pParentContext->guidHelper,
  1746. sizeof(GUID) ))
  1747. {
  1748. continue;
  1749. }
  1750. *ppParentContext = pParentContext;
  1751. return NO_ERROR;
  1752. }
  1753. return ERROR_NOT_FOUND;
  1754. }
  1755. DWORD
  1756. AppendFullContextName(
  1757. IN PCNS_CONTEXT_ATTRIBUTES pContext,
  1758. OUT LPWSTR *ppwszContextName
  1759. )
  1760. {
  1761. DWORD dwErr;
  1762. PCNS_CONTEXT_ATTRIBUTES pParent;
  1763. dwErr = GetParentContext(pContext, &pParent);
  1764. if (dwErr is NO_ERROR)
  1765. {
  1766. dwErr = AppendFullContextName(pParent, ppwszContextName);
  1767. if (dwErr)
  1768. {
  1769. return dwErr;
  1770. }
  1771. }
  1772. if (*ppwszContextName)
  1773. {
  1774. AppendString(ppwszContextName, L" ");
  1775. }
  1776. dwErr = AppendString(ppwszContextName, pContext->pwszContext);
  1777. return dwErr;
  1778. }