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.

2408 lines
59 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. if (!pClient->ClHandle) {
  447. FreeMem(pClient);
  448. return ERROR_NOT_ENOUGH_MEMORY;
  449. }
  450. //
  451. // set the other parameters in the client interface
  452. //
  453. pClient->ObjectType = ENUM_CLIENT_TYPE;
  454. pClient->ClRegCtx = ClRegCtx;
  455. InitializeListHead(&pClient->InterfaceList);
  456. ReferenceInit(&pClient->RefCount, pClient, DereferenceClient);
  457. REFADD(&pClient->RefCount, 'CLNT');
  458. __try {
  459. InitLock(pClient->Lock);
  460. } __except (EXCEPTION_EXECUTE_HANDLER) {
  461. Status = GetExceptionCode();
  462. IF_DEBUG(ERRORS) {
  463. WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status ));
  464. }
  465. FreeHandle(pClient->ClHandle);
  466. FreeMem(pClient);
  467. return Status;
  468. }
  469. SET_STATE(pClient->State, INSTALLING);
  470. } else {
  471. Status = ERROR_NOT_ENOUGH_MEMORY;
  472. }
  473. *ppClient = pClient;
  474. return Status;
  475. }
  476. DWORD
  477. CreateClInterfaceStruc(
  478. IN HANDLE ClIfcCtx,
  479. OUT PINTERFACE_STRUC *ppClIfc
  480. )
  481. {
  482. PINTERFACE_STRUC pClIfc;
  483. DWORD Status = NO_ERROR;
  484. AllocMem(&pClIfc, sizeof(INTERFACE_STRUC));
  485. if (pClIfc != NULL) {
  486. RtlZeroMemory(pClIfc, sizeof(INTERFACE_STRUC));
  487. //
  488. // acquire a new handle for the client
  489. //
  490. GetLock(pGlobals->Lock);
  491. pClIfc->ClHandle = AllocateHandle((PVOID)pClIfc);
  492. FreeLock(pGlobals->Lock);
  493. if (!pClIfc->ClHandle) {
  494. FreeMem(pClIfc);
  495. return ERROR_NOT_ENOUGH_MEMORY;
  496. }
  497. if ((pClIfc->IfcEvent = CreateEvent( NULL, // pointer to security attributes
  498. TRUE, // flag for manual-reset event
  499. FALSE, // flag for initial state
  500. NULL // pointer to event-object name);
  501. )) == NULL) {
  502. Status = GetLastError();
  503. IF_DEBUG(ERRORS) {
  504. WSPRINT(( "Error Creating Event for Interface: 0x%X:%d\n", pClIfc, Status));
  505. }
  506. FreeHandle(pClIfc->ClHandle);
  507. FreeMem(pClIfc);
  508. return Status;
  509. }
  510. //
  511. // set the other parameters in the client interface
  512. //
  513. pClIfc->ObjectType = ENUM_INTERFACE_TYPE;
  514. pClIfc->ClIfcCtx = ClIfcCtx;
  515. pClIfc->CallbackThreadId = 0;
  516. ReferenceInit(&pClIfc->RefCount, pClIfc, DereferenceInterface);
  517. REFADD(&pClIfc->RefCount, 'CIFC');
  518. InitializeListHead(&pClIfc->FlowList);
  519. __try {
  520. InitLock(pClIfc->Lock);
  521. } __except (EXCEPTION_EXECUTE_HANDLER) {
  522. Status = GetExceptionCode();
  523. IF_DEBUG(ERRORS) {
  524. WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status ));
  525. }
  526. CloseHandle(pClIfc->IfcEvent);
  527. FreeHandle(pClIfc->ClHandle);
  528. FreeMem(pClIfc);
  529. return Status;
  530. }
  531. SET_STATE(pClIfc->State, INSTALLING);
  532. pClIfc->Flags = 0; // reset flags
  533. } else {
  534. Status = ERROR_NOT_ENOUGH_MEMORY;
  535. }
  536. *ppClIfc = pClIfc;
  537. return Status;
  538. }
  539. DWORD
  540. CreateKernelInterfaceStruc(
  541. OUT PTC_IFC *ppTcIfc,
  542. IN DWORD AddressLength
  543. )
  544. {
  545. PTC_IFC pTcIfc;
  546. DWORD Status = NO_ERROR;
  547. IF_DEBUG(CALLS) {
  548. WSPRINT(("==> CreateKernelInterfaceStruc: AddressLength %d\n", AddressLength));
  549. }
  550. *ppTcIfc = NULL;
  551. AllocMem(&pTcIfc, sizeof(TC_IFC));
  552. if (pTcIfc) {
  553. RtlZeroMemory(pTcIfc, sizeof(TC_IFC));
  554. AllocMem(&pTcIfc->pAddressListDesc, AddressLength);
  555. if (pTcIfc->pAddressListDesc) {
  556. RtlZeroMemory(pTcIfc->pAddressListDesc, AddressLength);
  557. //
  558. // initialize the new structure
  559. //
  560. ReferenceInit(&pTcIfc->RefCount, pTcIfc, DereferenceKernelInterface);
  561. REFADD(&pTcIfc->RefCount, 'KIFC');
  562. SET_STATE(pTcIfc->State, INSTALLING);
  563. __try {
  564. InitLock(pTcIfc->Lock);
  565. } __except (EXCEPTION_EXECUTE_HANDLER) {
  566. Status = GetExceptionCode();
  567. IF_DEBUG(ERRORS) {
  568. WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status ));
  569. }
  570. FreeMem(pTcIfc->pAddressListDesc);
  571. FreeMem(pTcIfc);
  572. return Status;
  573. }
  574. InitializeListHead(&pTcIfc->ClIfcList);
  575. } else {
  576. FreeMem(pTcIfc);
  577. Status = ERROR_NOT_ENOUGH_MEMORY;
  578. return Status;
  579. }
  580. } else {
  581. Status = ERROR_NOT_ENOUGH_MEMORY;
  582. return Status;
  583. }
  584. *ppTcIfc = pTcIfc;
  585. IF_DEBUG(CALLS) {
  586. WSPRINT(("==> CreateKernelInterfaceStruc: Status%d\n", Status));
  587. }
  588. return Status;
  589. }
  590. DWORD
  591. DereferenceKernelInterface(
  592. PTC_IFC pTcIfc
  593. )
  594. {
  595. DWORD Status = NO_ERROR;
  596. IF_DEBUG(CALLS) {
  597. WSPRINT(("==> DereferenceKernelInterfaceStruc: %X\n", pTcIfc));
  598. }
  599. ASSERT(pTcIfc);
  600. ASSERT( IsListEmpty( &pTcIfc->ClIfcList ) );
  601. GetLock( pGlobals->Lock );
  602. RemoveEntryList(&pTcIfc->Linkage);
  603. FreeLock( pGlobals->Lock );
  604. DeleteLock(pTcIfc->Lock);
  605. FreeMem(pTcIfc->pAddressListDesc);
  606. FreeMem(pTcIfc);
  607. IF_DEBUG(CALLS) {
  608. WSPRINT(("==> DereferenceKernelInterfaceStruc: %d\n", Status));
  609. }
  610. return Status;
  611. }
  612. DWORD
  613. CreateFlowStruc(
  614. IN HANDLE ClFlowCtx,
  615. IN PTC_GEN_FLOW pGenFlow,
  616. OUT PFLOW_STRUC *ppFlow
  617. )
  618. {
  619. PFLOW_STRUC pFlow;
  620. DWORD Status = NO_ERROR;
  621. ULONG l;
  622. PUCHAR pCurrentObject;
  623. LONG BufRemaining;
  624. *ppFlow = NULL;
  625. __try {
  626. pCurrentObject = (PUCHAR) pGenFlow->TcObjects;
  627. BufRemaining = pGenFlow->TcObjectsLength;
  628. while ((BufRemaining > 0) && (((QOS_OBJECT_HDR*)pCurrentObject)->ObjectType != QOS_OBJECT_END_OF_LIST))
  629. {
  630. BufRemaining -= ((QOS_OBJECT_HDR*)pCurrentObject)->ObjectLength;
  631. pCurrentObject = pCurrentObject + ((QOS_OBJECT_HDR*)pCurrentObject)->ObjectLength;
  632. }
  633. if (BufRemaining < 0)
  634. return (ERROR_TC_OBJECT_LENGTH_INVALID);
  635. l = FIELD_OFFSET(TC_GEN_FLOW, TcObjects) + pGenFlow->TcObjectsLength;
  636. } __except (EXCEPTION_EXECUTE_HANDLER) {
  637. Status = GetExceptionCode();
  638. IF_DEBUG(ERRORS) {
  639. WSPRINT(("CreateFlowStruc: Invalid pGenFlow: = 0x%X\n",
  640. Status ));
  641. }
  642. return Status;
  643. }
  644. AllocMem(&pFlow, sizeof(FLOW_STRUC));
  645. if (pFlow != NULL) {
  646. RtlZeroMemory(pFlow, sizeof(FLOW_STRUC));
  647. //
  648. // acquire a new handle for the flow
  649. //
  650. pFlow->ClHandle = AllocateHandle((PVOID)pFlow);
  651. if (!pFlow->ClHandle) {
  652. FreeMem(pFlow);
  653. return ERROR_NOT_ENOUGH_MEMORY;
  654. }
  655. //
  656. // Allocate memory and save the generic flow structure
  657. //
  658. AllocMem(&pFlow->pGenFlow, l);
  659. if (pFlow->pGenFlow == NULL) {
  660. FreeHandle(pFlow->ClHandle);
  661. FreeMem(pFlow);
  662. pFlow = NULL;
  663. Status = ERROR_NOT_ENOUGH_MEMORY;
  664. } else {
  665. //
  666. // copy the generic flow into the new allocation
  667. //
  668. __try {
  669. RtlCopyMemory(pFlow->pGenFlow, pGenFlow, l);
  670. } __except (EXCEPTION_EXECUTE_HANDLER) {
  671. Status = GetExceptionCode();
  672. IF_DEBUG(ERRORS) {
  673. WSPRINT(("CreateFlowStruc: Exception Error: = 0x%X\n",
  674. Status ));
  675. }
  676. FreeMem(pFlow->pGenFlow);
  677. FreeHandle(pFlow->ClHandle);
  678. FreeMem(pFlow);
  679. return Status;
  680. }
  681. //
  682. // set the other parameters in the flow
  683. //
  684. pFlow->GenFlowLen = l;
  685. pFlow->ObjectType = ENUM_GEN_FLOW_TYPE;
  686. pFlow->ClFlowCtx = ClFlowCtx;
  687. pFlow->Flags = 0;
  688. pFlow->InstanceNameLength = 0;
  689. ReferenceInit(&pFlow->RefCount, pFlow, DereferenceFlow);
  690. REFADD(&pFlow->RefCount, 'FLOW');
  691. pFlow->FilterCount = 0;
  692. InitializeListHead(&pFlow->FilterList);
  693. __try {
  694. InitLock(pFlow->Lock);
  695. } __except (EXCEPTION_EXECUTE_HANDLER) {
  696. Status = GetExceptionCode();
  697. IF_DEBUG(ERRORS) {
  698. WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status ));
  699. }
  700. FreeHandle(pFlow->ClHandle);
  701. FreeMem(pFlow->pGenFlow);
  702. FreeMem(pFlow);
  703. return Status;
  704. }
  705. SET_STATE(pFlow->State, INSTALLING);
  706. //
  707. // Next create the event
  708. //
  709. pFlow->PendingEvent = CreateEvent(NULL, // default attr
  710. FALSE, // auto reset
  711. FALSE, // init = not signaled
  712. NULL // no name
  713. );
  714. if (!pFlow->PendingEvent)
  715. {
  716. // Failed to create event, get the error and free flow
  717. Status = GetLastError();
  718. DeleteFlowStruc(
  719. pFlow );
  720. return Status;
  721. }
  722. }
  723. } else {
  724. Status = ERROR_NOT_ENOUGH_MEMORY;
  725. }
  726. *ppFlow = pFlow;
  727. return Status;
  728. }
  729. DWORD
  730. CreateFilterStruc(
  731. IN PTC_GEN_FILTER pGenFilter,
  732. IN PFLOW_STRUC pFlow,
  733. OUT PFILTER_STRUC *ppFilter
  734. )
  735. {
  736. PFILTER_STRUC pFilter;
  737. DWORD Status = NO_ERROR;
  738. ULONG GenFilterSize;
  739. PTC_GEN_FILTER pGpcFilter;
  740. PUCHAR p;
  741. ULONG ProtocolId;
  742. ULONG PatternSize;
  743. PIP_PATTERN pIpPattern;
  744. PTC_IFC pTcIfc;
  745. int i,n;
  746. *ppFilter = NULL;
  747. pTcIfc = pFlow->pInterface->pTcIfc;
  748. ASSERT(pTcIfc);
  749. __try {
  750. switch (pGenFilter->AddressType) {
  751. case NDIS_PROTOCOL_ID_TCP_IP:
  752. ProtocolId = GPC_PROTOCOL_TEMPLATE_IP;
  753. PatternSize = sizeof(IP_PATTERN);
  754. break;
  755. default:
  756. return ERROR_INVALID_ADDRESS_TYPE;
  757. }
  758. if (PatternSize != pGenFilter->PatternSize ||
  759. pGenFilter->Pattern == NULL ||
  760. pGenFilter->Mask == NULL) {
  761. return ERROR_INVALID_PARAMETER;
  762. }
  763. } __except(EXCEPTION_EXECUTE_HANDLER) {
  764. Status = ERROR_INVALID_PARAMETER;
  765. IF_DEBUG(ERRORS) {
  766. WSPRINT(("CreateFilterStruc: Exception Error: = 0x%X\n",
  767. Status ));
  768. }
  769. return Status;
  770. }
  771. AllocMem(&pFilter, sizeof(FILTER_STRUC));
  772. if (pFilter != NULL) {
  773. RtlZeroMemory(pFilter, sizeof(FILTER_STRUC));
  774. //
  775. // Allocate memory and save the generic filter structure
  776. //
  777. GenFilterSize = sizeof(TC_GEN_FILTER) + 2*pGenFilter->PatternSize;
  778. AllocMem(&pGpcFilter, GenFilterSize);
  779. if (pGpcFilter == NULL) {
  780. FreeMem(pFilter);
  781. pFilter = NULL;
  782. Status = ERROR_NOT_ENOUGH_MEMORY;
  783. } else {
  784. //
  785. // copy the generic filter to local storage
  786. //
  787. pGpcFilter->AddressType = pGenFilter->AddressType;
  788. pGpcFilter->PatternSize = PatternSize;
  789. p = (PUCHAR)pGpcFilter + sizeof(TC_GEN_FILTER);
  790. __try {
  791. RtlCopyMemory(p, pGenFilter->Pattern, pGenFilter->PatternSize);
  792. if (pGenFilter->AddressType == NDIS_PROTOCOL_ID_TCP_IP) {
  793. if(pTcIfc->InterfaceIndex == IF_UNKNOWN) {
  794. if (NO_ERROR != (Status = GetInterfaceIndex(pTcIfc->pAddressListDesc,
  795. &pTcIfc->InterfaceIndex,
  796. &pTcIfc->SpecificLinkCtx))) {
  797. FreeMem(pFilter);
  798. FreeMem(pGpcFilter);
  799. return Status;
  800. }
  801. }
  802. //
  803. // IP pattern, set reserved fields
  804. //
  805. pIpPattern = (PIP_PATTERN)p;
  806. pIpPattern->Reserved1 = pFlow->pInterface->pTcIfc->InterfaceIndex;
  807. pIpPattern->Reserved2 = pFlow->pInterface->pTcIfc->SpecificLinkCtx;
  808. pIpPattern->Reserved3[0] = pIpPattern->Reserved3[1] = pIpPattern->Reserved3[2] = 0;
  809. }
  810. } __except (EXCEPTION_EXECUTE_HANDLER) {
  811. Status = ERROR_INVALID_PARAMETER;
  812. IF_DEBUG(ERRORS) {
  813. WSPRINT(("CreateFilterStruc: Exception Error: = 0x%X\n",
  814. Status ));
  815. }
  816. FreeMem(pGpcFilter);
  817. FreeMem(pFilter);
  818. return Status;
  819. }
  820. pGpcFilter->Pattern = (PVOID)p;
  821. p += pGenFilter->PatternSize;
  822. __try {
  823. RtlCopyMemory(p, pGenFilter->Mask, pGenFilter->PatternSize);
  824. if (pGenFilter->AddressType == NDIS_PROTOCOL_ID_TCP_IP) {
  825. //
  826. // IP pattern, set reserved fields
  827. //
  828. pIpPattern = (PIP_PATTERN)p;
  829. pIpPattern->Reserved1 = pIpPattern->Reserved2 = 0xffffffff;
  830. pIpPattern->Reserved3[0] = pIpPattern->Reserved3[1] = pIpPattern->Reserved3[2] = 0xff;
  831. }
  832. } __except (EXCEPTION_EXECUTE_HANDLER) {
  833. Status = ERROR_INVALID_PARAMETER;
  834. IF_DEBUG(ERRORS) {
  835. WSPRINT(("CreateFilterStruc: Exception Error: = 0x%X\n",
  836. Status ));
  837. }
  838. FreeMem(pGpcFilter);
  839. FreeMem(pFilter);
  840. return Status;
  841. }
  842. pGpcFilter->Mask = (PVOID)p;
  843. pFilter->pGpcFilter = pGpcFilter;
  844. //
  845. // acquire a new handle for the Filter
  846. //
  847. pFilter->ClHandle = AllocateHandle((PVOID)pFilter);
  848. // what if we're out of memory?
  849. if (!pFilter->ClHandle) {
  850. IF_DEBUG(ERRORS) {
  851. WSPRINT(("CreateFilterStruc: Cant allocate Handle\n"));
  852. }
  853. FreeMem(pGpcFilter);
  854. FreeMem(pFilter);
  855. return ERROR_NOT_ENOUGH_MEMORY;
  856. }
  857. //
  858. // set the other parameters in the Filter
  859. //
  860. pFilter->ObjectType = ENUM_FILTER_TYPE;
  861. pFilter->Flags = 0;
  862. ReferenceInit(&pFilter->RefCount, pFilter, DereferenceFilter);
  863. REFADD(&pFilter->RefCount, 'FILT');
  864. __try {
  865. InitLock(pFilter->Lock);
  866. } __except (EXCEPTION_EXECUTE_HANDLER) {
  867. Status = GetExceptionCode();
  868. IF_DEBUG(ERRORS) {
  869. WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status ));
  870. }
  871. FreeHandle(pFilter->ClHandle);
  872. FreeMem(pFilter);
  873. FreeMem(pGpcFilter);
  874. return Status;
  875. }
  876. SET_STATE(pFilter->State, INSTALLING);
  877. //
  878. // set the Gpc protocol template from the address type
  879. //
  880. pFilter->GpcProtocolTemplate = ProtocolId;
  881. }
  882. } else {
  883. Status = ERROR_NOT_ENOUGH_MEMORY;
  884. }
  885. *ppFilter = pFilter;
  886. return Status;
  887. }
  888. DWORD
  889. EnumAllInterfaces(VOID)
  890. {
  891. PCLIENT_STRUC pClient;
  892. DWORD Status;
  893. WMIHANDLE WmiHandle;
  894. ULONG MyBufferSize = 2 KiloBytes; // is this enough?!?
  895. PWNODE_ALL_DATA pWnode;
  896. PWNODE_ALL_DATA pWnodeBuffer;
  897. PTC_IFC pTcIfc;
  898. if (_init)
  899. return NO_ERROR;
  900. //
  901. // get a WMI block handle to the GUID_QOS_SUPPORTED
  902. //
  903. Status = WmiOpenBlock((GUID *)&GUID_QOS_TC_SUPPORTED, 0, &WmiHandle);
  904. if (ERROR_FAILED(Status)) {
  905. if (Status == ERROR_WMI_GUID_NOT_FOUND) {
  906. //
  907. // this means there is no TC data provider
  908. //
  909. Status = NO_ERROR; //ERROR_TC_NOT_SUPPORTED
  910. }
  911. return Status;
  912. }
  913. do {
  914. //
  915. // allocate a private buffer to retrieve all wnodes
  916. //
  917. AllocMem(&pWnodeBuffer, MyBufferSize);
  918. if (pWnodeBuffer == NULL) {
  919. WmiCloseBlock(WmiHandle);
  920. return ERROR_NOT_ENOUGH_MEMORY;
  921. }
  922. __try {
  923. Status = WmiQueryAllData(WmiHandle, &MyBufferSize, pWnodeBuffer);
  924. } __except (EXCEPTION_EXECUTE_HANDLER) {
  925. Status = GetExceptionCode();
  926. IF_DEBUG(ERRORS) {
  927. WSPRINT(("EnumAllInterfaces: Exception Error: = %X\n",
  928. Status ));
  929. }
  930. }
  931. if (Status == ERROR_INSUFFICIENT_BUFFER) {
  932. //
  933. // failed since the buffer was too small
  934. // release the buffer and double the size
  935. //
  936. MyBufferSize *= 2;
  937. FreeMem(pWnodeBuffer);
  938. pWnodeBuffer = NULL;
  939. }
  940. } while (Status == ERROR_INSUFFICIENT_BUFFER);
  941. if (!ERROR_FAILED(Status)) {
  942. ULONG dwInstanceNum;
  943. ULONG InstanceSize;
  944. PULONG lpdwNameOffsets;
  945. BOOL bFixedSize = FALSE;
  946. USHORT usNameLength;
  947. ULONG DescSize;
  948. PTC_SUPPORTED_INFO_BUFFER pTcInfoBuffer;
  949. pWnode = pWnodeBuffer;
  950. ASSERT(pWnode->WnodeHeader.Flags & WNODE_FLAG_ALL_DATA);
  951. do {
  952. //
  953. // Check for fixed instance size
  954. //
  955. if (pWnode->WnodeHeader.Flags & WNODE_FLAG_FIXED_INSTANCE_SIZE) {
  956. InstanceSize = pWnode->FixedInstanceSize;
  957. bFixedSize = TRUE;
  958. pTcInfoBuffer =
  959. (PTC_SUPPORTED_INFO_BUFFER)OffsetToPtr(pWnode,
  960. pWnode->DataBlockOffset);
  961. }
  962. //
  963. // Get a pointer to the array of offsets to the instance names
  964. //
  965. lpdwNameOffsets = (PULONG) OffsetToPtr(pWnode,
  966. pWnode->OffsetInstanceNameOffsets);
  967. for ( dwInstanceNum = 0;
  968. dwInstanceNum < pWnode->InstanceCount;
  969. dwInstanceNum++) {
  970. usNameLength =
  971. *(USHORT *)OffsetToPtr(pWnode,
  972. lpdwNameOffsets[dwInstanceNum]);
  973. //
  974. // Length and offset for variable data
  975. //
  976. if ( !bFixedSize ) {
  977. InstanceSize =
  978. pWnode->OffsetInstanceDataAndLength[dwInstanceNum].LengthInstanceData;
  979. pTcInfoBuffer =
  980. (PTC_SUPPORTED_INFO_BUFFER)OffsetToPtr(
  981. (PBYTE)pWnode,
  982. pWnode->OffsetInstanceDataAndLength[dwInstanceNum].OffsetInstanceData);
  983. }
  984. //
  985. // we have all that is needed. we need to figure if
  986. // there is enough buffer space to put the data as well
  987. //
  988. ASSERT(usNameLength < MAX_STRING_LENGTH);
  989. DescSize = InstanceSize - FIELD_OFFSET(TC_SUPPORTED_INFO_BUFFER, AddrListDesc);
  990. //
  991. // Allocate a new interface descriptor structure
  992. //
  993. CreateKernelInterfaceStruc(&pTcIfc, DescSize);
  994. if (pTcIfc != NULL) {
  995. //
  996. // copy the instance name string data
  997. //
  998. RtlCopyMemory(pTcIfc->InstanceName,
  999. OffsetToPtr(pWnode,
  1000. lpdwNameOffsets[dwInstanceNum]+2),
  1001. usNameLength );
  1002. pTcIfc->InstanceNameLength = usNameLength;
  1003. pTcIfc->InstanceName[usNameLength/sizeof(WCHAR)] =
  1004. (WCHAR)0;
  1005. //
  1006. // copy the instance ID string data
  1007. //
  1008. RtlCopyMemory(pTcIfc->InstanceID,
  1009. &pTcInfoBuffer->InstanceID[0],
  1010. pTcInfoBuffer->InstanceIDLength );
  1011. pTcIfc->InstanceIDLength = pTcInfoBuffer->InstanceIDLength;
  1012. pTcIfc->InstanceID[pTcInfoBuffer->InstanceIDLength/sizeof(WCHAR)] =
  1013. (WCHAR)0;
  1014. //
  1015. // copy the instance data
  1016. // in this case - the network address
  1017. //
  1018. pTcIfc->AddrListBytesCount = DescSize;
  1019. //
  1020. // a sizeof(ULONG) since the structure is defined as ARRAY
  1021. // and the first ULONG is the number of elements
  1022. //
  1023. RtlCopyMemory( pTcIfc->pAddressListDesc,
  1024. &pTcInfoBuffer->AddrListDesc,
  1025. DescSize );
  1026. if (NO_ERROR != GetInterfaceIndex(pTcIfc->pAddressListDesc,
  1027. &pTcIfc->InterfaceIndex,
  1028. &pTcIfc->SpecificLinkCtx)) {
  1029. pTcIfc->InterfaceIndex = IF_UNKNOWN;
  1030. pTcIfc->SpecificLinkCtx = IF_UNKNOWN;
  1031. }
  1032. // set the state to open
  1033. GetLock(pTcIfc->Lock);
  1034. SET_STATE(pTcIfc->State, OPEN);
  1035. FreeLock(pTcIfc->Lock);
  1036. //
  1037. // Add the structure to the global linked list
  1038. //
  1039. GetLock( pGlobals->Lock );
  1040. InsertTailList(&pGlobals->TcIfcList, &pTcIfc->Linkage );
  1041. FreeLock( pGlobals->Lock );
  1042. #if 0
  1043. //
  1044. // make sure we have one gpc client per address type
  1045. //
  1046. Status = OpenGpcClients(pTcIfc);
  1047. if (ERROR_FAILED(Status)) {
  1048. break;
  1049. }
  1050. #endif
  1051. } else {
  1052. //
  1053. // no more memory, quit here
  1054. //
  1055. Status = ERROR_NOT_ENOUGH_MEMORY;
  1056. break;
  1057. }
  1058. }
  1059. //
  1060. // Update Wnode to point to next node
  1061. //
  1062. if ( pWnode->WnodeHeader.Linkage != 0) {
  1063. pWnode = (PWNODE_ALL_DATA) OffsetToPtr( pWnode,
  1064. pWnode->WnodeHeader.Linkage);
  1065. } else {
  1066. pWnode = NULL;
  1067. }
  1068. } while (pWnode != NULL && !ERROR_FAILED(Status));
  1069. }
  1070. //
  1071. // release resources and close WMI handle
  1072. //
  1073. WmiCloseBlock(WmiHandle);
  1074. if (pWnodeBuffer)
  1075. FreeMem(pWnodeBuffer);
  1076. if (Status == NO_ERROR) {
  1077. _init = TRUE;
  1078. }
  1079. return Status;
  1080. }
  1081. DWORD
  1082. CloseInterface(
  1083. IN PINTERFACE_STRUC pInterface,
  1084. BOOLEAN RemoveFlows
  1085. )
  1086. {
  1087. IF_DEBUG(CALLS) {
  1088. WSPRINT(("==>CloseInterface: pInterface=%X\n",
  1089. pInterface));
  1090. }
  1091. if (RemoveFlows) {
  1092. CloseOpenFlows(pInterface);
  1093. }
  1094. REFDEL(&pInterface->RefCount, 'CIFC');
  1095. IF_DEBUG(CALLS) {
  1096. WSPRINT(("==>CloseInterface: NO_ERROR\n"));
  1097. }
  1098. return NO_ERROR;
  1099. }
  1100. DWORD
  1101. DeleteFlow(
  1102. IN PFLOW_STRUC pFlow,
  1103. IN BOOLEAN RemoveFilters
  1104. )
  1105. {
  1106. DWORD Status;
  1107. PLIST_ENTRY pEntry;
  1108. PFILTER_STRUC pFilter;
  1109. IF_DEBUG(CALLS) {
  1110. WSPRINT(("DeleteFlow: attempting to delete flow=0x%X\n",
  1111. PtrToUlong(pFlow)));
  1112. }
  1113. if (RemoveFilters) {
  1114. CloseOpenFilters(pFlow);
  1115. } else {
  1116. if (/*pFlow->FilterCount > 0*/ !IsListEmpty(&pFlow->FilterList)) {
  1117. IF_DEBUG(ERRORS) {
  1118. WSPRINT(("DeleteFlow: filter list NOT empty\n"));
  1119. }
  1120. #if DBG
  1121. pEntry = pFlow->FilterList.Flink;
  1122. while (pEntry != &pFlow->FilterList) {
  1123. pFilter = CONTAINING_RECORD(pEntry, FILTER_STRUC, Linkage);
  1124. IF_DEBUG(ERRORS) {
  1125. WSPRINT(("<==TcDeleteFlow: Filter %x (handle %x) is open with RefCount:%d\n", pFilter, pFilter->ClHandle, pFilter->RefCount));
  1126. }
  1127. pEntry = pEntry->Flink;
  1128. }
  1129. #endif
  1130. return ERROR_TC_SUPPORTED_OBJECTS_EXIST;
  1131. }
  1132. }
  1133. //
  1134. // can remove the flow now
  1135. //
  1136. Status = IoDeleteFlow( pFlow, (BOOLEAN)!RemoveFilters );
  1137. IF_DEBUG(CALLS) {
  1138. WSPRINT(("DeleteFlow: IoDeleteFlow returned=0x%X\n",
  1139. Status));
  1140. }
  1141. if (!ERROR_PENDING(Status)) {
  1142. //
  1143. // call completed, either success or failure...
  1144. //
  1145. CompleteDeleteFlow(pFlow, Status);
  1146. }
  1147. return Status;
  1148. }
  1149. DWORD
  1150. DeleteFilter(
  1151. IN PFILTER_STRUC pFilter
  1152. )
  1153. {
  1154. DWORD Status;
  1155. IF_DEBUG(CALLS) {
  1156. WSPRINT(( "DeleteFilter: attempting to delete=0x%X\n",
  1157. PtrToUlong(pFilter)));
  1158. }
  1159. //
  1160. // call to actually delete the filter
  1161. //
  1162. Status = IoDeleteFilter( pFilter );
  1163. IF_DEBUG(CALLS) {
  1164. WSPRINT(( "DeleteFilter: IoDeleteFilter returned=0x%X\n",
  1165. Status));
  1166. }
  1167. //ASSERT(Status == NO_ERROR);
  1168. REFDEL(&pFilter->RefCount, 'FILT');
  1169. return Status;
  1170. }
  1171. PGPC_CLIENT
  1172. FindGpcClient(
  1173. IN ULONG CfInfoType
  1174. )
  1175. {
  1176. PGPC_CLIENT pGpcClient = NULL;
  1177. PLIST_ENTRY pHead, pEntry;
  1178. GetLock( pGlobals->Lock );
  1179. pHead = &pGlobals->GpcClientList;
  1180. pEntry = pHead->Flink;
  1181. while (pHead != pEntry && pGpcClient == NULL) {
  1182. pGpcClient = CONTAINING_RECORD(pEntry, GPC_CLIENT, Linkage);
  1183. if (CfInfoType != pGpcClient->CfInfoType) {
  1184. //
  1185. // address type doesn't match!
  1186. //
  1187. pGpcClient = NULL;
  1188. }
  1189. pEntry = pEntry->Flink;
  1190. }
  1191. FreeLock( pGlobals->Lock );
  1192. return pGpcClient;
  1193. }
  1194. VOID
  1195. CompleteAddFlow(
  1196. IN PFLOW_STRUC pFlow,
  1197. IN DWORD Status
  1198. )
  1199. {
  1200. PINTERFACE_STRUC pInterface;
  1201. ASSERT(pFlow);
  1202. ASSERT(!ERROR_PENDING(Status));
  1203. IF_DEBUG(CALLS) {
  1204. WSPRINT(("CompleteAddFlow: pFlow=0x%X Status=0x%X\n",
  1205. PtrToUlong(pFlow), Status));
  1206. }
  1207. if(pFlow->CompletionBuffer) {
  1208. FreeMem(pFlow->CompletionBuffer);
  1209. pFlow->CompletionBuffer = NULL;
  1210. }
  1211. //
  1212. // Check if the interface is still around.
  1213. //
  1214. GetLock(pFlow->Lock);
  1215. pInterface = pFlow->pInterface;
  1216. FreeLock(pFlow->Lock);
  1217. if (ERROR_FAILED(Status)) {
  1218. //
  1219. // failed, release resources
  1220. //
  1221. CompleteDeleteFlow(pFlow, Status);
  1222. } else {
  1223. GetLock(pGlobals->Lock);
  1224. GetLock(pInterface->Lock);
  1225. if (QUERY_STATE(pInterface->State) != OPEN) {
  1226. FreeLock(pInterface->Lock);
  1227. FreeLock(pGlobals->Lock);
  1228. IF_DEBUG(ERRORS) {
  1229. WSPRINT(("CompleteAddFlow: Interface (%X) is NOT open pFlow=0x%X Status=0x%X\n", pInterface->ClHandle,
  1230. PtrToUlong(pFlow), Status));
  1231. }
  1232. //
  1233. // Delete the only ref we have on this flow and get out.
  1234. //
  1235. REFDEL(&pFlow->RefCount, 'FLOW');
  1236. } else {
  1237. FreeLock(pInterface->Lock);
  1238. //
  1239. // The flow is ready for business
  1240. //
  1241. GetLock(pFlow->Lock);
  1242. SET_STATE(pFlow->State, OPEN);
  1243. FreeLock(pFlow->Lock);
  1244. //
  1245. // Announce on the lists that we are ready for business
  1246. //
  1247. pInterface->FlowCount++;
  1248. REFADD(&pInterface->RefCount, 'FLOW');
  1249. InsertTailList(&pInterface->FlowList, &pFlow->Linkage);
  1250. FreeLock(pGlobals->Lock);
  1251. }
  1252. }
  1253. //
  1254. // This ref was taken in TcAddFlow.
  1255. //
  1256. REFDEL(&pInterface->RefCount, 'TCAF');
  1257. }
  1258. VOID
  1259. CompleteModifyFlow(
  1260. IN PFLOW_STRUC pFlow,
  1261. IN DWORD Status
  1262. )
  1263. {
  1264. ASSERT(pFlow);
  1265. ASSERT(!ERROR_PENDING(Status));
  1266. IF_DEBUG(CALLS) {
  1267. WSPRINT(("CompleteModifyFlow: pFlow=0x%X Status=0x%X\n",
  1268. PtrToUlong(pFlow), Status));
  1269. }
  1270. GetLock(pFlow->Lock);
  1271. if(pFlow->CompletionBuffer) {
  1272. FreeMem(pFlow->CompletionBuffer);
  1273. pFlow->CompletionBuffer = NULL;
  1274. }
  1275. if (ERROR_FAILED(Status)) {
  1276. //
  1277. // failed, release the newly allocated generic flow parameters
  1278. //
  1279. FreeMem(pFlow->pGenFlow1);
  1280. } else {
  1281. //
  1282. // modification accepted, update the generic flow parameters
  1283. //
  1284. FreeMem(pFlow->pGenFlow);
  1285. pFlow->pGenFlow = pFlow->pGenFlow1;
  1286. pFlow->GenFlowLen = pFlow->GenFlowLen;
  1287. }
  1288. //
  1289. // clear the installing flag
  1290. //
  1291. pFlow->Flags &= ~TC_FLAGS_MODIFYING;
  1292. pFlow->pGenFlow1 = NULL;
  1293. pFlow->GenFlowLen1 = 0;
  1294. FreeLock(pFlow->Lock);
  1295. //
  1296. // This ref was taken in TcModifyFlow
  1297. //
  1298. REFDEL(&pFlow->RefCount, 'TCMF');
  1299. IF_DEBUG(CALLS) {
  1300. WSPRINT(("CompleteModifyFlow: pFlow=0x%X Status=0x%X\n",
  1301. PtrToUlong(pFlow), Status));
  1302. }
  1303. }
  1304. VOID
  1305. CompleteDeleteFlow(
  1306. IN PFLOW_STRUC pFlow,
  1307. IN DWORD Status
  1308. )
  1309. {
  1310. ASSERT(pFlow);
  1311. //ASSERT(Status == NO_ERROR);
  1312. //ASSERT(pFlow->CompletionBuffer);
  1313. IF_DEBUG(CALLS) {
  1314. WSPRINT(("CompleteDeleteFlow: pFlow=0x%X Status=0x%X\n",
  1315. PtrToUlong(pFlow), Status));
  1316. }
  1317. //
  1318. // okay, release resources
  1319. //
  1320. GetLock(pFlow->Lock);
  1321. if (pFlow->CompletionBuffer) {
  1322. FreeMem(pFlow->CompletionBuffer);
  1323. pFlow->CompletionBuffer = NULL;
  1324. }
  1325. FreeLock(pFlow->Lock);
  1326. IF_DEBUG(REFCOUNTS) {
  1327. WSPRINT(("#21 DEREF FLOW %X (%X) ref(%d)\n", pFlow->ClHandle, pFlow, pFlow->RefCount));
  1328. }
  1329. REFDEL(&pFlow->RefCount, 'FLOW');
  1330. }
  1331. DWORD
  1332. OpenGpcClients(
  1333. IN ULONG CfInfoType
  1334. )
  1335. {
  1336. DWORD Status = NO_ERROR;
  1337. PLIST_ENTRY pHead, pEntry;
  1338. PGPC_CLIENT pGpcClient;
  1339. //int i;
  1340. if (FindGpcClient(CfInfoType) == NULL) {
  1341. //
  1342. // create an entry in the
  1343. //
  1344. AllocMem(&pGpcClient, sizeof(GPC_CLIENT) );
  1345. if (pGpcClient == NULL) {
  1346. return ERROR_NOT_ENOUGH_MEMORY;
  1347. }
  1348. pGpcClient->CfInfoType = CfInfoType;
  1349. pGpcClient->RefCount = 1;
  1350. //
  1351. // register the gpc client
  1352. //
  1353. Status = IoRegisterClient(pGpcClient);
  1354. if (ERROR_FAILED(Status)) {
  1355. FreeMem(pGpcClient);
  1356. } else {
  1357. GetLock( pGlobals->Lock);
  1358. InsertTailList(&pGlobals->GpcClientList, &pGpcClient->Linkage);
  1359. FreeLock( pGlobals->Lock);
  1360. }
  1361. }
  1362. return Status;
  1363. }
  1364. DWORD
  1365. DereferenceInterface(
  1366. IN PINTERFACE_STRUC pInterface
  1367. )
  1368. {
  1369. DWORD Status = NO_ERROR;
  1370. IF_DEBUG(CALLS) {
  1371. WSPRINT(("==>DereferenceInterface: IfcH=%X RefCount=%d\n",
  1372. pInterface->ClHandle, pInterface->RefCount));
  1373. }
  1374. FreeHandle(pInterface->ClHandle);
  1375. //GetLock(pGlobals->Lock);
  1376. IF_DEBUG(REFCOUNTS) {
  1377. WSPRINT(("==>DereferenceInterface: IfcH=%X Interface=%x\n",
  1378. pInterface->ClHandle, pInterface));
  1379. }
  1380. //
  1381. // close the interface and all flows/filters
  1382. //
  1383. RemoveEntryList(&pInterface->Linkage);
  1384. RemoveEntryList(&pInterface->NextIfc);
  1385. //
  1386. // Deregister from any guid notification requests
  1387. //
  1388. TcipDeleteInterfaceFromNotificationList(
  1389. pInterface,
  1390. 0
  1391. );
  1392. //
  1393. // #295267
  1394. // Do not dereference Client OR decrement Interface Count until
  1395. // the Interface is actually going away. Otherwise, the client structures
  1396. // are cleaned out, and when the ref count finally goes down and we
  1397. // touch this code path, we hit an AV.
  1398. //
  1399. pInterface->pClient->InterfaceCount--;
  1400. IF_DEBUG(HANDLES) {
  1401. WSPRINT(("DEREF Client A : %x\n", pInterface->pClient->ClHandle));
  1402. }
  1403. REFDEL(&pInterface->pClient->RefCount, 'CIFC');
  1404. REFDEL(&pInterface->pTcIfc->RefCount, 'CIFC');
  1405. //
  1406. // This is complex, so read carefully.
  1407. // We want CloseInterface to wait until the event is set (292120).
  1408. // It is likely that in case the TcCloseInterface call didn't
  1409. // come in, we dont have to set the Event since the TC_FLAGS_WAITING
  1410. // will not be set in that case.
  1411. //
  1412. if (!IS_WAITING(pInterface->Flags)) {
  1413. CloseHandle(pInterface->IfcEvent);
  1414. } else {
  1415. SetEvent(pInterface->IfcEvent);
  1416. }
  1417. //
  1418. // free the interface resources
  1419. //
  1420. DeleteLock(pInterface->Lock);
  1421. FreeMem(pInterface);
  1422. //FreeLock(pGlobals->Lock);
  1423. IF_DEBUG(CALLS) {
  1424. WSPRINT(("<==DereferenceInterface: Status=%X\n", Status));
  1425. }
  1426. return Status;
  1427. }
  1428. DWORD
  1429. DereferenceFlow(
  1430. IN PFLOW_STRUC pFlow
  1431. )
  1432. {
  1433. DWORD Status = NO_ERROR;
  1434. IF_DEBUG(CALLS) {
  1435. WSPRINT(("==>DereferenceFlow: FlowH=%X Flow=%X\n",
  1436. pFlow->ClHandle, pFlow));
  1437. }
  1438. //GetLock(pGlobals->Lock);
  1439. IF_DEBUG(REFCOUNTS) {
  1440. WSPRINT(("==>DereferenceFlow: FlowH=%X Flow=%X\n",
  1441. pFlow->ClHandle, pFlow));
  1442. }
  1443. FreeHandle(pFlow->ClHandle);
  1444. GetLock(pFlow->Lock);
  1445. if (QUERY_STATE(pFlow->State) != INSTALLING) {
  1446. FreeLock(pFlow->Lock);
  1447. RemoveEntryList(&pFlow->Linkage);
  1448. pFlow->pInterface->FlowCount--;
  1449. IF_DEBUG(HANDLES) {
  1450. WSPRINT(("DEREF Interface A : %x\n", pFlow->pInterface->ClHandle));
  1451. }
  1452. REFDEL(&pFlow->pInterface->RefCount, 'FLOW');
  1453. } else {
  1454. FreeLock(pFlow->Lock);
  1455. }
  1456. //
  1457. // moved here from CompleteDeleteFlow
  1458. //
  1459. //
  1460. // free the interface resources
  1461. //
  1462. DeleteFlowStruc(pFlow);
  1463. //FreeLock(pGlobals->Lock);
  1464. IF_DEBUG(CALLS) {
  1465. WSPRINT(("<==DereferenceFlow: Status=%X\n", Status));
  1466. }
  1467. return Status;
  1468. }
  1469. DWORD
  1470. DereferenceClient(
  1471. IN PCLIENT_STRUC pClient
  1472. )
  1473. {
  1474. //GetLock( pGlobals->Lock );
  1475. IF_DEBUG(REFCOUNTS) {
  1476. WSPRINT(("==>DereferenceClient: pClient=%x, Handle=%x, RefCount=%d\n",
  1477. pClient, pClient->ClHandle, pClient->RefCount));
  1478. }
  1479. GetLock(pClient->Lock);
  1480. SET_STATE(pClient->State, REMOVED);
  1481. FreeLock(pClient->Lock);
  1482. FreeHandle( pClient->ClHandle );
  1483. RemoveEntryList( &pClient->Linkage );
  1484. DeleteLock(pClient->Lock);
  1485. FreeMem( pClient );
  1486. //FreeLock( pGlobals->Lock );
  1487. return NO_ERROR;
  1488. }
  1489. DWORD
  1490. DereferenceFilter(
  1491. IN PFILTER_STRUC pFilter
  1492. )
  1493. {
  1494. DWORD Status = NO_ERROR;
  1495. IF_DEBUG(CALLS) {
  1496. WSPRINT(("==>DereferenceFilter: FilterH=%X RefCount=%d\n",
  1497. pFilter->ClHandle, pFilter->RefCount));
  1498. }
  1499. //GetLock(pGlobals->Lock);
  1500. IF_DEBUG(REFCOUNTS) {
  1501. WSPRINT(("==>DereferenceFilter: FilterH=%X Filter=%X on FLOW=%X\n",
  1502. pFilter->ClHandle, pFilter, pFilter->pFlow));
  1503. }
  1504. FreeHandle(pFilter->ClHandle);
  1505. //
  1506. // remove the flow from the list
  1507. //
  1508. GetLock(pFilter->Lock);
  1509. if (QUERY_STATE(pFilter->State) != INSTALLING) {
  1510. FreeLock(pFilter->Lock);
  1511. RemoveEntryList(&pFilter->Linkage);
  1512. pFilter->pFlow->FilterCount--;
  1513. IF_DEBUG(REFCOUNTS) {
  1514. WSPRINT(("#22 DEREF FLOW %X (%X) ref(%d)\n", pFilter->pFlow->ClHandle, pFilter->pFlow, pFilter->pFlow->RefCount));
  1515. }
  1516. REFDEL(&pFilter->pFlow->RefCount, 'FILT');
  1517. } else {
  1518. FreeLock(pFilter->Lock);
  1519. }
  1520. DeleteFilterStruc(pFilter);
  1521. //FreeLock(pGlobals->Lock);
  1522. IF_DEBUG(CALLS) {
  1523. WSPRINT(("<==DereferenceFilter: Status=%X\n", Status));
  1524. }
  1525. return Status;
  1526. }
  1527. DWORD
  1528. GetInterfaceIndex(
  1529. IN PADDRESS_LIST_DESCRIPTOR pAddressListDesc,
  1530. OUT PULONG pInterfaceIndex,
  1531. OUT PULONG pSpecificLinkCtx)
  1532. {
  1533. PNETWORK_ADDRESS_LIST pAddrList;
  1534. NETWORK_ADDRESS UNALIGNED *pAddr;
  1535. DWORD n,k;
  1536. DWORD Status = NO_ERROR;
  1537. PMIB_IPADDRTABLE pIpAddrTbl;
  1538. DWORD dwSize = 2 KiloBytes;
  1539. NETWORK_ADDRESS_IP UNALIGNED *pIpNetAddr = 0;
  1540. DWORD cAddr;
  1541. *pInterfaceIndex = 0;
  1542. *pSpecificLinkCtx = 0;
  1543. cAddr = pAddressListDesc->AddressList.AddressCount;
  1544. if (cAddr == 0) {
  1545. //
  1546. // no address
  1547. //
  1548. return NO_ERROR;
  1549. }
  1550. #if INTERFACE_ID
  1551. AllocMem(&pIpAddrTbl, dwSize);
  1552. if (pIpAddrTbl == NULL) {
  1553. return ERROR_NOT_ENOUGH_MEMORY;
  1554. }
  1555. pAddr = (UNALIGNED NETWORK_ADDRESS *) &pAddressListDesc->AddressList.Address[0];
  1556. for (n = 0; n < cAddr; n++) {
  1557. if (pAddr->AddressType == NDIS_PROTOCOL_ID_TCP_IP) {
  1558. pIpNetAddr = (UNALIGNED NETWORK_ADDRESS_IP *)&pAddr->Address[0];
  1559. break;
  1560. }
  1561. pAddr = (UNALIGNED NETWORK_ADDRESS *)(((PUCHAR)pAddr)
  1562. + pAddr->AddressLength
  1563. + FIELD_OFFSET(NETWORK_ADDRESS, Address));
  1564. }
  1565. if (pIpNetAddr) {
  1566. Status = GetIpAddrTableFromStack(
  1567. pIpAddrTbl,
  1568. dwSize,
  1569. FALSE
  1570. );
  1571. if (Status == NO_ERROR) {
  1572. //
  1573. // search for the matching IP address to IpAddr
  1574. // in the table we got back from the stack
  1575. //
  1576. for (k = 0; k < pIpAddrTbl->dwNumEntries; k++) {
  1577. if (pIpAddrTbl->table[k].dwAddr == pIpNetAddr->in_addr) {
  1578. //
  1579. // found one, get the index
  1580. //
  1581. *pInterfaceIndex = pIpAddrTbl->table[k].dwIndex;
  1582. break;
  1583. }
  1584. }
  1585. if (pAddressListDesc->MediaType == NdisMediumWan) {
  1586. if (n+1 < cAddr) {
  1587. //
  1588. // there is another address that contains
  1589. // the remote client address
  1590. // this should be used as the link ID
  1591. //
  1592. pAddr = (UNALIGNED NETWORK_ADDRESS *)(((PUCHAR)pAddr)
  1593. + pAddr->AddressLength
  1594. + FIELD_OFFSET(NETWORK_ADDRESS, Address));
  1595. if (pAddr->AddressType == NDIS_PROTOCOL_ID_TCP_IP) {
  1596. //
  1597. // parse the second IP address,
  1598. // this would be the remote IP address for dialin WAN
  1599. //
  1600. pIpNetAddr = (UNALIGNED NETWORK_ADDRESS_IP *)&pAddr->Address[0];
  1601. *pSpecificLinkCtx = pIpNetAddr->in_addr;
  1602. }
  1603. }
  1604. }
  1605. }
  1606. }
  1607. FreeMem(pIpAddrTbl);
  1608. #endif
  1609. return Status;
  1610. }