Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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