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.

1013 lines
23 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. routing\netsh\ipx\ipxmon\ipxmon.c
  5. Abstract:
  6. IPX Command dispatcher.
  7. Revision History:
  8. V Raman 11/25/98 Created
  9. --*/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. //
  13. // Guid for IPMON.DLL
  14. //
  15. // {b1641451-84b8-11d2-b940-3078302c2030}
  16. //
  17. static const GUID g_MyGuid = IPXMONTR_GUID;
  18. //
  19. // Well known ROUTING guid
  20. //
  21. static const GUID g_RoutingGuid = ROUTING_GUID;
  22. //
  23. // IPX monitor version
  24. //
  25. #define IPX_HELPER_VERSION 1
  26. //
  27. // random wrapper macros
  28. //
  29. #define MALLOC(x) HeapAlloc( GetProcessHeap(), 0, x )
  30. #define REALLOC(x,y) HeapReAlloc( GetProcessHeap(), 0, x, y )
  31. #define FREE(x) HeapFree( GetProcessHeap(), 0, x )
  32. //
  33. // The table of Add, Delete, Set and Show Commands for IPX RTR MGR
  34. // To add a command to one of the command groups, just add the
  35. // CMD_ENTRY to the correct table. To add a new cmd group, create its
  36. // cmd table and then add the group entry to group table
  37. //
  38. //
  39. // The commands are prefix-matched with the command-line, in sequential
  40. // order. So a command like 'ADD INTERFACE FILTER' must come before
  41. // the command 'ADD INTERFACE' in the table. Likewise,
  42. // a command like 'ADD ROUTE' must come before the command
  43. // 'ADD ROUTEPREF' in the table.
  44. //
  45. CMD_ENTRY g_IpxAddCmdTable[] =
  46. {
  47. CREATE_CMD_ENTRY( IPX_ADD_ROUTE, HandleIpxAddRoute),
  48. CREATE_CMD_ENTRY( IPX_ADD_SERVICE, HandleIpxAddService ),
  49. CREATE_CMD_ENTRY( IPX_ADD_FILTER, HandleIpxAddFilter ),
  50. CREATE_CMD_ENTRY( IPX_ADD_INTERFACE, HandleIpxAddInterface )
  51. };
  52. CMD_ENTRY g_IpxDelCmdTable[] =
  53. {
  54. CREATE_CMD_ENTRY( IPX_DELETE_ROUTE, HandleIpxDelRoute ),
  55. CREATE_CMD_ENTRY( IPX_DELETE_SERVICE, HandleIpxDelService ),
  56. CREATE_CMD_ENTRY( IPX_DELETE_FILTER, HandleIpxDelFilter ),
  57. CREATE_CMD_ENTRY( IPX_DELETE_INTERFACE, HandleIpxDelInterface )
  58. };
  59. CMD_ENTRY g_IpxSetCmdTable[] =
  60. {
  61. CREATE_CMD_ENTRY( IPX_SET_ROUTE, HandleIpxSetRoute ),
  62. CREATE_CMD_ENTRY( IPX_SET_SERVICE, HandleIpxSetService ),
  63. CREATE_CMD_ENTRY( IPX_SET_FILTER, HandleIpxSetFilter ),
  64. CREATE_CMD_ENTRY( IPX_SET_INTERFACE, HandleIpxSetInterface ),
  65. CREATE_CMD_ENTRY( IPX_SET_GLOBAL, HandleIpxSetLoglevel )
  66. };
  67. CMD_ENTRY g_IpxShowCmdTable[] =
  68. {
  69. CREATE_CMD_ENTRY( IPX_SHOW_ROUTE, HandleIpxShowRoute ),
  70. CREATE_CMD_ENTRY( IPX_SHOW_SERVICE, HandleIpxShowService),
  71. CREATE_CMD_ENTRY( IPX_SHOW_FILTER, HandleIpxShowFilter ),
  72. CREATE_CMD_ENTRY( IPX_SHOW_INTERFACE, HandleIpxShowInterface ),
  73. CREATE_CMD_ENTRY( IPX_SHOW_GLOBAL, HandleIpxShowLoglevel ),
  74. CREATE_CMD_ENTRY( IPX_SHOW_ROUTETABLE, HandleIpxShowRouteTable ),
  75. CREATE_CMD_ENTRY( IPX_SHOW_SERVICETABLE,HandleIpxShowServiceTable ),
  76. };
  77. CMD_GROUP_ENTRY g_IpxCmdGroups[] =
  78. {
  79. CREATE_CMD_GROUP_ENTRY( GROUP_ADD, g_IpxAddCmdTable ),
  80. CREATE_CMD_GROUP_ENTRY( GROUP_DELETE, g_IpxDelCmdTable ),
  81. CREATE_CMD_GROUP_ENTRY( GROUP_SET, g_IpxSetCmdTable ),
  82. CREATE_CMD_GROUP_ENTRY( GROUP_SHOW, g_IpxShowCmdTable )
  83. };
  84. ULONG g_ulNumGroups = sizeof(g_IpxCmdGroups)/sizeof(CMD_GROUP_ENTRY);
  85. //
  86. // Top level commands
  87. //
  88. CMD_ENTRY g_IpxCmds[] =
  89. {
  90. CREATE_CMD_ENTRY( IPX_UPDATE, HandleIpxUpdate )
  91. };
  92. ULONG g_ulNumTopCmds = sizeof(g_IpxCmds)/sizeof(CMD_ENTRY);
  93. //
  94. // Handle to this DLL
  95. //
  96. HANDLE g_hModule;
  97. //
  98. // Handle to router being administered
  99. //
  100. HANDLE g_hMprConfig;
  101. HANDLE g_hMprAdmin;
  102. HANDLE g_hMIBServer;
  103. //
  104. // Commit mode
  105. //
  106. BOOL g_bCommit;
  107. DWORD ParentVersion;
  108. BOOL g_bIpxDirty = FALSE;
  109. NS_CONTEXT_CONNECT_FN IpxConnect;
  110. NS_CONTEXT_SUBENTRY_FN IpxSubEntry;
  111. //
  112. // Variable that stores whether or not the helper has been
  113. // initialized
  114. //
  115. ULONG g_ulInitCount;
  116. //
  117. // Router name
  118. //
  119. PWCHAR g_pwszRouter = NULL;
  120. //
  121. // Prototype declarations for functions in this file
  122. //
  123. DWORD
  124. WINAPI
  125. IpxUnInit(
  126. IN DWORD dwReserved
  127. );
  128. BOOL
  129. IsHelpToken(
  130. PWCHAR pwszToken
  131. );
  132. BOOL
  133. IA64VersionCheck
  134. (
  135. IN UINT CIMOSType, // WMI: Win32_OperatingSystem OSType
  136. IN UINT CIMOSProductSuite, // WMI: Win32_OperatingSystem OSProductSuite
  137. IN LPCWSTR CIMOSVersion, // WMI: Win32_OperatingSystem Version
  138. IN LPCWSTR CIMOSBuildNumber, // WMI: Win32_OperatingSystem BuildNumber
  139. IN LPCWSTR CIMServicePackMajorVersion, // WMI: Win32_OperatingSystem ServicePackMajorVersion
  140. IN LPCWSTR CIMServicePackMinorVersion, // WMI: Win32_OperatingSystem ServicePackMinorVersion
  141. IN UINT CIMProcessorArchitecture, // WMI: Win32_Processor Architecture
  142. IN DWORD dwReserved
  143. )
  144. {
  145. if (CIMProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) // IA64=6 (x86 == 0)
  146. return TRUE;
  147. else
  148. return FALSE;
  149. }
  150. DWORD
  151. WINAPI
  152. IpxStartHelper(
  153. IN CONST GUID *pguidParent,
  154. IN DWORD dwVersion
  155. )
  156. /*++
  157. Routine Description :
  158. Registers the contexts supported by this helper
  159. Arguements :
  160. pguidParent - NETSH guid
  161. Return value :
  162. Don't know
  163. --*/
  164. {
  165. DWORD dwErr;
  166. NS_CONTEXT_ATTRIBUTES attMyAttributes;
  167. PNS_PRIV_CONTEXT_ATTRIBUTES pNsPrivContextAttributes;
  168. pNsPrivContextAttributes = MALLOC(sizeof(NS_PRIV_CONTEXT_ATTRIBUTES));
  169. if (!pNsPrivContextAttributes)
  170. {
  171. return ERROR_NOT_ENOUGH_MEMORY;
  172. }
  173. ParentVersion = dwVersion;
  174. ZeroMemory( &attMyAttributes, sizeof(NS_CONTEXT_ATTRIBUTES));
  175. ZeroMemory(pNsPrivContextAttributes, sizeof(NS_PRIV_CONTEXT_ATTRIBUTES));
  176. attMyAttributes.pwszContext = L"ipx";
  177. attMyAttributes.guidHelper = g_MyGuid;
  178. attMyAttributes.dwVersion = 1;
  179. attMyAttributes.dwFlags = 0;
  180. attMyAttributes.ulNumTopCmds = g_ulNumTopCmds;
  181. attMyAttributes.pTopCmds = (CMD_ENTRY (*)[])&g_IpxCmds;
  182. attMyAttributes.ulNumGroups = g_ulNumGroups;
  183. attMyAttributes.pCmdGroups = (CMD_GROUP_ENTRY (*)[])&g_IpxCmdGroups;
  184. attMyAttributes.pfnCommitFn = NULL;
  185. attMyAttributes.pfnDumpFn = IpxDump;
  186. attMyAttributes.pfnConnectFn= IpxConnect;
  187. attMyAttributes.pfnOsVersionCheck = IA64VersionCheck;
  188. pNsPrivContextAttributes->pfnEntryFn = NULL;
  189. pNsPrivContextAttributes->pfnSubEntryFn = IpxSubEntry;
  190. attMyAttributes.pReserved = pNsPrivContextAttributes;
  191. dwErr = RegisterContext( &attMyAttributes );
  192. return dwErr;
  193. }
  194. DWORD
  195. WINAPI
  196. InitHelperDll(
  197. IN DWORD dwNetshVersion,
  198. OUT PNS_DLL_ATTRIBUTES pDllTable
  199. )
  200. /*++
  201. Routine Description :
  202. initialize this helper DLL
  203. Arguements :
  204. pUtilityTable - List of helper functions from the SHELL
  205. pDllTable - Callbacks into this helper DLL passed back to the shell
  206. Return value :
  207. NO_ERROR - Success
  208. --*/
  209. {
  210. DWORD dwErr;
  211. NS_HELPER_ATTRIBUTES attMyAttributes;
  212. //
  213. // See if this is the first time we are being called
  214. //
  215. if ( InterlockedIncrement( &g_ulInitCount ) isnot 1 )
  216. {
  217. return NO_ERROR;
  218. }
  219. //
  220. // Connect to router config. Also serves as a check to
  221. // see if the router is configured on the machine
  222. //
  223. dwErr = MprConfigServerConnect( NULL, &g_hMprConfig );
  224. if( dwErr isnot NO_ERROR )
  225. {
  226. DisplayError( NULL, dwErr );
  227. return dwErr;
  228. }
  229. pDllTable->dwVersion = NETSH_VERSION_50;
  230. pDllTable->pfnStopFn = StopHelperDll;
  231. //
  232. // Register helpers
  233. //
  234. ZeroMemory( &attMyAttributes, sizeof(attMyAttributes) );
  235. attMyAttributes.guidHelper = g_MyGuid;
  236. attMyAttributes.dwVersion = IPX_HELPER_VERSION;
  237. attMyAttributes.pfnStart = IpxStartHelper;
  238. attMyAttributes.pfnStop = NULL;
  239. RegisterHelper( &g_RoutingGuid, &attMyAttributes );
  240. return NO_ERROR;
  241. }
  242. DWORD
  243. WINAPI
  244. StopHelperDll(
  245. IN DWORD dwReserved
  246. )
  247. /*++
  248. Routine Description :
  249. Arguements :
  250. Return value :
  251. --*/
  252. {
  253. if ( InterlockedDecrement( &g_ulInitCount ) isnot 0 )
  254. {
  255. return NO_ERROR;
  256. }
  257. #if 0
  258. IpxCommit(NETSH_FLUSH);
  259. #endif
  260. return NO_ERROR;
  261. }
  262. BOOL
  263. WINAPI
  264. IpxDllEntry(
  265. HINSTANCE hInstDll,
  266. DWORD fdwReason,
  267. LPVOID pReserved
  268. )
  269. /*++
  270. Routine Description :
  271. Arguements :
  272. Return value :
  273. --*/
  274. {
  275. switch (fdwReason)
  276. {
  277. case DLL_PROCESS_ATTACH:
  278. {
  279. g_hModule = hInstDll;
  280. DisableThreadLibraryCalls(hInstDll);
  281. break;
  282. }
  283. case DLL_PROCESS_DETACH:
  284. {
  285. break;
  286. }
  287. default:
  288. {
  289. break;
  290. }
  291. }
  292. return TRUE;
  293. }
  294. DWORD
  295. ConnectToRouter(
  296. IN LPCWSTR pwszRouter
  297. )
  298. {
  299. DWORD rc, dwErr;
  300. if (g_pwszRouter != pwszRouter)
  301. {
  302. if (g_hMprConfig)
  303. {
  304. MprConfigServerDisconnect(g_hMprConfig);
  305. g_hMprConfig = NULL;
  306. }
  307. if (g_hMprAdmin)
  308. {
  309. MprAdminServerDisconnect(g_hMprAdmin);
  310. g_hMprAdmin = NULL;
  311. }
  312. if (g_hMIBServer)
  313. {
  314. MprAdminMIBServerDisconnect(g_hMIBServer);
  315. g_hMIBServer = NULL;
  316. }
  317. }
  318. //
  319. // Connect to router config if required
  320. // (when is this ever required)
  321. //
  322. if ( !g_hMprConfig )
  323. {
  324. dwErr = MprConfigServerConnect( (LPWSTR)pwszRouter, &g_hMprConfig );
  325. if ( dwErr isnot NO_ERROR )
  326. {
  327. return ERROR_CONNECT_REMOTE_CONFIG;
  328. }
  329. }
  330. //
  331. // Check to see if router is running. If so, get the handles
  332. //
  333. do
  334. {
  335. if ( MprAdminIsServiceRunning( (LPWSTR)pwszRouter ) )
  336. {
  337. if ( MprAdminServerConnect( (LPWSTR)pwszRouter, &g_hMprAdmin ) ==
  338. NO_ERROR )
  339. {
  340. if ( MprAdminMIBServerConnect( (LPWSTR)pwszRouter, &g_hMIBServer ) ==
  341. NO_ERROR )
  342. {
  343. // DEBUG("Got server handle");
  344. break;
  345. }
  346. else
  347. {
  348. MprAdminServerDisconnect( g_hMprAdmin );
  349. }
  350. }
  351. }
  352. g_hMprAdmin = g_hMIBServer = NULL;
  353. } while (FALSE);
  354. return NO_ERROR;
  355. }
  356. DWORD WINAPI
  357. IpxConnect(
  358. IN LPCWSTR pwszRouter
  359. )
  360. {
  361. // If context info is dirty, reregister it
  362. if (g_bIpxDirty)
  363. {
  364. IpxStartHelper(NULL, ParentVersion);
  365. }
  366. return ConnectToRouter(pwszRouter);
  367. }
  368. BOOL
  369. IsHelpToken(
  370. PWCHAR pwszToken
  371. )
  372. /*++
  373. Routine Description :
  374. Arguements :
  375. Return value :
  376. --*/
  377. {
  378. if( MatchToken( pwszToken, CMD_IPX_HELP1 ) )
  379. {
  380. return TRUE;
  381. }
  382. if( MatchToken( pwszToken, CMD_IPX_HELP2 ) )
  383. {
  384. return TRUE;
  385. }
  386. return FALSE;
  387. }
  388. BOOL
  389. IsReservedKeyWord(
  390. PWCHAR pwszToken
  391. )
  392. /*++
  393. Routine Description :
  394. Arguements :
  395. Return value :
  396. --*/
  397. {
  398. return FALSE;
  399. }
  400. DWORD
  401. MungeArguments(
  402. IN OUT LPWSTR *ppwcArguments,
  403. IN DWORD dwArgCount,
  404. OUT PBYTE *ppbNewArg,
  405. OUT PDWORD pdwNewArgCount,
  406. OUT PBOOL pbFreeArg
  407. )
  408. /*++
  409. Routine Description :
  410. To conform to the routemon style of command line, the netsh command line
  411. is munged. Munging involves adding a space after the '=' for each
  412. "Option=Value" pair on the command line to convert it to "Option= Value".
  413. In addition, the first command line arguement is set to the process name
  414. "netsh" and all the remaining arguements are shifted one down. Again
  415. for conformance reasons.
  416. Arguements :
  417. ppwcArguments - Current argument list
  418. dwArgCount - Number of args in ppwcArguments
  419. pbNewArg - Pointer to a buffer that will contain the munged arglist
  420. pdwNewArgCount - New argument count after munging
  421. pbFreeArg - TRUE if pbNewArg needs to be freed by the invoker.
  422. Return value :
  423. NO_ERROR - Success
  424. ERROR_NOT_ENOUGH_MEMORY - Memory alloc failed
  425. --*/
  426. {
  427. DWORD dwIndex, dwInd, dwErr;
  428. BOOL bPresent = FALSE;
  429. PWCHAR *ppwcArgs;
  430. *pbFreeArg = FALSE;
  431. //
  432. // Scan arguement list to see if any are of the form "Option=Value"
  433. //
  434. for ( dwIndex = 0; dwIndex < dwArgCount; dwIndex++ )
  435. {
  436. if ( wcsstr( ppwcArguments[ dwIndex ], NETSH_ARG_DELIMITER ) )
  437. {
  438. //
  439. // there is an = in this arguement
  440. //
  441. bPresent = TRUE;
  442. break;
  443. }
  444. }
  445. //
  446. // if none of the args have an '=', then return the arg. list as is
  447. //
  448. if ( !bPresent )
  449. {
  450. *ppbNewArg = (PBYTE) ppwcArguments;
  451. return NO_ERROR;
  452. }
  453. //
  454. // Args. of the form "option=value" are present
  455. //
  456. ppwcArgs = (PWCHAR *) HeapAlloc(
  457. GetProcessHeap(), 0, 2 * dwArgCount * sizeof( PWCHAR )
  458. );
  459. if ( ppwcArgs == NULL )
  460. {
  461. return ERROR_NOT_ENOUGH_MEMORY;
  462. }
  463. ZeroMemory( ppwcArgs, 2 * dwArgCount * sizeof( PWCHAR ) );
  464. //
  465. // Copy args that do not have an '=' as is
  466. //
  467. for ( dwInd = 0; dwInd < dwIndex; dwInd++ )
  468. {
  469. DWORD dwLen = ( wcslen( ppwcArguments[ dwInd ] ) + 1 ) * sizeof( WCHAR );
  470. ppwcArgs[ dwInd ] = (PWCHAR) HeapAlloc(
  471. GetProcessHeap(), 0,
  472. ( wcslen( ppwcArguments[ dwInd ] ) + 1 )
  473. * sizeof( WCHAR )
  474. );
  475. if ( ppwcArgs[ dwInd ] == NULL )
  476. {
  477. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  478. goto cleanup;
  479. }
  480. wcscpy( ppwcArgs[ dwInd ], ppwcArguments[ dwInd ] );
  481. }
  482. //
  483. // Convert args. of the form "option=value" to the form "option= value".
  484. // The space is what its all about
  485. //
  486. for ( dwInd = dwIndex; dwIndex < dwArgCount; dwInd++, dwIndex++ )
  487. {
  488. //
  489. // Check if this arg. has an '=' sign
  490. //
  491. if ( wcsstr( ppwcArguments[ dwIndex ], NETSH_ARG_DELIMITER ) )
  492. {
  493. //
  494. // arg is of the form "option=value"
  495. //
  496. // break it into 2 arguments of the form
  497. // arg(i) == option=
  498. // argv(i+1) == value
  499. //
  500. PWCHAR pw1, pw2;
  501. DWORD dwLen;
  502. pw1 = wcstok( ppwcArguments[ dwIndex ], NETSH_ARG_DELIMITER );
  503. pw2 = wcstok( NULL, NETSH_ARG_DELIMITER );
  504. dwLen = ( wcslen( pw1 ) + 2 ) * sizeof( WCHAR );
  505. dwLen = ( wcslen( pw2 ) + 1 ) * sizeof( WCHAR );
  506. ppwcArgs[ dwInd ] = (PWCHAR) HeapAlloc(
  507. GetProcessHeap(), 0,
  508. ( wcslen( pw1 ) + 2 ) * sizeof( WCHAR )
  509. );
  510. ppwcArgs[ dwInd + 1] = (PWCHAR) HeapAlloc(
  511. GetProcessHeap(), 0,
  512. ( wcslen( pw2 ) + 1 ) * sizeof( WCHAR )
  513. );
  514. if ( ( ppwcArgs[ dwInd ] == NULL ) ||
  515. ( ppwcArgs[ dwInd + 1 ] == NULL ) )
  516. {
  517. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  518. goto cleanup;
  519. }
  520. wcscpy( ppwcArgs[ dwInd ], pw1 );
  521. wcscat( ppwcArgs[ dwInd++ ], NETSH_ARG_DELIMITER );
  522. wcscpy( ppwcArgs[ dwInd ], pw2 );
  523. (*pdwNewArgCount)++;
  524. }
  525. else
  526. {
  527. //
  528. // no = in this arg, copy as is
  529. //
  530. ppwcArgs[ dwInd ] = (PWCHAR) HeapAlloc(
  531. GetProcessHeap(), 0,
  532. ( wcslen( ppwcArguments[ dwIndex ] ) + 1 )
  533. * sizeof( WCHAR )
  534. );
  535. if ( ppwcArgs[ dwInd ] == NULL )
  536. {
  537. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  538. goto cleanup;
  539. }
  540. wcscpy( ppwcArgs[ dwInd ], ppwcArguments[ dwIndex ] );
  541. }
  542. }
  543. *pbFreeArg = TRUE;
  544. *ppbNewArg = (PBYTE) ppwcArgs;
  545. return NO_ERROR;
  546. cleanup :
  547. //
  548. // Error. Free all allocations
  549. //
  550. for ( dwInd = 0; dwInd < 2 * dwArgCount; dwInd++ )
  551. {
  552. if ( ppwcArgs[ dwInd ] )
  553. {
  554. HeapFree( GetProcessHeap(), 0, ppwcArgs[ dwInd ] );
  555. }
  556. }
  557. if ( ppwcArgs )
  558. {
  559. HeapFree( GetProcessHeap(), 0, ppwcArgs );
  560. }
  561. return dwErr;
  562. }
  563. VOID
  564. FreeArgTable(
  565. IN DWORD dwArgCount,
  566. IN OUT LPWSTR *ppwcArgs
  567. )
  568. /*++
  569. Routine Description :
  570. Frees the allocations for the argument table
  571. Arguments :
  572. dwArgCount - number of arguments in ppwcArguments
  573. ppwcArgs - Table of arguments
  574. Return Value :
  575. --*/
  576. {
  577. DWORD dwInd;
  578. for ( dwInd = 0; dwInd < 2 * dwArgCount; dwInd++ )
  579. {
  580. if ( ppwcArgs[ dwInd ] )
  581. {
  582. HeapFree( GetProcessHeap(), 0, ppwcArgs[ dwInd ] );
  583. }
  584. }
  585. if ( ppwcArgs )
  586. {
  587. HeapFree( GetProcessHeap(), 0, ppwcArgs );
  588. }
  589. }
  590. DWORD
  591. GetTagToken(
  592. IN HANDLE hModule,
  593. IN OUT LPWSTR *ppwcArguments,
  594. IN DWORD dwCurrentIndex,
  595. IN DWORD dwArgCount,
  596. IN PTAG_TYPE pttTagToken,
  597. IN DWORD dwNumTags,
  598. OUT PDWORD pdwOut
  599. )
  600. /*++
  601. Routine Description:
  602. Identifies each argument based on its tag. It assumes that each argument
  603. has a tag. It also removes tag= from each argument.
  604. Arguments:
  605. ppwcArguments - The argument array. Each argument has tag=value form
  606. dwCurrentIndex - ppwcArguments[dwCurrentIndex] is first arg.
  607. dwArgCount - ppwcArguments[dwArgCount - 1] is last arg.
  608. pttTagToken - Array of tag token ids that are allowed in the args
  609. dwNumTags - Size of pttTagToken
  610. pdwOut - Array identifying the type of each argument.
  611. Return Value:
  612. NO_ERROR, ERROR_INVALID_PARAMETER, ERROR_INVALID_OPTION_TAG
  613. --*/
  614. {
  615. DWORD i,j,len;
  616. PWCHAR pwcTag,pwcTagVal,pwszArg;
  617. BOOL bFound = FALSE;
  618. //
  619. // This function assumes that every argument has a tag
  620. // It goes ahead and removes the tag.
  621. //
  622. for (i = dwCurrentIndex; i < dwArgCount; i++)
  623. {
  624. len = wcslen(ppwcArguments[i]);
  625. if (len is 0)
  626. {
  627. //
  628. // something wrong with arg
  629. //
  630. pdwOut[i] = (DWORD) -1;
  631. continue;
  632. }
  633. pwszArg = HeapAlloc(GetProcessHeap(),0,(len + 1) * sizeof(WCHAR));
  634. if (pwszArg is NULL)
  635. {
  636. DisplayError(g_hModule, ERROR_NOT_ENOUGH_MEMORY);
  637. return ERROR_NOT_ENOUGH_MEMORY;
  638. }
  639. wcscpy(pwszArg, ppwcArguments[i]);
  640. pwcTag = wcstok(pwszArg, NETSH_ARG_DELIMITER);
  641. //
  642. // Got the first part
  643. // Now if next call returns NULL then there was no tag
  644. //
  645. pwcTagVal = wcstok((PWCHAR)NULL, NETSH_ARG_DELIMITER);
  646. if (pwcTagVal is NULL)
  647. {
  648. // DisplayMessage(g_hModule, MSG_IP_TAG_NOT_PRESENT, ppwcArguments[i] );
  649. HeapFree(GetProcessHeap(),0,pwszArg);
  650. return ERROR_INVALID_PARAMETER;
  651. }
  652. //
  653. // Got the tag. Now try to match it
  654. //
  655. bFound = FALSE;
  656. pdwOut[i - dwCurrentIndex] = (DWORD) -1;
  657. for ( j = 0; j < dwNumTags; j++)
  658. {
  659. if (MatchToken(pwcTag, pttTagToken[j].pwszTag))
  660. {
  661. //
  662. // Tag matched
  663. //
  664. bFound = TRUE;
  665. pdwOut[i - dwCurrentIndex] = j;
  666. break;
  667. }
  668. }
  669. if (bFound)
  670. {
  671. //
  672. // Remove tag from the argument
  673. //
  674. wcscpy(ppwcArguments[i], pwcTagVal);
  675. }
  676. else
  677. {
  678. //DisplayMessage(g_hModule, MSG_IP_INVALID_TAG, pwcTag);
  679. HeapFree(GetProcessHeap(),0,pwszArg);
  680. return ERROR_INVALID_OPTION_TAG;
  681. }
  682. HeapFree(GetProcessHeap(),0,pwszArg);
  683. }
  684. return NO_ERROR;
  685. }
  686. DWORD WINAPI
  687. IpxSubEntry(
  688. IN const NS_CONTEXT_ATTRIBUTES *pSubContext,
  689. IN LPCWSTR pwszMachine,
  690. IN OUT LPWSTR *ppwcArguments,
  691. IN DWORD dwArgCount,
  692. IN DWORD dwFlags,
  693. IN PVOID pvData,
  694. OUT LPWSTR pwcNewContext
  695. )
  696. {
  697. DWORD dwErr,
  698. dwNewArgCount = dwArgCount;
  699. PWCHAR *ppwcNewArg = NULL;
  700. BOOL bFreeNewArg;
  701. PNS_PRIV_CONTEXT_ATTRIBUTES pNsPrivContextAttributes = pSubContext->pReserved;
  702. dwErr = MungeArguments( ppwcArguments,
  703. dwArgCount,
  704. (PBYTE*) &ppwcNewArg,
  705. &dwNewArgCount,
  706. &bFreeNewArg );
  707. if (dwErr isnot NO_ERROR )
  708. {
  709. return dwErr;
  710. }
  711. if ( (pNsPrivContextAttributes) && (pNsPrivContextAttributes->pfnEntryFn) )
  712. {
  713. dwErr = (*pNsPrivContextAttributes->pfnEntryFn)( pwszMachine,
  714. ppwcNewArg,
  715. dwNewArgCount,
  716. dwFlags,
  717. g_hMIBServer,
  718. pwcNewContext );
  719. }
  720. else
  721. {
  722. dwErr = GenericMonitor(pSubContext,
  723. pwszMachine,
  724. ppwcNewArg,
  725. dwNewArgCount,
  726. dwFlags,
  727. g_hMIBServer,
  728. pwcNewContext );
  729. }
  730. if ( bFreeNewArg )
  731. {
  732. FreeArgTable( dwArgCount, ppwcNewArg );
  733. }
  734. return dwErr;
  735. }