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.

2530 lines
60 KiB

  1. /*++
  2. Copyright (c) 1996-1997 Microsoft Corporation
  3. Module Name:
  4. apiutil.c
  5. Abstract:
  6. This module contains the traffic control api utils
  7. Author:
  8. Jim Stewart ( jstew ) August 22, 1996
  9. Revision History:
  10. Ofer Bar (oferbar) Oct 1, 1997
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include <initguid.h>
  15. #define INITGUID
  16. #include "ntddtc.h"
  17. static BOOLEAN _init = FALSE;
  18. #if 0
  19. // Name of the DLL to load
  20. const CHAR IpHlpApiDllName[] = "iphlpapi";
  21. // Names of the functions called in IPHLPAPI
  22. const CHAR GET_IF_ENTRY[] = "GetIfEntry";
  23. const CHAR GET_IP_ADDR_TABLE[] = "GetIpAddrTable";
  24. const CHAR GET_BEST_ROUTE[] = "GetBestRoute";
  25. IPROUTE_IF IpRouteTab;
  26. #endif
  27. TCHAR SzBuf[MAX_PATH];
  28. //
  29. VOID
  30. MarkAllNodesForClosing(
  31. PINTERFACE_STRUC pInterface,
  32. STATE stateToMark
  33. )
  34. /*++
  35. Description:
  36. This routine will mark all flows and filters on a INTERFACE_STRUC (a client's interface struct)
  37. as close FORCED_KERNELCLOSE or EXIT_CLEANUP. Please note that it is already called with the global lock held.
  38. Arguments:
  39. pInterface - ptr to the interface
  40. stateToMark - the state to mark the nodes (FORCED_KERNELCLOSE or EXIT_CLEANUP)
  41. Return Value:
  42. nothing
  43. --*/
  44. {
  45. PLIST_ENTRY pEntry, pFilterEntry;
  46. PFLOW_STRUC pFlow;
  47. PFILTER_STRUC pFilter;
  48. ASSERT((stateToMark == FORCED_KERNELCLOSE) || (stateToMark == EXIT_CLEANUP));
  49. pEntry = pInterface->FlowList.Flink;
  50. while (pEntry != &pInterface->FlowList) {
  51. pFlow = CONTAINING_RECORD(pEntry, FLOW_STRUC, Linkage);
  52. //
  53. // For each flow and filter, first check if the user is trying to close it
  54. // if that is the case, do nothing, otherwise, mark it
  55. GetLock(pFlow->Lock);
  56. if (QUERY_STATE(pFlow->State) == OPEN) {
  57. // Cleanup from under teh user...
  58. SET_STATE(pFlow->State, stateToMark);
  59. } else {
  60. ASSERT(IsListEmpty(&pFlow->FilterList));
  61. // There's nothing to be done here.
  62. IF_DEBUG(WARNINGS) {
  63. WSPRINT(("Against a forced close - Flow is removed by the user\n", pFlow));
  64. }
  65. }
  66. pFilterEntry = pFlow->FilterList.Flink;
  67. while (pFilterEntry != &pFlow->FilterList) {
  68. pFilter = CONTAINING_RECORD(pFilterEntry, FILTER_STRUC, Linkage);
  69. GetLock(pFilter->Lock);
  70. if (QUERY_STATE(pFilter->State) == OPEN) {
  71. // Cleanup from under teh user...
  72. SET_STATE(pFilter->State, stateToMark);
  73. } else {
  74. // There's nothing to be done here.
  75. IF_DEBUG(WARNINGS) {
  76. WSPRINT(("Against a forced close - Filter is removed by the user\n", pFilter));
  77. }
  78. }
  79. pFilterEntry = pFilterEntry->Flink;
  80. FreeLock(pFilter->Lock);
  81. }
  82. pEntry = pEntry->Flink;
  83. FreeLock(pFlow->Lock);
  84. }
  85. }
  86. VOID
  87. CloseOpenFlows(
  88. IN PINTERFACE_STRUC pInterface
  89. )
  90. /*++
  91. Description:
  92. This routine closes any flows that are open on an interface.
  93. Arguments:
  94. pInterface - ptr to the interface
  95. Return Value:
  96. nothing
  97. --*/
  98. {
  99. DWORD Status = NO_ERROR;
  100. PLIST_ENTRY pEntry;
  101. PFLOW_STRUC pFlow;
  102. GetLock( pGlobals->Lock );
  103. pEntry = pInterface->FlowList.Flink;
  104. while (pEntry != &pInterface->FlowList) {
  105. pFlow = CONTAINING_RECORD( pEntry, FLOW_STRUC, Linkage );
  106. GetLock(pFlow->Lock);
  107. if ((QUERY_STATE(pFlow->State) == FORCED_KERNELCLOSE) ||
  108. (QUERY_STATE(pFlow->State) == EXIT_CLEANUP)) {
  109. pEntry = pEntry->Flink;
  110. FreeLock(pFlow->Lock);
  111. IF_DEBUG(SHUTDOWN) {
  112. WSPRINT(( "Closing Flow: 0x%X\n", pFlow));
  113. }
  114. Status = DeleteFlow( pFlow, TRUE );
  115. IF_DEBUG(SHUTDOWN) {
  116. WSPRINT(("CloseOpenFlows: DeleteFlow returned=0x%X\n",
  117. Status));
  118. }
  119. } else {
  120. pEntry = pEntry->Flink;
  121. FreeLock(pFlow->Lock);
  122. }
  123. }
  124. FreeLock( pGlobals->Lock );
  125. }
  126. VOID
  127. CloseOpenFilters(
  128. IN PFLOW_STRUC pFlow
  129. )
  130. /*++
  131. Description:
  132. This routine closes any filters that are open on a flow.
  133. Arguments:
  134. pFlow - ptr to the flow
  135. Return Value:
  136. nothing
  137. --*/
  138. {
  139. DWORD Status = NO_ERROR;
  140. PLIST_ENTRY pEntry;
  141. PFILTER_STRUC pFilter;
  142. IF_DEBUG(SHUTDOWN) {
  143. WSPRINT(( "CloseOpenFilters: Closing all Open Filters\n" ));
  144. }
  145. GetLock( pGlobals->Lock );
  146. pEntry = pFlow->FilterList.Flink;
  147. while (pEntry != &pFlow->FilterList) {
  148. pFilter = CONTAINING_RECORD( pEntry, FILTER_STRUC, Linkage );
  149. GetLock(pFilter->Lock);
  150. if ((QUERY_STATE(pFilter->State) == FORCED_KERNELCLOSE) ||
  151. (QUERY_STATE(pFilter->State) == EXIT_CLEANUP)) {
  152. // we can take a ref here, but we own it anyways!
  153. pEntry = pEntry->Flink;
  154. FreeLock(pFilter->Lock);
  155. Status = DeleteFilter( pFilter );
  156. IF_DEBUG(SHUTDOWN) {
  157. WSPRINT(( "CloseOpenFilters: DeleteFilter returned=0x%X\n",
  158. Status));
  159. }
  160. //ASSERT(Status == NO_ERROR);
  161. } else {
  162. pEntry = pEntry->Flink;
  163. FreeLock(pFilter->Lock);
  164. IF_DEBUG(SHUTDOWN) {
  165. WSPRINT(( "CloseOpenFilters: DeleteFilter (%x) was skipped because its state (%d)\n",
  166. pFilter, pFilter->State));
  167. }
  168. }
  169. }
  170. FreeLock( pGlobals->Lock );
  171. }
  172. VOID
  173. DeleteFlowStruc(
  174. IN PFLOW_STRUC pFlow
  175. )
  176. /*++
  177. Description:
  178. This routine frees the handle and memory associated
  179. with the structure.
  180. Arguments:
  181. pFlow - ptr to the flow
  182. Return Value:
  183. nothing
  184. --*/
  185. {
  186. if(pFlow->PendingEvent)
  187. CloseHandle(pFlow->PendingEvent);
  188. DeleteLock(pFlow->Lock);
  189. if (pFlow->pGenFlow) {
  190. FreeMem(pFlow->pGenFlow);
  191. pFlow->GenFlowLen = 0;
  192. }
  193. if (pFlow->pGenFlow1) {
  194. FreeMem(pFlow->pGenFlow1);
  195. pFlow->GenFlowLen1 = 0;
  196. }
  197. if (pFlow->pClassMapFlow)
  198. FreeMem(pFlow->pClassMapFlow);
  199. if (pFlow->pClassMapFlow1)
  200. FreeMem(pFlow->pClassMapFlow1);
  201. FreeMem(pFlow);
  202. }
  203. VOID
  204. DeleteFilterStruc(
  205. IN PFILTER_STRUC pFilter
  206. )
  207. /*++
  208. Description:
  209. This routine frees the handle and memory associated
  210. with the structure.
  211. Arguments:
  212. pFIlter
  213. Return Value:
  214. nothing
  215. --*/
  216. {
  217. if (pFilter->pGpcFilter)
  218. FreeMem(pFilter->pGpcFilter);
  219. DeleteLock(pFilter->Lock);
  220. FreeMem(pFilter);
  221. }
  222. PTC_IFC
  223. GetTcIfc(
  224. IN LPWSTR pInterfaceName
  225. )
  226. {
  227. PTC_IFC pIfc = NULL;
  228. PLIST_ENTRY pHead, pEntry;
  229. DWORD Status = NO_ERROR;
  230. GetLock(pGlobals->Lock);
  231. pHead = &pGlobals->TcIfcList;
  232. pEntry = pHead->Flink;
  233. while (pEntry != pHead && pIfc == NULL) {
  234. pIfc = CONTAINING_RECORD(pEntry, TC_IFC, Linkage);
  235. __try {
  236. if (wcsncmp(pInterfaceName,
  237. pIfc->InstanceName,
  238. wcslen(pIfc->InstanceName)) != 0) {
  239. //
  240. // not found
  241. //
  242. pIfc = NULL;
  243. }
  244. } __except (EXCEPTION_EXECUTE_HANDLER) {
  245. Status = GetExceptionCode();
  246. IF_DEBUG(ERRORS) {
  247. WSPRINT(("GetTcIfc: Invalid pInterfaceName(%x) Exception: = 0x%X\n",
  248. pInterfaceName, Status ));
  249. }
  250. FreeLock(pGlobals->Lock);
  251. return NULL;
  252. }
  253. pEntry = pEntry->Flink;
  254. }
  255. FreeLock(pGlobals->Lock);
  256. return pIfc;
  257. }
  258. PTC_IFC
  259. GetTcIfcWithRef(
  260. IN LPWSTR pInterfaceName,
  261. IN ULONG RefType
  262. )
  263. {
  264. PTC_IFC pIfc = NULL;
  265. PLIST_ENTRY pHead, pEntry;
  266. DWORD Status = NO_ERROR;
  267. GetLock(pGlobals->Lock);
  268. pHead = &pGlobals->TcIfcList;
  269. pEntry = pHead->Flink;
  270. while (pEntry != pHead && pIfc == NULL) {
  271. pIfc = CONTAINING_RECORD(pEntry, TC_IFC, Linkage);
  272. __try {
  273. if (wcsncmp(pInterfaceName,
  274. pIfc->InstanceName,
  275. wcslen(pIfc->InstanceName)) != 0) {
  276. //
  277. // not found
  278. //
  279. pIfc = NULL;
  280. }
  281. } __except (EXCEPTION_EXECUTE_HANDLER) {
  282. Status = GetExceptionCode();
  283. IF_DEBUG(ERRORS) {
  284. WSPRINT(("GetTcIfc: Invalid pInterfaceName(%x) Exception: = 0x%X\n",
  285. pInterfaceName, Status ));
  286. }
  287. FreeLock(pGlobals->Lock);
  288. return NULL;
  289. }
  290. pEntry = pEntry->Flink;
  291. }
  292. if (pIfc) {
  293. GetLock(pIfc->Lock);
  294. if (QUERY_STATE(pIfc->State)== OPEN) {
  295. FreeLock(pIfc->Lock);
  296. REFADD(&pIfc->RefCount, RefType);
  297. FreeLock(pGlobals->Lock);
  298. return pIfc;
  299. } else {
  300. FreeLock(pIfc->Lock);
  301. FreeLock(pGlobals->Lock);
  302. return NULL;
  303. }
  304. } else {
  305. FreeLock(pGlobals->Lock);
  306. return NULL;
  307. }
  308. }
  309. DWORD
  310. UpdateTcIfcList(
  311. IN LPWSTR InstanceName,
  312. IN ULONG IndicationBufferSize,
  313. IN PTC_INDICATION_BUFFER IndicationBuffer,
  314. IN DWORD IndicationCode
  315. )
  316. {
  317. DWORD Status = NO_ERROR;
  318. PTC_IFC pTcIfc;
  319. ULONG l;
  320. PADDRESS_LIST_DESCRIPTOR pAddrListDesc;
  321. switch (IndicationCode) {
  322. case TC_NOTIFY_IFC_UP:
  323. //
  324. // Allocate a new interface descriptor structure
  325. //
  326. l = IndicationBufferSize
  327. - FIELD_OFFSET(TC_INDICATION_BUFFER,InfoBuffer) - FIELD_OFFSET(TC_SUPPORTED_INFO_BUFFER, AddrListDesc);
  328. CreateKernelInterfaceStruc(&pTcIfc, l);
  329. if (pTcIfc) {
  330. //
  331. // copy the instance name string data
  332. //
  333. wcscpy(pTcIfc->InstanceName, InstanceName);
  334. pTcIfc->InstanceNameLength = wcslen(InstanceName) * sizeof(WCHAR);
  335. //
  336. // copy the instance ID string data
  337. //
  338. pTcIfc->InstanceIDLength = IndicationBuffer->InfoBuffer.InstanceIDLength;
  339. memcpy((PVOID)pTcIfc->InstanceID,
  340. (PVOID)IndicationBuffer->InfoBuffer.InstanceID,
  341. pTcIfc->InstanceIDLength);
  342. pTcIfc->InstanceID[pTcIfc->InstanceIDLength/sizeof(WCHAR)] = L'\0';
  343. //
  344. // copy the instance data
  345. // in this case - the network address
  346. //
  347. pTcIfc->AddrListBytesCount = l;
  348. RtlCopyMemory( pTcIfc->pAddressListDesc,
  349. &IndicationBuffer->InfoBuffer.AddrListDesc,
  350. l );
  351. if (NO_ERROR != GetInterfaceIndex(pTcIfc->pAddressListDesc,
  352. &pTcIfc->InterfaceIndex,
  353. &pTcIfc->SpecificLinkCtx)) {
  354. pTcIfc->InterfaceIndex = IF_UNKNOWN;
  355. pTcIfc->SpecificLinkCtx = IF_UNKNOWN;
  356. }
  357. //
  358. //
  359. // Add the structure to the global linked list
  360. //
  361. GetLock(pTcIfc->Lock);
  362. SET_STATE(pTcIfc->State, OPEN);
  363. FreeLock(pTcIfc->Lock);
  364. GetLock( pGlobals->Lock );
  365. InsertTailList(&pGlobals->TcIfcList, &pTcIfc->Linkage );
  366. FreeLock( pGlobals->Lock );
  367. #if 0
  368. //
  369. // there's a new TC inetrface, check the GPC client list
  370. //
  371. OpenGpcClients(pTcIfc);
  372. #endif
  373. } else {
  374. Status = ERROR_NOT_ENOUGH_MEMORY;
  375. }
  376. break;
  377. case TC_NOTIFY_IFC_CLOSE:
  378. pTcIfc = GetTcIfc(InstanceName);
  379. REFDEL(&pTcIfc->RefCount, 'KIFC');
  380. break;
  381. case TC_NOTIFY_IFC_CHANGE:
  382. pTcIfc = GetTcIfc(InstanceName);
  383. if (pTcIfc == NULL) {
  384. return Status;
  385. }
  386. //
  387. // copy the instance ID string data
  388. //
  389. pTcIfc->InstanceIDLength = IndicationBuffer->InfoBuffer.InstanceIDLength;
  390. memcpy(pTcIfc->InstanceID,
  391. IndicationBuffer->InfoBuffer.InstanceID,
  392. pTcIfc->InstanceIDLength);
  393. pTcIfc->InstanceID[pTcIfc->InstanceIDLength/sizeof(WCHAR)] = L'\0';
  394. l = IndicationBufferSize
  395. - FIELD_OFFSET(TC_INDICATION_BUFFER,InfoBuffer) - FIELD_OFFSET(TC_SUPPORTED_INFO_BUFFER, AddrListDesc);
  396. AllocMem(&pAddrListDesc, l);
  397. if (pAddrListDesc) {
  398. //
  399. // copy the instance data
  400. // in this case - the network address
  401. //
  402. RtlCopyMemory( pAddrListDesc,
  403. &IndicationBuffer->InfoBuffer.AddrListDesc,
  404. l );
  405. GetLock( pGlobals->Lock );
  406. FreeMem(pTcIfc->pAddressListDesc);
  407. pTcIfc->AddrListBytesCount = l;
  408. pTcIfc->pAddressListDesc = pAddrListDesc;
  409. if (NO_ERROR != GetInterfaceIndex(pTcIfc->pAddressListDesc,
  410. &pTcIfc->InterfaceIndex,
  411. &pTcIfc->SpecificLinkCtx)) {
  412. pTcIfc->InterfaceIndex = IF_UNKNOWN;
  413. pTcIfc->SpecificLinkCtx = IF_UNKNOWN;
  414. }
  415. FreeLock( pGlobals->Lock );
  416. #if 0
  417. //
  418. // there's a new addr list, check the GPC client list
  419. //
  420. OpenGpcClients(pTcIfc);
  421. #endif
  422. } else {
  423. Status = ERROR_NOT_ENOUGH_MEMORY;
  424. }
  425. break;
  426. default:
  427. ASSERT(0);
  428. }
  429. return Status;
  430. }
  431. DWORD
  432. CreateClientStruc(
  433. IN HANDLE ClRegCtx,
  434. OUT PCLIENT_STRUC *ppClient
  435. )
  436. {
  437. PCLIENT_STRUC pClient;
  438. DWORD Status = NO_ERROR;
  439. AllocMem(&pClient, sizeof(CLIENT_STRUC));
  440. if (pClient != NULL) {
  441. RtlZeroMemory(pClient, sizeof(CLIENT_STRUC));
  442. //
  443. // acquire a new handle for the client
  444. //
  445. pClient->ClHandle = AllocateHandle((PVOID)pClient);
  446. //
  447. // set the other parameters in the client interface
  448. //
  449. pClient->ObjectType = ENUM_CLIENT_TYPE;
  450. pClient->ClRegCtx = ClRegCtx;
  451. InitializeListHead(&pClient->InterfaceList);
  452. ReferenceInit(&pClient->RefCount, pClient, DereferenceClient);
  453. REFADD(&pClient->RefCount, 'CLNT');
  454. __try {
  455. InitLock(pClient->Lock);
  456. } __except (EXCEPTION_EXECUTE_HANDLER) {
  457. Status = GetExceptionCode();
  458. IF_DEBUG(ERRORS) {
  459. WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status ));
  460. }
  461. FreeMem(pClient);
  462. return Status;
  463. }
  464. SET_STATE(pClient->State, INSTALLING);
  465. } else {
  466. Status = ERROR_NOT_ENOUGH_MEMORY;
  467. }
  468. *ppClient = pClient;
  469. return Status;
  470. }
  471. DWORD
  472. CreateClInterfaceStruc(
  473. IN HANDLE ClIfcCtx,
  474. OUT PINTERFACE_STRUC *ppClIfc
  475. )
  476. {
  477. PINTERFACE_STRUC pClIfc;
  478. DWORD Status = NO_ERROR;
  479. AllocMem(&pClIfc, sizeof(INTERFACE_STRUC));
  480. if (pClIfc != NULL) {
  481. RtlZeroMemory(pClIfc, sizeof(INTERFACE_STRUC));
  482. if ((pClIfc->IfcEvent = CreateEvent( NULL, // pointer to security attributes
  483. TRUE, // flag for manual-reset event
  484. FALSE, // flag for initial state
  485. NULL // pointer to event-object name);
  486. )) == NULL) {
  487. Status = GetLastError();
  488. IF_DEBUG(ERRORS) {
  489. WSPRINT(( "Error Creating Event for Interface: 0x%X:%d\n", pClIfc, Status));
  490. }
  491. FreeMem(pClIfc);
  492. return Status;
  493. }
  494. //
  495. // acquire a new handle for the client
  496. //
  497. GetLock(pGlobals->Lock);
  498. pClIfc->ClHandle = AllocateHandle((PVOID)pClIfc);
  499. FreeLock(pGlobals->Lock);
  500. //
  501. // set the other parameters in the client interface
  502. //
  503. pClIfc->ObjectType = ENUM_INTERFACE_TYPE;
  504. pClIfc->ClIfcCtx = ClIfcCtx;
  505. pClIfc->CallbackThreadId = 0;
  506. ReferenceInit(&pClIfc->RefCount, pClIfc, DereferenceInterface);
  507. REFADD(&pClIfc->RefCount, 'CIFC');
  508. InitializeListHead(&pClIfc->FlowList);
  509. __try {
  510. InitLock(pClIfc->Lock);
  511. } __except (EXCEPTION_EXECUTE_HANDLER) {
  512. Status = GetExceptionCode();
  513. IF_DEBUG(ERRORS) {
  514. WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status ));
  515. }
  516. FreeMem(pClIfc);
  517. return Status;
  518. }
  519. SET_STATE(pClIfc->State, INSTALLING);
  520. pClIfc->Flags = 0; // reset flags
  521. } else {
  522. Status = ERROR_NOT_ENOUGH_MEMORY;
  523. }
  524. *ppClIfc = pClIfc;
  525. return Status;
  526. }
  527. DWORD
  528. CreateKernelInterfaceStruc(
  529. OUT PTC_IFC *ppTcIfc,
  530. IN DWORD AddressLength
  531. )
  532. {
  533. PTC_IFC pTcIfc;
  534. DWORD Status = NO_ERROR;
  535. IF_DEBUG(CALLS) {
  536. WSPRINT(("==> CreateKernelInterfaceStruc: AddressLength %d\n", AddressLength));
  537. }
  538. *ppTcIfc = NULL;
  539. AllocMem(&pTcIfc, sizeof(TC_IFC));
  540. if (pTcIfc) {
  541. RtlZeroMemory(pTcIfc, sizeof(TC_IFC));
  542. AllocMem(&pTcIfc->pAddressListDesc, AddressLength);
  543. if (pTcIfc->pAddressListDesc) {
  544. RtlZeroMemory(pTcIfc->pAddressListDesc, AddressLength);
  545. //
  546. // initialize the new structure
  547. //
  548. ReferenceInit(&pTcIfc->RefCount, pTcIfc, DereferenceKernelInterface);
  549. REFADD(&pTcIfc->RefCount, 'KIFC');
  550. SET_STATE(pTcIfc->State, INSTALLING);
  551. __try {
  552. InitLock(pTcIfc->Lock);
  553. } __except (EXCEPTION_EXECUTE_HANDLER) {
  554. Status = GetExceptionCode();
  555. IF_DEBUG(ERRORS) {
  556. WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status ));
  557. }
  558. FreeMem(pTcIfc->pAddressListDesc);
  559. FreeMem(pTcIfc);
  560. return Status;
  561. }
  562. InitializeListHead(&pTcIfc->ClIfcList);
  563. } else {
  564. FreeMem(pTcIfc);
  565. Status = ERROR_NOT_ENOUGH_MEMORY;
  566. return Status;
  567. }
  568. } else {
  569. Status = ERROR_NOT_ENOUGH_MEMORY;
  570. return Status;
  571. }
  572. *ppTcIfc = pTcIfc;
  573. IF_DEBUG(CALLS) {
  574. WSPRINT(("==> CreateKernelInterfaceStruc: Status%d\n", Status));
  575. }
  576. return Status;
  577. }
  578. DWORD
  579. DereferenceKernelInterface(
  580. PTC_IFC pTcIfc
  581. )
  582. {
  583. DWORD Status = NO_ERROR;
  584. IF_DEBUG(CALLS) {
  585. WSPRINT(("==> DereferenceKernelInterfaceStruc: %X\n", pTcIfc));
  586. }
  587. ASSERT(pTcIfc);
  588. ASSERT( IsListEmpty( &pTcIfc->ClIfcList ) );
  589. GetLock( pGlobals->Lock );
  590. RemoveEntryList(&pTcIfc->Linkage);
  591. FreeLock( pGlobals->Lock );
  592. DeleteLock(pTcIfc->Lock);
  593. FreeMem(pTcIfc->pAddressListDesc);
  594. FreeMem(pTcIfc);
  595. IF_DEBUG(CALLS) {
  596. WSPRINT(("==> DereferenceKernelInterfaceStruc: %d\n", Status));
  597. }
  598. return Status;
  599. }
  600. DWORD
  601. CreateFlowStruc(
  602. IN HANDLE ClFlowCtx,
  603. IN PTC_GEN_FLOW pGenFlow,
  604. OUT PFLOW_STRUC *ppFlow
  605. )
  606. {
  607. PFLOW_STRUC pFlow;
  608. DWORD Status = NO_ERROR;
  609. ULONG l;
  610. PUCHAR pCurrentObject;
  611. LONG BufRemaining;
  612. *ppFlow = NULL;
  613. __try {
  614. pCurrentObject = (PUCHAR) pGenFlow->TcObjects;
  615. BufRemaining = pGenFlow->TcObjectsLength;
  616. while ((BufRemaining > 0) && (((QOS_OBJECT_HDR*)pCurrentObject)->ObjectType != QOS_OBJECT_END_OF_LIST))
  617. {
  618. BufRemaining -= ((QOS_OBJECT_HDR*)pCurrentObject)->ObjectLength;
  619. pCurrentObject = pCurrentObject + ((QOS_OBJECT_HDR*)pCurrentObject)->ObjectLength;
  620. }
  621. if (BufRemaining < 0)
  622. return (ERROR_TC_OBJECT_LENGTH_INVALID);
  623. l = FIELD_OFFSET(TC_GEN_FLOW, TcObjects) + pGenFlow->TcObjectsLength;
  624. } __except (EXCEPTION_EXECUTE_HANDLER) {
  625. Status = GetExceptionCode();
  626. IF_DEBUG(ERRORS) {
  627. WSPRINT(("CreateFlowStruc: Invalid pGenFlow: = 0x%X\n",
  628. Status ));
  629. }
  630. return Status;
  631. }
  632. AllocMem(&pFlow, sizeof(FLOW_STRUC));
  633. if (pFlow != NULL) {
  634. RtlZeroMemory(pFlow, sizeof(FLOW_STRUC));
  635. //
  636. // Allocate memory and save the generic flow structure
  637. //
  638. AllocMem(&pFlow->pGenFlow, l);
  639. if (pFlow->pGenFlow == NULL) {
  640. FreeMem(pFlow);
  641. pFlow = NULL;
  642. Status = ERROR_NOT_ENOUGH_MEMORY;
  643. } else {
  644. //
  645. // copy the generic flow into the new allocation
  646. //
  647. __try {
  648. RtlCopyMemory(pFlow->pGenFlow, pGenFlow, l);
  649. } __except (EXCEPTION_EXECUTE_HANDLER) {
  650. Status = GetExceptionCode();
  651. IF_DEBUG(ERRORS) {
  652. WSPRINT(("CreateFlowStruc: Exception Error: = 0x%X\n",
  653. Status ));
  654. }
  655. return Status;
  656. }
  657. //
  658. // acquire a new handle for the flow
  659. //
  660. pFlow->ClHandle = AllocateHandle((PVOID)pFlow);
  661. //
  662. // set the other parameters in the flow
  663. //
  664. pFlow->GenFlowLen = l;
  665. pFlow->ObjectType = ENUM_GEN_FLOW_TYPE;
  666. pFlow->ClFlowCtx = ClFlowCtx;
  667. pFlow->Flags = 0;
  668. pFlow->InstanceNameLength = 0;
  669. ReferenceInit(&pFlow->RefCount, pFlow, DereferenceFlow);
  670. REFADD(&pFlow->RefCount, 'FLOW');
  671. pFlow->FilterCount = 0;
  672. InitializeListHead(&pFlow->FilterList);
  673. __try {
  674. InitLock(pFlow->Lock);
  675. } __except (EXCEPTION_EXECUTE_HANDLER) {
  676. Status = GetExceptionCode();
  677. IF_DEBUG(ERRORS) {
  678. WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status ));
  679. }
  680. FreeHandle(pFlow->ClHandle);
  681. FreeMem(pFlow->pGenFlow);
  682. FreeMem(pFlow);
  683. return Status;
  684. }
  685. SET_STATE(pFlow->State, INSTALLING);
  686. //
  687. // Next create the event
  688. //
  689. pFlow->PendingEvent = CreateEvent(NULL, // default attr
  690. FALSE, // auto reset
  691. FALSE, // init = not signaled
  692. NULL // no name
  693. );
  694. if (!pFlow->PendingEvent)
  695. {
  696. // Failed to create event, get the error and free flow
  697. Status = GetLastError();
  698. DeleteFlowStruc(
  699. pFlow );
  700. return Status;
  701. }
  702. }
  703. } else {
  704. Status = ERROR_NOT_ENOUGH_MEMORY;
  705. }
  706. *ppFlow = pFlow;
  707. return Status;
  708. }
  709. DWORD
  710. CreateClassMapFlowStruc(
  711. IN HANDLE ClFlowCtx,
  712. IN PTC_CLASS_MAP_FLOW pClassMapFlow,
  713. OUT PFLOW_STRUC *ppFlow
  714. )
  715. {
  716. PFLOW_STRUC pFlow;
  717. DWORD Status = NO_ERROR;
  718. ULONG l;
  719. return ERROR_CALL_NOT_IMPLEMENTED;
  720. #if NEVER
  721. // As this is not published in MSDN and not implemented in PSCHED also
  722. *ppFlow = NULL;
  723. AllocMem(&pFlow, sizeof(FLOW_STRUC));
  724. if (pFlow != NULL) {
  725. RtlZeroMemory(pFlow, sizeof(FLOW_STRUC));
  726. //
  727. // Allocate memory and save the generic flow structure
  728. //
  729. l = sizeof(TC_CLASS_MAP_FLOW) + pClassMapFlow->ObjectsLength;
  730. AllocMem(&pFlow->pClassMapFlow, l);
  731. if (pFlow->pClassMapFlow == NULL) {
  732. FreeMem(pFlow);
  733. pFlow = NULL;
  734. Status = ERROR_NOT_ENOUGH_MEMORY;
  735. } else {
  736. //
  737. // copy the generic flow into the new allocation
  738. //
  739. __try {
  740. RtlCopyMemory(pFlow->pClassMapFlow, pClassMapFlow, l);
  741. } __except (EXCEPTION_EXECUTE_HANDLER) {
  742. Status = GetExceptionCode();
  743. IF_DEBUG(ERRORS) {
  744. WSPRINT(("CreateClassMapFlowStruc: Exception Error: = 0x%X\n",
  745. Status ));
  746. }
  747. return Status;
  748. }
  749. //
  750. // acquire a new handle for the flow
  751. //
  752. pFlow->ClHandle = AllocateHandle((PVOID)pFlow);
  753. //
  754. // set the other parameters in the flow
  755. //
  756. pFlow->ObjectType = ENUM_CLASS_MAP_FLOW_TYPE;
  757. pFlow->ClFlowCtx = ClFlowCtx;
  758. pFlow->Flags = 0;
  759. pFlow->InstanceNameLength = 0;
  760. InitializeListHead(&pFlow->FilterList);
  761. __try {
  762. InitLock(pFlow->Lock);
  763. } __except (EXCEPTION_EXECUTE_HANDLER) {
  764. Status = GetExceptionCode();
  765. IF_DEBUG(ERRORS) {
  766. WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status ));
  767. }
  768. if(pFlow->pClassMapFlow)
  769. FreeMem(pFlow->pClassMapFlow);
  770. if(pFlow)
  771. FreeMem(pFlow);
  772. return Status;
  773. }
  774. //
  775. //
  776. //
  777. pFlow->PendingEvent = CreateEvent(NULL, // default attr
  778. FALSE, // auto reset
  779. FALSE, // init = not signaled
  780. NULL // no name
  781. );
  782. if (!pFlow->PendingEvent)
  783. {
  784. // Failed to create event, get the error and free flow
  785. Status = GetLastError();
  786. DeleteFlowStruc(
  787. pFlow );
  788. return Status;
  789. }
  790. }
  791. } else {
  792. Status = ERROR_NOT_ENOUGH_MEMORY;
  793. }
  794. *ppFlow = pFlow;
  795. return Status;
  796. #endif
  797. }
  798. DWORD
  799. CreateFilterStruc(
  800. IN PTC_GEN_FILTER pGenFilter,
  801. IN PFLOW_STRUC pFlow,
  802. OUT PFILTER_STRUC *ppFilter
  803. )
  804. {
  805. PFILTER_STRUC pFilter;
  806. DWORD Status = NO_ERROR;
  807. ULONG GenFilterSize;
  808. PTC_GEN_FILTER pGpcFilter;
  809. PUCHAR p;
  810. ULONG ProtocolId;
  811. ULONG PatternSize;
  812. PIP_PATTERN pIpPattern;
  813. PTC_IFC pTcIfc;
  814. int i,n;
  815. *ppFilter = NULL;
  816. pTcIfc = pFlow->pInterface->pTcIfc;
  817. ASSERT(pTcIfc);
  818. __try {
  819. switch (pGenFilter->AddressType) {
  820. case NDIS_PROTOCOL_ID_TCP_IP:
  821. ProtocolId = GPC_PROTOCOL_TEMPLATE_IP;
  822. PatternSize = sizeof(IP_PATTERN);
  823. break;
  824. case NDIS_PROTOCOL_ID_IPX:
  825. ProtocolId = GPC_PROTOCOL_TEMPLATE_IPX;
  826. PatternSize = sizeof(IPX_PATTERN);
  827. break;
  828. default:
  829. return ERROR_INVALID_ADDRESS_TYPE;
  830. }
  831. if (PatternSize != pGenFilter->PatternSize ||
  832. pGenFilter->Pattern == NULL ||
  833. pGenFilter->Mask == NULL) {
  834. return ERROR_INVALID_PARAMETER;
  835. }
  836. } __except(EXCEPTION_EXECUTE_HANDLER) {
  837. Status = ERROR_INVALID_PARAMETER;
  838. IF_DEBUG(ERRORS) {
  839. WSPRINT(("CreateFilterStruc: Exception Error: = 0x%X\n",
  840. Status ));
  841. }
  842. return Status;
  843. }
  844. AllocMem(&pFilter, sizeof(FILTER_STRUC));
  845. if (pFilter != NULL) {
  846. RtlZeroMemory(pFilter, sizeof(FILTER_STRUC));
  847. //
  848. // Allocate memory and save the generic filter structure
  849. //
  850. GenFilterSize = sizeof(TC_GEN_FILTER) + 2*pGenFilter->PatternSize;
  851. AllocMem(&pGpcFilter, GenFilterSize);
  852. if (pGpcFilter == NULL) {
  853. FreeMem(pFilter);
  854. pFilter = NULL;
  855. Status = ERROR_NOT_ENOUGH_MEMORY;
  856. } else {
  857. //
  858. // copy the generic filter to local storage
  859. //
  860. pGpcFilter->AddressType = pGenFilter->AddressType;
  861. pGpcFilter->PatternSize = PatternSize;
  862. p = (PUCHAR)pGpcFilter + sizeof(TC_GEN_FILTER);
  863. __try {
  864. RtlCopyMemory(p, pGenFilter->Pattern, pGenFilter->PatternSize);
  865. if (pGenFilter->AddressType == NDIS_PROTOCOL_ID_TCP_IP) {
  866. if(pTcIfc->InterfaceIndex == IF_UNKNOWN) {
  867. if (NO_ERROR != (Status = GetInterfaceIndex(pTcIfc->pAddressListDesc,
  868. &pTcIfc->InterfaceIndex,
  869. &pTcIfc->SpecificLinkCtx))) {
  870. FreeMem(pFilter);
  871. FreeMem(pGpcFilter);
  872. return Status;
  873. }
  874. }
  875. //
  876. // IP pattern, set reserved fields
  877. //
  878. pIpPattern = (PIP_PATTERN)p;
  879. pIpPattern->Reserved1 = pFlow->pInterface->pTcIfc->InterfaceIndex;
  880. pIpPattern->Reserved2 = pFlow->pInterface->pTcIfc->SpecificLinkCtx;
  881. pIpPattern->Reserved3[0] = pIpPattern->Reserved3[1] = pIpPattern->Reserved3[2] = 0;
  882. }
  883. } __except (EXCEPTION_EXECUTE_HANDLER) {
  884. Status = ERROR_INVALID_PARAMETER;
  885. IF_DEBUG(ERRORS) {
  886. WSPRINT(("CreateFilterStruc: Exception Error: = 0x%X\n",
  887. Status ));
  888. }
  889. FreeMem(pGpcFilter);
  890. FreeMem(pFilter);
  891. return Status;
  892. }
  893. pGpcFilter->Pattern = (PVOID)p;
  894. p += pGenFilter->PatternSize;
  895. __try {
  896. RtlCopyMemory(p, pGenFilter->Mask, pGenFilter->PatternSize);
  897. if (pGenFilter->AddressType == NDIS_PROTOCOL_ID_TCP_IP) {
  898. //
  899. // IP pattern, set reserved fields
  900. //
  901. pIpPattern = (PIP_PATTERN)p;
  902. pIpPattern->Reserved1 = pIpPattern->Reserved2 = 0xffffffff;
  903. pIpPattern->Reserved3[0] = pIpPattern->Reserved3[1] = pIpPattern->Reserved3[2] = 0xff;
  904. }
  905. } __except (EXCEPTION_EXECUTE_HANDLER) {
  906. Status = ERROR_INVALID_PARAMETER;
  907. IF_DEBUG(ERRORS) {
  908. WSPRINT(("CreateFilterStruc: Exception Error: = 0x%X\n",
  909. Status ));
  910. }
  911. FreeMem(pGpcFilter);
  912. FreeMem(pFilter);
  913. return Status;
  914. }
  915. pGpcFilter->Mask = (PVOID)p;
  916. pFilter->pGpcFilter = pGpcFilter;
  917. //
  918. // acquire a new handle for the Filter
  919. //
  920. pFilter->ClHandle = AllocateHandle((PVOID)pFilter);
  921. // what if we're out of memory?
  922. if (!pFilter->ClHandle) {
  923. IF_DEBUG(ERRORS) {
  924. WSPRINT(("CreateFilterStruc: Cant allocate Handle\n"));
  925. }
  926. FreeMem(pGpcFilter);
  927. FreeMem(pFilter);
  928. return ERROR_NOT_ENOUGH_MEMORY;
  929. }
  930. //
  931. // set the other parameters in the Filter
  932. //
  933. pFilter->ObjectType = ENUM_FILTER_TYPE;
  934. pFilter->Flags = 0;
  935. ReferenceInit(&pFilter->RefCount, pFilter, DereferenceFilter);
  936. REFADD(&pFilter->RefCount, 'FILT');
  937. __try {
  938. InitLock(pFilter->Lock);
  939. } __except (EXCEPTION_EXECUTE_HANDLER) {
  940. Status = GetExceptionCode();
  941. IF_DEBUG(ERRORS) {
  942. WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status ));
  943. }
  944. FreeHandle(pFilter->ClHandle);
  945. FreeMem(pFilter);
  946. FreeMem(pGpcFilter);
  947. return Status;
  948. }
  949. SET_STATE(pFilter->State, INSTALLING);
  950. //
  951. // set the Gpc protocol template from the address type
  952. //
  953. pFilter->GpcProtocolTemplate = ProtocolId;
  954. }
  955. } else {
  956. Status = ERROR_NOT_ENOUGH_MEMORY;
  957. }
  958. *ppFilter = pFilter;
  959. return Status;
  960. }
  961. DWORD
  962. EnumAllInterfaces(VOID)
  963. {
  964. PCLIENT_STRUC pClient;
  965. DWORD Status;
  966. WMIHANDLE WmiHandle;
  967. ULONG MyBufferSize = 2 KiloBytes; // is this enough?!?
  968. PWNODE_ALL_DATA pWnode;
  969. PWNODE_ALL_DATA pWnodeBuffer;
  970. PTC_IFC pTcIfc;
  971. if (_init)
  972. return NO_ERROR;
  973. //
  974. // get a WMI block handle to the GUID_QOS_SUPPORTED
  975. //
  976. Status = WmiOpenBlock((GUID *)&GUID_QOS_TC_SUPPORTED, 0, &WmiHandle);
  977. if (ERROR_FAILED(Status)) {
  978. if (Status == ERROR_WMI_GUID_NOT_FOUND) {
  979. //
  980. // this means there is no TC data provider
  981. //
  982. Status = NO_ERROR; //ERROR_TC_NOT_SUPPORTED
  983. }
  984. return Status;
  985. }
  986. do {
  987. //
  988. // allocate a private buffer to retrieve all wnodes
  989. //
  990. AllocMem(&pWnodeBuffer, MyBufferSize);
  991. if (pWnodeBuffer == NULL) {
  992. WmiCloseBlock(WmiHandle);
  993. return ERROR_NOT_ENOUGH_MEMORY;
  994. }
  995. __try {
  996. Status = WmiQueryAllData(WmiHandle, &MyBufferSize, pWnodeBuffer);
  997. } __except (EXCEPTION_EXECUTE_HANDLER) {
  998. Status = GetExceptionCode();
  999. IF_DEBUG(ERRORS) {
  1000. WSPRINT(("EnumAllInterfaces: Exception Error: = %X\n",
  1001. Status ));
  1002. }
  1003. }
  1004. if (Status == ERROR_INSUFFICIENT_BUFFER) {
  1005. //
  1006. // failed since the buffer was too small
  1007. // release the buffer and double the size
  1008. //
  1009. MyBufferSize *= 2;
  1010. FreeMem(pWnodeBuffer);
  1011. pWnodeBuffer = NULL;
  1012. }
  1013. } while (Status == ERROR_INSUFFICIENT_BUFFER);
  1014. if (!ERROR_FAILED(Status)) {
  1015. ULONG dwInstanceNum;
  1016. ULONG InstanceSize;
  1017. PULONG lpdwNameOffsets;
  1018. BOOL bFixedSize = FALSE;
  1019. USHORT usNameLength;
  1020. ULONG DescSize;
  1021. PTC_SUPPORTED_INFO_BUFFER pTcInfoBuffer;
  1022. pWnode = pWnodeBuffer;
  1023. ASSERT(pWnode->WnodeHeader.Flags & WNODE_FLAG_ALL_DATA);
  1024. do {
  1025. //
  1026. // Check for fixed instance size
  1027. //
  1028. if (pWnode->WnodeHeader.Flags & WNODE_FLAG_FIXED_INSTANCE_SIZE) {
  1029. InstanceSize = pWnode->FixedInstanceSize;
  1030. bFixedSize = TRUE;
  1031. pTcInfoBuffer =
  1032. (PTC_SUPPORTED_INFO_BUFFER)OffsetToPtr(pWnode,
  1033. pWnode->DataBlockOffset);
  1034. }
  1035. //
  1036. // Get a pointer to the array of offsets to the instance names
  1037. //
  1038. lpdwNameOffsets = (PULONG) OffsetToPtr(pWnode,
  1039. pWnode->OffsetInstanceNameOffsets);
  1040. for ( dwInstanceNum = 0;
  1041. dwInstanceNum < pWnode->InstanceCount;
  1042. dwInstanceNum++) {
  1043. usNameLength =
  1044. *(USHORT *)OffsetToPtr(pWnode,
  1045. lpdwNameOffsets[dwInstanceNum]);
  1046. //
  1047. // Length and offset for variable data
  1048. //
  1049. if ( !bFixedSize ) {
  1050. InstanceSize =
  1051. pWnode->OffsetInstanceDataAndLength[dwInstanceNum].LengthInstanceData;
  1052. pTcInfoBuffer =
  1053. (PTC_SUPPORTED_INFO_BUFFER)OffsetToPtr(
  1054. (PBYTE)pWnode,
  1055. pWnode->OffsetInstanceDataAndLength[dwInstanceNum].OffsetInstanceData);
  1056. }
  1057. //
  1058. // we have all that is needed. we need to figure if
  1059. // there is enough buffer space to put the data as well
  1060. //
  1061. ASSERT(usNameLength < MAX_STRING_LENGTH);
  1062. DescSize = InstanceSize - FIELD_OFFSET(TC_SUPPORTED_INFO_BUFFER, AddrListDesc);
  1063. //
  1064. // Allocate a new interface descriptor structure
  1065. //
  1066. CreateKernelInterfaceStruc(&pTcIfc, DescSize);
  1067. if (pTcIfc != NULL) {
  1068. //
  1069. // copy the instance name string data
  1070. //
  1071. RtlCopyMemory(pTcIfc->InstanceName,
  1072. OffsetToPtr(pWnode,
  1073. lpdwNameOffsets[dwInstanceNum]+2),
  1074. usNameLength );
  1075. pTcIfc->InstanceNameLength = usNameLength;
  1076. pTcIfc->InstanceName[usNameLength/sizeof(WCHAR)] =
  1077. (WCHAR)0;
  1078. //
  1079. // copy the instance ID string data
  1080. //
  1081. RtlCopyMemory(pTcIfc->InstanceID,
  1082. &pTcInfoBuffer->InstanceID[0],
  1083. pTcInfoBuffer->InstanceIDLength );
  1084. pTcIfc->InstanceIDLength = pTcInfoBuffer->InstanceIDLength;
  1085. pTcIfc->InstanceID[pTcInfoBuffer->InstanceIDLength/sizeof(WCHAR)] =
  1086. (WCHAR)0;
  1087. //
  1088. // copy the instance data
  1089. // in this case - the network address
  1090. //
  1091. pTcIfc->AddrListBytesCount = DescSize;
  1092. //
  1093. // a sizeof(ULONG) since the structure is defined as ARRAY
  1094. // and the first ULONG is the number of elements
  1095. //
  1096. RtlCopyMemory( pTcIfc->pAddressListDesc,
  1097. &pTcInfoBuffer->AddrListDesc,
  1098. DescSize );
  1099. if (NO_ERROR != GetInterfaceIndex(pTcIfc->pAddressListDesc,
  1100. &pTcIfc->InterfaceIndex,
  1101. &pTcIfc->SpecificLinkCtx)) {
  1102. pTcIfc->InterfaceIndex = IF_UNKNOWN;
  1103. pTcIfc->SpecificLinkCtx = IF_UNKNOWN;
  1104. }
  1105. // set the state to open
  1106. GetLock(pTcIfc->Lock);
  1107. SET_STATE(pTcIfc->State, OPEN);
  1108. FreeLock(pTcIfc->Lock);
  1109. //
  1110. // Add the structure to the global linked list
  1111. //
  1112. GetLock( pGlobals->Lock );
  1113. InsertTailList(&pGlobals->TcIfcList, &pTcIfc->Linkage );
  1114. FreeLock( pGlobals->Lock );
  1115. #if 0
  1116. //
  1117. // make sure we have one gpc client per address type
  1118. //
  1119. Status = OpenGpcClients(pTcIfc);
  1120. if (ERROR_FAILED(Status)) {
  1121. break;
  1122. }
  1123. #endif
  1124. } else {
  1125. //
  1126. // no more memory, quit here
  1127. //
  1128. Status = ERROR_NOT_ENOUGH_MEMORY;
  1129. break;
  1130. }
  1131. }
  1132. //
  1133. // Update Wnode to point to next node
  1134. //
  1135. if ( pWnode->WnodeHeader.Linkage != 0) {
  1136. pWnode = (PWNODE_ALL_DATA) OffsetToPtr( pWnode,
  1137. pWnode->WnodeHeader.Linkage);
  1138. } else {
  1139. pWnode = NULL;
  1140. }
  1141. } while (pWnode != NULL && !ERROR_FAILED(Status));
  1142. }
  1143. //
  1144. // release resources and close WMI handle
  1145. //
  1146. WmiCloseBlock(WmiHandle);
  1147. if (pWnodeBuffer)
  1148. FreeMem(pWnodeBuffer);
  1149. if (Status == NO_ERROR) {
  1150. _init = TRUE;
  1151. }
  1152. return Status;
  1153. }
  1154. DWORD
  1155. CloseInterface(
  1156. IN PINTERFACE_STRUC pInterface,
  1157. BOOLEAN RemoveFlows
  1158. )
  1159. {
  1160. IF_DEBUG(CALLS) {
  1161. WSPRINT(("==>CloseInterface: pInterface=%X\n",
  1162. pInterface));
  1163. }
  1164. if (RemoveFlows) {
  1165. CloseOpenFlows(pInterface);
  1166. }
  1167. REFDEL(&pInterface->RefCount, 'CIFC');
  1168. IF_DEBUG(CALLS) {
  1169. WSPRINT(("==>CloseInterface: NO_ERROR\n"));
  1170. }
  1171. return NO_ERROR;
  1172. }
  1173. DWORD
  1174. DeleteFlow(
  1175. IN PFLOW_STRUC pFlow,
  1176. IN BOOLEAN RemoveFilters
  1177. )
  1178. {
  1179. DWORD Status;
  1180. PLIST_ENTRY pEntry;
  1181. PFILTER_STRUC pFilter;
  1182. IF_DEBUG(CALLS) {
  1183. WSPRINT(("DeleteFlow: attempting to delete flow=0x%X\n",
  1184. PtrToUlong(pFlow)));
  1185. }
  1186. if (RemoveFilters) {
  1187. CloseOpenFilters(pFlow);
  1188. } else {
  1189. if (/*pFlow->FilterCount > 0*/ !IsListEmpty(&pFlow->FilterList)) {
  1190. IF_DEBUG(ERRORS) {
  1191. WSPRINT(("DeleteFlow: filter list NOT empty\n"));
  1192. }
  1193. #if DBG
  1194. pEntry = pFlow->FilterList.Flink;
  1195. while (pEntry != &pFlow->FilterList) {
  1196. pFilter = CONTAINING_RECORD(pEntry, FILTER_STRUC, Linkage);
  1197. IF_DEBUG(ERRORS) {
  1198. WSPRINT(("<==TcDeleteFlow: Filter %x (handle %x) is open with RefCount:%d\n", pFilter, pFilter->ClHandle, pFilter->RefCount));
  1199. }
  1200. pEntry = pEntry->Flink;
  1201. }
  1202. #endif
  1203. return ERROR_TC_SUPPORTED_OBJECTS_EXIST;
  1204. }
  1205. }
  1206. //
  1207. // can remove the flow now
  1208. //
  1209. Status = IoDeleteFlow( pFlow, (BOOLEAN)!RemoveFilters );
  1210. IF_DEBUG(CALLS) {
  1211. WSPRINT(("DeleteFlow: IoDeleteFlow returned=0x%X\n",
  1212. Status));
  1213. }
  1214. if (!ERROR_PENDING(Status)) {
  1215. //
  1216. // call completed, either success or failure...
  1217. //
  1218. CompleteDeleteFlow(pFlow, Status);
  1219. }
  1220. return Status;
  1221. }
  1222. DWORD
  1223. DeleteFilter(
  1224. IN PFILTER_STRUC pFilter
  1225. )
  1226. {
  1227. DWORD Status;
  1228. IF_DEBUG(CALLS) {
  1229. WSPRINT(( "DeleteFilter: attempting to delete=0x%X\n",
  1230. PtrToUlong(pFilter)));
  1231. }
  1232. //
  1233. // call to actually delete the filter
  1234. //
  1235. Status = IoDeleteFilter( pFilter );
  1236. IF_DEBUG(CALLS) {
  1237. WSPRINT(( "DeleteFilter: IoDeleteFilter returned=0x%X\n",
  1238. Status));
  1239. }
  1240. //ASSERT(Status == NO_ERROR);
  1241. REFDEL(&pFilter->RefCount, 'FILT');
  1242. return Status;
  1243. }
  1244. PGPC_CLIENT
  1245. FindGpcClient(
  1246. IN ULONG CfInfoType
  1247. )
  1248. {
  1249. PGPC_CLIENT pGpcClient = NULL;
  1250. PLIST_ENTRY pHead, pEntry;
  1251. GetLock( pGlobals->Lock );
  1252. pHead = &pGlobals->GpcClientList;
  1253. pEntry = pHead->Flink;
  1254. while (pHead != pEntry && pGpcClient == NULL) {
  1255. pGpcClient = CONTAINING_RECORD(pEntry, GPC_CLIENT, Linkage);
  1256. if (CfInfoType != pGpcClient->CfInfoType) {
  1257. //
  1258. // address type doesn't match!
  1259. //
  1260. pGpcClient = NULL;
  1261. }
  1262. pEntry = pEntry->Flink;
  1263. }
  1264. FreeLock( pGlobals->Lock );
  1265. return pGpcClient;
  1266. }
  1267. VOID
  1268. CompleteAddFlow(
  1269. IN PFLOW_STRUC pFlow,
  1270. IN DWORD Status
  1271. )
  1272. {
  1273. PINTERFACE_STRUC pInterface;
  1274. ASSERT(pFlow);
  1275. ASSERT(!ERROR_PENDING(Status));
  1276. IF_DEBUG(CALLS) {
  1277. WSPRINT(("CompleteAddFlow: pFlow=0x%X Status=0x%X\n",
  1278. PtrToUlong(pFlow), Status));
  1279. }
  1280. if(pFlow->CompletionBuffer) {
  1281. FreeMem(pFlow->CompletionBuffer);
  1282. pFlow->CompletionBuffer = NULL;
  1283. }
  1284. //
  1285. // Check if the interface is still around.
  1286. //
  1287. GetLock(pFlow->Lock);
  1288. pInterface = pFlow->pInterface;
  1289. FreeLock(pFlow->Lock);
  1290. if (ERROR_FAILED(Status)) {
  1291. //
  1292. // failed, release resources
  1293. //
  1294. CompleteDeleteFlow(pFlow, Status);
  1295. } else {
  1296. GetLock(pGlobals->Lock);
  1297. GetLock(pInterface->Lock);
  1298. if (QUERY_STATE(pInterface->State) != OPEN) {
  1299. FreeLock(pInterface->Lock);
  1300. FreeLock(pGlobals->Lock);
  1301. IF_DEBUG(ERRORS) {
  1302. WSPRINT(("CompleteAddFlow: Interface (%X) is NOT open pFlow=0x%X Status=0x%X\n", pInterface->ClHandle,
  1303. PtrToUlong(pFlow), Status));
  1304. }
  1305. //
  1306. // Delete the only ref we have on this flow and get out.
  1307. //
  1308. REFDEL(&pFlow->RefCount, 'FLOW');
  1309. } else {
  1310. FreeLock(pInterface->Lock);
  1311. //
  1312. // The flow is ready for business
  1313. //
  1314. GetLock(pFlow->Lock);
  1315. SET_STATE(pFlow->State, OPEN);
  1316. FreeLock(pFlow->Lock);
  1317. //
  1318. // Announce on the lists that we are ready for business
  1319. //
  1320. pInterface->FlowCount++;
  1321. REFADD(&pInterface->RefCount, 'FLOW');
  1322. InsertTailList(&pInterface->FlowList, &pFlow->Linkage);
  1323. FreeLock(pGlobals->Lock);
  1324. }
  1325. }
  1326. //
  1327. // This ref was taken in TcAddFlow.
  1328. //
  1329. REFDEL(&pInterface->RefCount, 'TCAF');
  1330. }
  1331. VOID
  1332. CompleteModifyFlow(
  1333. IN PFLOW_STRUC pFlow,
  1334. IN DWORD Status
  1335. )
  1336. {
  1337. ASSERT(pFlow);
  1338. ASSERT(!ERROR_PENDING(Status));
  1339. IF_DEBUG(CALLS) {
  1340. WSPRINT(("CompleteModifyFlow: pFlow=0x%X Status=0x%X\n",
  1341. PtrToUlong(pFlow), Status));
  1342. }
  1343. GetLock(pFlow->Lock);
  1344. if(pFlow->CompletionBuffer) {
  1345. FreeMem(pFlow->CompletionBuffer);
  1346. pFlow->CompletionBuffer = NULL;
  1347. }
  1348. if (ERROR_FAILED(Status)) {
  1349. //
  1350. // failed, release the newly allocated generic flow parameters
  1351. //
  1352. FreeMem(pFlow->pGenFlow1);
  1353. } else {
  1354. //
  1355. // modification accepted, update the generic flow parameters
  1356. //
  1357. FreeMem(pFlow->pGenFlow);
  1358. pFlow->pGenFlow = pFlow->pGenFlow1;
  1359. pFlow->GenFlowLen = pFlow->GenFlowLen;
  1360. }
  1361. //
  1362. // clear the installing flag
  1363. //
  1364. pFlow->Flags &= ~TC_FLAGS_MODIFYING;
  1365. pFlow->pGenFlow1 = NULL;
  1366. pFlow->GenFlowLen1 = 0;
  1367. FreeLock(pFlow->Lock);
  1368. //
  1369. // This ref was taken in TcModifyFlow
  1370. //
  1371. REFDEL(&pFlow->RefCount, 'TCMF');
  1372. IF_DEBUG(CALLS) {
  1373. WSPRINT(("CompleteModifyFlow: pFlow=0x%X Status=0x%X\n",
  1374. PtrToUlong(pFlow), Status));
  1375. }
  1376. }
  1377. VOID
  1378. CompleteDeleteFlow(
  1379. IN PFLOW_STRUC pFlow,
  1380. IN DWORD Status
  1381. )
  1382. {
  1383. ASSERT(pFlow);
  1384. //ASSERT(Status == NO_ERROR);
  1385. //ASSERT(pFlow->CompletionBuffer);
  1386. IF_DEBUG(CALLS) {
  1387. WSPRINT(("CompleteDeleteFlow: pFlow=0x%X Status=0x%X\n",
  1388. PtrToUlong(pFlow), Status));
  1389. }
  1390. //
  1391. // okay, release resources
  1392. //
  1393. GetLock(pFlow->Lock);
  1394. if (pFlow->CompletionBuffer) {
  1395. FreeMem(pFlow->CompletionBuffer);
  1396. pFlow->CompletionBuffer = NULL;
  1397. }
  1398. FreeLock(pFlow->Lock);
  1399. IF_DEBUG(REFCOUNTS) {
  1400. WSPRINT(("#21 DEREF FLOW %X (%X) ref(%d)\n", pFlow->ClHandle, pFlow, pFlow->RefCount));
  1401. }
  1402. REFDEL(&pFlow->RefCount, 'FLOW');
  1403. }
  1404. DWORD
  1405. OpenGpcClients(
  1406. IN ULONG CfInfoType
  1407. )
  1408. {
  1409. DWORD Status = NO_ERROR;
  1410. PLIST_ENTRY pHead, pEntry;
  1411. PGPC_CLIENT pGpcClient;
  1412. //int i;
  1413. if (FindGpcClient(CfInfoType) == NULL) {
  1414. //
  1415. // create an entry in the
  1416. //
  1417. AllocMem(&pGpcClient, sizeof(GPC_CLIENT) );
  1418. if (pGpcClient == NULL) {
  1419. return ERROR_NOT_ENOUGH_MEMORY;
  1420. }
  1421. pGpcClient->CfInfoType = CfInfoType;
  1422. pGpcClient->RefCount = 1;
  1423. //
  1424. // register the gpc client
  1425. //
  1426. Status = IoRegisterClient(pGpcClient);
  1427. if (ERROR_FAILED(Status)) {
  1428. FreeMem(pGpcClient);
  1429. } else {
  1430. GetLock( pGlobals->Lock);
  1431. InsertTailList(&pGlobals->GpcClientList, &pGpcClient->Linkage);
  1432. FreeLock( pGlobals->Lock);
  1433. }
  1434. }
  1435. return Status;
  1436. }
  1437. DWORD
  1438. DereferenceInterface(
  1439. IN PINTERFACE_STRUC pInterface
  1440. )
  1441. {
  1442. DWORD Status = NO_ERROR;
  1443. IF_DEBUG(CALLS) {
  1444. WSPRINT(("==>DereferenceInterface: IfcH=%X RefCount=%d\n",
  1445. pInterface->ClHandle, pInterface->RefCount));
  1446. }
  1447. FreeHandle(pInterface->ClHandle);
  1448. //GetLock(pGlobals->Lock);
  1449. IF_DEBUG(REFCOUNTS) {
  1450. WSPRINT(("==>DereferenceInterface: IfcH=%X Interface=%x\n",
  1451. pInterface->ClHandle, pInterface));
  1452. }
  1453. //
  1454. // close the interface and all flows/filters
  1455. //
  1456. RemoveEntryList(&pInterface->Linkage);
  1457. RemoveEntryList(&pInterface->NextIfc);
  1458. //
  1459. // Deregister from any guid notification requests
  1460. //
  1461. TcipDeleteInterfaceFromNotificationList(
  1462. pInterface,
  1463. 0
  1464. );
  1465. //
  1466. // #295267
  1467. // Do not dereference Client OR decrement Interface Count until
  1468. // the Interface is actually going away. Otherwise, the client structures
  1469. // are cleaned out, and when the ref count finally goes down and we
  1470. // touch this code path, we hit an AV.
  1471. //
  1472. pInterface->pClient->InterfaceCount--;
  1473. IF_DEBUG(HANDLES) {
  1474. WSPRINT(("DEREF Client A : %x\n", pInterface->pClient->ClHandle));
  1475. }
  1476. REFDEL(&pInterface->pClient->RefCount, 'CIFC');
  1477. REFDEL(&pInterface->pTcIfc->RefCount, 'CIFC');
  1478. //
  1479. // This is complex, so read carefully.
  1480. // We want CloseInterface to wait until the event is set (292120).
  1481. // It is likely that in case the TcCloseInterface call didn't
  1482. // come in, we dont have to set the Event since the TC_FLAGS_WAITING
  1483. // will not be set in that case.
  1484. //
  1485. if (!IS_WAITING(pInterface->Flags)) {
  1486. CloseHandle(pInterface->IfcEvent);
  1487. } else {
  1488. SetEvent(pInterface->IfcEvent);
  1489. }
  1490. //
  1491. // free the interface resources
  1492. //
  1493. DeleteLock(pInterface->Lock);
  1494. FreeMem(pInterface);
  1495. //FreeLock(pGlobals->Lock);
  1496. IF_DEBUG(CALLS) {
  1497. WSPRINT(("<==DereferenceInterface: Status=%X\n", Status));
  1498. }
  1499. return Status;
  1500. }
  1501. DWORD
  1502. DereferenceFlow(
  1503. IN PFLOW_STRUC pFlow
  1504. )
  1505. {
  1506. DWORD Status = NO_ERROR;
  1507. IF_DEBUG(CALLS) {
  1508. WSPRINT(("==>DereferenceFlow: FlowH=%X Flow=%X\n",
  1509. pFlow->ClHandle, pFlow));
  1510. }
  1511. //GetLock(pGlobals->Lock);
  1512. IF_DEBUG(REFCOUNTS) {
  1513. WSPRINT(("==>DereferenceFlow: FlowH=%X Flow=%X\n",
  1514. pFlow->ClHandle, pFlow));
  1515. }
  1516. //
  1517. // remove the flow from the list
  1518. //
  1519. FreeHandle(pFlow->ClHandle);
  1520. GetLock(pFlow->Lock);
  1521. if (QUERY_STATE(pFlow->State) != INSTALLING) {
  1522. FreeLock(pFlow->Lock);
  1523. RemoveEntryList(&pFlow->Linkage);
  1524. pFlow->pInterface->FlowCount--;
  1525. IF_DEBUG(HANDLES) {
  1526. WSPRINT(("DEREF Interface A : %x\n", pFlow->pInterface->ClHandle));
  1527. }
  1528. REFDEL(&pFlow->pInterface->RefCount, 'FLOW');
  1529. } else {
  1530. FreeLock(pFlow->Lock);
  1531. }
  1532. //
  1533. // moved here from CompleteDeleteFlow
  1534. //
  1535. //
  1536. // free the interface resources
  1537. //
  1538. DeleteFlowStruc(pFlow);
  1539. //FreeLock(pGlobals->Lock);
  1540. IF_DEBUG(CALLS) {
  1541. WSPRINT(("<==DereferenceFlow: Status=%X\n", Status));
  1542. }
  1543. return Status;
  1544. }
  1545. DWORD
  1546. DereferenceClient(
  1547. IN PCLIENT_STRUC pClient
  1548. )
  1549. {
  1550. //GetLock( pGlobals->Lock );
  1551. IF_DEBUG(REFCOUNTS) {
  1552. WSPRINT(("==>DereferenceClient: pClient=%x, Handle=%x, RefCount=%d\n",
  1553. pClient, pClient->ClHandle, pClient->RefCount));
  1554. }
  1555. GetLock(pClient->Lock);
  1556. SET_STATE(pClient->State, REMOVED);
  1557. FreeLock(pClient->Lock);
  1558. FreeHandle( pClient->ClHandle );
  1559. RemoveEntryList( &pClient->Linkage );
  1560. DeleteLock(pClient->Lock);
  1561. FreeMem( pClient );
  1562. //FreeLock( pGlobals->Lock );
  1563. return NO_ERROR;
  1564. }
  1565. DWORD
  1566. DereferenceFilter(
  1567. IN PFILTER_STRUC pFilter
  1568. )
  1569. {
  1570. DWORD Status = NO_ERROR;
  1571. IF_DEBUG(CALLS) {
  1572. WSPRINT(("==>DereferenceFilter: FilterH=%X RefCount=%d\n",
  1573. pFilter->ClHandle, pFilter->RefCount));
  1574. }
  1575. //GetLock(pGlobals->Lock);
  1576. IF_DEBUG(REFCOUNTS) {
  1577. WSPRINT(("==>DereferenceFilter: FilterH=%X Filter=%X on FLOW=%X\n",
  1578. pFilter->ClHandle, pFilter, pFilter->pFlow));
  1579. }
  1580. FreeHandle(pFilter->ClHandle);
  1581. //
  1582. // remove the flow from the list
  1583. //
  1584. GetLock(pFilter->Lock);
  1585. if (QUERY_STATE(pFilter->State) != INSTALLING) {
  1586. FreeLock(pFilter->Lock);
  1587. RemoveEntryList(&pFilter->Linkage);
  1588. pFilter->pFlow->FilterCount--;
  1589. IF_DEBUG(REFCOUNTS) {
  1590. WSPRINT(("#22 DEREF FLOW %X (%X) ref(%d)\n", pFilter->pFlow->ClHandle, pFilter->pFlow, pFilter->pFlow->RefCount));
  1591. }
  1592. REFDEL(&pFilter->pFlow->RefCount, 'FILT');
  1593. } else {
  1594. FreeLock(pFilter->Lock);
  1595. }
  1596. DeleteFilterStruc(pFilter);
  1597. //FreeLock(pGlobals->Lock);
  1598. IF_DEBUG(CALLS) {
  1599. WSPRINT(("<==DereferenceFilter: Status=%X\n", Status));
  1600. }
  1601. return Status;
  1602. }
  1603. DWORD
  1604. GetInterfaceIndex(
  1605. IN PADDRESS_LIST_DESCRIPTOR pAddressListDesc,
  1606. OUT PULONG pInterfaceIndex,
  1607. OUT PULONG pSpecificLinkCtx)
  1608. {
  1609. PNETWORK_ADDRESS_LIST pAddrList;
  1610. NETWORK_ADDRESS UNALIGNED *pAddr;
  1611. DWORD n,k;
  1612. DWORD Status = NO_ERROR;
  1613. PMIB_IPADDRTABLE pIpAddrTbl;
  1614. DWORD dwSize = 2 KiloBytes;
  1615. NETWORK_ADDRESS_IP UNALIGNED *pIpNetAddr = 0;
  1616. DWORD cAddr;
  1617. *pInterfaceIndex = 0;
  1618. *pSpecificLinkCtx = 0;
  1619. cAddr = pAddressListDesc->AddressList.AddressCount;
  1620. if (cAddr == 0) {
  1621. //
  1622. // no address
  1623. //
  1624. return NO_ERROR;
  1625. }
  1626. #if INTERFACE_ID
  1627. AllocMem(&pIpAddrTbl, dwSize);
  1628. if (pIpAddrTbl == NULL) {
  1629. return ERROR_NOT_ENOUGH_MEMORY;
  1630. }
  1631. pAddr = (UNALIGNED NETWORK_ADDRESS *) &pAddressListDesc->AddressList.Address[0];
  1632. for (n = 0; n < cAddr; n++) {
  1633. if (pAddr->AddressType == NDIS_PROTOCOL_ID_TCP_IP) {
  1634. pIpNetAddr = (UNALIGNED NETWORK_ADDRESS_IP *)&pAddr->Address[0];
  1635. break;
  1636. }
  1637. pAddr = (UNALIGNED NETWORK_ADDRESS *)(((PUCHAR)pAddr)
  1638. + pAddr->AddressLength
  1639. + FIELD_OFFSET(NETWORK_ADDRESS, Address));
  1640. }
  1641. if (pIpNetAddr) {
  1642. Status = GetIpAddrTableFromStack(
  1643. pIpAddrTbl,
  1644. dwSize,
  1645. FALSE
  1646. );
  1647. if (Status == NO_ERROR) {
  1648. //
  1649. // search for the matching IP address to IpAddr
  1650. // in the table we got back from the stack
  1651. //
  1652. for (k = 0; k < pIpAddrTbl->dwNumEntries; k++) {
  1653. if (pIpAddrTbl->table[k].dwAddr == pIpNetAddr->in_addr) {
  1654. //
  1655. // found one, get the index
  1656. //
  1657. *pInterfaceIndex = pIpAddrTbl->table[k].dwIndex;
  1658. break;
  1659. }
  1660. }
  1661. if (pAddressListDesc->MediaType == NdisMediumWan) {
  1662. if (n+1 < cAddr) {
  1663. //
  1664. // there is another address that contains
  1665. // the remote client address
  1666. // this should be used as the link ID
  1667. //
  1668. pAddr = (UNALIGNED NETWORK_ADDRESS *)(((PUCHAR)pAddr)
  1669. + pAddr->AddressLength
  1670. + FIELD_OFFSET(NETWORK_ADDRESS, Address));
  1671. if (pAddr->AddressType == NDIS_PROTOCOL_ID_TCP_IP) {
  1672. //
  1673. // parse the second IP address,
  1674. // this would be the remote IP address for dialin WAN
  1675. //
  1676. pIpNetAddr = (UNALIGNED NETWORK_ADDRESS_IP *)&pAddr->Address[0];
  1677. *pSpecificLinkCtx = pIpNetAddr->in_addr;
  1678. }
  1679. }
  1680. }
  1681. }
  1682. }
  1683. FreeMem(pIpAddrTbl);
  1684. #endif
  1685. return Status;
  1686. }