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.

863 lines
18 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. misc.c
  5. Abstract:
  6. Miscellaneous management functions
  7. Author:
  8. Stefan Solomon 03/13/1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. UCHAR bcastnode[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  14. VOID
  15. SetAdapterBindingInfo(PIPX_ADAPTER_BINDING_INFO abip,
  16. PACB acbp);
  17. VOID
  18. RMCreateLocalRoute(PICB icbp);
  19. VOID
  20. RMDeleteLocalRoute(PICB icbp);
  21. VOID
  22. ExternalBindInterfaceToAdapter(PICB icbp);
  23. VOID
  24. ExternalUnbindInterfaceFromAdapter(ULONG InterfaceIndex);
  25. /*++
  26. Function: GetTocEntry
  27. Descr: Returns a pointer to the specified table of contents entry
  28. in the interface info block.
  29. --*/
  30. PIPX_TOC_ENTRY
  31. GetTocEntry(PIPX_INFO_BLOCK_HEADER InterfaceInfop,
  32. ULONG InfoEntryType)
  33. {
  34. PIPX_TOC_ENTRY tocep;
  35. UINT i;
  36. for(i=0, tocep = InterfaceInfop->TocEntry;
  37. i<InterfaceInfop->TocEntriesCount;
  38. i++, tocep++) {
  39. if(tocep->InfoType == InfoEntryType) {
  40. return tocep;
  41. }
  42. }
  43. return NULL;
  44. }
  45. /*++
  46. Function: GetInfoEntry
  47. Descr: Returns a pointer to the specified info entry in the interface
  48. control block. If more then one entries, returns a pointer to
  49. the first one.
  50. --*/
  51. LPVOID
  52. GetInfoEntry(PIPX_INFO_BLOCK_HEADER InterfaceInfop,
  53. ULONG InfoEntryType)
  54. {
  55. PIPX_TOC_ENTRY tocep;
  56. if(tocep = GetTocEntry(InterfaceInfop, InfoEntryType)) {
  57. return((LPVOID)((PUCHAR)InterfaceInfop + tocep->Offset));
  58. }
  59. else
  60. {
  61. return NULL;
  62. }
  63. }
  64. /*++
  65. Function: UpdateStaticIfEntries
  66. Descr: Compares the entries in the interface info block with the
  67. stored static entries. Deletes the entries not present
  68. in the interface info blolck and adds the new entries
  69. --*/
  70. DWORD
  71. UpdateStaticIfEntries(
  72. PICB icbp,
  73. HANDLE EnumHandle, // handle for the get next enumeration
  74. ULONG StaticEntrySize,
  75. ULONG NewStaticEntriesCount, // number of new static entries
  76. LPVOID NewStaticEntry, // start of the new entries array
  77. ULONG (*GetNextStaticEntry)(HANDLE EnumHandle, LPVOID entry),
  78. ULONG (*DeleteStaticEntry)(ULONG IfIndex, LPVOID entry),
  79. ULONG (*CreateStaticEntry)(PICB icbp, LPVOID entry))
  80. {
  81. PUCHAR EntryIsNew, nsep, OldStaticEntry;
  82. BOOL found;
  83. UINT i;
  84. // delete non-present entries and add the new entries
  85. // array of flags to mark the new entries
  86. if((EntryIsNew = GlobalAlloc(GPTR, NewStaticEntriesCount)) == NULL) {
  87. return 1;
  88. }
  89. memset(EntryIsNew, 1, NewStaticEntriesCount);
  90. if((OldStaticEntry = GlobalAlloc(GPTR, StaticEntrySize)) == NULL) {
  91. GlobalFree(EntryIsNew);
  92. return 1;
  93. }
  94. if(EnumHandle) {
  95. while(!GetNextStaticEntry(EnumHandle, OldStaticEntry))
  96. {
  97. // compare it with each new static static entry until we find a match
  98. found = FALSE;
  99. for(i = 0, nsep = NewStaticEntry;
  100. i<NewStaticEntriesCount;
  101. i++, nsep+= StaticEntrySize) {
  102. if(!memcmp(OldStaticEntry, nsep, StaticEntrySize)) {
  103. // match - set the flags to OLD
  104. EntryIsNew[i] = 0;
  105. found = TRUE;
  106. break;
  107. }
  108. }
  109. if(!found) {
  110. // non present old entry -> delete it
  111. DeleteStaticEntry(icbp->InterfaceIndex, OldStaticEntry);
  112. }
  113. }
  114. }
  115. // all compared and old non-present ones deleted
  116. // now, add all the new ones
  117. for(i=0, nsep = NewStaticEntry;
  118. i<NewStaticEntriesCount;
  119. i++, nsep+= StaticEntrySize) {
  120. if(EntryIsNew[i]) {
  121. CreateStaticEntry(icbp, nsep);
  122. }
  123. }
  124. GlobalFree(EntryIsNew);
  125. return 0;
  126. }
  127. /*++
  128. Function: GetInterfaceAnsiName
  129. Arguments:
  130. AnsiInterfaceNameBuffer - buffer of IPX_INTERFACE_ANSI_NAME_LEN
  131. UnicodeInterfaceNameBuffer -
  132. Descr:
  133. --*/
  134. VOID
  135. GetInterfaceAnsiName(PUCHAR AnsiInterfaceNameBuffer,
  136. PWSTR UnicodeInterfaceNameBuffer)
  137. {
  138. UNICODE_STRING UnicodeInterfaceName;
  139. ANSI_STRING AnsiInterfaceName;
  140. NTSTATUS ntStatus;
  141. // init a unicode string with the interface name string
  142. RtlInitUnicodeString(&UnicodeInterfaceName, UnicodeInterfaceNameBuffer);
  143. // make the interface name unicode string an ansi string
  144. // in an rtl allocated buffer
  145. ntStatus = RtlUnicodeStringToAnsiString(&AnsiInterfaceName,
  146. &UnicodeInterfaceName,
  147. TRUE // allocate the ansi buffer
  148. );
  149. if (ntStatus != STATUS_SUCCESS)
  150. {
  151. return;
  152. }
  153. // copy the interface name into the supplied buffer, up to the
  154. // argument buffer max size
  155. memcpy(AnsiInterfaceNameBuffer,
  156. AnsiInterfaceName.Buffer,
  157. min(AnsiInterfaceName.MaximumLength, IPX_INTERFACE_ANSI_NAME_LEN));
  158. // free the rtl allocated buffer
  159. RtlFreeAnsiString(&AnsiInterfaceName);
  160. }
  161. /*++
  162. Function: BindInterfaceToAdapter
  163. Descr: Binds the interface to the adapter in the router manager and in
  164. all the other modules and creates a local route for the interface
  165. in the RTM
  166. --*/
  167. VOID
  168. BindInterfaceToAdapter(PICB icbp,
  169. PACB acbp)
  170. {
  171. DWORD rc;
  172. Trace(BIND_TRACE, "BindInterfaceToAdapter: Bind interface # %d to adapter # %d",
  173. icbp->InterfaceIndex,
  174. acbp->AdapterIndex);
  175. if(icbp->acbp != NULL)
  176. {
  177. Trace(BIND_TRACE, "BindInterfaceToAdapter: interface # %d already bound !!!",
  178. icbp->InterfaceIndex);
  179. //SS_ASSERT(FALSE);
  180. return;
  181. }
  182. // Make sure that the adapter is not currently claimed by any
  183. // interface either.
  184. //
  185. if ((acbp->icbp) && (acbp->icbp->acbp == acbp))
  186. {
  187. Trace(
  188. BIND_TRACE,
  189. "BindInterfaceToAdapter: adapter # %d already bound to int # %d!!",
  190. acbp->AdapterIndex,
  191. acbp->icbp->InterfaceIndex);
  192. return;
  193. }
  194. // internal bind the adapter control block and the interface control block
  195. icbp->acbp = acbp;
  196. acbp->icbp = icbp;
  197. // if a connection was requested on this if, mark that it has been done
  198. if(icbp->ConnectionRequestPending) {
  199. icbp->ConnectionRequestPending = FALSE;
  200. }
  201. if(!icbp->InterfaceReachable) {
  202. // we should never hit this code path in normal operation
  203. // However, should anybody atempt and succeed a dial (manually?) on an
  204. // interface marked unreachable, we should reset our state
  205. // icbp->InterfaceReachable = TRUE;
  206. if(icbp->AdminState == ADMIN_STATE_ENABLED) {
  207. // enable all static routes for this interface
  208. EnableStaticRoutes(icbp->InterfaceIndex);
  209. // enable external interfaces. Implicitly, this will enable static services
  210. // bound to this interface to be advertised
  211. ExternalEnableInterface(icbp->InterfaceIndex);
  212. }
  213. }
  214. if (icbp->AdminState==ADMIN_STATE_ENABLED) {
  215. icbp->OperState = OPER_STATE_UP;
  216. // create a local route entry in RTM for the connected interface
  217. RMCreateLocalRoute(icbp);
  218. }
  219. ExternalBindInterfaceToAdapter(icbp);
  220. // if the interface is a local client type (i.e. host doing manual dial from
  221. // the local machine, try to update the internal routing table
  222. if(icbp->MIBInterfaceType == IF_TYPE_ROUTER_WORKSTATION_DIALOUT) {
  223. if((rc = RtProtRequestRoutesUpdate(icbp->InterfaceIndex)) == NO_ERROR) {
  224. icbp->UpdateReq.RoutesReqStatus = UPDATE_PENDING;
  225. }
  226. else
  227. {
  228. Trace(UPDATE_TRACE, "BindInterfaceToAdapter: Routing Update is Disabled");
  229. }
  230. if((rc = RtProtRequestServicesUpdate(icbp->InterfaceIndex)) == NO_ERROR) {
  231. icbp->UpdateReq.ServicesReqStatus = UPDATE_PENDING;
  232. }
  233. else
  234. {
  235. Trace(UPDATE_TRACE, "BindInterfaceToAdapter: Services Update is Disabled");
  236. }
  237. }
  238. }
  239. /*++
  240. Function: UnbindInterfaceFromAdapter
  241. Descr: Unbind the Rip, Sap and Forwarder interfaces with this index from
  242. the respective adapter
  243. --*/
  244. VOID
  245. UnbindInterfaceFromAdapter(PICB icbp)
  246. {
  247. PACB acbp;
  248. ULONG new_if_oper_state;
  249. acbp = icbp->acbp;
  250. if (acbp==NULL) {
  251. Trace(BIND_TRACE, "UnbindInterfaceFromAdapter:Interface # %d is not bound to any adapter",
  252. icbp->InterfaceIndex);
  253. return;
  254. }
  255. Trace(BIND_TRACE, "UnbindInterfaceFromAdapter: Unbind interface # %d from adapter # %d",
  256. icbp->InterfaceIndex,
  257. acbp->AdapterIndex);
  258. switch(icbp->MIBInterfaceType) {
  259. case IF_TYPE_PERSONAL_WAN_ROUTER:
  260. case IF_TYPE_WAN_WORKSTATION:
  261. case IF_TYPE_WAN_ROUTER:
  262. case IF_TYPE_ROUTER_WORKSTATION_DIALOUT:
  263. if (icbp->AdminState==ADMIN_STATE_ENABLED) {
  264. icbp->OperState = OPER_STATE_SLEEPING;
  265. break;
  266. }
  267. default:
  268. icbp->OperState = OPER_STATE_DOWN;
  269. break;
  270. }
  271. if (icbp->AdminState==ADMIN_STATE_ENABLED) {
  272. // delete local route and ext unbind
  273. RMDeleteLocalRoute(icbp);
  274. }
  275. ExternalUnbindInterfaceFromAdapter(icbp->InterfaceIndex);
  276. // if there were updates going on they will get cancelled automatically
  277. // by the respective routing protocols.
  278. // We just have to reset the update state in the ICB
  279. ResetUpdateRequest(icbp);
  280. // Now we can unbind the adapter from interface
  281. acbp->icbp = NULL;
  282. icbp->acbp = NULL;
  283. }
  284. /*++
  285. Function: GetNextInterfaceIndex
  286. Descr: Returns the next available interface index. There are a number of
  287. policies to consider here. The one we'll use is to keep the
  288. interface index a small number and to return the first unused
  289. interface index between 1 and MAX_INTERFACE_INDEX.
  290. Note: Called with database locked
  291. --*/
  292. ULONG
  293. GetNextInterfaceIndex(VOID)
  294. {
  295. PICB icbp;
  296. PLIST_ENTRY lep;
  297. ULONG i;
  298. if((icbp = GetInterfaceByIndex(1)) == NULL) {
  299. return 1;
  300. }
  301. lep = icbp->IndexListLinkage.Flink;
  302. i = 2;
  303. while(lep != &IndexIfList)
  304. {
  305. icbp = CONTAINING_RECORD(lep, ICB, IndexListLinkage);
  306. if(i < icbp->InterfaceIndex) {
  307. return i;
  308. }
  309. i = icbp->InterfaceIndex + 1;
  310. if(i == MAX_INTERFACE_INDEX) {
  311. // abort
  312. SS_ASSERT(FALSE);
  313. return i;
  314. }
  315. lep = icbp->IndexListLinkage.Flink;
  316. }
  317. SS_ASSERT(i < MAX_INTERFACE_INDEX);
  318. return i;
  319. }
  320. VOID
  321. SetAdapterBindingInfo(PIPX_ADAPTER_BINDING_INFO abip,
  322. PACB acbp)
  323. {
  324. abip->AdapterIndex = acbp->AdapterIndex;
  325. memcpy(abip->Network, acbp->AdapterInfo.Network, 4);
  326. memcpy(abip->LocalNode, acbp->AdapterInfo.LocalNode, 6);
  327. if(acbp->AdapterInfo.NdisMedium != NdisMediumWan) {
  328. memcpy(abip->RemoteNode, bcastnode, 6);
  329. }
  330. else
  331. {
  332. memcpy(abip->RemoteNode, acbp->AdapterInfo.RemoteNode, 6);
  333. }
  334. abip->MaxPacketSize = acbp->AdapterInfo.MaxPacketSize;
  335. abip->LinkSpeed = acbp->AdapterInfo.LinkSpeed;
  336. }
  337. VOID
  338. ExternalBindInterfaceToAdapter(PICB icbp)
  339. {
  340. PACB acbp;
  341. IPX_ADAPTER_BINDING_INFO abi;
  342. acbp = icbp->acbp;
  343. SetAdapterBindingInfo(&abi, acbp);
  344. FwBindFwInterfaceToAdapter(icbp->InterfaceIndex, &abi);
  345. BindRoutingProtocolsIfsToAdapter(icbp->InterfaceIndex, &abi);
  346. }
  347. VOID
  348. ExternalUnbindInterfaceFromAdapter(ULONG InterfaceIndex)
  349. {
  350. UnbindRoutingProtocolsIfsFromAdapter(InterfaceIndex);
  351. FwUnbindFwInterfaceFromAdapter(InterfaceIndex);
  352. }
  353. VOID
  354. ExternalEnableInterface(ULONG InterfaceIndex)
  355. {
  356. RoutingProtocolsEnableIpxInterface(InterfaceIndex);
  357. FwEnableFwInterface(InterfaceIndex);
  358. }
  359. VOID
  360. ExternalDisableInterface(ULONG InterfaceIndex)
  361. {
  362. FwDisableFwInterface(InterfaceIndex);
  363. RoutingProtocolsDisableIpxInterface(InterfaceIndex);
  364. }
  365. VOID
  366. RMCreateLocalRoute(PICB icbp)
  367. {
  368. PADAPTER_INFO aip;
  369. // check if a network number has been assigned to this interface
  370. aip = &(icbp->acbp->AdapterInfo);
  371. if(!memcmp(aip->Network, nullnet, 4)) {
  372. // no net number
  373. return;
  374. }
  375. // if the interface is a remote workstation and global wan net exists,
  376. // we are done.
  377. if((icbp->MIBInterfaceType == IF_TYPE_WAN_WORKSTATION) &&
  378. EnableGlobalWanNet &&
  379. !LanOnlyMode) {
  380. SS_ASSERT(!memcmp(aip->Network, GlobalWanNet, 4));
  381. return;
  382. }
  383. CreateLocalRoute(icbp);
  384. }
  385. VOID
  386. RMDeleteLocalRoute(PICB icbp)
  387. {
  388. PADAPTER_INFO aip;
  389. // check if a network number has been assigned to this interface
  390. aip = &(icbp->acbp->AdapterInfo);
  391. if(!memcmp(aip->Network, nullnet, 4)) {
  392. // no net number
  393. return;
  394. }
  395. // if the interface is a remote workstation and global wan net exists,
  396. // we are done.
  397. if((icbp->MIBInterfaceType == IF_TYPE_WAN_WORKSTATION) &&
  398. EnableGlobalWanNet &&
  399. !LanOnlyMode) {
  400. SS_ASSERT(!memcmp(aip->Network, GlobalWanNet, 4));
  401. return;
  402. }
  403. DeleteLocalRoute(icbp);
  404. }
  405. VOID
  406. AdminEnable(PICB icbp)
  407. {
  408. PACB acbp;
  409. IPX_ADAPTER_BINDING_INFO aii;
  410. if(icbp->AdminState == ADMIN_STATE_ENABLED) {
  411. return;
  412. }
  413. icbp->AdminState = ADMIN_STATE_ENABLED;
  414. InterfaceEnabled (icbp->hDIMInterface, PID_IPX, TRUE);
  415. if(icbp->acbp != NULL) {
  416. // bound to adapter
  417. icbp->OperState = OPER_STATE_UP;
  418. RMCreateLocalRoute(icbp);
  419. }
  420. else {
  421. switch(icbp->MIBInterfaceType) {
  422. case IF_TYPE_PERSONAL_WAN_ROUTER:
  423. case IF_TYPE_WAN_WORKSTATION:
  424. case IF_TYPE_WAN_ROUTER:
  425. case IF_TYPE_ROUTER_WORKSTATION_DIALOUT:
  426. icbp->OperState = OPER_STATE_SLEEPING;
  427. break;
  428. default:
  429. icbp->OperState = OPER_STATE_DOWN;
  430. break;
  431. }
  432. }
  433. // if REACHABLE, resume advertising routes and services
  434. if(icbp->InterfaceReachable) {
  435. // enable all static routes for this interface
  436. EnableStaticRoutes(icbp->InterfaceIndex);
  437. // enable external interfaces. Implicitly, this will enable static services
  438. // bound to this interface to be advertised
  439. ExternalEnableInterface(icbp->InterfaceIndex);
  440. }
  441. }
  442. VOID
  443. AdminDisable(PICB icbp)
  444. {
  445. if(icbp->AdminState == ADMIN_STATE_DISABLED) {
  446. return;
  447. }
  448. icbp->AdminState = ADMIN_STATE_DISABLED;
  449. InterfaceEnabled (icbp->hDIMInterface, PID_IPX, FALSE);
  450. icbp->OperState = OPER_STATE_DOWN;
  451. if(icbp->acbp != NULL)
  452. RMDeleteLocalRoute(icbp);
  453. // disable all static routes for this interface
  454. DisableStaticRoutes(icbp->InterfaceIndex);
  455. // disable external interfaces. Implicitly, static services bound to this
  456. // interface will stop being advertised.
  457. ExternalDisableInterface(icbp->InterfaceIndex);
  458. }
  459. NET_INTERFACE_TYPE
  460. MapIpxToNetInterfaceType(PICB icbp)
  461. {
  462. NET_INTERFACE_TYPE NetInterfaceType;
  463. switch(icbp->MIBInterfaceType) {
  464. case IF_TYPE_WAN_ROUTER:
  465. case IF_TYPE_PERSONAL_WAN_ROUTER:
  466. NetInterfaceType = DEMAND_DIAL;
  467. break;
  468. case IF_TYPE_ROUTER_WORKSTATION_DIALOUT:
  469. NetInterfaceType = LOCAL_WORKSTATION_DIAL;
  470. break;
  471. case IF_TYPE_WAN_WORKSTATION:
  472. NetInterfaceType = REMOTE_WORKSTATION_DIAL;
  473. break;
  474. default:
  475. NetInterfaceType = PERMANENT;
  476. break;
  477. }
  478. return NetInterfaceType;
  479. }
  480. /*++
  481. Function: I_SetFilters
  482. Descr: Internal parses the traffic filter info block and sets the filter
  483. driver info.
  484. --*/
  485. /*
  486. DWORD
  487. I_SetFilters(ULONG InterfaceIndex,
  488. ULONG FilterMode, // inbound or outbound
  489. LPVOID FilterInfop)
  490. {
  491. PIPX_TRAFFIC_FILTER_GLOBAL_INFO gip;
  492. PIPX_TOC_ENTRY tocep;
  493. LPVOID FilterDriverInfop;
  494. ULONG FilterDriverInfoSize;
  495. DWORD rc;
  496. if(FilterInfop == NULL) {
  497. // remove all filters
  498. rc = SetFilters(InterfaceIndex,
  499. FilterMode, // in or outbound,
  500. 0,
  501. 0,
  502. NULL,
  503. 0);
  504. return rc;
  505. }
  506. gip = GetInfoEntry((PIPX_INFO_BLOCK_HEADER)FilterInfop,
  507. IPX_TRAFFIC_FILTER_GLOBAL_INFO_TYPE);
  508. if(gip == NULL) {
  509. return ERROR_CAN_NOT_COMPLETE;
  510. }
  511. FilterDriverInfop = GetInfoEntry((PIPX_INFO_BLOCK_HEADER)FilterInfop,
  512. IPX_TRAFFIC_FILTER_INFO_TYPE);
  513. if(FilterDriverInfop == NULL) {
  514. rc = SetFilters(InterfaceIndex,
  515. FilterMode, // in or outbound,
  516. 0, // pass or don't pass
  517. 0, // filter size
  518. NULL,
  519. 0);
  520. return rc;
  521. }
  522. tocep = GetTocEntry((PIPX_INFO_BLOCK_HEADER)FilterInfop,
  523. IPX_TRAFFIC_FILTER_INFO_TYPE);
  524. FilterDriverInfoSize = tocep->Count * tocep->InfoSize;
  525. rc = SetFilters(InterfaceIndex,
  526. FilterMode, // in or outbound,
  527. gip->FilterAction, // pass or don't pass
  528. tocep->InfoSize, // filter size
  529. FilterDriverInfop,
  530. FilterDriverInfoSize);
  531. return rc;
  532. }
  533. */
  534. /*++
  535. Function: I_GetFilters
  536. Descr: Internal builds the traffic filters info block from the filter driver
  537. information.
  538. --*/
  539. /*
  540. typedef struct _FILTERS_INFO_HEADER {
  541. IPX_INFO_BLOCK_HEADER Header;
  542. IPX_TOC_ENTRY TocEntry;
  543. IPX_TRAFFIC_FILTER_GLOBAL_INFO GlobalInfo;
  544. } FILTERS_INFO_HEADER, *PFILTERS_INFO_HEADER;
  545. DWORD
  546. I_GetFilters(ULONG InterfaceIndex,
  547. ULONG FilterMode,
  548. LPVOID FilterInfop,
  549. PULONG FilterInfoSize)
  550. {
  551. DWORD rc;
  552. ULONG FilterAction;
  553. ULONG FilterSize;
  554. PFILTERS_INFO_HEADER fhp;
  555. LPVOID FilterDriverInfop;
  556. ULONG FilterDriverInfoSize = 0;
  557. PIPX_TOC_ENTRY tocep;
  558. if((FilterInfop == NULL) || (*FilterInfoSize == 0)) {
  559. // we are asked for size
  560. rc = GetFilters(InterfaceIndex,
  561. FilterMode,
  562. &FilterAction,
  563. &FilterSize,
  564. NULL,
  565. &FilterDriverInfoSize);
  566. if((rc != NO_ERROR) && (rc != ERROR_INSUFFICIENT_BUFFER)) {
  567. return ERROR_CAN_NOT_COMPLETE;
  568. }
  569. if(FilterDriverInfoSize) {
  570. // there are filters
  571. *FilterInfoSize = sizeof(FILTERS_INFO_HEADER) + FilterDriverInfoSize;
  572. return ERROR_INSUFFICIENT_BUFFER;
  573. }
  574. else
  575. {
  576. // NO filters exist
  577. *FilterInfoSize = 0;
  578. return NO_ERROR;
  579. }
  580. }
  581. if(*FilterInfoSize <= sizeof(FILTERS_INFO_HEADER)) {
  582. return ERROR_INSUFFICIENT_BUFFER;
  583. }
  584. FilterDriverInfoSize = *FilterInfoSize - sizeof(FILTERS_INFO_HEADER);
  585. FilterDriverInfop = (LPVOID)((PUCHAR)FilterInfop + sizeof(FILTERS_INFO_HEADER));
  586. rc = GetFilters(InterfaceIndex,
  587. FilterMode,
  588. &FilterAction,
  589. &FilterSize,
  590. FilterDriverInfop,
  591. &FilterDriverInfoSize);
  592. if(rc != NO_ERROR) {
  593. if(rc == ERROR_MORE_DATA) {
  594. *FilterInfoSize = sizeof(FILTERS_INFO_HEADER) + FilterDriverInfoSize;
  595. return ERROR_INSUFFICIENT_BUFFER;
  596. }
  597. else
  598. {
  599. return ERROR_CAN_NOT_COMPLETE;
  600. }
  601. }
  602. // got it
  603. fhp = (PFILTERS_INFO_HEADER)FilterInfop;
  604. fhp->Header.Version = IPX_ROUTER_VERSION_1;
  605. fhp->Header.Size = *FilterInfoSize;
  606. fhp->Header.TocEntriesCount = 2;
  607. tocep = fhp->Header.TocEntry;
  608. tocep->InfoType = IPX_TRAFFIC_FILTER_GLOBAL_INFO_TYPE;
  609. tocep->InfoSize = sizeof(IPX_TRAFFIC_FILTER_GLOBAL_INFO);
  610. tocep->Count = 1;
  611. tocep->Offset = (ULONG)((PUCHAR)&(fhp->GlobalInfo) - (PUCHAR)FilterInfop);
  612. tocep++;
  613. tocep->InfoType = IPX_TRAFFIC_FILTER_INFO_TYPE;
  614. tocep->InfoSize = FilterSize;
  615. tocep->Count = FilterDriverInfoSize / FilterSize;
  616. tocep->Offset = sizeof(FILTERS_INFO_HEADER);
  617. fhp->GlobalInfo.FilterAction = FilterAction;
  618. return NO_ERROR;
  619. }
  620. */