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.

2251 lines
56 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. #if (WINVER >= 0x0501)
  583. if ((_wcsicmp(pwszConfigDll, L"ipxmontr.dll") == 0) or
  584. (_wcsicmp(pwszConfigDll, L"ipxpromn.dll") == 0))
  585. {
  586. return ERROR_NOT_SUPPORTED;
  587. }
  588. #endif
  589. //
  590. // Need to add entry in the dll table
  591. //
  592. phtTmp = MALLOC((g_dwNumDlls + 1) * sizeof(NS_DLL_TABLE_ENTRY));
  593. if (phtTmp is NULL)
  594. {
  595. return ERROR_NOT_ENOUGH_MEMORY;
  596. }
  597. CopyMemory(phtTmp, g_DllTable,
  598. g_dwNumDlls * sizeof(NS_DLL_TABLE_ENTRY));
  599. ZeroMemory(&phtTmp[g_dwNumDlls], sizeof(NS_DLL_TABLE_ENTRY));
  600. phtTmp[g_dwNumDlls].pwszValueName = MALLOC( (wcslen(pwszValueName) + 1)
  601. * sizeof(WCHAR));
  602. if (!phtTmp[g_dwNumDlls].pwszValueName)
  603. {
  604. return ERROR_NOT_ENOUGH_MEMORY;
  605. }
  606. wcscpy(phtTmp[g_dwNumDlls].pwszValueName, pwszValueName);
  607. phtTmp[g_dwNumDlls].pwszDLLName = MALLOC( (wcslen(pwszConfigDll) + 1)
  608. * sizeof(WCHAR));
  609. if (!phtTmp[g_dwNumDlls].pwszDLLName)
  610. {
  611. return ERROR_NOT_ENOUGH_MEMORY;
  612. }
  613. wcscpy(phtTmp[g_dwNumDlls].pwszDLLName, pwszConfigDll);
  614. _wcsupr(phtTmp[g_dwNumDlls].pwszDLLName);
  615. g_dwNumDlls ++;
  616. FREE(g_DllTable);
  617. g_DllTable = phtTmp;
  618. return LoadDll(g_dwNumDlls - 1);
  619. }
  620. DWORD
  621. InstallDll(
  622. IN LPCWSTR pwszConfigDll
  623. )
  624. /*++
  625. Called by: HandleAddHelper()
  626. --*/
  627. {
  628. DWORD i, dwErr;
  629. HKEY hBaseKey;
  630. DWORD dwResult = ERROR_SUCCESS;
  631. BOOL bFound = FALSE;
  632. WCHAR wcszKeyName[80];
  633. LPWSTR p, q;
  634. LPWSTR pwszConfigDllCopy;
  635. //
  636. // Check to see if the DLL is already present.
  637. //
  638. for (i = 0; i < g_dwNumDlls; i++)
  639. {
  640. if (_wcsicmp(g_DllTable[i].pwszDLLName, pwszConfigDll) == 0)
  641. {
  642. bFound = TRUE;
  643. break;
  644. }
  645. }
  646. do
  647. {
  648. if (bFound)
  649. break;
  650. //
  651. // Add the key to the registry
  652. //
  653. //
  654. // Create Base Key. If it already exists, fine.
  655. //
  656. dwResult = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
  657. REG_KEY_NETSH_HELPER,
  658. 0,
  659. L"STRING",
  660. REG_OPTION_NON_VOLATILE,
  661. KEY_ALL_ACCESS,
  662. NULL,
  663. &hBaseKey,
  664. NULL);
  665. if(dwResult != ERROR_SUCCESS)
  666. {
  667. break;
  668. }
  669. //
  670. // Add key for the Dll
  671. //
  672. pwszConfigDllCopy = _wcsdup(pwszConfigDll);
  673. if (!pwszConfigDllCopy)
  674. {
  675. return ERROR_NOT_ENOUGH_MEMORY;
  676. }
  677. p = pwszConfigDllCopy;
  678. if ((q = wcsrchr(pwszConfigDllCopy, L'/')) isnot NULL)
  679. {
  680. p = q+1;
  681. }
  682. else if ((q = wcsrchr(pwszConfigDllCopy, L'\\')) isnot NULL)
  683. {
  684. p = q+1;
  685. }
  686. wcscpy(wcszKeyName, p);
  687. if ((p = wcsrchr(wcszKeyName, L'.')) isnot NULL)
  688. {
  689. *p = L'\0';
  690. }
  691. dwResult = RegSetValueExW(hBaseKey,
  692. wcszKeyName,
  693. 0,
  694. REG_SZ,
  695. (PBYTE) pwszConfigDllCopy,
  696. (wcslen(pwszConfigDllCopy) + 1) * sizeof(WCHAR));
  697. RegCloseKey(hBaseKey);
  698. free(pwszConfigDllCopy);
  699. } while (FALSE);
  700. if (dwResult != ERROR_SUCCESS)
  701. {
  702. //
  703. // Could not install key successfully
  704. //
  705. PrintMessageFromModule(g_hModule, EMSG_INSTALL_KEY_FAILED, pwszConfigDll);
  706. return dwResult;
  707. }
  708. dwErr = AddDllEntry(wcszKeyName, pwszConfigDll);
  709. StartNewHelpers();
  710. return dwErr;
  711. }
  712. DWORD
  713. UninstallDll(
  714. IN LPCWSTR pwszConfigDll,
  715. IN BOOL fDeleteFromRegistry
  716. )
  717. {
  718. DWORD i, j;
  719. HKEY hBaseKey;
  720. DWORD dwResult = ERROR_SUCCESS;
  721. BOOL bFound = FALSE;
  722. PNS_DLL_TABLE_ENTRY phtTmp = NULL;
  723. //
  724. // Check to see if the DLL is present.
  725. //
  726. for (i = 0; i < g_dwNumDlls; i++)
  727. {
  728. if (_wcsicmp(g_DllTable[i].pwszDLLName, pwszConfigDll) == 0)
  729. {
  730. bFound = TRUE;
  731. break;
  732. }
  733. }
  734. if (!bFound)
  735. {
  736. //
  737. // DLL to be uninstalled not found.
  738. //
  739. return ERROR_NOT_FOUND;
  740. }
  741. // Uninstall all helpers for this DLL
  742. for (j=0; j<g_dwNumHelpers; j++)
  743. {
  744. if (g_HelperTable[j].dwDllIndex is i)
  745. {
  746. DeleteHelper(j);
  747. j--;
  748. }
  749. }
  750. do
  751. {
  752. if (fDeleteFromRegistry)
  753. {
  754. //
  755. // Delete the key from registry
  756. //
  757. //
  758. // Open Base Key.
  759. //
  760. dwResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  761. REG_KEY_NETSH_HELPER,
  762. 0,
  763. KEY_ALL_ACCESS,
  764. &hBaseKey);
  765. if(dwResult != ERROR_SUCCESS)
  766. {
  767. break;
  768. }
  769. //
  770. // Delete key for the Dll
  771. //
  772. dwResult = RegDeleteValueW(hBaseKey,
  773. g_DllTable[i].pwszValueName);
  774. RegCloseKey(hBaseKey);
  775. }
  776. } while (FALSE);
  777. if (dwResult != ERROR_SUCCESS)
  778. {
  779. //
  780. // Could not uninstall key successfully
  781. //
  782. PrintMessageFromModule(g_hModule,
  783. EMSG_UNINSTALL_KEY_FAILED,
  784. pwszConfigDll);
  785. return dwResult;
  786. }
  787. //
  788. // Key succesfully deleted from registry. If a DLL table is currently
  789. // available, then reflect changes in it too.
  790. //
  791. FREE( g_DllTable[i].pwszDLLName );
  792. g_DllTable[i].pwszDLLName = NULL;
  793. FREE( g_DllTable[i].pwszValueName );
  794. g_DllTable[i].pwszValueName = NULL;
  795. phtTmp = MALLOC((g_dwNumDlls - 1) * sizeof(NS_DLL_TABLE_ENTRY));
  796. if (phtTmp is NULL)
  797. {
  798. return ERROR_NOT_ENOUGH_MEMORY;
  799. }
  800. CopyMemory(phtTmp,
  801. g_DllTable,
  802. i * sizeof(NS_DLL_TABLE_ENTRY));
  803. CopyMemory(phtTmp + i,
  804. g_DllTable + i + 1,
  805. (g_dwNumDlls - 1 - i) * sizeof(NS_DLL_TABLE_ENTRY));
  806. g_dwNumDlls --;
  807. // Update the DLL index in all helpers
  808. for (j=0; j<g_dwNumHelpers; j++)
  809. {
  810. if (g_HelperTable[j].dwDllIndex > i)
  811. {
  812. g_HelperTable[j].dwDllIndex--;
  813. }
  814. }
  815. //
  816. // Unload the dll if it was loaded
  817. //
  818. if (g_DllTable[i].bLoaded)
  819. {
  820. #if 0
  821. if (pHelperTable[i].pfnUnInitFn)
  822. (pHelperTable[i].pfnUnInitFn)(0);
  823. #endif
  824. FreeLibrary(g_DllTable[i].hDll);
  825. }
  826. FREE(g_DllTable);
  827. g_DllTable = phtTmp;
  828. return ERROR_SUCCESS;
  829. }
  830. VOID
  831. LoadDllInfoFromRegistry(
  832. VOID
  833. )
  834. /*++
  835. Routine Description:
  836. Loads information about the helper DLLs from the registry.
  837. Arguments:
  838. Return Value:
  839. --*/
  840. {
  841. DWORD dwResult, i, dwMaxValueLen, dwValueLen;
  842. DWORD dwMaxValueNameLen, dwValueNameLen;
  843. DWORD dwSize,dwType,dwNumDlls;
  844. FILETIME ftLastTime;
  845. HKEY hkeyDlls = NULL;
  846. LPWSTR pwValue = NULL;
  847. LPWSTR pwValueName = NULL;
  848. do {
  849. //
  850. // Open Base Key
  851. //
  852. dwResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  853. REG_KEY_NETSH_HELPER,
  854. 0,
  855. KEY_READ,
  856. &hkeyDlls);
  857. if(dwResult != NO_ERROR)
  858. {
  859. break;
  860. }
  861. //
  862. // Get Number of DLLs
  863. //
  864. dwResult = RegQueryInfoKey(hkeyDlls,
  865. NULL,
  866. NULL,
  867. NULL,
  868. NULL,
  869. NULL,
  870. NULL,
  871. &dwNumDlls,
  872. &dwMaxValueNameLen,
  873. &dwMaxValueLen,
  874. NULL,
  875. NULL);
  876. if(dwResult != NO_ERROR)
  877. {
  878. break;
  879. }
  880. if(dwNumDlls == 0)
  881. {
  882. //
  883. // Nothing registered
  884. //
  885. break;
  886. }
  887. //
  888. // Key len is in WCHARS
  889. //
  890. dwSize = dwMaxValueNameLen + 1;
  891. pwValueName = HeapAlloc(GetProcessHeap(),
  892. HEAP_ZERO_MEMORY,
  893. dwSize * sizeof(WCHAR));
  894. if(pwValueName is NULL)
  895. {
  896. PrintMessageFromModule(g_hModule, MSG_NOT_ENOUGH_MEMORY);
  897. break;
  898. }
  899. dwSize = dwMaxValueLen + 1;
  900. pwValue = HeapAlloc(GetProcessHeap(),
  901. HEAP_ZERO_MEMORY,
  902. dwSize);
  903. if(pwValue is NULL)
  904. {
  905. FREE(pwValueName);
  906. PrintMessageFromModule(g_hModule, MSG_NOT_ENOUGH_MEMORY);
  907. break;
  908. }
  909. for(i = 0; i < dwNumDlls; i++)
  910. {
  911. dwValueLen = dwMaxValueLen + 1;
  912. dwValueNameLen = dwMaxValueNameLen + 1;
  913. dwResult = RegEnumValueW(hkeyDlls,
  914. i,
  915. pwValueName,
  916. &dwValueNameLen,
  917. NULL,
  918. NULL,
  919. (PBYTE)pwValue,
  920. &dwValueLen);
  921. if(dwResult isnot NO_ERROR)
  922. {
  923. if(dwResult is ERROR_NO_MORE_ITEMS)
  924. {
  925. //
  926. // Done
  927. //
  928. break;
  929. }
  930. continue;
  931. }
  932. dwResult = AddDllEntry(pwValueName, pwValue);
  933. }
  934. } while (FALSE);
  935. if (hkeyDlls)
  936. {
  937. RegCloseKey(hkeyDlls);
  938. }
  939. if (pwValueName)
  940. {
  941. FREE(pwValueName);
  942. }
  943. if (pwValue)
  944. {
  945. FREE(pwValue);
  946. }
  947. StartNewHelpers();
  948. return;
  949. }
  950. DWORD
  951. GetContextEntry(
  952. IN PNS_HELPER_TABLE_ENTRY pHelper,
  953. IN LPCWSTR pwszContext,
  954. OUT PCNS_CONTEXT_ATTRIBUTES *ppContext
  955. )
  956. {
  957. DWORD k;
  958. PCNS_CONTEXT_ATTRIBUTES pSubContext;
  959. for ( k = 0 ; k < pHelper->ulNumSubContexts ; k++)
  960. {
  961. pSubContext = (PCNS_CONTEXT_ATTRIBUTES)
  962. (pHelper->pSubContextTable + k*pHelper->ulSubContextSize);
  963. if (MatchToken(pwszContext, pSubContext->pwszContext))
  964. {
  965. *ppContext = (PCNS_CONTEXT_ATTRIBUTES)pSubContext;
  966. return NO_ERROR;
  967. }
  968. }
  969. return ERROR_NOT_FOUND;
  970. }
  971. DWORD
  972. FreeHelpers(
  973. VOID
  974. )
  975. {
  976. DWORD i;
  977. for (i = 0; i < g_dwNumHelpers; i++)
  978. {
  979. if (g_HelperTable[i].nha.pfnStop)
  980. (g_HelperTable[i].nha.pfnStop)(0);
  981. }
  982. FREE(g_HelperTable);
  983. return NO_ERROR;
  984. }
  985. DWORD
  986. FreeDlls(
  987. VOID
  988. )
  989. {
  990. DWORD i;
  991. for (i = 0; i < g_dwNumDlls; i++)
  992. {
  993. if (g_DllTable[i].bLoaded)
  994. {
  995. FreeLibrary(g_DllTable[i].hDll);
  996. }
  997. }
  998. FREE(g_DllTable);
  999. return NO_ERROR;
  1000. }
  1001. DWORD
  1002. ShowHelpers(
  1003. PNS_HELPER_TABLE_ENTRY pHelper,
  1004. DWORD dwLevel
  1005. )
  1006. {
  1007. DWORD i, dwDllIndex, dwErr = NO_ERROR, j;
  1008. WCHAR rgwcHelperGuid[MAX_NAME_LEN];
  1009. PCNS_CONTEXT_ATTRIBUTES pSubContext;
  1010. PNS_HELPER_TABLE_ENTRY pChildHelper;
  1011. for (i = 0; i < pHelper->ulNumSubContexts; i++)
  1012. {
  1013. pSubContext = (PCNS_CONTEXT_ATTRIBUTES)
  1014. (pHelper->pSubContextTable + i*pHelper->ulSubContextSize);
  1015. dwErr = GetHelperEntry( &pSubContext->guidHelper, &pChildHelper );
  1016. if (dwErr)
  1017. {
  1018. return dwErr;
  1019. }
  1020. ConvertGuidToString(&pSubContext->guidHelper,
  1021. rgwcHelperGuid);
  1022. dwDllIndex = pChildHelper->dwDllIndex;
  1023. PrintMessageFromModule( g_hModule,
  1024. MSG_SHOW_HELPER_INFO,
  1025. rgwcHelperGuid,
  1026. g_DllTable[dwDllIndex].pwszDLLName );
  1027. for (j=0; j<dwLevel; j++)
  1028. {
  1029. PrintMessageFromModule(g_hModule, MSG_SHOW_HELPER_INFO1);
  1030. }
  1031. PrintMessageFromModule( g_hModule,
  1032. MSG_SHOW_HELPER_INFO2,
  1033. pSubContext->pwszContext );
  1034. dwErr = ShowHelpers( pChildHelper, dwLevel+1 );
  1035. }
  1036. return dwErr;
  1037. }
  1038. DWORD
  1039. HandleShowHelper(
  1040. LPCWSTR pwszMachine,
  1041. LPWSTR *ppwcArguments,
  1042. DWORD dwCurrentIndex,
  1043. DWORD dwArgCount,
  1044. DWORD dwFlags,
  1045. PVOID pvData,
  1046. BOOL *pbDone
  1047. )
  1048. /*++
  1049. Routine Description:
  1050. Arguments:
  1051. None
  1052. Return Value:
  1053. None
  1054. --*/
  1055. {
  1056. DWORD i, dwHelperIdx, dwDllIndex, dwErr = NO_ERROR;
  1057. WCHAR rgwcHelperGuid[MAX_NAME_LEN];
  1058. PNS_HELPER_TABLE_ENTRY pHelper = g_CurrentHelper;
  1059. PCNS_CONTEXT_ATTRIBUTES pContext;
  1060. WCHAR rgwcParentGuid[MAX_NAME_LEN];
  1061. BOOL bFound;
  1062. dwErr = GetRootContext(&pContext, &pHelper);
  1063. if (dwErr isnot NO_ERROR)
  1064. {
  1065. return dwErr;
  1066. }
  1067. PrintMessageFromModule(g_hModule, MSG_SHOW_HELPER_HDR);
  1068. ShowHelpers(pHelper, 0);
  1069. // Show orphaned DLLs
  1070. for (bFound=FALSE,i=0; i<g_dwNumDlls; i++)
  1071. {
  1072. if (!g_DllTable[i].bLoaded)
  1073. {
  1074. if (!bFound)
  1075. {
  1076. PrintMessageFromModule( g_hModule, MSG_SHOW_HELPER_DLL_HDR );
  1077. bFound = TRUE;
  1078. }
  1079. PrintMessage( L"%1!s!\n", g_DllTable[i].pwszDLLName );
  1080. }
  1081. }
  1082. // Show orphaned helpers
  1083. for (bFound=FALSE,i=0; i<g_dwNumHelpers; i++)
  1084. {
  1085. if (!g_HelperTable[i].bStarted)
  1086. {
  1087. ConvertGuidToString(&g_HelperTable[i].nha.guidHelper,
  1088. rgwcHelperGuid);
  1089. ConvertGuidToString(&g_HelperTable[i].guidParent,
  1090. rgwcParentGuid);
  1091. if (!bFound)
  1092. {
  1093. PrintMessageFromModule( g_hModule, MSG_SHOW_HELPER_ORPHAN_HDR );
  1094. bFound = TRUE;
  1095. }
  1096. PrintMessageFromModule(g_hModule,
  1097. MSG_SHOW_HELPER_ORPHAN_INFO,
  1098. rgwcHelperGuid,
  1099. g_DllTable[g_HelperTable[i].dwDllIndex].pwszDLLName,
  1100. rgwcParentGuid);
  1101. }
  1102. }
  1103. return NO_ERROR;
  1104. }
  1105. DWORD
  1106. HandleAddHelper(
  1107. LPCWSTR pwszMachine,
  1108. LPWSTR *ppwcArguments,
  1109. DWORD dwCurrentIndex,
  1110. DWORD dwArgCount,
  1111. DWORD dwFlags,
  1112. PVOID pvData,
  1113. BOOL *pbDone
  1114. )
  1115. /*++
  1116. Routine Description:
  1117. Installs a helper under the shell
  1118. Arguments:
  1119. Return Value:
  1120. NO_ERROR
  1121. --*/
  1122. {
  1123. DWORD dwErr;
  1124. if (dwArgCount-dwCurrentIndex != 1
  1125. || IsHelpToken(ppwcArguments[dwCurrentIndex]))
  1126. {
  1127. //
  1128. // Install requires only the dll name
  1129. //
  1130. return ERROR_INVALID_SYNTAX;
  1131. }
  1132. #if 0
  1133. if(IsReservedKeyWord(ppwcArguments[dwCurrentIndex]))
  1134. {
  1135. PrintMessageFromModule(g_hModule, EMSG_RSVD_KEYWORD,
  1136. ppwcArguments[dwCurrentIndex]);
  1137. return ERROR_INVALID_PARAMETER;
  1138. }
  1139. #endif
  1140. dwErr = InstallDll(ppwcArguments[dwCurrentIndex]);
  1141. if (dwErr is ERROR_NOT_ENOUGH_MEMORY)
  1142. {
  1143. PrintMessageFromModule(g_hModule, MSG_NOT_ENOUGH_MEMORY);
  1144. dwErr = ERROR_SUPPRESS_OUTPUT;
  1145. }
  1146. if (dwErr is ERROR_SUCCESS)
  1147. {
  1148. dwErr = ERROR_OKAY;
  1149. }
  1150. return dwErr;
  1151. }
  1152. DWORD
  1153. HandleDelHelper(
  1154. LPCWSTR pwszMachine,
  1155. LPWSTR *ppwcArguments,
  1156. DWORD dwCurrentIndex,
  1157. DWORD dwArgCount,
  1158. DWORD dwFlags,
  1159. PVOID pvData,
  1160. BOOL *pbDone
  1161. )
  1162. /*++
  1163. Routine Description:
  1164. Removes a helper from under the Shell
  1165. Arguments:
  1166. Return Value:
  1167. NO_ERROR
  1168. --*/
  1169. {
  1170. DWORD dwErr;
  1171. if (dwArgCount-dwCurrentIndex != 1)
  1172. {
  1173. //
  1174. // Uninstall requires name of helper
  1175. //
  1176. return ERROR_INVALID_SYNTAX;
  1177. }
  1178. dwErr = UninstallDll(ppwcArguments[dwCurrentIndex], TRUE);
  1179. if (dwErr is ERROR_NOT_ENOUGH_MEMORY)
  1180. {
  1181. PrintMessageFromModule(g_hModule, MSG_NOT_ENOUGH_MEMORY);
  1182. }
  1183. if (dwErr is ERROR_SUCCESS)
  1184. {
  1185. dwErr = ERROR_OKAY;
  1186. }
  1187. return dwErr;
  1188. }
  1189. DWORD
  1190. GenericDeleteContext(
  1191. IN PNS_HELPER_TABLE_ENTRY pParentHelper,
  1192. IN DWORD dwContextIdx
  1193. )
  1194. {
  1195. DWORD dwResult = ERROR_SUCCESS;
  1196. PBYTE phtTmp = NULL;
  1197. phtTmp = MALLOC((pParentHelper->ulNumSubContexts - 1)
  1198. * pParentHelper->ulSubContextSize);
  1199. if (phtTmp is NULL)
  1200. {
  1201. return ERROR_NOT_ENOUGH_MEMORY;
  1202. }
  1203. CopyMemory(phtTmp,
  1204. pParentHelper->pSubContextTable,
  1205. dwContextIdx * pParentHelper->ulSubContextSize);
  1206. CopyMemory(phtTmp + dwContextIdx * pParentHelper->ulSubContextSize,
  1207. pParentHelper->pSubContextTable + (dwContextIdx + 1) * pParentHelper->ulSubContextSize,
  1208. (pParentHelper->ulNumSubContexts - 1 - dwContextIdx)
  1209. * pParentHelper->ulSubContextSize);
  1210. pParentHelper->ulNumSubContexts --;
  1211. FREE(pParentHelper->pSubContextTable);
  1212. pParentHelper->pSubContextTable = phtTmp;
  1213. return ERROR_SUCCESS;
  1214. }
  1215. DWORD
  1216. GenericFindContext(
  1217. IN PNS_HELPER_TABLE_ENTRY pParentHelper,
  1218. IN LPCWSTR pwszContext,
  1219. OUT PDWORD pdwIndex
  1220. )
  1221. {
  1222. DWORD i;
  1223. PCNS_CONTEXT_ATTRIBUTES pSubContext;
  1224. for (i=0; i<pParentHelper->ulNumSubContexts; i++)
  1225. {
  1226. pSubContext = (PCNS_CONTEXT_ATTRIBUTES)
  1227. (pParentHelper->pSubContextTable + i*pParentHelper->ulSubContextSize);
  1228. if (!_wcsicmp(pwszContext, pSubContext->pwszContext))
  1229. {
  1230. *pdwIndex = i;
  1231. return NO_ERROR;
  1232. }
  1233. }
  1234. return ERROR_NOT_FOUND;
  1235. }
  1236. DWORD
  1237. GenericAddContext(
  1238. IN PNS_HELPER_TABLE_ENTRY pParentHelper,
  1239. IN PCNS_CONTEXT_ATTRIBUTES pChildContext
  1240. )
  1241. {
  1242. PBYTE phtTmp;
  1243. DWORD i;
  1244. PCNS_CONTEXT_ATTRIBUTES pSubContext;
  1245. // Find where in the table the new entry should go
  1246. for (i=0; i<pParentHelper->ulNumSubContexts; i++)
  1247. {
  1248. pSubContext = (PCNS_CONTEXT_ATTRIBUTES)
  1249. (pParentHelper->pSubContextTable + i*pParentHelper->ulSubContextSize);
  1250. if (_wcsicmp(pChildContext->pwszContext, pSubContext->pwszContext) < 0)
  1251. {
  1252. break;
  1253. }
  1254. }
  1255. //
  1256. // Need to add entries in the context table
  1257. //
  1258. phtTmp = MALLOC((pParentHelper->ulNumSubContexts + 1) *
  1259. pParentHelper->ulSubContextSize );
  1260. if (phtTmp is NULL)
  1261. {
  1262. return ERROR_NOT_ENOUGH_MEMORY;
  1263. }
  1264. // Copy all contexts which come before the new one
  1265. if (i > 0)
  1266. {
  1267. CopyMemory(phtTmp, pParentHelper->pSubContextTable,
  1268. i * pParentHelper->ulSubContextSize);
  1269. }
  1270. CopyMemory(phtTmp + i*pParentHelper->ulSubContextSize,
  1271. pChildContext, pParentHelper->ulSubContextSize);
  1272. // Copy any contexts which come after the new one
  1273. if (i < pParentHelper->ulNumSubContexts)
  1274. {
  1275. CopyMemory(phtTmp + (i+1)*pParentHelper->ulSubContextSize,
  1276. pParentHelper->pSubContextTable + i*pParentHelper->ulSubContextSize,
  1277. (pParentHelper->ulNumSubContexts - i)
  1278. * pParentHelper->ulSubContextSize);
  1279. }
  1280. (pParentHelper->ulNumSubContexts) ++;
  1281. FREE(pParentHelper->pSubContextTable);
  1282. pParentHelper->pSubContextTable = phtTmp;
  1283. return ERROR_SUCCESS;
  1284. }
  1285. DWORD WINAPI
  1286. RegisterContext(
  1287. IN CONST NS_CONTEXT_ATTRIBUTES *pChildContext
  1288. )
  1289. {
  1290. DWORD dwErr, i;
  1291. PNS_HELPER_TABLE_ENTRY pParentHelper;
  1292. CONST GUID *pguidParent;
  1293. ULONG nGroups, nSubGroups;
  1294. if (!pChildContext)
  1295. {
  1296. return ERROR_INVALID_PARAMETER;
  1297. }
  1298. if ( (!pChildContext->pwszContext) ||
  1299. (wcslen(pChildContext->pwszContext) == 0) ||
  1300. (wcschr(pChildContext->pwszContext, L' ') != 0) ||
  1301. (wcschr(pChildContext->pwszContext, L'=') != 0) )
  1302. {
  1303. return ERROR_INVALID_PARAMETER;
  1304. }
  1305. for (nGroups = 0; nGroups < pChildContext->ulNumTopCmds; nGroups++)
  1306. {
  1307. CMD_ENTRY *cmd = &((*pChildContext->pTopCmds)[nGroups]);
  1308. if ( (!cmd->pwszCmdToken) ||
  1309. (wcslen(cmd->pwszCmdToken) == 0) ||
  1310. (wcschr(cmd->pwszCmdToken, L' ') != 0) ||
  1311. (wcschr(cmd->pwszCmdToken, L'=') != 0) )
  1312. {
  1313. PrintMessageFromModule(g_hModule, MSG_INVALID_TOPLEVEL_CMD, cmd->pwszCmdToken);
  1314. ASSERT(FALSE);
  1315. }
  1316. }
  1317. for (nGroups = 0; nGroups < pChildContext->ulNumGroups; nGroups++)
  1318. {
  1319. CMD_GROUP_ENTRY *grpCmd = &((*pChildContext->pCmdGroups)[nGroups]);
  1320. if ( (!grpCmd->pwszCmdGroupToken) ||
  1321. (wcslen(grpCmd->pwszCmdGroupToken) == 0) ||
  1322. (wcschr(grpCmd->pwszCmdGroupToken, L' ') != 0) ||
  1323. (wcschr(grpCmd->pwszCmdGroupToken, L'=') != 0) )
  1324. {
  1325. PrintMessageFromModule(g_hModule, MSG_INVALID_CMD_GROUP, grpCmd->pwszCmdGroupToken);
  1326. ASSERT(FALSE);
  1327. }
  1328. for (nSubGroups = 0; nSubGroups < grpCmd->ulCmdGroupSize; nSubGroups++)
  1329. {
  1330. CMD_ENTRY *cmd = &((grpCmd->pCmdGroup)[nSubGroups]);
  1331. if ( (!cmd->pwszCmdToken) ||
  1332. (wcslen(cmd->pwszCmdToken) == 0) ||
  1333. (wcschr(cmd->pwszCmdToken, L' ') != 0) ||
  1334. (wcschr(cmd->pwszCmdToken, L'=') != 0) )
  1335. {
  1336. PrintMessageFromModule(g_hModule, MSG_INVALID_CMD, cmd->pwszCmdToken);
  1337. ASSERT(FALSE);
  1338. }
  1339. }
  1340. }
  1341. // Get parent guid from child guid
  1342. dwErr = FindHelper( &pChildContext->guidHelper, &i );
  1343. if (dwErr)
  1344. {
  1345. return dwErr;
  1346. }
  1347. pguidParent = &g_HelperTable[i].guidParent;
  1348. dwErr = GetHelperEntry( pguidParent, &pParentHelper );
  1349. if (dwErr)
  1350. {
  1351. return dwErr;
  1352. }
  1353. dwErr = GenericFindContext(pParentHelper, pChildContext->pwszContext, &i);
  1354. if (dwErr is NO_ERROR)
  1355. {
  1356. CopyMemory( pParentHelper->pSubContextTable + i*pParentHelper->ulSubContextSize,
  1357. pChildContext,
  1358. pParentHelper->ulSubContextSize );
  1359. return NO_ERROR;
  1360. }
  1361. return GenericAddContext( pParentHelper, pChildContext );
  1362. }
  1363. DWORD
  1364. WINAPI
  1365. GetHostMachineInfo(
  1366. IN OUT UINT *puiCIMOSType, // WMI: Win32_OperatingSystem OSType
  1367. IN OUT UINT *puiCIMOSProductSuite, // WMI: Win32_OperatingSystem OSProductSuite
  1368. IN OUT LPWSTR pszCIMOSVersion, // WMI: Win32_OperatingSystem Version
  1369. IN OUT LPWSTR pszCIMOSBuildNumber, // WMI: Win32_OperatingSystem BuildNumber
  1370. IN OUT LPWSTR pszCIMServicePackMajorVersion, // WMI: Win32_OperatingSystem ServicePackMajorVersion
  1371. IN OUT LPWSTR pszCIMServicePackMinorVersion, // WMI: Win32_OperatingSystem ServicePackMinorVersion
  1372. IN OUT UINT *puiCIMProcessorArchitecture) // WMI: Win32_Processor Architecture
  1373. {
  1374. if (!g_CIMSucceeded)
  1375. return ERROR_HOST_UNREACHABLE;
  1376. if (puiCIMOSType)
  1377. *puiCIMOSType = g_CIMOSType;
  1378. if (puiCIMOSProductSuite)
  1379. *puiCIMOSProductSuite = g_CIMOSProductSuite;
  1380. if (puiCIMProcessorArchitecture)
  1381. *puiCIMProcessorArchitecture = g_CIMProcessorArchitecture;
  1382. if (pszCIMOSVersion)
  1383. wcsncpy(pszCIMOSVersion, g_CIMOSVersion, MAX_PATH);
  1384. if (pszCIMOSBuildNumber)
  1385. wcsncpy(pszCIMOSBuildNumber, g_CIMOSBuildNumber, MAX_PATH);
  1386. if (pszCIMServicePackMajorVersion)
  1387. wcsncpy(pszCIMServicePackMajorVersion, g_CIMServicePackMajorVersion, MAX_PATH);
  1388. if (pszCIMServicePackMinorVersion)
  1389. wcsncpy(pszCIMServicePackMinorVersion, g_CIMServicePackMinorVersion, MAX_PATH);
  1390. return NO_ERROR;
  1391. }
  1392. BOOL VerifyOsVersion(IN PNS_OSVERSIONCHECK pfnVersionCheck)
  1393. {
  1394. DWORD dwRetVal;
  1395. if (!pfnVersionCheck)
  1396. {
  1397. return TRUE;
  1398. }
  1399. else
  1400. {
  1401. if (g_CIMSucceeded)
  1402. {
  1403. dwRetVal = pfnVersionCheck(
  1404. g_CIMOSType,
  1405. g_CIMOSProductSuite,
  1406. g_CIMOSVersion,
  1407. g_CIMOSBuildNumber,
  1408. g_CIMServicePackMajorVersion,
  1409. g_CIMServicePackMinorVersion,
  1410. g_CIMProcessorArchitecture,
  1411. 0);
  1412. return dwRetVal;
  1413. }
  1414. else
  1415. {
  1416. return FALSE;
  1417. }
  1418. }
  1419. }
  1420. DWORD WINAPI
  1421. GenericMonitor(
  1422. IN const NS_CONTEXT_ATTRIBUTES *pGenericContext,
  1423. IN LPCWSTR pwszMachine,
  1424. IN OUT LPWSTR *ppwcArguments,
  1425. IN DWORD dwArgCount,
  1426. IN DWORD dwFlags,
  1427. IN LPCVOID pvData,
  1428. OUT LPWSTR pwcNewContext
  1429. )
  1430. {
  1431. DWORD dwErr = NO_ERROR, dwIndex, i, j;
  1432. BOOL bFound = FALSE;
  1433. DWORD dwNumMatched;
  1434. DWORD dwCmdHelpToken;
  1435. LPCWSTR pwszCmdToken;
  1436. PNS_DLL_TABLE_ENTRY pDll;
  1437. PNS_HELPER_TABLE_ENTRY pHelper;
  1438. PCNS_CONTEXT_ATTRIBUTES pSubContext;
  1439. PCNS_CONTEXT_ATTRIBUTES pContext = pGenericContext;
  1440. GetHelperEntry( &pContext->guidHelper, &pHelper);
  1441. GetDllEntry( pHelper->dwDllIndex, &pDll);
  1442. g_CurrentContext = pContext;
  1443. g_CurrentHelper = pHelper;
  1444. if (pContext->pfnConnectFn)
  1445. {
  1446. dwErr = pContext->pfnConnectFn(pwszMachine);
  1447. if (dwErr)
  1448. {
  1449. PrintError(NULL, dwErr);
  1450. return ERROR_SUPPRESS_OUTPUT;
  1451. }
  1452. }
  1453. //
  1454. // See if command is a context switch.
  1455. //
  1456. if (dwArgCount is 1)
  1457. {
  1458. UpdateNewContext(pwcNewContext,
  1459. pContext->pwszContext,
  1460. dwArgCount);
  1461. return ERROR_CONTEXT_SWITCH;
  1462. }
  1463. //
  1464. // See if the command is a ubiquitous command
  1465. //
  1466. for (i=0; i<g_ulNumUbiqCmds; i++)
  1467. {
  1468. if (g_UbiqCmds[i].dwFlags & ~dwFlags)
  1469. {
  1470. continue;
  1471. }
  1472. if (MatchToken(ppwcArguments[1],
  1473. g_UbiqCmds[i].pwszCmdToken))
  1474. {
  1475. if (!VerifyOsVersion(g_UbiqCmds[i].pOsVersionCheck))
  1476. {
  1477. continue;
  1478. }
  1479. dwErr = GetHelperEntry( &g_NetshGuid, &pHelper );
  1480. GetDllEntry( pHelper->dwDllIndex, &pDll);
  1481. return ExecuteHandler( pDll->hDll,
  1482. &g_UbiqCmds[i],
  1483. ppwcArguments,
  1484. 2,
  1485. dwArgCount,
  1486. dwFlags,
  1487. pvData,
  1488. NULL,
  1489. &g_bDone );
  1490. }
  1491. }
  1492. //
  1493. // See if the command is a top level (non group) command
  1494. //
  1495. for(i = 0; i < pContext->ulNumTopCmds; i++)
  1496. {
  1497. // If the command does not match the current display requirements,
  1498. // don't execute it EXCEPT in the case of a hidden cmd. we still
  1499. // want to execute those.
  1500. //
  1501. if (((*pContext->pTopCmds)[i].dwFlags & ~dwFlags) &&
  1502. ((*pContext->pTopCmds)[i].dwFlags & ~CMD_FLAG_HIDDEN)
  1503. )
  1504. {
  1505. continue;
  1506. }
  1507. if (MatchToken(ppwcArguments[1],
  1508. (*pContext->pTopCmds)[i].pwszCmdToken))
  1509. {
  1510. if (!VerifyOsVersion( (*pContext->pTopCmds)[i].pOsVersionCheck) )
  1511. {
  1512. continue;
  1513. }
  1514. return ExecuteHandler( pDll->hDll,
  1515. &(*pContext->pTopCmds)[i],
  1516. ppwcArguments,
  1517. 2,
  1518. dwArgCount,
  1519. dwFlags,
  1520. pvData,
  1521. NULL,
  1522. &g_bDone );
  1523. }
  1524. }
  1525. //
  1526. // Check to see if it is meant for one of the
  1527. // helpers under it.
  1528. //
  1529. for (i=0; i<pHelper->ulNumSubContexts; i++)
  1530. {
  1531. pSubContext = (PCNS_CONTEXT_ATTRIBUTES)
  1532. (pHelper->pSubContextTable + i*pHelper->ulSubContextSize);
  1533. if (pSubContext->dwFlags & ~dwFlags)
  1534. {
  1535. continue;
  1536. }
  1537. if (!VerifyOsVersion(pSubContext->pfnOsVersionCheck))
  1538. {
  1539. continue;
  1540. }
  1541. if (MatchToken( ppwcArguments[1],
  1542. pSubContext->pwszContext))
  1543. {
  1544. dwIndex = i;
  1545. bFound = TRUE;
  1546. break;
  1547. }
  1548. }
  1549. if (bFound)
  1550. {
  1551. PNS_PRIV_CONTEXT_ATTRIBUTES pNsPrivContextAttributes;
  1552. PNS_PRIV_CONTEXT_ATTRIBUTES pNsPrivSubContextAttributes;
  1553. //
  1554. // Intended for one of the helpers under this one
  1555. // Pass on the command to the helper
  1556. //
  1557. UpdateNewContext(pwcNewContext,
  1558. pSubContext->pwszContext,
  1559. dwArgCount - 1);
  1560. //
  1561. // Call entry point of the helper.
  1562. //
  1563. pNsPrivContextAttributes = pContext->pReserved;
  1564. pNsPrivSubContextAttributes = pSubContext->pReserved;
  1565. if ( (pNsPrivContextAttributes) && (pNsPrivContextAttributes->pfnSubEntryFn) )
  1566. {
  1567. dwErr = (*pNsPrivContextAttributes->pfnSubEntryFn)(
  1568. pSubContext,
  1569. pwszMachine,
  1570. ppwcArguments + 1,
  1571. dwArgCount - 1,
  1572. dwFlags,
  1573. NULL,
  1574. pwcNewContext);
  1575. }
  1576. else
  1577. {
  1578. if ( (!pNsPrivSubContextAttributes) || (!pNsPrivSubContextAttributes->pfnEntryFn) )
  1579. {
  1580. dwErr = GenericMonitor( pSubContext,
  1581. pwszMachine,
  1582. ppwcArguments + 1,
  1583. dwArgCount - 1,
  1584. dwFlags,
  1585. NULL,
  1586. pwcNewContext);
  1587. }
  1588. else
  1589. {
  1590. dwErr = (pNsPrivSubContextAttributes->pfnEntryFn)(
  1591. pwszMachine,
  1592. ppwcArguments + 1,
  1593. dwArgCount - 1,
  1594. dwFlags,
  1595. NULL,
  1596. pwcNewContext);
  1597. }
  1598. }
  1599. return dwErr;
  1600. }
  1601. //
  1602. // It is a command group
  1603. //
  1604. bFound = FALSE;
  1605. for(i = 0; i < pContext->ulNumGroups; i++)
  1606. {
  1607. if ((*pContext->pCmdGroups)[i].dwFlags & ~dwFlags)
  1608. {
  1609. continue;
  1610. }
  1611. if (MatchToken(ppwcArguments[1],
  1612. (*pContext->pCmdGroups)[i].pwszCmdGroupToken))
  1613. {
  1614. LPCWSTR pwszCmdGroupToken = (*pContext->pCmdGroups)[i].pwszCmdGroupToken;
  1615. if (!VerifyOsVersion((*pContext->pCmdGroups)[i].pOsVersionCheck))
  1616. {
  1617. continue;
  1618. }
  1619. // See if it's a request for help
  1620. if ((dwArgCount<3) || IsHelpToken(ppwcArguments[2]))
  1621. {
  1622. return DisplayContextHelp(
  1623. pContext,
  1624. CMD_FLAG_PRIVATE,
  1625. dwFlags,
  1626. dwArgCount-2+1,
  1627. (*pContext->pCmdGroups)[i].pwszCmdGroupToken );
  1628. }
  1629. //
  1630. // Command matched entry i, so look at the table of sub commands
  1631. // for this command
  1632. //
  1633. for (j = 0; j < (*pContext->pCmdGroups)[i].ulCmdGroupSize; j++)
  1634. {
  1635. // If the command does not match the current display requirements,
  1636. // don't execute it EXCEPT in the case of a hidden cmd. we still
  1637. // want to execute those.
  1638. //
  1639. if (((*pContext->pCmdGroups)[i].pCmdGroup[j].dwFlags & ~dwFlags) &&
  1640. ((*pContext->pCmdGroups)[i].pCmdGroup[j].dwFlags & ~CMD_FLAG_HIDDEN)
  1641. )
  1642. {
  1643. continue;
  1644. }
  1645. if (MatchCmdLine(ppwcArguments + 2,
  1646. dwArgCount - 1,
  1647. (*pContext->pCmdGroups)[i].pCmdGroup[j].pwszCmdToken,
  1648. &dwNumMatched))
  1649. {
  1650. if (!VerifyOsVersion((*pContext->pCmdGroups)[i].pCmdGroup[j].pOsVersionCheck))
  1651. {
  1652. continue;
  1653. }
  1654. return ExecuteHandler( pDll->hDll,
  1655. &(*pContext->pCmdGroups)[i].pCmdGroup[j],
  1656. ppwcArguments,
  1657. dwNumMatched + 2,
  1658. dwArgCount,
  1659. dwFlags,
  1660. pvData,
  1661. pwszCmdGroupToken, // the command group name
  1662. &g_bDone );
  1663. }
  1664. }
  1665. return ERROR_CMD_NOT_FOUND;
  1666. }
  1667. }
  1668. return ERROR_CMD_NOT_FOUND;
  1669. }
  1670. DWORD
  1671. WINAPI
  1672. NetshStartHelper(
  1673. IN CONST GUID *pguidParent,
  1674. IN DWORD dwVersion
  1675. )
  1676. {
  1677. DWORD dwErr;
  1678. NS_CONTEXT_ATTRIBUTES attMyAttributes;
  1679. // ParentVersion = dwVersion;
  1680. ZeroMemory(&attMyAttributes, sizeof(attMyAttributes));
  1681. attMyAttributes.pwszContext = L"netsh";
  1682. attMyAttributes.guidHelper = g_NetshGuid;
  1683. attMyAttributes.dwVersion = 1;
  1684. attMyAttributes.dwFlags = 0;
  1685. attMyAttributes.ulNumTopCmds = g_ulNumShellCmds;
  1686. attMyAttributes.pTopCmds = (CMD_ENTRY (*)[])&g_ShellCmds;
  1687. attMyAttributes.ulNumGroups = g_ulNumGroups;
  1688. attMyAttributes.pCmdGroups = (CMD_GROUP_ENTRY (*)[])&g_ShellCmdGroups;
  1689. dwErr = RegisterContext( &attMyAttributes );
  1690. return dwErr;
  1691. }
  1692. DWORD
  1693. WINAPI
  1694. InitHelperDll(
  1695. IN DWORD dwNetshVersion,
  1696. OUT PVOID pReserved
  1697. )
  1698. {
  1699. NS_HELPER_ATTRIBUTES attMyAttributes;
  1700. ZeroMemory( &attMyAttributes, sizeof(attMyAttributes) );
  1701. attMyAttributes.guidHelper = g_NullGuid;
  1702. attMyAttributes.dwVersion = 1;
  1703. RegisterHelper( &g_NullGuid, &attMyAttributes );
  1704. attMyAttributes.guidHelper = g_NetshGuid;
  1705. attMyAttributes.dwVersion = 1;
  1706. attMyAttributes.pfnStart = NetshStartHelper;
  1707. RegisterHelper( &g_NullGuid, &attMyAttributes );
  1708. return NO_ERROR;
  1709. }
  1710. DWORD
  1711. GetRootContext(
  1712. OUT PCNS_CONTEXT_ATTRIBUTES *ppContext,
  1713. OUT PNS_HELPER_TABLE_ENTRY *ppHelper
  1714. )
  1715. {
  1716. PCNS_CONTEXT_ATTRIBUTES pContext;
  1717. DWORD dwErr, k;
  1718. PNS_HELPER_TABLE_ENTRY pNull;
  1719. dwErr = GetHelperEntry( &g_NetshGuid, ppHelper );
  1720. dwErr = GetHelperEntry( &g_NullGuid, &pNull );
  1721. for ( k = 0 ; k < pNull->ulNumSubContexts ; k++)
  1722. {
  1723. pContext = (PCNS_CONTEXT_ATTRIBUTES)
  1724. (pNull->pSubContextTable + k*pNull->ulSubContextSize);
  1725. if (memcmp( &g_NetshGuid, &pContext->guidHelper, sizeof(GUID) ))
  1726. {
  1727. continue;
  1728. }
  1729. *ppContext = pContext;
  1730. return NO_ERROR;
  1731. }
  1732. return dwErr;
  1733. }
  1734. DWORD
  1735. GetParentContext(
  1736. IN PCNS_CONTEXT_ATTRIBUTES pChildContext,
  1737. OUT PCNS_CONTEXT_ATTRIBUTES *ppParentContext
  1738. )
  1739. {
  1740. DWORD dwErr, k;
  1741. PNS_HELPER_TABLE_ENTRY pChild, pParent, pGrandParent;
  1742. PCNS_CONTEXT_ATTRIBUTES pParentContext;
  1743. // For now, just pick the first context in the parent helper
  1744. // To do this, we need to look through the grandparent's subcontexts
  1745. dwErr = GetHelperEntry( &pChildContext->guidHelper, &pChild );
  1746. if (dwErr)
  1747. {
  1748. return dwErr;
  1749. }
  1750. dwErr = GetHelperEntry( &pChild->guidParent, &pParent );
  1751. if (dwErr)
  1752. {
  1753. return dwErr;
  1754. }
  1755. dwErr = GetHelperEntry( &pParent->guidParent, &pGrandParent );
  1756. if (dwErr)
  1757. {
  1758. return dwErr;
  1759. }
  1760. for ( k = 0 ; k < pGrandParent->ulNumSubContexts ; k++)
  1761. {
  1762. pParentContext = (PCNS_CONTEXT_ATTRIBUTES)
  1763. (pGrandParent->pSubContextTable + k*pGrandParent->ulSubContextSize);
  1764. if (memcmp( &pChild->guidParent,
  1765. &pParentContext->guidHelper,
  1766. sizeof(GUID) ))
  1767. {
  1768. continue;
  1769. }
  1770. *ppParentContext = pParentContext;
  1771. return NO_ERROR;
  1772. }
  1773. return ERROR_NOT_FOUND;
  1774. }
  1775. DWORD
  1776. AppendFullContextName(
  1777. IN PCNS_CONTEXT_ATTRIBUTES pContext,
  1778. OUT LPWSTR *ppwszContextName
  1779. )
  1780. {
  1781. DWORD dwErr;
  1782. PCNS_CONTEXT_ATTRIBUTES pParent;
  1783. dwErr = GetParentContext(pContext, &pParent);
  1784. if (dwErr is NO_ERROR)
  1785. {
  1786. dwErr = AppendFullContextName(pParent, ppwszContextName);
  1787. if (dwErr)
  1788. {
  1789. return dwErr;
  1790. }
  1791. }
  1792. if (*ppwszContextName)
  1793. {
  1794. AppendString(ppwszContextName, L" ");
  1795. }
  1796. dwErr = AppendString(ppwszContextName, pContext->pwszContext);
  1797. return dwErr;
  1798. }