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.

3696 lines
95 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. api.c
  5. Abstract:
  6. This module contains the traffic control apis.
  7. Author:
  8. Jim Stewart ( jstew ) July 28, 1996
  9. Revision History:
  10. Ofer Bar ( oferbar ) Oct 1, 1997 - Rev 2
  11. Shreedhar Madhavapeddi (ShreeM) March 10, 1999 Rev 3
  12. --*/
  13. /*
  14. *********************************************************************
  15. Revision 3 => Changes [ShreeM]
  16. 1. Build concrete state machines for Interface, Flow and Filter structures.
  17. 2. Define Locks for each of these structures.
  18. 3. Use above Locks for recording every state transistion.
  19. 4. Use debug logs to record transitions.
  20. 5. The Global lock is always taken before any of the Flow, Filter or Interface locks.
  21. */
  22. #include "precomp.h"
  23. //#pragma hdrstop
  24. //#include "oscode.h"
  25. /*
  26. ************************************************************************
  27. Description:
  28. This will create a new client handle and will also associate
  29. it with a client's handler list. It also checks for the version number.
  30. Arguments:
  31. TciVersion - The client expected version
  32. ClientHandlerList - The client's handler list
  33. pClientHandle - output client handle
  34. Return Value:
  35. NO_ERROR
  36. ERROR_NOT_ENOUGH_MEMORY out of memory
  37. ERROR_INVALID_PARAMETER one of the parameters is NULL
  38. ERROR_INCOMPATIBLE_TC_VERSION wrong version
  39. ERROR_NO_SYSTEM_RESOURCES not enough resources (handles)
  40. ************************************************************************
  41. */
  42. DWORD
  43. APIENTRY
  44. TcRegisterClient(
  45. IN ULONG TciVersion,
  46. IN HANDLE ClRegCtx,
  47. IN PTCI_CLIENT_FUNC_LIST ClientHandlerList,
  48. OUT PHANDLE pClientHandle
  49. )
  50. {
  51. DWORD Status;
  52. PCLIENT_STRUC pClient;
  53. BOOL RegisterWithGpc = FALSE;
  54. VERIFY_INITIALIZATION_STATUS;
  55. IF_DEBUG(CALLS) {
  56. WSPRINT(("==>TcRegisterClient: Called: Ver= %d, Ctx=%x\n",
  57. TciVersion, ClRegCtx));
  58. }
  59. if (IsBadWritePtr(pClientHandle,sizeof(HANDLE))) {
  60. Status = ERROR_INVALID_PARAMETER;
  61. IF_DEBUG(ERRORS) {
  62. WSPRINT(("TcRegisterClient: Error = 0x%X\n", Status ));
  63. }
  64. return Status;
  65. }
  66. //
  67. // Set a default pClientHandle as early as possible
  68. //
  69. __try {
  70. *pClientHandle = TC_INVALID_HANDLE;
  71. } __except (EXCEPTION_EXECUTE_HANDLER) {
  72. Status = GetExceptionCode();
  73. IF_DEBUG(ERRORS) {
  74. WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status ));
  75. }
  76. return Status;
  77. }
  78. if (TciVersion != CURRENT_TCI_VERSION) {
  79. Status = ERROR_INCOMPATIBLE_TCI_VERSION;
  80. IF_DEBUG(ERRORS) {
  81. WSPRINT(("TcRegisterClient: Error = 0x%X\n", Status ));
  82. }
  83. return Status;
  84. }
  85. if (IsBadReadPtr(ClientHandlerList,sizeof(TCI_CLIENT_FUNC_LIST))) {
  86. Status = ERROR_INVALID_PARAMETER;
  87. IF_DEBUG(ERRORS) {
  88. WSPRINT(("TcRegisterClient: Error = 0x%X\n", Status ));
  89. }
  90. return Status;
  91. }
  92. if (IsBadCodePtr((FARPROC) ClientHandlerList->ClNotifyHandler)) {
  93. //
  94. // a client must support a notification handler
  95. //
  96. Status = ERROR_INVALID_PARAMETER;
  97. IF_DEBUG(ERRORS) {
  98. WSPRINT(("TcRegisterClient: Error = 0x%X\n", Status ));
  99. }
  100. return Status;
  101. }
  102. // Prevent another thread from doing TcRegisterClient and TcDeregisterClient
  103. GetLock( ClientRegDeregLock );
  104. //
  105. // finish initialization (if needed)
  106. //
  107. InitializeWmi();
  108. Status = EnumAllInterfaces();
  109. if (ERROR_FAILED(Status)) {
  110. FreeLock( ClientRegDeregLock );
  111. return Status;
  112. }
  113. Status = OpenGpcClients(GPC_CF_QOS);
  114. if (ERROR_FAILED(Status)) {
  115. IF_DEBUG(ERRORS) {
  116. WSPRINT(("TcRegisterClient: Error = 0x%X\n", Status ));
  117. }
  118. FreeLock( ClientRegDeregLock );
  119. return Status;
  120. }
  121. //
  122. // allocate a new client structure and link it on the global list
  123. //
  124. Status = CreateClientStruc(0, // This will be the client reg ctx
  125. &pClient
  126. );
  127. if (ERROR_FAILED(Status)) {
  128. IF_DEBUG(ERRORS) {
  129. WSPRINT(("TcRegisterClient: Error = 0x%X\n", Status ));
  130. }
  131. FreeLock( ClientRegDeregLock );
  132. return Status;
  133. }
  134. //
  135. // copy the handler list privately
  136. //
  137. __try {
  138. RtlCopyMemory(&pClient->ClHandlers,
  139. ClientHandlerList,
  140. sizeof(TCI_CLIENT_FUNC_LIST));
  141. } __except (EXCEPTION_EXECUTE_HANDLER) {
  142. Status = GetExceptionCode();
  143. IF_DEBUG(ERRORS) {
  144. WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status ));
  145. }
  146. FreeLock( ClientRegDeregLock );
  147. return Status;
  148. }
  149. pClient->ClRegCtx = ClRegCtx;
  150. //
  151. // Update linked lists, add the client to the global linked list of
  152. // clients.
  153. //
  154. // NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE!
  155. //
  156. // Once we add the client to the list, it can get notified by an
  157. // incoming event, for example: TC_NOTIFY_IFC_CHANGE,
  158. // so everything should be in place by the time we release the lock!
  159. //
  160. GetLock(pClient->Lock);
  161. SET_STATE(pClient->State, OPEN);
  162. FreeLock(pClient->Lock);
  163. GetLock( pGlobals->Lock );
  164. // If this is the first client then register for GPC notifications
  165. if ( IsListEmpty( &pGlobals->ClientList ) )
  166. RegisterWithGpc = TRUE;
  167. InsertTailList( &pGlobals->ClientList, &pClient->Linkage );
  168. FreeLock( pGlobals->Lock );
  169. //
  170. // so far so good, set the returned handle
  171. //
  172. __try {
  173. *pClientHandle = (HANDLE)pClient->ClHandle;
  174. } __except (EXCEPTION_EXECUTE_HANDLER) {
  175. Status = GetExceptionCode();
  176. IF_DEBUG(ERRORS) {
  177. WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status ));
  178. }
  179. // We couldn't return the handle so we do our best effort to undo
  180. // the client registration
  181. TcDeregisterClient((HANDLE)pClient->ClHandle);
  182. FreeLock( ClientRegDeregLock );
  183. return Status;
  184. }
  185. if ( RegisterWithGpc )
  186. {
  187. Status = StartGpcNotifyThread();
  188. if ( Status )
  189. {
  190. // We couldn't return the handle so we do our best effort to undo
  191. // the client registration
  192. TcDeregisterClient((HANDLE)pClient->ClHandle);
  193. FreeLock( ClientRegDeregLock );
  194. return Status;
  195. }
  196. }
  197. // Finally allow other TcRegisterClient and TcDeregisterClient to go through
  198. FreeLock( ClientRegDeregLock );
  199. IF_DEBUG(CALLS) {
  200. WSPRINT(("<==TcRegisterClient: ClHandle=%d Status=%X\n",
  201. pClient->ClHandle, Status));
  202. }
  203. return Status;
  204. }
  205. /*
  206. ************************************************************************
  207. Description:
  208. The will call the system to enumerate all the TC aware interfaces.
  209. For each interface, it will return the interface instance name and
  210. a list of supported network addresses. This list can also be empty
  211. if the interface currently does not have an address associated with.
  212. On return, *pBufferSize is set to the actual number of bytes filled
  213. in Buffer. If the buffer is too small to hold all the interfaces
  214. data, it will return ERROR_INSUFFICIENT_BUFFER.
  215. Arguments:
  216. ClientHandle - the client handle from TcRegisterClient
  217. pBufferSize - in: allocate buffer size, out: returned byte count
  218. InterfaceBuffer - the buffer
  219. Return Value:
  220. NO_ERROR
  221. ERROR_INVALID_HANDLE invalid client handle
  222. ERROR_INVALID_PARAMETER one of the parameters is NULL
  223. ERROR_INSUFFICIENT_BUFFER buffer too small to enumerate all interfaces
  224. ERROR_NOT_ENOUGH_MEMORY system out of memory
  225. ************************************************************************
  226. */
  227. DWORD
  228. APIENTRY
  229. TcEnumerateInterfaces(
  230. IN HANDLE ClientHandle,
  231. IN OUT PULONG pBufferSize,
  232. OUT PTC_IFC_DESCRIPTOR InterfaceBuffer
  233. )
  234. {
  235. PCLIENT_STRUC pClient;
  236. DWORD Status = NO_ERROR;
  237. ULONG MyBufferSize = 2 KiloBytes; // is this enough?!?
  238. ULONG Offset2IfcName;
  239. ULONG Offset2IfcID;
  240. INT t, InputBufSize, CurrentLength = 0;
  241. PLIST_ENTRY pHead, pEntry;
  242. PTC_IFC pTcIfc;
  243. IF_DEBUG(CALLS) {
  244. WSPRINT(("==>TcEnumerateInterfaces: Called: ClientHandle= %d",
  245. ClientHandle ));
  246. }
  247. VERIFY_INITIALIZATION_STATUS;
  248. if ( IsBadWritePtr(pBufferSize, sizeof(ULONG))
  249. || IsBadWritePtr(InterfaceBuffer, *pBufferSize) ) {
  250. return ERROR_INVALID_PARAMETER;
  251. }
  252. __try {
  253. InputBufSize = *pBufferSize;
  254. *pBufferSize = 0; // reset it in case of an error
  255. } __except (EXCEPTION_EXECUTE_HANDLER) {
  256. Status = GetExceptionCode();
  257. return Status;
  258. }
  259. pClient = (PCLIENT_STRUC)GetHandleObjectWithRef(ClientHandle, ENUM_CLIENT_TYPE, 'TCEI');
  260. if (pClient == NULL) {
  261. return ERROR_INVALID_HANDLE;
  262. }
  263. ASSERT((HANDLE)pClient->ClHandle == ClientHandle);
  264. GetLock(pGlobals->Lock);
  265. //
  266. // walk the list of TC interfaces
  267. //
  268. pHead = &pGlobals->TcIfcList;
  269. pEntry = pHead->Flink;
  270. while (pEntry != pHead) {
  271. pTcIfc = (PTC_IFC)CONTAINING_RECORD(pEntry,
  272. TC_IFC,
  273. Linkage
  274. );
  275. //
  276. // 273978 - if the interface is down - dont show it.
  277. //
  278. GetLock(pTcIfc->Lock);
  279. if (QUERY_STATE(pTcIfc->State) != OPEN) {
  280. FreeLock(pTcIfc->Lock);
  281. pEntry = pEntry->Flink;
  282. continue;
  283. }
  284. FreeLock(pTcIfc->Lock);
  285. //
  286. // calculate the offset to the interface name buffer data
  287. //
  288. Offset2IfcName = FIELD_OFFSET(TC_IFC_DESCRIPTOR, AddressListDesc) +
  289. pTcIfc->AddrListBytesCount;
  290. //
  291. // calculate the offset to the interface ID buffer data
  292. //
  293. Offset2IfcID = Offset2IfcName +
  294. pTcIfc->InstanceNameLength + sizeof(WCHAR);
  295. //
  296. // total descriptor length
  297. //
  298. t = Offset2IfcID
  299. + pTcIfc->InstanceIDLength + sizeof(WCHAR); // ID
  300. t = MULTIPLE_OF_EIGHT(t);
  301. if (t <= InputBufSize - CurrentLength) {
  302. __try {
  303. //
  304. // enough space in the buffer
  305. //
  306. InterfaceBuffer->Length = t;
  307. //
  308. // update the interface name pointer, place it right after
  309. // the address desc. buffer
  310. //
  311. InterfaceBuffer->pInterfaceName =
  312. (LPWSTR)((PUCHAR)InterfaceBuffer + Offset2IfcName);
  313. //
  314. // update the interface ID ID pointer, place it right after
  315. // the Interface Name string
  316. //
  317. InterfaceBuffer->pInterfaceID =
  318. (LPWSTR)((PUCHAR)InterfaceBuffer + Offset2IfcID);
  319. //
  320. // copy the address list
  321. //
  322. RtlCopyMemory(&InterfaceBuffer->AddressListDesc,
  323. pTcIfc->pAddressListDesc,
  324. pTcIfc->AddrListBytesCount
  325. );
  326. //
  327. // copy the interface name
  328. //
  329. RtlCopyMemory(InterfaceBuffer->pInterfaceName,
  330. &pTcIfc->InstanceName[0],
  331. pTcIfc->InstanceNameLength + sizeof(WCHAR)
  332. );
  333. //
  334. // copy the interface ID
  335. //
  336. RtlCopyMemory(InterfaceBuffer->pInterfaceID,
  337. &pTcIfc->InstanceID[0],
  338. pTcIfc->InstanceIDLength + sizeof(WCHAR)
  339. );
  340. //
  341. // update the output buffer size
  342. //
  343. CurrentLength += t;
  344. //
  345. // advance the interface buffer to the next free space
  346. //
  347. InterfaceBuffer =
  348. (PTC_IFC_DESCRIPTOR)((PUCHAR)InterfaceBuffer + t);
  349. } __except (EXCEPTION_EXECUTE_HANDLER) {
  350. Status = GetExceptionCode();
  351. IF_DEBUG(ERRORS) {
  352. WSPRINT(("TcEnumerateInterfaces: Exception Error: = 0x%X\n",
  353. Status ));
  354. }
  355. break;
  356. }
  357. //
  358. // get next entry in the linked list
  359. //
  360. pEntry = pEntry->Flink;
  361. } else {
  362. //
  363. // buffer too small to contain data
  364. // so lets just
  365. //
  366. CurrentLength += t;
  367. //
  368. // get next entry in the linked list
  369. //
  370. pEntry = pEntry->Flink;
  371. Status = ERROR_INSUFFICIENT_BUFFER;
  372. }
  373. }
  374. FreeLock(pGlobals->Lock);
  375. REFDEL(&pClient->RefCount, 'TCEI');
  376. __try {
  377. *pBufferSize = CurrentLength;
  378. } __except (EXCEPTION_EXECUTE_HANDLER) {
  379. Status = GetExceptionCode();
  380. IF_DEBUG(ERRORS) {
  381. WSPRINT(("TcEnumerateInterfaces: Exception Error: = 0x%X\n",
  382. Status ));
  383. }
  384. }
  385. IF_DEBUG(CALLS) {
  386. WSPRINT(("<==TcEnumerateInterfaces: Returned= 0x%X\n", Status ));
  387. }
  388. return Status;
  389. }
  390. /*
  391. ************************************************************************
  392. Description:
  393. This routine will open an interface for the client.
  394. It needs to know the interface name, as it was returned from
  395. TcEnumerateInterfaces. The client is also expected to give a context
  396. that will be passed to the client upon certains notifications.
  397. Arguments:
  398. InterfaceName - the intefrace name
  399. ClientHandle - as returned from TcRegisterClient
  400. ClIfcCtx - a client context for this specific interface
  401. pIfcHandle - returned interface handle
  402. Return Value:
  403. NO_ERROR
  404. ERROR_INVALID_PARAMETER one of the parameters is NULL
  405. ERROR_NOT_ENOUGH_MEMORY system out of memory
  406. ERROR_NOT_FOUND failed to find an interface with the name provided
  407. ************************************************************************
  408. */
  409. DWORD
  410. APIENTRY
  411. TcOpenInterfaceW(
  412. IN LPWSTR pInterfaceName,
  413. IN HANDLE ClientHandle,
  414. IN HANDLE ClIfcCtx,
  415. OUT PHANDLE pIfcHandle
  416. )
  417. {
  418. DWORD Status;
  419. ULONG Instance;
  420. PINTERFACE_STRUC pClInterface;
  421. PCLIENT_STRUC pClient;
  422. HANDLE Handle;
  423. PTC_IFC pTcIfc;
  424. VERIFY_INITIALIZATION_STATUS;
  425. //
  426. // Validate the pifcHandle
  427. //
  428. if (IsBadWritePtr(pIfcHandle, sizeof(HANDLE))) {
  429. return ERROR_INVALID_PARAMETER;
  430. }
  431. // Set a return value early
  432. __try {
  433. *pIfcHandle = TC_INVALID_HANDLE;
  434. } __except (EXCEPTION_EXECUTE_HANDLER) {
  435. Status = GetExceptionCode();
  436. IF_DEBUG(ERRORS) {
  437. WSPRINT(("TcOpenInterfaces: Exception Error: = 0x%X\n",
  438. Status ));
  439. }
  440. return Status;
  441. }
  442. //
  443. // Validate the pInterfaceName
  444. //
  445. if (IsBadStringPtrW(pInterfaceName,MAX_STRING_LENGTH)) {
  446. return ERROR_INVALID_PARAMETER;
  447. }
  448. IF_DEBUG(CALLS) {
  449. WSPRINT(("==>TcOpenInterface: Called: ClientHandle= %d, Name=%S\n",
  450. ClientHandle, pInterfaceName));
  451. }
  452. pClient = (PCLIENT_STRUC)GetHandleObjectWithRef(ClientHandle, ENUM_CLIENT_TYPE, 'TCOI');
  453. if (pClient == NULL) {
  454. return ERROR_INVALID_HANDLE;
  455. }
  456. ASSERT((HANDLE)pClient->ClHandle == ClientHandle);
  457. //
  458. // verify that the interface name exist
  459. //
  460. pTcIfc = GetTcIfcWithRef(pInterfaceName, 'TCOI');
  461. if (pTcIfc == NULL) {
  462. REFDEL(&pClient->RefCount, 'TCOI');
  463. return ERROR_NOT_FOUND;
  464. }
  465. //
  466. // create a client interface structure
  467. //
  468. Status = CreateClInterfaceStruc(ClIfcCtx, &pClInterface);
  469. if (ERROR_FAILED(Status)) {
  470. REFDEL(&pClient->RefCount, 'TCOI');
  471. REFDEL(&pTcIfc->RefCount, 'TCOI');
  472. return Status;
  473. } else {
  474. REFADD(&pClInterface->RefCount, 'TCOI');
  475. }
  476. //
  477. // set up the client interface structure and link it to the client data
  478. //
  479. pClInterface->pTcIfc = pTcIfc;
  480. pClInterface->pClient = pClient;
  481. GetLock(pClInterface->Lock);
  482. SET_STATE(pClInterface->State, OPEN);
  483. FreeLock(pClInterface->Lock);
  484. GetLock(pGlobals->Lock);
  485. //
  486. // add the interface on the client's list
  487. //
  488. GetLock(pClient->Lock);
  489. GetLock(pTcIfc->Lock);
  490. if ( (QUERY_STATE(pClient->State) != OPEN)
  491. || (QUERY_STATE(pTcIfc->State) != OPEN) )
  492. {
  493. FreeLock(pTcIfc->Lock);
  494. FreeLock(pClient->Lock);
  495. FreeLock(pGlobals->Lock);
  496. IF_DEBUG(CALLS) {
  497. WSPRINT(("<==TcOpenInterface: IfcHandle=%d Status=%X\n",
  498. pClInterface->ClHandle, Status));
  499. }
  500. //
  501. // Ideally we need to dereference the Interface, we really
  502. // need only a subset of the functions.
  503. //
  504. FreeHandle(pClInterface->ClHandle);
  505. CloseHandle(pClInterface->IfcEvent);
  506. FreeMem(pClInterface);
  507. REFDEL(&pClient->RefCount, 'TCOI');
  508. REFDEL(&pTcIfc->RefCount, 'TCOI');
  509. return ERROR_NOT_FOUND;
  510. }
  511. __try {
  512. // the handle is all the client wants.
  513. *pIfcHandle = (HANDLE)pClInterface->ClHandle;
  514. } __except (EXCEPTION_EXECUTE_HANDLER) {
  515. Status = GetExceptionCode();
  516. IF_DEBUG(ERRORS) {
  517. WSPRINT(("TcOpenInterfaceW: Exception Error: = 0x%X\n",
  518. Status ));
  519. }
  520. FreeLock(pTcIfc->Lock);
  521. FreeLock(pClient->Lock);
  522. FreeLock(pGlobals->Lock);
  523. REFDEL(&pClient->RefCount, 'TCOI');
  524. REFDEL(&pTcIfc->RefCount, 'TCOI');
  525. REFDEL(&pClInterface->RefCount, 'TCOI');
  526. return Status;
  527. }
  528. InsertTailList( &pClient->InterfaceList, &pClInterface->Linkage );
  529. //
  530. // for every interface add one ref count
  531. //
  532. REFADD(&pClient->RefCount, 'CIFC');
  533. REFADD(&pTcIfc->RefCount, 'CIFC');
  534. pClient->InterfaceCount++;
  535. //
  536. // add the interface on the TC interface list for back reference
  537. //
  538. InsertTailList( &pTcIfc->ClIfcList, &pClInterface->NextIfc );
  539. FreeLock(pTcIfc->Lock);
  540. FreeLock(pClient->Lock);
  541. FreeLock(pGlobals->Lock);
  542. REFDEL(&pClient->RefCount, 'TCOI');
  543. REFDEL(&pTcIfc->RefCount, 'TCOI');
  544. REFDEL(&pClInterface->RefCount, 'TCOI');
  545. IF_DEBUG(CALLS) {
  546. WSPRINT(("<==TcOpenInterface: IfcHandle=%d Status=%X\n",
  547. pClInterface->ClHandle, Status));
  548. }
  549. return Status;
  550. }
  551. /*
  552. ************************************************************************
  553. Description:
  554. The ANSI version of TcOpenInterfaceW
  555. Arguments:
  556. See TcOpenInterfaceW
  557. Return Value:
  558. See TcOpenInterfaceW
  559. ************************************************************************
  560. */
  561. DWORD
  562. APIENTRY
  563. TcOpenInterfaceA(
  564. IN LPSTR pInterfaceName,
  565. IN HANDLE ClientHandle,
  566. IN HANDLE ClIfcCtx,
  567. OUT PHANDLE pIfcHandle
  568. )
  569. {
  570. LPWSTR pWstr;
  571. int l;
  572. DWORD Status;
  573. if (IsBadWritePtr(pIfcHandle,sizeof(HANDLE))) {
  574. return ERROR_INVALID_PARAMETER;
  575. }
  576. __try {
  577. *pIfcHandle = TC_INVALID_HANDLE;
  578. } __except (EXCEPTION_EXECUTE_HANDLER) {
  579. Status = GetExceptionCode();
  580. IF_DEBUG(ERRORS) {
  581. WSPRINT(("TcOpenInterfaceA: Exception Error: = 0x%X\n",
  582. Status ));
  583. }
  584. return Status;
  585. }
  586. if (IsBadStringPtrA(pInterfaceName,MAX_STRING_LENGTH)) {
  587. return ERROR_INVALID_PARAMETER;
  588. }
  589. __try {
  590. l = strlen(pInterfaceName) + 1;
  591. AllocMem(&pWstr, l*sizeof(WCHAR));
  592. if (pWstr == NULL) {
  593. return ERROR_NOT_ENOUGH_MEMORY;
  594. }
  595. if ( -1 == mbstowcs(pWstr, pInterfaceName, l)) {
  596. FreeMem(pWstr);
  597. return ERROR_NO_UNICODE_TRANSLATION;
  598. }
  599. } __except (EXCEPTION_EXECUTE_HANDLER) {
  600. Status = GetExceptionCode();
  601. IF_DEBUG(ERRORS) {
  602. WSPRINT(("TcOpenInterfaceA: Exception Error: = 0x%X\n",
  603. Status ));
  604. }
  605. return Status;
  606. }
  607. Status = TcOpenInterfaceW(pWstr,
  608. ClientHandle,
  609. ClIfcCtx,
  610. pIfcHandle
  611. );
  612. FreeMem(pWstr);
  613. return Status;
  614. }
  615. /*
  616. ************************************************************************
  617. Description:
  618. This will close the interface previously open witt TcOpenInterface.
  619. All flows should be deleted before calling it, o/w an error will be
  620. returned. All notificaitons will stop being reported on this interface.
  621. Arguments:
  622. InterfaceHandle - the interface handle
  623. Return Value:
  624. NO_ERROR
  625. ERROR_INVALID_HANDLE bad interface handle
  626. ERROR_TC_SUPPORTED_OBJECTS_EXIST not all flows have been deleted for
  627. this interface
  628. ************************************************************************
  629. */
  630. DWORD
  631. APIENTRY
  632. TcCloseInterface(
  633. IN HANDLE InterfaceHandle
  634. )
  635. {
  636. DWORD Status = NO_ERROR;
  637. PINTERFACE_STRUC pInterface;
  638. HANDLE hWaitEvent;
  639. PFLOW_STRUC pFlow;
  640. PLIST_ENTRY pEntry;
  641. VERIFY_INITIALIZATION_STATUS;
  642. IF_DEBUG(CALLS) {
  643. WSPRINT(("==>TcCloseInterface: Called: IfcHandle= %d\n",
  644. InterfaceHandle));
  645. }
  646. pInterface = (PINTERFACE_STRUC)GetHandleObjectWithRef(InterfaceHandle,
  647. ENUM_INTERFACE_TYPE, 'TCCI');
  648. if (pInterface == NULL) {
  649. IF_DEBUG(ERRORS) {
  650. WSPRINT(("==>TcCloseInterface: ERROR_INVALID_HANDLE\n"));
  651. }
  652. //
  653. // If the Interface State is FORCED_KERNELCLOSE, it means we need
  654. // to hang out here until the callback (in cbinterfacenotifyclient is done).
  655. //
  656. GetLock( pGlobals->Lock );
  657. pInterface = (PINTERFACE_STRUC)GetHandleObject(InterfaceHandle,
  658. ENUM_INTERFACE_TYPE);
  659. if (pInterface) {
  660. if (pInterface->CallbackThreadId == GetCurrentThreadId()) {
  661. // same thread - bail!
  662. FreeLock(pGlobals->Lock);
  663. } else {
  664. GetLock(pInterface->Lock);
  665. // This is the state before the callback, so we shall wait here.
  666. if (QUERY_STATE(pInterface->State) == FORCED_KERNELCLOSE) {
  667. REFADD(&pInterface->RefCount, 'TCCW');
  668. pInterface->Flags |= TC_FLAGS_WAITING;
  669. FreeLock(pInterface->Lock);
  670. hWaitEvent = pInterface->IfcEvent;
  671. IF_DEBUG(INTERFACES) {
  672. WSPRINT(("<==TcCloseInterface: Premature Forced Kernel Close, waiting for the callbacks to complete\n"));
  673. }
  674. FreeLock(pGlobals->Lock);
  675. REFDEL(&pInterface->RefCount, 'TCCW');
  676. WaitForSingleObject(hWaitEvent, INFINITE);
  677. CloseHandle(hWaitEvent);
  678. } else {
  679. FreeLock(pInterface->Lock);
  680. FreeLock(pGlobals->Lock);
  681. }
  682. }
  683. } else {
  684. FreeLock(pGlobals->Lock);
  685. }
  686. return ERROR_INVALID_HANDLE;
  687. }
  688. ASSERT((HANDLE)pInterface->ClHandle == InterfaceHandle);
  689. //
  690. // release the ref count we added when we opened the interface
  691. //
  692. GetLock( pGlobals->Lock );
  693. if (pInterface->FlowCount > 0) {
  694. IF_DEBUG(ERRORS) {
  695. WSPRINT(("<==TcCloseInterface: ERROR: there are still open flows on this interface!\n"));
  696. }
  697. #if DBG
  698. pEntry = pInterface->FlowList.Flink;
  699. while (pEntry != &pInterface->FlowList) {
  700. pFlow = CONTAINING_RECORD(pEntry, FLOW_STRUC, Linkage);
  701. IF_DEBUG(ERRORS) {
  702. WSPRINT(("<==TcCloseInterface: Flow %x (handle %x) is open with RefCount:%d\n", pFlow, pFlow->ClHandle, pFlow->RefCount));
  703. }
  704. pEntry = pEntry->Flink;
  705. }
  706. #endif
  707. FreeLock(pGlobals->Lock);
  708. REFDEL(&pInterface->RefCount, 'TCCI');
  709. Status = ERROR_TC_SUPPORTED_OBJECTS_EXIST;
  710. return Status;
  711. }
  712. //
  713. // OK, so we are taking it out for sure now.
  714. //
  715. GetLock(pInterface->Lock);
  716. if (QUERY_STATE(pInterface->State) == OPEN) {
  717. SET_STATE(pInterface->State, USERCLOSED_KERNELCLOSEPENDING);
  718. FreeLock(pInterface->Lock);
  719. } else if (QUERY_STATE(pInterface->State) == FORCED_KERNELCLOSE) {
  720. //
  721. // if the interface is going down, we are going to notify the
  722. // client, make sure we wait here till the callbacks are done.
  723. //
  724. FreeLock(pInterface->Lock);
  725. pInterface->Flags |= TC_FLAGS_WAITING;
  726. hWaitEvent = pInterface->IfcEvent;
  727. IF_DEBUG(INTERFACES) {
  728. WSPRINT(("<==TcCloseInterface: Forced Kernel Close, waiting for the callbacks to complete\n"));
  729. }
  730. FreeLock(pGlobals->Lock);
  731. REFDEL(&pInterface->RefCount, 'TCCI');
  732. WaitForSingleObject(hWaitEvent, INFINITE);
  733. CloseHandle(hWaitEvent);
  734. return ERROR_INVALID_HANDLE;
  735. } else {
  736. //
  737. // Is someone else (wmi) already taking it out.
  738. //
  739. FreeLock(pInterface->Lock);
  740. FreeLock( pGlobals->Lock );
  741. REFDEL(&pInterface->RefCount, 'TCCI');
  742. return ERROR_INVALID_HANDLE;
  743. }
  744. FreeLock(pGlobals->Lock);
  745. Status = CloseInterface(pInterface, FALSE);
  746. IF_DEBUG(CALLS) {
  747. WSPRINT(("<==TcCloseInterface: Status=%X\n",
  748. Status));
  749. }
  750. //
  751. // Shall we wait until the last interface goes away? (292120 D)
  752. //
  753. GetLock( pGlobals->Lock );
  754. if (pInterface->CallbackThreadId != 0 ) {
  755. //
  756. // We are doing a notification, don't block (343058)
  757. //
  758. FreeLock(pGlobals->Lock);
  759. REFDEL(&pInterface->RefCount, 'TCCI');
  760. } else {
  761. pInterface->Flags |= TC_FLAGS_WAITING;
  762. hWaitEvent = pInterface->IfcEvent;
  763. IF_DEBUG(INTERFACES) {
  764. WSPRINT(("<==TcCloseInterface: Waiting for event to get set when we are ready to delete!!\n"));
  765. }
  766. FreeLock(pGlobals->Lock);
  767. REFDEL(&pInterface->RefCount, 'TCCI');
  768. WaitForSingleObject(hWaitEvent, INFINITE);
  769. CloseHandle(hWaitEvent);
  770. }
  771. return Status;
  772. }
  773. /*
  774. ************************************************************************
  775. Description:
  776. This call will add a new flow on the interface.
  777. Arguments:
  778. IfcHandle - the interface handle to add the flow on
  779. ClFlowCtx - a client given flow context
  780. AddressType - determines what protocol template to use with the GPC
  781. Flags - reserved, will be used to indicate a persistent flow
  782. pGenericFlow - flow parameters
  783. pFlowHandle - returned flow handle in case of success
  784. Return Value:
  785. NO_ERROR
  786. ERROR_SIGNAL_PENDING
  787. General error codes:
  788. ERROR_INVALID_HANDLE bad handle.
  789. ERROR_NOT_ENOUGH_MEMORY system out of memory
  790. ERROR_INVALID_PARAMETER a general parameter is invalid
  791. TC specific error codes:
  792. ERROR_INVALID_SERVICE_TYPE unspecified or bad intserv service type
  793. ERROR_INVALID_TOKEN_RATE unspecified or bad TokenRate
  794. ERROR_INVALID_PEAK_RATE bad PeakBandwidth
  795. ERROR_INVALID_SD_MODE invalid ShapeDiscardMode
  796. ERROR_INVALID_PRIORITY invalid priority value
  797. ERROR_INVALID_TRAFFIC_CLASS invalid traffic class value
  798. ERROR_ADDRESS_TYPE_NOT_SUPPORTED the address type is not supported for
  799. this interface
  800. ERROR_NO_SYSTEM_RESOURCES not enough resources to accommodate flows
  801. ************************************************************************
  802. */
  803. DWORD
  804. APIENTRY
  805. TcAddFlow(
  806. IN HANDLE IfcHandle,
  807. IN HANDLE ClFlowCtx,
  808. IN ULONG Flags,
  809. IN PTC_GEN_FLOW pGenericFlow,
  810. OUT PHANDLE pFlowHandle
  811. )
  812. {
  813. DWORD Status, Status2 = NO_ERROR;
  814. PFLOW_STRUC pFlow;
  815. PINTERFACE_STRUC pInterface;
  816. PCLIENT_STRUC pClient;
  817. PGPC_CLIENT pGpcClient;
  818. ULONG l;
  819. HANDLE hFlowTemp;
  820. IF_DEBUG(CALLS) {
  821. WSPRINT(("==>TcAddFlow: Called: IfcHandle= %d, ClFlowCtx=%d\n",
  822. IfcHandle, ClFlowCtx ));
  823. }
  824. VERIFY_INITIALIZATION_STATUS;
  825. if (IsBadWritePtr(pFlowHandle,sizeof(HANDLE))) {
  826. Status = ERROR_INVALID_PARAMETER;
  827. IF_DEBUG(ERRORS) {
  828. WSPRINT(("TcAddFlow: Error = 0x%X\n", Status ));
  829. }
  830. return Status;
  831. }
  832. __try {
  833. *pFlowHandle = TC_INVALID_HANDLE;
  834. if (IsBadReadPtr(pGenericFlow, sizeof(TC_GEN_FLOW))) {
  835. Status = ERROR_INVALID_PARAMETER;
  836. IF_DEBUG(ERRORS) {
  837. WSPRINT(("TcAddFlow: Error = 0x%X\n", Status ));
  838. }
  839. return Status;
  840. }
  841. l = FIELD_OFFSET(TC_GEN_FLOW, TcObjects) + pGenericFlow->TcObjectsLength;
  842. } __except (EXCEPTION_EXECUTE_HANDLER) {
  843. Status = GetExceptionCode();
  844. IF_DEBUG(ERRORS) {
  845. WSPRINT(("TcAddFlow: Exception Error: = 0x%X\n", Status ));
  846. }
  847. return Status;
  848. }
  849. if (IsBadReadPtr(pGenericFlow, l)) {
  850. Status = ERROR_INVALID_PARAMETER;
  851. IF_DEBUG(ERRORS) {
  852. WSPRINT(("TcAddFlow: Error = 0x%X\n", Status ));
  853. }
  854. return Status;
  855. }
  856. pInterface = (PINTERFACE_STRUC)GetHandleObjectWithRef(IfcHandle,
  857. ENUM_INTERFACE_TYPE, 'TCAF');
  858. if (pInterface == NULL) {
  859. Status = ERROR_INVALID_HANDLE;
  860. IF_DEBUG(ERRORS) {
  861. WSPRINT(("TcAddFlow: Error = 0x%X\n", Status ));
  862. }
  863. return Status;
  864. }
  865. ASSERT((HANDLE)pInterface->ClHandle == IfcHandle);
  866. //
  867. // search for an open GPC client that supports this address type
  868. //
  869. pGpcClient = FindGpcClient(GPC_CF_QOS);
  870. if (pGpcClient == NULL) {
  871. //
  872. // not found!
  873. //
  874. Status = ERROR_ADDRESS_TYPE_NOT_SUPPORTED;
  875. IF_DEBUG(ERRORS) {
  876. WSPRINT(("TcAddFlow: Error = 0x%X\n", Status ));
  877. }
  878. REFDEL(&pInterface->RefCount, 'TCAF');
  879. return Status;
  880. }
  881. //
  882. // create a new flow structure
  883. //
  884. Status = CreateFlowStruc(ClFlowCtx, pGenericFlow, &pFlow);
  885. if (ERROR_FAILED(Status)) {
  886. IF_DEBUG(ERRORS) {
  887. WSPRINT(("TcAddFlow: Error = 0x%X\n", Status ));
  888. }
  889. REFDEL(&pInterface->RefCount, 'TCAF');
  890. return Status;
  891. }
  892. pClient = pInterface->pClient;
  893. //
  894. // initialize the flow structure and add it on the intefrace list
  895. //
  896. pFlow->pInterface = pInterface;
  897. pFlow->UserFlags = Flags;
  898. pFlow->pGpcClient = pGpcClient;
  899. //
  900. // call to actually add the flow
  901. //
  902. Status = IoAddFlow( pFlow, TRUE );
  903. if (!ERROR_FAILED(Status)) {
  904. __try {
  905. *pFlowHandle = (HANDLE)pFlow->ClHandle;
  906. } __except (EXCEPTION_EXECUTE_HANDLER) {
  907. Status2 = GetExceptionCode();
  908. IF_DEBUG(ERRORS) {
  909. WSPRINT(("TcAddFlow: Exception Error: = 0x%X\n", Status2 ));
  910. }
  911. hFlowTemp = (HANDLE)pFlow->ClHandle;
  912. }
  913. }
  914. if (!ERROR_PENDING(Status)) {
  915. //
  916. // call completed, either success or failure...
  917. //
  918. CompleteAddFlow(pFlow, Status);
  919. }
  920. //
  921. // !!! don't reference pFlow after this since it may be gone!!!
  922. //
  923. if (Status2 != NO_ERROR) {
  924. // We won't be able to return the flow, so we need to try to delete it
  925. // and return the error
  926. TcDeleteFlow(hFlowTemp);
  927. return (Status2);
  928. }
  929. IF_DEBUG(CALLS) {
  930. WSPRINT(("<==TcAddFlow: Returned= 0x%X\n", Status ));
  931. }
  932. return Status;
  933. }
  934. /*
  935. ************************************************************************
  936. Description:
  937. This call will modify the flow.
  938. Arguments:
  939. FlowHandle - flow handle to modify
  940. pGenericFlow - new flow parameters
  941. Return Value:
  942. See TcAddFlow
  943. ************************************************************************
  944. */
  945. DWORD
  946. APIENTRY
  947. TcModifyFlow(
  948. IN HANDLE FlowHandle,
  949. IN PTC_GEN_FLOW pGenericFlow
  950. )
  951. {
  952. DWORD Status;
  953. PFLOW_STRUC pFlow;
  954. ULONG l;
  955. IF_DEBUG(CALLS) {
  956. WSPRINT(("==>TcModifyFlow: Called: FlowHandle= %d\n",
  957. FlowHandle ));
  958. }
  959. VERIFY_INITIALIZATION_STATUS;
  960. if (IsBadReadPtr(pGenericFlow,sizeof(TC_GEN_FLOW))) {
  961. Status = ERROR_INVALID_PARAMETER;
  962. IF_DEBUG(ERRORS) {
  963. WSPRINT(("TcModifyFlow: Error = 0x%X\n", Status ));
  964. }
  965. return Status;
  966. }
  967. //
  968. // Figure out the full length for immediate verification and also for later usage
  969. //
  970. __try {
  971. l = FIELD_OFFSET(TC_GEN_FLOW, TcObjects) + pGenericFlow->TcObjectsLength;
  972. } __except (EXCEPTION_EXECUTE_HANDLER) {
  973. Status = GetExceptionCode();
  974. IF_DEBUG(ERRORS) {
  975. WSPRINT(("TcModifyFlow: Exception Error: = 0x%X\n",
  976. Status ));
  977. }
  978. return Status;
  979. }
  980. if (IsBadReadPtr(pGenericFlow,l)) {
  981. Status = ERROR_INVALID_PARAMETER;
  982. IF_DEBUG(ERRORS) {
  983. WSPRINT(("TcModifyFlow: Error = 0x%X\n", Status ));
  984. }
  985. return Status;
  986. }
  987. pFlow = (PFLOW_STRUC)GetHandleObjectWithRef(FlowHandle, ENUM_GEN_FLOW_TYPE, 'TCMF');
  988. if (pFlow == NULL) {
  989. Status = ERROR_INVALID_HANDLE;
  990. IF_DEBUG(ERRORS) {
  991. WSPRINT(("TcModifyFlow: Error = 0x%X\n", Status ));
  992. }
  993. return Status;
  994. }
  995. else if (pFlow == INVALID_HANDLE_VALUE )
  996. {
  997. Status = ERROR_NOT_READY;
  998. IF_DEBUG(ERRORS) {
  999. WSPRINT(("TcModifyFlow: Error = 0x%X\n", Status ));
  1000. }
  1001. return Status;
  1002. }
  1003. ASSERT((HANDLE)pFlow->ClHandle == FlowHandle);
  1004. GetLock(pFlow->Lock);
  1005. if (IS_MODIFYING(pFlow->Flags)) {
  1006. FreeLock(pFlow->Lock);
  1007. IF_DEBUG(REFCOUNTS) {
  1008. WSPRINT(("0 DEREF FLOW %X (%X) - ref (%d)\n", pFlow->ClHandle, pFlow, pFlow->RefCount));
  1009. }
  1010. REFDEL(&pFlow->RefCount, 'TCMF');
  1011. return ERROR_NOT_READY;
  1012. }
  1013. AllocMem(&pFlow->pGenFlow1, l);
  1014. if (pFlow->pGenFlow1 == NULL) {
  1015. Status = ERROR_NOT_ENOUGH_MEMORY;
  1016. IF_DEBUG(ERRORS) {
  1017. WSPRINT(("TcModifyFlow: Error = 0x%X\n", Status ));
  1018. }
  1019. FreeLock(pFlow->Lock);
  1020. IF_DEBUG(REFCOUNTS) {
  1021. WSPRINT(("1 DEREF FLOW %X (%X) - ref (%d)\n", pFlow->ClHandle, pFlow, pFlow->RefCount));
  1022. }
  1023. REFDEL(&pFlow->RefCount, 'TCMF');
  1024. return Status;
  1025. }
  1026. __try {
  1027. RtlCopyMemory(pFlow->pGenFlow1, pGenericFlow, l);
  1028. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1029. Status = GetExceptionCode();
  1030. IF_DEBUG(ERRORS) {
  1031. WSPRINT(("TcModifyFlow: Exception Error: = 0x%X\n",
  1032. Status ));
  1033. }
  1034. FreeLock(pFlow->Lock);
  1035. //IF_DEBUG(REFCOUNTS) { WSPRINT(("2\n"));
  1036. IF_DEBUG(REFCOUNTS) {
  1037. WSPRINT(("2 DEREF FLOW %X (%X) ref (%d)\n", pFlow->ClHandle, pFlow, pFlow->RefCount));
  1038. }
  1039. REFDEL(&pFlow->RefCount, 'TCMF');
  1040. return Status;
  1041. }
  1042. pFlow->Flags |= TC_FLAGS_MODIFYING;
  1043. pFlow->GenFlowLen1 = l;
  1044. FreeLock(pFlow->Lock);
  1045. //
  1046. // call to actually modify the flow
  1047. //
  1048. Status = IoModifyFlow( pFlow, TRUE );
  1049. if (!ERROR_PENDING(Status)) {
  1050. //
  1051. // call completed, either success or failure...
  1052. //
  1053. CompleteModifyFlow(pFlow, Status);
  1054. }
  1055. //
  1056. // !!! don't reference pFlow after this since it may be gone!!!
  1057. //
  1058. //IF_DEBUG(REFCOUNTS) { WSPRINT(("3\n"));
  1059. IF_DEBUG(REFCOUNTS) {
  1060. WSPRINT(("3 DEREF FLOW %X (%X), ref(%d)\n", pFlow->ClHandle, pFlow, pFlow->RefCount));
  1061. }
  1062. IF_DEBUG(CALLS) {
  1063. WSPRINT(("<==TcModifyFlow: Returned= 0x%X\n", Status ));
  1064. }
  1065. return Status;
  1066. }
  1067. /*
  1068. ************************************************************************
  1069. Description:
  1070. This will delete the flow. All the filters must have been deleted
  1071. by now, o/w an error code will be returned. Also the handle is
  1072. invalidated. No TC_NOTIFY_FLOW_CLOSE will be reported for this flow.
  1073. Arguments:
  1074. FlowHandle - handle of the flow to delete
  1075. Return Value:
  1076. NO_ERROR
  1077. ERROR_SIGNAL_PENDING
  1078. ERROR_INVALID_HANDLE invalid or NULL handle
  1079. ERROR_TC_SUPPORTED_OBJECTS_EXIST not all the filters have been deleted
  1080. ************************************************************************
  1081. */
  1082. DWORD
  1083. APIENTRY
  1084. TcDeleteFlow(
  1085. IN HANDLE FlowHandle
  1086. )
  1087. {
  1088. DWORD Status;
  1089. PFLOW_STRUC pFlow;
  1090. IF_DEBUG(CALLS) {
  1091. WSPRINT(("==>TcDeleteFlow: Called: FlowHandle= %d\n",
  1092. FlowHandle ));
  1093. }
  1094. VERIFY_INITIALIZATION_STATUS;
  1095. pFlow = (PFLOW_STRUC)GetHandleObjectWithRef(FlowHandle, ENUM_GEN_FLOW_TYPE, 'TCDF');
  1096. if (pFlow == NULL) {
  1097. Status = ERROR_INVALID_HANDLE;
  1098. IF_DEBUG(ERRORS) {
  1099. WSPRINT(("TcDeleteFlow: Error = 0x%X\n", Status ));
  1100. }
  1101. return Status;
  1102. }
  1103. else if (pFlow == INVALID_HANDLE_VALUE )
  1104. {
  1105. Status = ERROR_NOT_READY;
  1106. IF_DEBUG(ERRORS) {
  1107. WSPRINT(("TcDeleteFlow: Error = 0x%X\n", Status ));
  1108. }
  1109. return ERROR_NOT_READY;
  1110. }
  1111. ASSERT((HANDLE)pFlow->ClHandle == FlowHandle);
  1112. //
  1113. // Set the state and call to actually delete the flow
  1114. //
  1115. GetLock(pFlow->Lock);
  1116. if (QUERY_STATE(pFlow->State) == OPEN) {
  1117. if (IS_MODIFYING(pFlow->Flags))
  1118. {
  1119. //
  1120. // Someone else is taking this out.
  1121. //
  1122. FreeLock(pFlow->Lock);
  1123. REFDEL(&pFlow->RefCount, 'TCDF');
  1124. return ERROR_NOT_READY;
  1125. }
  1126. SET_STATE(pFlow->State, USERCLOSED_KERNELCLOSEPENDING);
  1127. FreeLock(pFlow->Lock);
  1128. } else {
  1129. //
  1130. // Someone else is taking this out.
  1131. //
  1132. FreeLock(pFlow->Lock);
  1133. REFDEL(&pFlow->RefCount, 'TCDF');
  1134. return ERROR_INVALID_HANDLE;
  1135. }
  1136. Status = DeleteFlow(pFlow, FALSE);
  1137. if (ERROR_FAILED(Status)) {
  1138. GetLock(pFlow->Lock);
  1139. SET_STATE(pFlow->State, OPEN);
  1140. FreeLock(pFlow->Lock);
  1141. }
  1142. //
  1143. // !!! don't reference pFlow after this since it may be gone!!!
  1144. //
  1145. //IF_DEBUG(REFCOUNTS) { WSPRINT(("4\n"));
  1146. IF_DEBUG(REFCOUNTS) {
  1147. WSPRINT(("4 DEREF FLOW %X (%X) ref(%d)\n", pFlow->ClHandle, pFlow, pFlow->RefCount));
  1148. }
  1149. REFDEL(&pFlow->RefCount, 'TCDF');
  1150. IF_DEBUG(CALLS) {
  1151. WSPRINT(("<==TcDeleteFlow: Returned= 0x%X\n", Status ));
  1152. }
  1153. return Status;
  1154. }
  1155. /*
  1156. ************************************************************************
  1157. Description:
  1158. Will add a filter and attach it to the flow.
  1159. Arguments:
  1160. FlowHandle - handle of the flow to add the filter on
  1161. pGenericFilter - the filter characteristics
  1162. pFilterHandle - the returned filter handle after success
  1163. Return Value:
  1164. NO_ERROR
  1165. General error codes:
  1166. ERROR_INVALID_HANDLE bad handle.
  1167. ERROR_NOT_ENOUGH_MEMORY system out of memory
  1168. ERROR_INVALID_PARAMETER a general parameter is invalid
  1169. TC specific error codes:
  1170. ERROR_INVALID_ADDRESS_TYPE invalid address type
  1171. ERROR_DUPLICATE_FILTER attempt to install identical filters on
  1172. different flows
  1173. ERROR_FILTER_CONFLICT attempt to install conflicting filter
  1174. ************************************************************************
  1175. */
  1176. DWORD
  1177. APIENTRY
  1178. TcAddFilter(
  1179. IN HANDLE FlowHandle,
  1180. IN PTC_GEN_FILTER pGenericFilter,
  1181. OUT PHANDLE pFilterHandle
  1182. )
  1183. {
  1184. DWORD Status;
  1185. PFLOW_STRUC pFlow;
  1186. PFILTER_STRUC pFilter;
  1187. ULONG PatternSize;
  1188. IF_DEBUG(CALLS) {
  1189. WSPRINT(("==>TcAddFilter: Called: FlowHandle=%d\n", FlowHandle ));
  1190. }
  1191. VERIFY_INITIALIZATION_STATUS;
  1192. if (IsBadWritePtr(pFilterHandle,sizeof(HANDLE))) {
  1193. Status = ERROR_INVALID_PARAMETER;
  1194. IF_DEBUG(ERRORS) {
  1195. WSPRINT(("TcAddFilter: Error = 0x%X\n", Status ));
  1196. }
  1197. return Status;
  1198. }
  1199. __try {
  1200. *pFilterHandle = TC_INVALID_HANDLE;
  1201. if ( IsBadReadPtr(pGenericFilter,sizeof(TC_GEN_FILTER))
  1202. || IsBadReadPtr(pGenericFilter->Pattern,pGenericFilter->PatternSize)
  1203. || IsBadReadPtr(pGenericFilter->Mask,pGenericFilter->PatternSize)) {
  1204. Status = ERROR_INVALID_PARAMETER;
  1205. IF_DEBUG(ERRORS) {
  1206. WSPRINT(("TcAddFilter: Error = 0x%X\n", Status ));
  1207. }
  1208. return Status;
  1209. }
  1210. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1211. Status = GetExceptionCode();
  1212. IF_DEBUG(ERRORS) {
  1213. WSPRINT(("TcAddFilter: Exception Error: = 0x%X\n", Status ));
  1214. }
  1215. return Status;
  1216. }
  1217. pFlow = (PFLOW_STRUC)GetHandleObjectWithRef(FlowHandle,
  1218. ENUM_GEN_FLOW_TYPE, 'TAFL');
  1219. if (pFlow == NULL) {
  1220. Status = ERROR_INVALID_HANDLE;
  1221. IF_DEBUG(ERRORS) {
  1222. WSPRINT(("TcAddFilter: Error = 0x%X\n", Status ));
  1223. }
  1224. return Status;
  1225. }
  1226. else if (pFlow == INVALID_HANDLE_VALUE )
  1227. {
  1228. Status = ERROR_NOT_READY;
  1229. IF_DEBUG(ERRORS) {
  1230. WSPRINT(("TcAddFilter: Error = 0x%X\n", Status ));
  1231. }
  1232. return Status;
  1233. }
  1234. ASSERT((HANDLE)pFlow->ClHandle == FlowHandle);
  1235. //
  1236. // create a new filter structure
  1237. //
  1238. Status = CreateFilterStruc(pGenericFilter, pFlow, &pFilter);
  1239. if ( Status != NO_ERROR ) {
  1240. if ( ERROR_PENDING(Status) )
  1241. Status = ERROR_NOT_READY;
  1242. IF_DEBUG(ERRORS) {
  1243. WSPRINT(("TcAddFilter: Error = 0x%X\n", Status ));
  1244. }
  1245. //IF_DEBUG(REFCOUNTS) { WSPRINT(("5\n"));
  1246. IF_DEBUG(REFCOUNTS) {
  1247. WSPRINT(("5 DEREF FLOW %X (%X) ref(%d)\n", pFlow->ClHandle, pFlow, pFlow->RefCount));
  1248. }
  1249. REFDEL(&pFlow->RefCount, 'TAFL');
  1250. return Status;
  1251. }
  1252. //
  1253. // initialize the filter structure and add it on the flow list
  1254. //
  1255. pFilter->pFlow = pFlow;
  1256. //
  1257. // call to actually add the filter
  1258. //
  1259. Status = IoAddFilter( pFilter );
  1260. if (!ERROR_FAILED(Status)) {
  1261. __try {
  1262. *pFilterHandle = (HANDLE)pFilter->ClHandle;
  1263. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1264. Status = GetExceptionCode();
  1265. IF_DEBUG(ERRORS) {
  1266. WSPRINT(("TcAddFilter: Exception Error: = 0x%X\n", Status ));
  1267. }
  1268. }
  1269. GetLock(pGlobals->Lock);
  1270. GetLock(pFlow->Lock);
  1271. if (QUERY_STATE(pFlow->State) == OPEN) {
  1272. SET_STATE(pFilter->State, OPEN);
  1273. InsertTailList(&pFlow->FilterList, &pFilter->Linkage);
  1274. REFADD(&pFlow->RefCount, 'FILT');
  1275. FreeLock(pFlow->Lock);
  1276. }
  1277. else {
  1278. IF_DEBUG(WARNINGS) {
  1279. WSPRINT(("Flow %X (handle %X) is not OPEN! \n", pFlow, pFlow->ClHandle));
  1280. }
  1281. FreeLock(pFlow->Lock);
  1282. DeleteFilter(pFilter);
  1283. Status = ERROR_INVALID_HANDLE;
  1284. }
  1285. FreeLock(pGlobals->Lock);
  1286. } else {
  1287. //
  1288. // failed, release the filter resources
  1289. //
  1290. REFDEL(&pFilter->RefCount, 'FILT');
  1291. }
  1292. //IF_DEBUG(REFCOUNTS) { WSPRINT(("6\n"));
  1293. IF_DEBUG(REFCOUNTS) {
  1294. WSPRINT(("6 DEREF FLOW %X (%X) (%d)\n", pFlow->ClHandle, pFlow, pFlow->RefCount));
  1295. }
  1296. REFDEL(&pFlow->RefCount, 'TAFL');
  1297. IF_DEBUG(CALLS) {
  1298. WSPRINT(("<==TcAddFilter: Returned= 0x%X\n", Status ));
  1299. }
  1300. return Status;
  1301. }
  1302. /*
  1303. ************************************************************************
  1304. Description:
  1305. Deletes the filter and invalidates the handle.
  1306. Arguments:
  1307. FilterHandle - handle of the filter to be deleted
  1308. Return Value:
  1309. NO_ERROR
  1310. ERROR_INVALID_HANDLE invalid or NULL handle
  1311. ************************************************************************
  1312. */
  1313. DWORD
  1314. APIENTRY
  1315. TcDeleteFilter(
  1316. IN HANDLE FilterHandle
  1317. )
  1318. {
  1319. DWORD Status;
  1320. PFILTER_STRUC pFilter;
  1321. IF_DEBUG(CALLS) {
  1322. WSPRINT(("==>TcDeleteFilter: Called: FilterHandle=%d\n",
  1323. FilterHandle ));
  1324. }
  1325. VERIFY_INITIALIZATION_STATUS;
  1326. pFilter = (PFILTER_STRUC)GetHandleObjectWithRef(FilterHandle,
  1327. ENUM_FILTER_TYPE, 'TDFL');
  1328. if (pFilter == NULL) {
  1329. Status = ERROR_INVALID_HANDLE;
  1330. IF_DEBUG(ERRORS) {
  1331. WSPRINT(("TcDeleteFilter: Error = 0x%X\n", Status ));
  1332. }
  1333. return Status;
  1334. }
  1335. ASSERT((HANDLE)pFilter->ClHandle == FilterHandle);
  1336. GetLock(pFilter->Lock);
  1337. if (QUERY_STATE(pFilter->State) == OPEN) {
  1338. SET_STATE(pFilter->State, USERCLOSED_KERNELCLOSEPENDING);
  1339. FreeLock(pFilter->Lock);
  1340. } else {
  1341. //
  1342. // Someone else is taking this out.
  1343. //
  1344. FreeLock(pFilter->Lock);
  1345. REFDEL(&pFilter->RefCount, 'TDFL');
  1346. return ERROR_INVALID_HANDLE;
  1347. }
  1348. Status = DeleteFilter(pFilter);
  1349. IF_DEBUG(CALLS) {
  1350. WSPRINT(("<==TcDeleteFilter: Returned= 0x%X\n", Status ));
  1351. }
  1352. REFDEL(&pFilter->RefCount, 'TDFL');
  1353. return Status;
  1354. }
  1355. /*
  1356. ************************************************************************
  1357. Description:
  1358. This will deregister the client and release all associated resources.
  1359. TC_NOTIFY_IFC_CHANGE notifications will no longer be reported to
  1360. this client. All interface must have being close prior to calling
  1361. this API, o/w an error will be returned.
  1362. Arguments:
  1363. ClientHandle - handle of the client to be deregistered
  1364. Return Value:
  1365. NO_ERROR
  1366. ERROR_INVALID_HANDLE invalid or NULL handle
  1367. ERROR_TC_SUPPORTED_OBJECTS_EXIST not all the interfaces have been
  1368. closed for this client
  1369. ************************************************************************
  1370. */
  1371. DWORD
  1372. TcDeregisterClient(
  1373. IN HANDLE ClientHandle
  1374. )
  1375. {
  1376. DWORD Status;
  1377. ULONG Instance;
  1378. PINTERFACE_STRUC pClInterface;
  1379. PCLIENT_STRUC pClient;
  1380. PLIST_ENTRY pEntry;
  1381. BOOLEAN fOpenInterfacesFound;
  1382. BOOLEAN fDeRegisterWithGpc = FALSE;
  1383. VERIFY_INITIALIZATION_STATUS;
  1384. Status = NO_ERROR;
  1385. fOpenInterfacesFound = FALSE;
  1386. IF_DEBUG(CALLS) {
  1387. WSPRINT(("==>TcDeregisterClient: ClientHandle=%d\n",
  1388. ClientHandle));
  1389. }
  1390. pClient = (PCLIENT_STRUC)GetHandleObject(ClientHandle, ENUM_CLIENT_TYPE);
  1391. if (pClient == NULL) {
  1392. IF_DEBUG(ERRORS) {
  1393. WSPRINT(("<==TcDeregisterClient: ERROR_INVALID_HANDLE\n"));
  1394. }
  1395. return ERROR_INVALID_HANDLE;
  1396. }
  1397. ASSERT((HANDLE)pClient->ClHandle == ClientHandle);
  1398. // Prevent another thread from doing TcRegisterClient and TcDeregisterClient
  1399. GetLock( ClientRegDeregLock );
  1400. GetLock( pGlobals->Lock );
  1401. // Go through the interface list and check if any interfaces are open.
  1402. // for a checked build, lets dump out the interfaces and the refcounts on these
  1403. // interfaces too. [ShreeM]
  1404. pEntry = pClient->InterfaceList.Flink;
  1405. while (pEntry != &pClient->InterfaceList) {
  1406. pClInterface = CONTAINING_RECORD(pEntry, INTERFACE_STRUC, Linkage);
  1407. GetLock(pClInterface->Lock);
  1408. if ((QUERY_STATE(pClInterface->State) == FORCED_KERNELCLOSE) ||
  1409. (QUERY_STATE(pClInterface->State) == KERNELCLOSED_USERCLEANUP)) {
  1410. #if DBG
  1411. IF_DEBUG(WARNINGS) {
  1412. WSPRINT(("<==TcDeregisterClient: Interface %x (H%x) is FORCED_KERNELCLOSE with RefCount:%d\n",
  1413. pClInterface, pClInterface->ClHandle, pClInterface->RefCount));
  1414. }
  1415. #endif
  1416. } else {
  1417. fOpenInterfacesFound = TRUE;
  1418. #if DBG
  1419. IF_DEBUG(ERRORS) {
  1420. WSPRINT(("<==TcDeregisterClient: Interface %x (H%x) is open with RefCount:%d\n", pClInterface, pClInterface->ClHandle, pClInterface->RefCount));
  1421. }
  1422. #endif
  1423. }
  1424. pEntry = pEntry->Flink;
  1425. FreeLock(pClInterface->Lock);
  1426. if (fOpenInterfacesFound) {
  1427. IF_DEBUG(ERRORS) {
  1428. WSPRINT(("<==TcDeregisterClient: ERROR_TC_SUPPORTED_OBJECTS_EXIST (%d Interfaces)\n", pClient->InterfaceCount));
  1429. }
  1430. FreeLock( ClientRegDeregLock );
  1431. FreeLock( pGlobals->Lock );
  1432. return ERROR_TC_SUPPORTED_OBJECTS_EXIST;
  1433. }
  1434. }
  1435. //
  1436. // Lets mark it as deleting.
  1437. //
  1438. GetLock(pClient->Lock);
  1439. SET_STATE(pClient->State, USERCLOSED_KERNELCLOSEPENDING);
  1440. FreeLock(pClient->Lock);
  1441. IF_DEBUG(HANDLES) {
  1442. WSPRINT(("<==TcDeregisterClient: client (%x), RefCount:%d\n", pClient->ClHandle, pClient->RefCount));
  1443. }
  1444. REFDEL(&pClient->RefCount, 'CLNT');
  1445. if ( IsListEmpty( &pGlobals->ClientList ) )
  1446. fDeRegisterWithGpc = TRUE;
  1447. FreeLock( pGlobals->Lock );
  1448. if ( fDeRegisterWithGpc )
  1449. {
  1450. // When there are no clients left stop listening to
  1451. // GPC notifications.
  1452. Status = StopGpcNotifyThread();
  1453. }
  1454. FreeLock( ClientRegDeregLock );
  1455. IF_DEBUG(CALLS) {
  1456. WSPRINT(("<==TcDeregisterClient: NO_ERROR\n" ));
  1457. }
  1458. return NO_ERROR;
  1459. }
  1460. /*
  1461. ************************************************************************
  1462. Description:
  1463. Sends a WMI query on the guid with the instance name.
  1464. Also sets the notification state to TRUE (=notify) or FALSE (dont notify).
  1465. Arguments:
  1466. IfcHandle - interface to send the query to
  1467. pGuidParam - GUID of the queried property
  1468. NotifyChange - set the notification state for this property
  1469. BufferSize - size of allocated buffer
  1470. Buffer - the buffer for returned result
  1471. Return Value:
  1472. NO_ERROR
  1473. ERROR_INVALID_HANDLE bad interface handle
  1474. ERROR_INVALID_PARAMETER bad parameter
  1475. ERROR_INSUFFICIENT_BUFFER buffer too small for result
  1476. ERROR_NOT_SUPPORTED unsupported GUID
  1477. ************************************************************************
  1478. */
  1479. DWORD
  1480. APIENTRY
  1481. TcQueryInterface(
  1482. IN HANDLE IfcHandle,
  1483. IN LPGUID pGuidParam,
  1484. IN BOOLEAN NotifyChange,
  1485. IN OUT PULONG pBufferSize,
  1486. OUT PVOID Buffer
  1487. )
  1488. {
  1489. DWORD Status;
  1490. PINTERFACE_STRUC pInterface;
  1491. WMIHANDLE hWmiHandle;
  1492. TCHAR cstr[MAX_STRING_LENGTH];
  1493. PWNODE_SINGLE_INSTANCE pWnode;
  1494. ULONG cBufSize;
  1495. ULONG InputBufferSize;
  1496. IF_DEBUG(CALLS) {
  1497. WSPRINT(("==>TcQueryInterface: Called: Name=%d\n",
  1498. IfcHandle));
  1499. }
  1500. VERIFY_INITIALIZATION_STATUS;
  1501. if (IsBadWritePtr(pBufferSize, sizeof(ULONG))) {
  1502. return ERROR_INVALID_PARAMETER;
  1503. }
  1504. __try {
  1505. InputBufferSize = *pBufferSize;
  1506. *pBufferSize = 0;
  1507. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1508. Status = GetExceptionCode();
  1509. IF_DEBUG(ERRORS) {
  1510. WSPRINT(("TcModifyFlow: Exception Error: = 0x%X\n",
  1511. Status ));
  1512. }
  1513. return Status;
  1514. }
  1515. if (IsBadReadPtr(pGuidParam,sizeof(GUID))) {
  1516. return ERROR_INVALID_PARAMETER;
  1517. }
  1518. if ( (InputBufferSize != 0)
  1519. && (IsBadWritePtr(Buffer,InputBufferSize)) )
  1520. {
  1521. return ERROR_INVALID_PARAMETER;
  1522. }
  1523. pInterface = (PINTERFACE_STRUC)GetHandleObjectWithRef(IfcHandle,
  1524. ENUM_INTERFACE_TYPE, 'TCQI');
  1525. if (pInterface == NULL) {
  1526. return ERROR_INVALID_HANDLE;
  1527. }
  1528. Status = WmiOpenBlock( pGuidParam, // object
  1529. 0, // access
  1530. &hWmiHandle
  1531. );
  1532. if (ERROR_FAILED(Status)) {
  1533. TC_TRACE(ERRORS, ("[TcQueryInterface]: WmiOpenBlock failed with %x \n", Status));
  1534. REFDEL(&pInterface->RefCount, 'TCQI');
  1535. return Status;
  1536. }
  1537. //
  1538. // allocate memory for the output wnode
  1539. //
  1540. cBufSize = sizeof(WNODE_SINGLE_INSTANCE)
  1541. + InputBufferSize
  1542. + MAX_STRING_LENGTH * sizeof(TCHAR);
  1543. AllocMem(&pWnode, cBufSize);
  1544. if (pWnode == NULL) {
  1545. Status = ERROR_NOT_ENOUGH_MEMORY;
  1546. } else {
  1547. //
  1548. // query for the single instance
  1549. //
  1550. #ifndef UNICODE
  1551. if (-1 == wcstombs(cstr,
  1552. pInterface->pTcIfc->InstanceName,
  1553. pInterface->pTcIfc->InstanceNameLength
  1554. ))
  1555. {
  1556. Status = ERROR_NO_UNICODE_TRANSLATION;
  1557. }
  1558. else
  1559. {
  1560. Status = WmiQuerySingleInstance( hWmiHandle,
  1561. cstr,
  1562. &cBufSize,
  1563. pWnode
  1564. );
  1565. }
  1566. #else
  1567. Status = WmiQuerySingleInstance( hWmiHandle,
  1568. pInterface->pTcIfc->InstanceName,
  1569. &cBufSize,
  1570. pWnode
  1571. );
  1572. #endif
  1573. if (!ERROR_FAILED(Status))
  1574. {
  1575. Status = WmiNotificationRegistration(pGuidParam,
  1576. NotifyChange,
  1577. CbWmiParamNotification,
  1578. PtrToUlong(IfcHandle),
  1579. NOTIFICATION_CALLBACK_DIRECT
  1580. );
  1581. if (Status == ERROR_WMI_ALREADY_DISABLED ||
  1582. Status == ERROR_WMI_ALREADY_ENABLED) {
  1583. //
  1584. // ignore these errors, we assumed it's okay
  1585. //
  1586. Status = NO_ERROR;
  1587. }
  1588. //
  1589. // Now that we are registered with WMI - add it OR delete it from our list. (258218)
  1590. //
  1591. if (NotifyChange) {
  1592. if (!TcipAddToNotificationList(
  1593. pGuidParam,
  1594. pInterface,
  1595. 0
  1596. )) {
  1597. //
  1598. // Failed to put it on the list for some reason..
  1599. //
  1600. TC_TRACE(ERRORS, ("[TcQueryInterface]: Could not add the GUID/IFC to private list \n"));
  1601. }
  1602. } else {
  1603. if (!TcipDeleteFromNotificationList(
  1604. pGuidParam,
  1605. pInterface,
  1606. 0
  1607. )) {
  1608. //
  1609. // Failed to remove it from the list for some reason..
  1610. //
  1611. TC_TRACE(ERRORS, ("[TcQueryInterface]: Could not remove the GUID/IFC from private list \n"));
  1612. }
  1613. }
  1614. }
  1615. if (!ERROR_FAILED(Status)) {
  1616. //
  1617. // parse the wnode
  1618. //
  1619. //
  1620. // check to see if the user allocated enough space for the
  1621. // returned buffer
  1622. //
  1623. if (pWnode->SizeDataBlock <= InputBufferSize) {
  1624. __try {
  1625. RtlCopyMemory(Buffer,
  1626. (PBYTE)OffsetToPtr(pWnode, pWnode->DataBlockOffset),
  1627. pWnode->SizeDataBlock
  1628. );
  1629. *pBufferSize = pWnode->SizeDataBlock;
  1630. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1631. Status = GetExceptionCode();
  1632. TC_TRACE(ERRORS, ("[TcQueryInterface]: Exception 0x%x while copying data \n", Status));
  1633. }
  1634. } else {
  1635. //
  1636. // output buffer too small
  1637. //
  1638. Status = ERROR_INSUFFICIENT_BUFFER;
  1639. __try {
  1640. *pBufferSize = pWnode->SizeDataBlock;
  1641. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1642. Status = GetExceptionCode();
  1643. }
  1644. }
  1645. }
  1646. }
  1647. WmiCloseBlock(hWmiHandle);
  1648. if (pWnode)
  1649. FreeMem(pWnode);
  1650. REFDEL(&pInterface->RefCount, 'TCQI');
  1651. IF_DEBUG(CALLS) {
  1652. WSPRINT(("<==TcQueryInterface: Returned= 0x%X\n", Status ));
  1653. }
  1654. return Status;
  1655. }
  1656. /*
  1657. ************************************************************************
  1658. Description:
  1659. Sends a WMI set on the GUID with the instance name.
  1660. Not all propertied are writeable.
  1661. Arguments:
  1662. IfcHandle - interface handle to set the property on
  1663. pGuidParam - GUID of the property
  1664. BufferSize - allocate buffer size
  1665. Buffer - buffer that contains the data to be set
  1666. Return Value:
  1667. NO_ERROR
  1668. ERROR_INVALID_HANDLE bad interface handle
  1669. ERROR_INVALID_PARAMETER bad parameter
  1670. ERROR_NOT_SUPPORTED unsupported GUID
  1671. ERROR_WRITE_PROTECT GUID is read-only
  1672. ************************************************************************
  1673. */
  1674. DWORD
  1675. APIENTRY
  1676. TcSetInterface(
  1677. IN HANDLE IfcHandle,
  1678. IN LPGUID pGuidParam,
  1679. IN ULONG BufferSize,
  1680. IN PVOID Buffer
  1681. )
  1682. {
  1683. DWORD Status;
  1684. PINTERFACE_STRUC pInterface;
  1685. WMIHANDLE hWmiHandle;
  1686. TCHAR cstr[MAX_STRING_LENGTH];
  1687. PWNODE_SINGLE_INSTANCE pWnode;
  1688. ULONG cBufSize;
  1689. VERIFY_INITIALIZATION_STATUS;
  1690. if ( IsBadReadPtr(pGuidParam,sizeof(GUID))
  1691. || (BufferSize == 0)
  1692. || IsBadReadPtr(Buffer,BufferSize)) {
  1693. return ERROR_INVALID_PARAMETER;
  1694. }
  1695. pInterface = (PINTERFACE_STRUC)GetHandleObjectWithRef(IfcHandle,
  1696. ENUM_INTERFACE_TYPE, 'TCSI');
  1697. if (pInterface == NULL) {
  1698. return ERROR_INVALID_HANDLE;
  1699. }
  1700. __try {
  1701. Status = WmiOpenBlock( pGuidParam, // object
  1702. 0, // access
  1703. &hWmiHandle
  1704. );
  1705. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1706. Status = GetExceptionCode();
  1707. IF_DEBUG(ERRORS) {
  1708. WSPRINT(("TcSetInterface: Exception Error: = 0x%X\n",
  1709. Status ));
  1710. }
  1711. REFDEL(&pInterface->RefCount, 'TCSI');
  1712. return Status;
  1713. }
  1714. if (ERROR_FAILED(Status)) {
  1715. TC_TRACE(ERRORS, ("[TcSetInterface]: WmiOpenBlock failed with error 0x%x \n", Status));
  1716. REFDEL(&pInterface->RefCount, 'TCSI');
  1717. return Status;
  1718. }
  1719. //
  1720. // allocate memory for the output wnode
  1721. //
  1722. cBufSize = sizeof(WNODE_SINGLE_INSTANCE)
  1723. + BufferSize
  1724. + MAX_STRING_LENGTH * sizeof(TCHAR);
  1725. AllocMem(&pWnode, cBufSize);
  1726. if (pWnode == NULL) {
  1727. Status = ERROR_NOT_ENOUGH_MEMORY;
  1728. } else {
  1729. //
  1730. // set the single instance
  1731. //
  1732. __try {
  1733. #ifndef UNICODE
  1734. if (-1 == wcstombs(cstr,
  1735. pInterface->pTcIfc->InstanceName,
  1736. pInterface->pTcIfc->InstanceNameLength
  1737. )) {
  1738. Status = ERROR_NO_UNICODE_TRANSLATION;
  1739. }
  1740. else {
  1741. Status = WmiSetSingleInstance( hWmiHandle,
  1742. cstr,
  1743. 1,
  1744. BufferSize,
  1745. Buffer
  1746. );
  1747. }
  1748. #else
  1749. Status = WmiSetSingleInstance( hWmiHandle,
  1750. pInterface->pTcIfc->InstanceName,
  1751. 1,
  1752. BufferSize,
  1753. Buffer
  1754. );
  1755. #endif
  1756. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1757. Status = GetExceptionCode();
  1758. IF_DEBUG(ERRORS) {
  1759. WSPRINT(("TcSetInterface: Exception Error: = 0x%X\n",
  1760. Status ));
  1761. }
  1762. }
  1763. }
  1764. WmiCloseBlock(hWmiHandle);
  1765. if (pWnode)
  1766. FreeMem(pWnode);
  1767. REFDEL(&pInterface->RefCount, 'TCSI');
  1768. return Status;
  1769. }
  1770. /*
  1771. ************************************************************************
  1772. Description:
  1773. Will issue a WMI query on the specific flow instance name.
  1774. Arguments:
  1775. pFlowName - flow instance name
  1776. pGuidParam - GUID of the queried property
  1777. BufferSize - size of allocated buffer
  1778. Buffer - the buffer for returned result
  1779. Return Value:
  1780. NO_ERROR
  1781. ERROR_INVALID_PARAMETER bad parameter
  1782. ERROR_INSUFFICIENT_BUFFER buffer too small for result
  1783. ERROR_NOT_SUPPORTED unsupported GUID
  1784. ERROR_WMI_GUID_NOT_FOUND
  1785. ERROR_WMI_INSTANCE_NOT_FOUND
  1786. ************************************************************************
  1787. */
  1788. DWORD
  1789. APIENTRY
  1790. TcQueryFlowW(
  1791. IN LPWSTR pFlowName,
  1792. IN LPGUID pGuidParam,
  1793. IN OUT PULONG pBufferSize,
  1794. OUT PVOID Buffer
  1795. )
  1796. {
  1797. DWORD Status;
  1798. HANDLE hWmiHandle;
  1799. TCHAR cstr[MAX_STRING_LENGTH];
  1800. PWNODE_SINGLE_INSTANCE pWnode;
  1801. ULONG cBufSize;
  1802. ULONG InputBufferSize;
  1803. if (IsBadWritePtr(pBufferSize, sizeof(ULONG)))
  1804. {
  1805. return ERROR_INVALID_PARAMETER;
  1806. }
  1807. __try {
  1808. InputBufferSize = *pBufferSize;
  1809. *pBufferSize = 0;
  1810. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1811. Status = GetExceptionCode();
  1812. IF_DEBUG(ERRORS) {
  1813. WSPRINT(("TcSetFlowW: Exception Error: = 0x%X\n",
  1814. Status ));
  1815. }
  1816. return Status;
  1817. }
  1818. if ( IsBadReadPtr(pGuidParam, sizeof(GUID))
  1819. || IsBadStringPtr(pFlowName, MAX_STRING_LENGTH)
  1820. || IsBadWritePtr(Buffer,InputBufferSize) )
  1821. {
  1822. return ERROR_INVALID_PARAMETER;
  1823. }
  1824. Status = WmiOpenBlock(pGuidParam, // object
  1825. 0, // access
  1826. &hWmiHandle);
  1827. if (ERROR_FAILED(Status)) {
  1828. TC_TRACE(ERRORS, ("[TcQueryInterface]: WmiOpenBlock Error: = 0x%X\n", Status ));
  1829. return Status;
  1830. }
  1831. //
  1832. // allocate memory for the output wnode
  1833. //
  1834. cBufSize = sizeof(WNODE_SINGLE_INSTANCE)
  1835. + InputBufferSize
  1836. + MAX_STRING_LENGTH * sizeof(TCHAR);
  1837. AllocMem(&pWnode, cBufSize);
  1838. if (pWnode == NULL) {
  1839. Status = ERROR_NOT_ENOUGH_MEMORY;
  1840. }
  1841. else
  1842. {
  1843. //
  1844. // query for the single instance
  1845. //
  1846. #ifndef UNICODE
  1847. if (-1 == wcstombs(cstr,
  1848. pFlowName,
  1849. wcslen(pFlowName)
  1850. ))
  1851. {
  1852. Status = ERROR_NO_UNICODE_TRANSLATION;
  1853. }
  1854. else
  1855. {
  1856. Status = WmiQuerySingleInstance( hWmiHandle,
  1857. cstr,
  1858. &cBufSize,
  1859. pWnode
  1860. );
  1861. }
  1862. #else
  1863. Status = WmiQuerySingleInstance( hWmiHandle,
  1864. pFlowName,
  1865. &cBufSize,
  1866. pWnode
  1867. );
  1868. #endif
  1869. if (!ERROR_FAILED(Status)) {
  1870. //
  1871. // parse the wnode
  1872. //
  1873. //
  1874. // check to see if the user allocated enough space for the
  1875. // returned buffer
  1876. //
  1877. if (pWnode->SizeDataBlock <= InputBufferSize) {
  1878. __try {
  1879. RtlCopyMemory(Buffer,
  1880. (PBYTE)OffsetToPtr(pWnode, pWnode->DataBlockOffset),
  1881. pWnode->SizeDataBlock
  1882. );
  1883. *pBufferSize = pWnode->SizeDataBlock;
  1884. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1885. Status = GetExceptionCode();
  1886. TC_TRACE(ERRORS, ("[TcQueryInterface]: RtlCopyMemory Exception Error: = 0x%X\n", Status ));
  1887. }
  1888. } else {
  1889. //
  1890. // output buffer too small
  1891. //
  1892. __try {
  1893. *pBufferSize = pWnode->SizeDataBlock;
  1894. Status = ERROR_INSUFFICIENT_BUFFER;
  1895. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1896. Status = GetExceptionCode();
  1897. TC_TRACE(ERRORS, ("[TcQueryInterface]: RtlCopyMemory Exception Error: = 0x%X\n", Status ));
  1898. }
  1899. }
  1900. }
  1901. }
  1902. WmiCloseBlock(hWmiHandle);
  1903. if(pWnode)
  1904. FreeMem(pWnode);
  1905. return Status;
  1906. }
  1907. /*
  1908. ************************************************************************
  1909. Description:
  1910. The ANSI version of TcQueryFlowW
  1911. Arguments:
  1912. See TcQueryFlowW
  1913. Return Value:
  1914. See TcQueryFlowW
  1915. ************************************************************************
  1916. */
  1917. DWORD
  1918. APIENTRY
  1919. TcQueryFlowA(
  1920. IN LPSTR pFlowName,
  1921. IN LPGUID pGuidParam,
  1922. IN OUT PULONG pBufferSize,
  1923. OUT PVOID Buffer
  1924. )
  1925. {
  1926. LPWSTR pWstr = NULL;
  1927. int l;
  1928. DWORD Status;
  1929. if (IsBadStringPtrA(pFlowName,MAX_STRING_LENGTH)) {
  1930. return ERROR_INVALID_PARAMETER;
  1931. }
  1932. l = strlen(pFlowName) + 1;
  1933. AllocMem(&pWstr, l*sizeof(WCHAR));
  1934. if (pWstr == NULL) {
  1935. return ERROR_NOT_ENOUGH_MEMORY;
  1936. }
  1937. if (-1 == mbstowcs(pWstr, pFlowName, l)) {
  1938. FreeMem(pWstr);
  1939. return ERROR_NO_UNICODE_TRANSLATION;
  1940. }
  1941. Status = TcQueryFlowW(pWstr,
  1942. pGuidParam,
  1943. pBufferSize,
  1944. Buffer
  1945. );
  1946. FreeMem(pWstr);
  1947. return Status;
  1948. }
  1949. /*
  1950. ************************************************************************
  1951. Description:
  1952. Will issue a WMI set on the specific flow instance name.
  1953. Arguments:
  1954. pFlowName - flow instance name
  1955. pGuidParam - GUID of the queried property
  1956. BufferSize - size of allocated buffer
  1957. Buffer - the buffer to set
  1958. Return Value:
  1959. NO_ERROR
  1960. ERROR_INVALID_PARAMETER bad parameter
  1961. ERROR_INSUFFICIENT_BUFFER buffer too small for result
  1962. ERROR_NOT_SUPPORTED unsupported GUID
  1963. ERROR_WMI_GUID_NOT_FOUND
  1964. ERROR_WMI_INSTANCE_NOT_FOUND
  1965. ************************************************************************
  1966. */
  1967. DWORD
  1968. APIENTRY
  1969. TcSetFlowW(
  1970. IN LPWSTR pFlowName,
  1971. IN LPGUID pGuidParam,
  1972. IN ULONG BufferSize,
  1973. IN PVOID Buffer
  1974. )
  1975. {
  1976. DWORD Status;
  1977. HANDLE hWmiHandle;
  1978. TCHAR cstr[MAX_STRING_LENGTH];
  1979. PWNODE_SINGLE_INSTANCE pWnode;
  1980. ULONG cBufSize;
  1981. if ( IsBadStringPtr(pFlowName,MAX_STRING_LENGTH)
  1982. || IsBadReadPtr(pGuidParam,sizeof(GUID))
  1983. || (BufferSize == 0)
  1984. || IsBadReadPtr(Buffer,BufferSize)) {
  1985. return ERROR_INVALID_PARAMETER;
  1986. }
  1987. Status = WmiOpenBlock( pGuidParam, // object
  1988. 0, // access
  1989. &hWmiHandle
  1990. );
  1991. if (ERROR_FAILED(Status)) {
  1992. TC_TRACE(ERRORS, ("[TcSetFlow]: WmiOpenBlock failed with 0x%x \n", Status));
  1993. return Status;
  1994. }
  1995. //
  1996. // allocate memory for the output wnode
  1997. //
  1998. cBufSize = sizeof(WNODE_SINGLE_INSTANCE)
  1999. + BufferSize
  2000. + MAX_STRING_LENGTH * sizeof(TCHAR);
  2001. AllocMem(&pWnode, cBufSize);
  2002. if (pWnode == NULL) {
  2003. Status = ERROR_NOT_ENOUGH_MEMORY;
  2004. } else {
  2005. //
  2006. // set the single instance
  2007. //
  2008. __try {
  2009. #ifndef UNICODE
  2010. if (-1 == wcstombs(cstr,
  2011. pFlowName,
  2012. wcslen(pFlowName)
  2013. )) {
  2014. Status = ERROR_NO_UNICODE_TRANSLATION;
  2015. } else {
  2016. Status = WmiQuerySingleInstance( hWmiHandle,
  2017. cstr,
  2018. &cBufSize,
  2019. pWnode
  2020. );
  2021. }
  2022. #else
  2023. Status = WmiSetSingleInstance( hWmiHandle,
  2024. pFlowName,
  2025. 1,
  2026. BufferSize,
  2027. Buffer
  2028. );
  2029. #endif
  2030. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2031. Status = GetExceptionCode();
  2032. IF_DEBUG(ERRORS) {
  2033. WSPRINT(("TcSetFlowW: Exception Error: = 0x%X\n",
  2034. Status ));
  2035. }
  2036. }
  2037. }
  2038. WmiCloseBlock(hWmiHandle);
  2039. if (pWnode)
  2040. FreeMem(pWnode);
  2041. return Status;
  2042. }
  2043. /*
  2044. ************************************************************************
  2045. Description:
  2046. The ANSI version of TcSetFlowW
  2047. Arguments:
  2048. See TcSetFlowW
  2049. Return Value:
  2050. See TcSetFlowW
  2051. ************************************************************************
  2052. */
  2053. DWORD
  2054. APIENTRY
  2055. TcSetFlowA(
  2056. IN LPSTR pFlowName,
  2057. IN LPGUID pGuidParam,
  2058. IN ULONG BufferSize,
  2059. IN PVOID Buffer
  2060. )
  2061. {
  2062. LPWSTR pWstr;
  2063. int l;
  2064. DWORD Status;
  2065. if (IsBadStringPtrA(pFlowName,MAX_STRING_LENGTH)) {
  2066. return ERROR_INVALID_PARAMETER;
  2067. }
  2068. l = strlen(pFlowName) + 1;
  2069. AllocMem(&pWstr, l*sizeof(WCHAR));
  2070. if (pWstr == NULL) {
  2071. return ERROR_NOT_ENOUGH_MEMORY;
  2072. }
  2073. if(-1 == mbstowcs(pWstr, pFlowName, l)) {
  2074. // couldn't convert some multibyte characters - bail with error.
  2075. FreeMem(pWstr);
  2076. return ERROR_NO_UNICODE_TRANSLATION;
  2077. }
  2078. Status = TcSetFlowW(pWstr,
  2079. pGuidParam,
  2080. BufferSize,
  2081. Buffer
  2082. );
  2083. FreeMem(pWstr);
  2084. return Status;
  2085. }
  2086. /*
  2087. ************************************************************************
  2088. Description:
  2089. Will return the flow inatsnace name associated with the flow handle.
  2090. Arguments:
  2091. FlowHandle - the flow handle
  2092. StrSize - how many TCHAR can fit in the string buffer
  2093. pFlowName - a pointer to a string buffer
  2094. Return Value:
  2095. See TcGetFlowNameW
  2096. ************************************************************************
  2097. */
  2098. DWORD
  2099. APIENTRY
  2100. TcGetFlowNameW(
  2101. IN HANDLE FlowHandle,
  2102. IN ULONG StrSize,
  2103. OUT LPWSTR pFlowName
  2104. )
  2105. {
  2106. PFLOW_STRUC pFlow;
  2107. DWORD Status;
  2108. VERIFY_INITIALIZATION_STATUS;
  2109. if (IsBadWritePtr(pFlowName,StrSize*sizeof(WCHAR))) {
  2110. return ERROR_INVALID_PARAMETER;
  2111. }
  2112. pFlow = (PFLOW_STRUC)GetHandleObjectWithRef(FlowHandle, ENUM_GEN_FLOW_TYPE, 'TGFW');
  2113. if (pFlow == NULL) {
  2114. return ERROR_INVALID_HANDLE;
  2115. }
  2116. else if (pFlow == INVALID_HANDLE_VALUE )
  2117. {
  2118. Status = ERROR_NOT_READY;
  2119. IF_DEBUG(ERRORS) {
  2120. WSPRINT(("TcGetFlowNameW: Error = 0x%X\n", Status ));
  2121. }
  2122. return ERROR_NOT_READY;
  2123. }
  2124. ASSERT((HANDLE)pFlow->ClHandle == FlowHandle);
  2125. if (pFlow->InstanceNameLength+sizeof(WCHAR) > (USHORT)StrSize) {
  2126. //IF_DEBUG(REFCOUNTS) { WSPRINT(("8\n"));
  2127. IF_DEBUG(REFCOUNTS) {
  2128. WSPRINT(("8 DEREF FLOW %X (%X) ref(%d)\n", pFlow->ClHandle, pFlow, pFlow->RefCount));
  2129. }
  2130. REFDEL(&pFlow->RefCount, 'TGFW');
  2131. return ERROR_INSUFFICIENT_BUFFER;
  2132. }
  2133. __try {
  2134. wcscpy(pFlowName, pFlow->InstanceName);
  2135. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2136. Status = GetExceptionCode();
  2137. IF_DEBUG(ERRORS) {
  2138. WSPRINT(("TcGetFlowName: Exception Error: = 0x%X\n", Status ));
  2139. }
  2140. REFDEL(&pFlow->RefCount, 'TGFW');
  2141. return Status;
  2142. }
  2143. IF_DEBUG(REFCOUNTS) {
  2144. WSPRINT(("9 DEREF FLOW %X (%X) ref(%d)\n", pFlow->ClHandle, pFlow, pFlow->RefCount));
  2145. }
  2146. REFDEL(&pFlow->RefCount, 'TGFW');
  2147. return NO_ERROR;
  2148. }
  2149. /*
  2150. ************************************************************************
  2151. Description:
  2152. The ANSI version of TcGetFlowNameW
  2153. Arguments:
  2154. See TcGetFlowNameW
  2155. Return Value:
  2156. See TcGetFlowNameW
  2157. ************************************************************************
  2158. */
  2159. DWORD
  2160. APIENTRY
  2161. TcGetFlowNameA(
  2162. IN HANDLE FlowHandle,
  2163. IN ULONG StrSize,
  2164. OUT LPSTR pFlowName
  2165. )
  2166. {
  2167. PFLOW_STRUC pFlow;
  2168. DWORD Status = NO_ERROR;
  2169. VERIFY_INITIALIZATION_STATUS;
  2170. if (IsBadWritePtr(pFlowName,StrSize * sizeof(CHAR))) {
  2171. return ERROR_INVALID_PARAMETER;
  2172. }
  2173. pFlow = (PFLOW_STRUC)GetHandleObjectWithRef(FlowHandle, ENUM_GEN_FLOW_TYPE, 'TGFA');
  2174. if (pFlow == NULL) {
  2175. return ERROR_INVALID_HANDLE;
  2176. }
  2177. else if (pFlow == INVALID_HANDLE_VALUE )
  2178. {
  2179. Status = ERROR_NOT_READY;
  2180. IF_DEBUG(ERRORS) {
  2181. WSPRINT(("TcGetFlowNameA: Error = 0x%X\n", Status ));
  2182. }
  2183. return ERROR_NOT_READY;
  2184. }
  2185. ASSERT((HANDLE)pFlow->ClHandle == FlowHandle);
  2186. if (pFlow->InstanceNameLength+sizeof(CHAR) > (USHORT)StrSize) {
  2187. IF_DEBUG(REFCOUNTS) {
  2188. WSPRINT(("11 DEREF FLOW %X (%X) ref(%d)\n", pFlow->ClHandle, pFlow, pFlow->RefCount));
  2189. }
  2190. REFDEL(&pFlow->RefCount, 'TGFA');
  2191. return ERROR_INSUFFICIENT_BUFFER;
  2192. }
  2193. __try {
  2194. if (-1 == wcstombs(
  2195. pFlowName,
  2196. pFlow->InstanceName,
  2197. pFlow->InstanceNameLength)) {
  2198. Status = ERROR_NO_UNICODE_TRANSLATION;
  2199. }
  2200. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2201. Status = GetExceptionCode();
  2202. IF_DEBUG(ERRORS) {
  2203. WSPRINT(("TcGetFlowName: Exception Error: = 0x%X\n", Status ));
  2204. }
  2205. REFDEL(&pFlow->RefCount, 'TGFA');
  2206. return Status;
  2207. }
  2208. IF_DEBUG(REFCOUNTS) {
  2209. WSPRINT(("12 DEREF FLOW %X (%X) ref(%d)\n", pFlow->ClHandle, pFlow, pFlow->RefCount));
  2210. }
  2211. REFDEL(&pFlow->RefCount, 'TGFA');
  2212. return Status;
  2213. }
  2214. /*
  2215. ************************************************************************
  2216. Description:
  2217. This will return a specified number of flows with their respective
  2218. filter, given the buffer is big enough. The user allocates the buffer,
  2219. and passes a pointer to an enumeration token. This will be used
  2220. by the GPC to keep track what was the last enumerated flow and will
  2221. initially be point to a NULL value (reset by TC_RESET_ENUM_TOKEN).
  2222. The user will also pass the number of requested flow and will get back
  2223. the actual number of flows that have been placed in the buffer.
  2224. If the buffer is too small, an error code will be returned. If there are
  2225. no more flows to enumerate, NO_ERROR will be returned and pFlowCount
  2226. will be set to zero. It is invalid to request zero flows
  2227. Arguments:
  2228. IfcHandle - the interface to enumerate flows on
  2229. pEnumToken - enumeration handles pointer,
  2230. user must not change after the first call
  2231. pFlowCount - in: # of requested flows; out: actual # of flows returned
  2232. pBufSize - in: allocated bytes; out: filled bytes
  2233. Buffer - formatted data
  2234. Return Value:
  2235. NO_ERROR
  2236. ERROR_INVALID_HANDLE bad interface handle
  2237. ERROR_INVALID_PARAMETER one of the pointers is null or either
  2238. pFlowCount or pBufSize are set to zero
  2239. ERROR_INSUFFICIENT_BUFFER indicates that the provided buffer is too
  2240. small to return even the information for a
  2241. single flow and the attached filters.
  2242. ERROR_NOT_ENOUGH_MEMORY out of memory
  2243. ERROR_INVALID_DATA enumeration handle no longer valid
  2244. ************************************************************************
  2245. */
  2246. DWORD
  2247. APIENTRY
  2248. TcEnumerateFlows(
  2249. IN HANDLE IfcHandle,
  2250. IN OUT PHANDLE pEnumHandle,
  2251. IN OUT PULONG pFlowCount,
  2252. IN OUT PULONG pBufSize,
  2253. OUT PENUMERATION_BUFFER Buffer
  2254. )
  2255. {
  2256. DWORD Status;
  2257. PINTERFACE_STRUC pInterface;
  2258. PGPC_ENUM_CFINFO_RES OutBuffer;
  2259. ULONG cFlows;
  2260. ULONG BufSize;
  2261. ULONG TotalFlows;
  2262. ULONG TotalBytes;
  2263. PFLOW_STRUC pFlow;
  2264. PGPC_CLIENT pGpcClient;
  2265. PLIST_ENTRY pHead, pEntry;
  2266. GPC_HANDLE GpcFlowHandle;
  2267. PGPC_ENUM_CFINFO_BUFFER pGpcEnumBuf;
  2268. PCF_INFO_QOS pCfInfo;
  2269. ULONG Len, i, j;
  2270. ULONG GenFlowSize;
  2271. PCHAR p;
  2272. BOOLEAN bMore;
  2273. PTC_GEN_FILTER pFilter;
  2274. PGPC_GEN_PATTERN pPattern;
  2275. ULONG InputBufSize;
  2276. ULONG InputFlowCount;
  2277. VERIFY_INITIALIZATION_STATUS;
  2278. IF_DEBUG(CALLS) {
  2279. WSPRINT(("==>TcEnumerateFlows: Called: IfcHandle= %d",
  2280. IfcHandle ));
  2281. }
  2282. if ( IsBadWritePtr(pBufSize, sizeof(ULONG))
  2283. || IsBadWritePtr(pFlowCount, sizeof(ULONG))
  2284. || IsBadWritePtr(pEnumHandle,sizeof(HANDLE)) ) {
  2285. return ERROR_INVALID_PARAMETER;
  2286. }
  2287. __try {
  2288. InputBufSize = *pBufSize;
  2289. // *pBufSize = 0; // reset it in case of an error
  2290. InputFlowCount = *pFlowCount;
  2291. GpcFlowHandle = *pEnumHandle;
  2292. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2293. Status = GetExceptionCode();
  2294. return Status;
  2295. }
  2296. if ( IsBadWritePtr(Buffer, InputBufSize)
  2297. || (InputFlowCount == 0) ) {
  2298. return ERROR_INVALID_PARAMETER;
  2299. }
  2300. if (InputBufSize == 0) {
  2301. return ERROR_INSUFFICIENT_BUFFER;
  2302. }
  2303. pInterface = (PINTERFACE_STRUC)GetHandleObjectWithRef(IfcHandle,
  2304. ENUM_INTERFACE_TYPE, 'TCEF');
  2305. if (pInterface == NULL) {
  2306. return ERROR_INVALID_HANDLE;
  2307. }
  2308. pGpcClient = FindGpcClient(GPC_CF_QOS);
  2309. if (pGpcClient == NULL) {
  2310. REFDEL(&pInterface->RefCount, 'TCEF');
  2311. return ERROR_DEV_NOT_EXIST;
  2312. }
  2313. //
  2314. // We are enumerating flows on the interface. we cant afford to have the
  2315. // flows deleted from teh list, therefore we shall take the global lock here.
  2316. //
  2317. GetLock(pGlobals->Lock);
  2318. // back to regularly scheduled programming
  2319. TotalFlows = 0;
  2320. TotalBytes = 0;
  2321. bMore = TRUE;
  2322. while (bMore) {
  2323. BufSize = InputBufSize - TotalBytes;
  2324. cFlows = InputFlowCount - TotalFlows;
  2325. Status = IoEnumerateFlows(pGpcClient,
  2326. &GpcFlowHandle,
  2327. &cFlows,
  2328. &BufSize,
  2329. &OutBuffer
  2330. );
  2331. if (!ERROR_FAILED(Status)) {
  2332. //
  2333. // parse the output buffer and return only the flows that have the
  2334. // interface name in them
  2335. //
  2336. pGpcEnumBuf = &OutBuffer->EnumBuffer[0];
  2337. for (i = 0; i < cFlows; i++) {
  2338. //
  2339. // get the CfInfo
  2340. //
  2341. pCfInfo = (PCF_INFO_QOS)((PCHAR)pGpcEnumBuf +
  2342. pGpcEnumBuf->CfInfoOffset);
  2343. //
  2344. // check if this flow belongs to this interface
  2345. //
  2346. if (wcscmp(pCfInfo->InstanceName,
  2347. pInterface->pTcIfc->InstanceName) == 0) {
  2348. //
  2349. // the flow is installed on this instance
  2350. //
  2351. GenFlowSize = FIELD_OFFSET(TC_GEN_FLOW, TcObjects)
  2352. + pCfInfo->GenFlow.TcObjectsLength;
  2353. //
  2354. // The GPC used GPC_GEN_PATTERN when it computed
  2355. // PatternMaskLen. But, we are using TC_GEN_FILTER
  2356. // to display the patterns. So, we need to account
  2357. // for the difference in GPC_GEN_PATTERN and
  2358. // TC_GEN_FILTER.
  2359. //
  2360. // No, this cannot be made cleaner by getting the GPC
  2361. // to use TC_GEN_FILTER. The GPC is a generic packet
  2362. // classifier and hence shouldn't know about TC_GEN_FILTER.
  2363. //
  2364. Len = FIELD_OFFSET(ENUMERATION_BUFFER, GenericFilter)
  2365. + GenFlowSize
  2366. + pGpcEnumBuf->PatternMaskLen
  2367. - pGpcEnumBuf->PatternCount * sizeof(GPC_GEN_PATTERN)
  2368. + pGpcEnumBuf->PatternCount * sizeof(TC_GEN_FILTER);
  2369. Len = ((Len + (sizeof(PVOID)-1)) & ~(sizeof(PVOID)-1));
  2370. if (TotalBytes + Len > InputBufSize) {
  2371. //
  2372. // not enough buffer output space
  2373. //
  2374. if (TotalFlows == 0)
  2375. Status = ERROR_INSUFFICIENT_BUFFER;
  2376. bMore = FALSE;
  2377. break;
  2378. }
  2379. //
  2380. // fill the output buffer
  2381. //
  2382. __try {
  2383. Buffer->Length = Len;
  2384. Buffer->OwnerProcessId = PtrToUlong(pGpcEnumBuf->OwnerClientCtx);
  2385. Buffer->FlowNameLength = pGpcEnumBuf->InstanceNameLength;
  2386. wcscpy(Buffer->FlowName, pGpcEnumBuf->InstanceName);
  2387. Buffer->NumberOfFilters = pGpcEnumBuf->PatternCount;
  2388. pFilter = (PTC_GEN_FILTER)
  2389. ((PCHAR)Buffer
  2390. + FIELD_OFFSET(ENUMERATION_BUFFER, GenericFilter));
  2391. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2392. Status = GetExceptionCode();
  2393. break;
  2394. }
  2395. pPattern = &pGpcEnumBuf->GenericPattern[0];
  2396. //
  2397. // fill the filters
  2398. //
  2399. for (j = 0; j < pGpcEnumBuf->PatternCount; j++) {
  2400. switch(pPattern->ProtocolId) {
  2401. case GPC_PROTOCOL_TEMPLATE_IP:
  2402. pFilter->AddressType = NDIS_PROTOCOL_ID_TCP_IP;
  2403. ASSERT(pPattern->PatternSize
  2404. == sizeof(IP_PATTERN));
  2405. break;
  2406. case GPC_PROTOCOL_TEMPLATE_IPX:
  2407. pFilter->AddressType = NDIS_PROTOCOL_ID_IPX;
  2408. ASSERT(pPattern->PatternSize
  2409. == sizeof(IPX_PATTERN));
  2410. break;
  2411. default:
  2412. ASSERT(0);
  2413. }
  2414. pFilter->PatternSize = pPattern->PatternSize ;
  2415. pFilter->Pattern = (PVOID)((PCHAR)pFilter
  2416. + sizeof(TC_GEN_FILTER));
  2417. pFilter->Mask = (PVOID)((PCHAR)pFilter->Pattern
  2418. + pPattern->PatternSize);
  2419. //
  2420. // copy the pattern
  2421. //
  2422. p = ((PUCHAR)pPattern) + pPattern->PatternOffset;
  2423. RtlCopyMemory(pFilter->Pattern,
  2424. p,
  2425. pPattern->PatternSize);
  2426. //
  2427. // copy the mask
  2428. //
  2429. p = ((PUCHAR)pPattern) + pPattern->MaskOffset;
  2430. RtlCopyMemory(pFilter->Mask,
  2431. p,
  2432. pPattern->PatternSize);
  2433. //
  2434. // advance the filter pointer to the next item
  2435. //
  2436. pFilter = (PTC_GEN_FILTER)
  2437. ((PCHAR)pFilter
  2438. + sizeof(TC_GEN_FILTER)
  2439. + pPattern->PatternSize * 2);
  2440. pPattern = (PGPC_GEN_PATTERN)(p + pPattern->PatternSize);
  2441. } // for (...)
  2442. //
  2443. // fill the flow
  2444. //
  2445. __try {
  2446. Buffer->pFlow = (PTC_GEN_FLOW)pFilter;
  2447. RtlCopyMemory(pFilter,
  2448. &pCfInfo->GenFlow,
  2449. GenFlowSize
  2450. );
  2451. //
  2452. // advance to the next available slot in
  2453. // the output buffer
  2454. //
  2455. Buffer = (PENUMERATION_BUFFER)((PCHAR)Buffer + Len);
  2456. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2457. Status = GetExceptionCode();
  2458. break;
  2459. }
  2460. //
  2461. // update total counts
  2462. //
  2463. TotalBytes += Len;
  2464. TotalFlows++;
  2465. }
  2466. //
  2467. // advance to the next entry in the GPC returned buffer
  2468. //
  2469. pGpcEnumBuf = (PGPC_ENUM_CFINFO_BUFFER)((PCHAR)pGpcEnumBuf
  2470. + pGpcEnumBuf->Length);
  2471. }
  2472. //
  2473. // release the buffer
  2474. //
  2475. FreeMem(OutBuffer);
  2476. //
  2477. // check to see if we still have room for more flows
  2478. // and adjust the call parameters
  2479. //
  2480. if (TotalFlows == InputFlowCount ||
  2481. TotalBytes + sizeof(ENUMERATION_BUFFER) > InputBufSize ) {
  2482. //
  2483. // that's it, stop enumerating here
  2484. //
  2485. break;
  2486. }
  2487. //
  2488. // check the GpcFlowHandle and quit if needed
  2489. //
  2490. if (GpcFlowHandle == NULL) {
  2491. break;
  2492. }
  2493. } else {
  2494. //
  2495. // there was some error returned,
  2496. // we still have to check if that's the first call
  2497. //
  2498. //
  2499. if (Status == ERROR_INVALID_DATA) {
  2500. __try {
  2501. *pEnumHandle = NULL;
  2502. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2503. Status = GetExceptionCode();
  2504. }
  2505. } else if (TotalFlows > 0) {
  2506. Status = NO_ERROR;
  2507. }
  2508. break;
  2509. }
  2510. } // while
  2511. if (!ERROR_FAILED(Status)) {
  2512. __try {
  2513. *pEnumHandle = GpcFlowHandle;
  2514. *pFlowCount = TotalFlows;
  2515. *pBufSize = TotalBytes;
  2516. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2517. Status = GetExceptionCode();
  2518. }
  2519. }
  2520. //
  2521. // Free all the flow refs taken at the start.
  2522. //
  2523. FreeLock(pGlobals->Lock);
  2524. REFDEL(&pInterface->RefCount, 'TCEF');
  2525. IF_DEBUG(CALLS) {
  2526. WSPRINT(("<==TcEnumerateFlows: Returned= 0x%X\n", Status ));
  2527. }
  2528. return Status;
  2529. }