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.

1996 lines
44 KiB

  1. /*
  2. ************************************************************************
  3. Copyright (c) 1996-1997 Microsoft Corporation
  4. Module Name:
  5. gpcdb.c
  6. Abstract:
  7. This file contains specific patterns database routines
  8. Author:
  9. Ofer Bar -April 15, 1997
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. ************************************************************************
  14. */
  15. #include "gpcpre.h"
  16. //
  17. // locals
  18. //
  19. /*
  20. ************************************************************************
  21. CreateNewCfBlock -
  22. create and return a new CF block for internal use
  23. Arguments
  24. CfId -
  25. MaxPriorities -
  26. Returns
  27. pointer to the new CF block or NULL for no memory resources
  28. ************************************************************************
  29. */
  30. PCF_BLOCK
  31. CreateNewCfBlock(
  32. IN ULONG CfId,
  33. IN ULONG MaxPriorities
  34. )
  35. {
  36. PCF_BLOCK pCf;
  37. int i;
  38. GPC_STATUS Status;
  39. GpcAllocFromLL(&pCf, &ClassificationFamilyLL, ClassificationFamilyTag);
  40. if (pCf) {
  41. //
  42. // reset all
  43. //
  44. NdisZeroMemory(pCf, sizeof(CF_BLOCK));
  45. InitializeListHead(&pCf->ClientList);
  46. InitializeListHead(&pCf->BlobList);
  47. NDIS_INIT_LOCK(&pCf->Lock);
  48. //pCf->ClientSync = 0;
  49. //INIT_LOCK(&pCf->ClientSync);
  50. NDIS_INIT_LOCK(&pCf->ClientSync);
  51. pCf->NumberOfClients = 0;
  52. pCf->AssignedIndex = CfId;
  53. pCf->MaxPriorities = MaxPriorities;
  54. ReferenceInit(&pCf->RefCount, pCf, ReleaseCfBlock);
  55. REFADD(&pCf->RefCount, 'CFBK');
  56. //
  57. // for each protocol, reset the generic pattern
  58. // this will be dynamically allocated later
  59. // when pattern are installed
  60. //
  61. for (i = 0; i < GPC_PROTOCOL_TEMPLATE_MAX; i++) {
  62. Status = InitializeGenericDb(&pCf->arpGenericDb[i],
  63. MaxPriorities,
  64. glData.pProtocols[i].PatternSize);
  65. if (Status != GPC_STATUS_SUCCESS) {
  66. REFDEL(&pCf->RefCount, 'CFBK');
  67. pCf = NULL;
  68. break;
  69. }
  70. }
  71. }
  72. return pCf;
  73. }
  74. /*
  75. ************************************************************************
  76. ReleaseCfBlock -
  77. Release the CF block
  78. Arguments
  79. pCf - the CF block to release
  80. Returns
  81. void
  82. ************************************************************************
  83. */
  84. VOID
  85. ReleaseCfBlock(
  86. IN PCF_BLOCK pCf
  87. )
  88. {
  89. int i;
  90. ASSERT(pCf);
  91. ASSERT(IsListEmpty(&pCf->ClientList));
  92. ASSERT(IsListEmpty(&pCf->BlobList));
  93. ASSERT(pCf->NumberOfClients == 0);
  94. for (i = 0; i < GPC_PROTOCOL_TEMPLATE_MAX; i++) {
  95. if (pCf->arpGenericDb[i]) {
  96. UninitializeGenericDb(&pCf->arpGenericDb[i],
  97. pCf->MaxPriorities
  98. );
  99. }
  100. }
  101. NdisFreeSpinLock(&pCf->Lock);
  102. //
  103. // just free the memory
  104. //
  105. GpcFreeToLL(pCf, &ClassificationFamilyLL, ClassificationFamilyTag);
  106. }
  107. /*
  108. ************************************************************************
  109. CreateNewClientBlock -
  110. create and return a new client block for internal use
  111. Arguments
  112. none
  113. Returns
  114. pointer to the new client block or NULL for no memory resources
  115. ************************************************************************
  116. */
  117. PCLIENT_BLOCK
  118. CreateNewClientBlock(VOID)
  119. {
  120. PCLIENT_BLOCK pClient;
  121. GpcAllocFromLL(&pClient, &ClientLL, ClientTag);
  122. if (pClient) {
  123. //
  124. // reset all
  125. //
  126. NdisZeroMemory(pClient, sizeof(CLIENT_BLOCK));
  127. pClient->ObjectType = GPC_ENUM_CLIENT_TYPE;
  128. pClient->ClHandle = NULL;
  129. NDIS_INIT_LOCK(&pClient->Lock);
  130. InitializeListHead(&pClient->BlobList);
  131. ReferenceInit(&pClient->RefCount, pClient, DereferenceClient);
  132. REFADD(&pClient->RefCount, 'CLNT');
  133. }
  134. return pClient;
  135. }
  136. /*
  137. ************************************************************************
  138. CreateNewPatternBlock -
  139. create and return a new pattern block for internal use
  140. Arguments
  141. none
  142. Returns
  143. pointer to the new pattern block or NULL for no memory resources
  144. ************************************************************************
  145. */
  146. PPATTERN_BLOCK
  147. CreateNewPatternBlock(
  148. IN ULONG Flags
  149. )
  150. {
  151. PPATTERN_BLOCK pPattern;
  152. int i;
  153. GpcAllocFromLL(&pPattern, &PatternLL, PatternTag);
  154. if (pPattern) {
  155. //
  156. // reset all
  157. //
  158. TRACE(PATTERN, pPattern, sizeof(PATTERN_BLOCK), "CreateNewPatternBlock");
  159. NdisZeroMemory(pPattern, sizeof(PATTERN_BLOCK));
  160. pPattern->ObjectType = GPC_ENUM_PATTERN_TYPE;
  161. for (i = 0; i < GPC_CF_MAX; i++) {
  162. InitializeListHead(&pPattern->BlobLinkage[i]);
  163. }
  164. InitializeListHead(&pPattern->TimerLinkage);
  165. NDIS_INIT_LOCK(&pPattern->Lock);
  166. pPattern->Flags = Flags;
  167. ReferenceInit(&pPattern->RefCount, pPattern, DereferencePattern);
  168. REFADD(&pPattern->RefCount, 'FILT');
  169. pPattern->ClientRefCount = 1;
  170. pPattern->State = GPC_STATE_INIT;
  171. //AllocateHandle(&pPattern->ClHandle, (PVOID)pPattern);
  172. }
  173. return pPattern;
  174. }
  175. /*
  176. ************************************************************************
  177. CreateNewBlobBlock -
  178. create and return a new blob block for internal use.
  179. A copy of ClientData is being place pointed by the new blob
  180. Arguments
  181. none
  182. Returns
  183. pointer to the new blob block or NULL for no memory resources
  184. ************************************************************************
  185. */
  186. PBLOB_BLOCK
  187. CreateNewBlobBlock(
  188. IN ULONG ClientDataSize,
  189. IN PVOID pClientData
  190. )
  191. {
  192. PBLOB_BLOCK pBlob;
  193. GpcAllocFromLL(&pBlob, &CfInfoLL, CfInfoTag);
  194. if (pBlob) {
  195. //
  196. // reset all
  197. //
  198. NdisZeroMemory(pBlob, sizeof(BLOB_BLOCK));
  199. GpcAllocMem(&pBlob->pClientData, ClientDataSize, CfInfoDataTag);
  200. if (pBlob->pClientData) {
  201. pBlob->ObjectType = GPC_ENUM_CFINFO_TYPE;
  202. pBlob->ClHandle = NULL;
  203. InitializeListHead(&pBlob->ClientLinkage);
  204. InitializeListHead(&pBlob->PatternList);
  205. InitializeListHead(&pBlob->CfLinkage);
  206. pBlob->State = GPC_STATE_INIT;
  207. pBlob->Flags = 0;
  208. ReferenceInit(&pBlob->RefCount, pBlob, DereferenceBlob);
  209. REFADD(&pBlob->RefCount, 'BLOB');
  210. pBlob->ClientDataSize = ClientDataSize;
  211. pBlob->LastStatus = GPC_STATUS_SUCCESS;
  212. NdisMoveMemory(pBlob->pClientData, pClientData, ClientDataSize);
  213. NDIS_INIT_LOCK(&pBlob->Lock);
  214. //
  215. // that's for the notified client about the CfInfo Add
  216. //
  217. pBlob->pNotifiedClient = NULL;
  218. pBlob->NotifiedClientCtx = NULL;
  219. } else {
  220. GpcFreeToLL(pBlob, &CfInfoLL, CfInfoTag);
  221. pBlob = NULL;
  222. }
  223. }
  224. return pBlob;
  225. }
  226. /*
  227. ************************************************************************
  228. AssignNewClientIndex -
  229. Finds and returns a new index for a client on the CF. It also sets
  230. the index as busy in the CF block.
  231. Arguments
  232. pClient - poinetr to the client block
  233. Returns
  234. a client index or (-1) for none
  235. ************************************************************************
  236. */
  237. ULONG
  238. AssignNewClientIndex(
  239. IN PCF_BLOCK pCfBlock
  240. )
  241. {
  242. ULONG i;
  243. for (i = 0; i < MAX_CLIENTS_CTX_PER_BLOB; i++) {
  244. if (TEST_BIT_OFF(pCfBlock->ClientIndexes, (1 << i)))
  245. break;
  246. }
  247. if (i < MAX_CLIENTS_CTX_PER_BLOB) {
  248. //
  249. // found a zero bit, set it on
  250. //
  251. pCfBlock->ClientIndexes |= (1 << i);
  252. } else {
  253. i = (-1);
  254. }
  255. return i;
  256. }
  257. /*
  258. ************************************************************************
  259. ReleaseClientBlock -
  260. Release the client block
  261. Arguments
  262. pClientBlock - the client block to release
  263. Returns
  264. void
  265. ************************************************************************
  266. */
  267. VOID
  268. ReleaseClientBlock(
  269. IN PCLIENT_BLOCK pClientBlock
  270. )
  271. {
  272. NdisFreeSpinLock(&pClientBlock->Lock);
  273. //
  274. // just free the memory
  275. //
  276. GpcFreeToLL(pClientBlock, &ClientLL, ClientTag);
  277. }
  278. /*
  279. ************************************************************************
  280. ReleasePatternBlock -
  281. Release the pattern block
  282. Arguments
  283. pPatternBlock - the pattern block to release
  284. Returns
  285. void
  286. ************************************************************************
  287. */
  288. VOID
  289. ReleasePatternBlock(
  290. IN PPATTERN_BLOCK pPatternBlock
  291. )
  292. {
  293. #if DBG
  294. pPatternBlock->TimeToLive = 0xdeadbeef;
  295. #endif
  296. //
  297. // just free the memory
  298. //
  299. GpcFreeToLL(pPatternBlock, &PatternLL, PatternTag);
  300. }
  301. /*
  302. ************************************************************************
  303. ReleaseBlobBlock -
  304. Release the blob block
  305. Arguments
  306. pBlobBlock - the blob block to release
  307. Returns
  308. void
  309. ************************************************************************
  310. */
  311. VOID
  312. ReleaseBlobBlock(
  313. IN PBLOB_BLOCK pBlobBlock
  314. )
  315. {
  316. //
  317. // just free the memory
  318. //
  319. GpcFreeMem(pBlobBlock->pClientData, CfInfoDataTag);
  320. ASSERT(pBlobBlock->pNewClientData == NULL);
  321. GpcFreeToLL(pBlobBlock, &CfInfoLL, CfInfoTag);
  322. }
  323. /*
  324. ************************************************************************
  325. CreateNewClassificationBlock -
  326. create and return a new classification block for internal use
  327. Arguments
  328. NumEntries - number of entries
  329. Returns
  330. pointer to the new classification block or NULL for no memory resources
  331. ************************************************************************
  332. */
  333. PCLASSIFICATION_BLOCK
  334. CreateNewClassificationBlock(
  335. IN ULONG NumEntries
  336. )
  337. {
  338. PCLASSIFICATION_BLOCK pClassification;
  339. ULONG l;
  340. l = sizeof(CLASSIFICATION_BLOCK) + sizeof(PBLOB_BLOCK) * (NumEntries-1);
  341. GpcAllocMem(&pClassification, l, ClassificationBlockTag);
  342. if (pClassification) {
  343. //
  344. // reset all
  345. //
  346. NdisZeroMemory(pClassification, l);
  347. pClassification->NumberOfElements = NumEntries;
  348. }
  349. return pClassification;
  350. }
  351. /*
  352. ************************************************************************
  353. ReleaseClassificationBlock -
  354. Release the Classification block
  355. Arguments
  356. pClassificationBlock - the Classification block to release
  357. Returns
  358. void
  359. ************************************************************************
  360. */
  361. VOID
  362. ReleaseClassificationBlock(
  363. IN PCLASSIFICATION_BLOCK pClassificationBlock
  364. )
  365. {
  366. if (pClassificationBlock) {
  367. //
  368. // release the memory block
  369. //
  370. GpcFreeMem(pClassificationBlock, ClassificationBlockTag);
  371. }
  372. }
  373. /*
  374. ************************************************************************
  375. GpcCalcHash -
  376. Calculate the hash table key for a specific pattern
  377. Arguments
  378. ProtocolTempId - The protocol template
  379. pPattern - a pointer to the pattern
  380. Returns
  381. ULONG - the hash key, (-1) if Protocol value is illegal
  382. ************************************************************************
  383. */
  384. ULONG
  385. GpcCalcHash(
  386. IN ULONG ProtocolTempId,
  387. IN PUCHAR pPattern
  388. )
  389. {
  390. ULONG Key = (-1);
  391. ULONG temp;
  392. PULONG Cheat;
  393. PGPC_IP_PATTERN pIpPatt;
  394. PGPC_IPX_PATTERN pIpxPatt;
  395. const ULONG MagicNumber = 0x9e4155b9; // magic number - hocus pocus
  396. TRACE(LOOKUP, ProtocolTempId, pPattern, "GpcClacHash");
  397. ASSERT(pPattern);
  398. switch (ProtocolTempId) {
  399. case GPC_PROTOCOL_TEMPLATE_IP:
  400. //
  401. // the IP protocol template, this function was contributed by
  402. // JohnDo
  403. //
  404. pIpPatt = (PGPC_IP_PATTERN)pPattern;
  405. temp = (pIpPatt->SrcAddr << 16) ^ (pIpPatt->SrcAddr >> 16)
  406. ^ pIpPatt->DstAddr ^ pIpPatt->ProtocolId ^ pIpPatt->gpcSpi;
  407. Key = temp * MagicNumber;
  408. break;
  409. case GPC_PROTOCOL_TEMPLATE_IPX:
  410. //
  411. // the IPX protocol template, this function was contributed by
  412. // JohnDo
  413. //
  414. Cheat = (PULONG)pPattern;
  415. temp =
  416. (Cheat[0] << 16) ^ (Cheat[0] >> 16) ^
  417. (Cheat[1] << 16) ^ (Cheat[1] >> 16) ^
  418. (Cheat[2] << 16) ^ (Cheat[2] >> 16) ^
  419. Cheat[3] ^ Cheat[4] ^ Cheat[5];
  420. Key = temp * MagicNumber;
  421. break;
  422. default:
  423. //
  424. // illegal value
  425. //
  426. ASSERT(0);
  427. }
  428. //
  429. // -1 is a bad key
  430. //
  431. if (Key == (-1))
  432. Key = 0;
  433. TRACE(LOOKUP, Key, 0, "GpcClacHash==>");
  434. return Key;
  435. }
  436. /*
  437. ************************************************************************
  438. DereferencePattern -
  439. Decrement the RefCount and deletes the pattern block if the count reaches
  440. zero.
  441. Arguments
  442. pPattern - a pointer to the pattern
  443. Returns
  444. void
  445. ************************************************************************
  446. */
  447. VOID
  448. DereferencePattern(
  449. IN PPATTERN_BLOCK pPattern
  450. )
  451. {
  452. ASSERT(pPattern);
  453. //ASSERT(pPattern->RefCount.Count > 0);
  454. TRACE(PATTERN, pPattern, pPattern->DbCtx, "DereferencePattern");
  455. ProtocolStatInc(pPattern->ProtocolTemplate,
  456. DerefPattern2Zero);
  457. ASSERT(IsListEmpty(&pPattern->TimerLinkage));
  458. //
  459. // no longer do we need this CB
  460. //
  461. ReleaseClassificationBlock(pPattern->pClassificationBlock);
  462. //
  463. // time to remove the pattern
  464. //
  465. ReleasePatternBlock(pPattern);
  466. }
  467. /*
  468. ************************************************************************
  469. DereferenceBlob -
  470. Decrement the RefCount and deletes the blob block if the count reaches
  471. zero.
  472. Arguments
  473. pBlob - a pointer to the blob
  474. Returns
  475. void
  476. ************************************************************************
  477. */
  478. VOID
  479. DereferenceBlob(
  480. IN PBLOB_BLOCK pBlob
  481. )
  482. {
  483. ASSERT(pBlob);
  484. //ASSERT(*ppBlob);
  485. //TRACE(BLOB, *ppBlob, (*ppBlob)->RefCount, "DereferenceBlob");
  486. //ASSERT((*ppBlob)->RefCount.Count > 0);
  487. CfStatInc(pBlob->pOwnerClient->pCfBlock->AssignedIndex,DerefBlobs2Zero);
  488. //
  489. // time to remove the blob
  490. //
  491. ReleaseBlobBlock(pBlob);
  492. }
  493. /*
  494. ************************************************************************
  495. DereferenceClient -
  496. Decrement the RefCount and deletes the client block if the count reaches
  497. zero.
  498. Arguments
  499. pClient - pointer to the client block
  500. Returns
  501. void
  502. ************************************************************************
  503. */
  504. VOID
  505. DereferenceClient(
  506. IN PCLIENT_BLOCK pClient
  507. )
  508. {
  509. PCF_BLOCK pCf;
  510. KIRQL irql;
  511. ASSERT(pClient);
  512. //TRACE(CLIENT, pClient, pClient->RefCount, "DereferenceClient");
  513. //ASSERT(pClient->RefCount.Count > 0);
  514. pCf = pClient->pCfBlock;
  515. RSC_WRITE_LOCK(&pCf->ClientSync, &irql);
  516. //
  517. // time to remove the client
  518. //
  519. GpcRemoveEntryList(&pClient->ClientLinkage);
  520. ReleaseClientIndex(pCf->ClientIndexes, pClient->AssignedIndex);
  521. ReleaseClientBlock(pClient);
  522. RSC_WRITE_UNLOCK(&pCf->ClientSync, irql);
  523. }
  524. /*
  525. ************************************************************************
  526. ClientAddCfInfo -
  527. Arguments
  528. Returns
  529. ************************************************************************
  530. */
  531. GPC_STATUS
  532. ClientAddCfInfo(
  533. IN PCLIENT_BLOCK pClient,
  534. IN PBLOB_BLOCK pBlob,
  535. OUT PGPC_CLIENT_HANDLE pClientCfInfoContext
  536. )
  537. {
  538. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  539. DEFINE_KIRQL(dbgIrql);
  540. TRACE(PATTERN, pClient, pBlob, "ClientAddCfInfo");
  541. *pClientCfInfoContext = NULL;
  542. if (pClient->State == GPC_STATE_READY) {
  543. if (pClient->FuncList.ClAddCfInfoNotifyHandler) {
  544. NdisInterlockedIncrement(&pBlob->ClientStatusCountDown);
  545. GET_IRQL(dbgIrql);
  546. TRACE(PATTERN, pClient, dbgIrql, "ClientAddCfInfo (2)");
  547. Status = (pClient->FuncList.ClAddCfInfoNotifyHandler)
  548. (
  549. pClient->ClientCtx,
  550. (GPC_HANDLE)pBlob,
  551. pBlob->ClientDataSize,
  552. pBlob->pClientData,
  553. pClientCfInfoContext
  554. );
  555. VERIFY_IRQL(dbgIrql);
  556. TRACE(PATTERN, *pClientCfInfoContext, Status, "ClientAddCfInfo (3)");
  557. if (Status != GPC_STATUS_PENDING) {
  558. NdisInterlockedDecrement(&pBlob->ClientStatusCountDown);
  559. }
  560. }
  561. }
  562. return Status;
  563. }
  564. /*
  565. ************************************************************************
  566. ClientAddCfInfoComplete -
  567. Arguments
  568. Returns
  569. ************************************************************************
  570. */
  571. VOID
  572. ClientAddCfInfoComplete(
  573. IN PCLIENT_BLOCK pClient,
  574. IN PBLOB_BLOCK pBlob,
  575. IN GPC_STATUS Status
  576. )
  577. {
  578. ULONG CfIndex;
  579. DEFINE_KIRQL(dbgIrql);
  580. TRACE(PATTERN, pClient, pBlob, "ClientAddCfInfoComplete");
  581. ASSERT(Status != GPC_STATUS_PENDING);
  582. ASSERT(pClient);
  583. ASSERT(pBlob);
  584. if (pClient->State == GPC_STATE_READY) {
  585. #if NO_USER_PENDING
  586. //
  587. // the user is blocking on this call
  588. //
  589. CTESignal(&pBlob->WaitBlock, Status);
  590. #else
  591. CfIndex = pClient->pCfBlock->AssignedIndex;
  592. if (NT_SUCCESS(Status)) {
  593. CfStatInc(CfIndex,CreatedBlobs);
  594. CfStatInc(CfIndex,CurrentBlobs);
  595. } else {
  596. CfStatInc(CfIndex,RejectedBlobs);
  597. }
  598. if (pClient->FuncList.ClAddCfInfoCompleteHandler) {
  599. GET_IRQL(dbgIrql);
  600. TRACE(PATTERN, pClient, dbgIrql, "ClientAddCfInfoComplete (2)");
  601. TRACE(PATTERN, pClient, pBlob->arClientCtx[pClient->AssignedIndex], "ClientAddCfInfoComplete (3)");
  602. (pClient->FuncList.ClAddCfInfoCompleteHandler)
  603. (
  604. pClient->ClientCtx,
  605. pBlob->arClientCtx[pClient->AssignedIndex],
  606. Status
  607. );
  608. VERIFY_IRQL(dbgIrql);
  609. TRACE(PATTERN, pClient, Status, "ClientAddCfInfoComplete (4)");
  610. } else if (IS_USERMODE_CLIENT(pClient)
  611. &&
  612. pClient == pBlob->pOwnerClient ) {
  613. GET_IRQL(dbgIrql);
  614. TRACE(PATTERN, pClient, dbgIrql, "ClientAddCfInfoComplete (5)");
  615. //
  616. // this is a user mode client - call the specific routine
  617. // to complete a pending IRP, but only if the client is the
  618. // blob owner
  619. //
  620. UMCfInfoComplete( OP_ADD_CFINFO, pClient, pBlob, Status );
  621. VERIFY_IRQL(dbgIrql);
  622. TRACE(PATTERN, pClient, Status, "ClientAddCfInfoComplete (6)");
  623. }
  624. if (NT_SUCCESS(Status)) {
  625. pBlob->State = GPC_STATE_READY;
  626. } else {
  627. //
  628. // remove the blob
  629. //
  630. REFDEL(&pBlob->RefCount, 'BLOB');
  631. }
  632. #endif
  633. }
  634. }
  635. /*
  636. ************************************************************************
  637. ClientModifyCfInfoComplete -
  638. Arguments
  639. Returns
  640. ************************************************************************
  641. */
  642. VOID
  643. ClientModifyCfInfoComplete(
  644. IN PCLIENT_BLOCK pClient,
  645. IN PBLOB_BLOCK pBlob,
  646. IN GPC_STATUS Status
  647. )
  648. {
  649. DEFINE_KIRQL(dbgIrql);
  650. TRACE(PATTERN, pClient, pBlob, "ClientModifyCfInfoComplete");
  651. ASSERT(Status != GPC_STATUS_PENDING);
  652. if (pClient->State == GPC_STATE_READY) {
  653. if (pClient->FuncList.ClModifyCfInfoCompleteHandler) {
  654. GET_IRQL(dbgIrql);
  655. TRACE(PATTERN, pClient, dbgIrql, "ClientModifyCfInfoComplete (2)");
  656. (pClient->FuncList.ClModifyCfInfoCompleteHandler)
  657. (
  658. pClient->ClientCtx,
  659. pBlob->arClientCtx[pClient->AssignedIndex],
  660. Status
  661. );
  662. VERIFY_IRQL(dbgIrql);
  663. TRACE(PATTERN, pBlob->arClientCtx[pClient->AssignedIndex], Status, "ClientModifyCfInfoComplete (3)");
  664. } else if (IS_USERMODE_CLIENT(pClient)) {
  665. GET_IRQL(dbgIrql);
  666. TRACE(PATTERN, pClient, dbgIrql, "ClientModifyCfInfoComplete (4)");
  667. UMCfInfoComplete( OP_MODIFY_CFINFO, pClient, pBlob, Status );
  668. VERIFY_IRQL(dbgIrql);
  669. TRACE(PATTERN, pBlob->arClientCtx[pClient->AssignedIndex], Status, "ClientModifyCfInfoComplete (5)");
  670. }
  671. }
  672. }
  673. /*
  674. ************************************************************************
  675. ClientModifyCfInfo -
  676. Arguments
  677. Returns
  678. ************************************************************************
  679. */
  680. GPC_STATUS
  681. ClientModifyCfInfo(
  682. IN PCLIENT_BLOCK pClient,
  683. IN PBLOB_BLOCK pBlob,
  684. IN ULONG CfInfoSize,
  685. IN PVOID pClientData
  686. )
  687. {
  688. GPC_STATUS Status = GPC_STATUS_IGNORED;
  689. DEFINE_KIRQL(dbgIrql);
  690. TRACE(PATTERN, pClient, pBlob, "ClientModifyCfInfo");
  691. if (pClient->State == GPC_STATE_READY) {
  692. if (pClient->FuncList.ClModifyCfInfoNotifyHandler) {
  693. NdisInterlockedIncrement(&pBlob->ClientStatusCountDown);
  694. GET_IRQL(dbgIrql);
  695. TRACE(PATTERN, pClient, dbgIrql, "ClientModifyCfInfo (2)");
  696. Status = (pClient->FuncList.ClModifyCfInfoNotifyHandler)
  697. (pClient->ClientCtx,
  698. pBlob->arClientCtx[pClient->AssignedIndex],
  699. CfInfoSize,
  700. pClientData
  701. );
  702. VERIFY_IRQL(dbgIrql);
  703. TRACE(PATTERN, pBlob->arClientCtx[pClient->AssignedIndex], Status, "ClientModifyCfInfo (3)");
  704. if (Status != GPC_STATUS_PENDING) {
  705. NdisInterlockedDecrement(&pBlob->ClientStatusCountDown);
  706. }
  707. }
  708. }
  709. return Status;
  710. }
  711. /*
  712. ************************************************************************
  713. ClientRemoveCfInfoComplete -
  714. Arguments
  715. Returns
  716. ************************************************************************
  717. */
  718. VOID
  719. ClientRemoveCfInfoComplete(
  720. IN PCLIENT_BLOCK pClient,
  721. IN PBLOB_BLOCK pBlob,
  722. IN GPC_STATUS Status
  723. )
  724. {
  725. ULONG CfIndex;
  726. DEFINE_KIRQL(dbgIrql);
  727. TRACE(PATTERN, pClient, pBlob, "ClientRemoveCfInfoComplete");
  728. ASSERT(Status != GPC_STATUS_PENDING);
  729. ASSERT(pClient);
  730. ASSERT(pBlob);
  731. #if NO_USER_PENDING
  732. //
  733. // the user is blocking on this call
  734. //
  735. CTESignal(&pBlob->WaitBlock, Status);
  736. #else
  737. CfIndex = pClient->pCfBlock->AssignedIndex;
  738. if (NT_SUCCESS(Status)) {
  739. CfStatInc(CfIndex,DeletedBlobs);
  740. CfStatDec(CfIndex,CurrentBlobs);
  741. }
  742. if (pClient->FuncList.ClRemoveCfInfoCompleteHandler) {
  743. GET_IRQL(dbgIrql);
  744. TRACE(PATTERN, pClient, pBlob->arClientCtx[pClient->AssignedIndex], "ClientRemoveCfInfoComplete (2)");
  745. (pClient->FuncList.ClRemoveCfInfoCompleteHandler)
  746. (
  747. pClient->ClientCtx,
  748. pBlob->arClientCtx[pClient->AssignedIndex],
  749. Status
  750. );
  751. VERIFY_IRQL(dbgIrql);
  752. TRACE(PATTERN, pClient, Status, "ClientRemoveCfInfoComplete (3)");
  753. } else if (IS_USERMODE_CLIENT(pClient)) {
  754. GET_IRQL(dbgIrql);
  755. TRACE(PATTERN, pClient, pBlob->arClientCtx[pClient->AssignedIndex], "ClientRemoveCfInfoComplete (4)");
  756. UMCfInfoComplete( OP_REMOVE_CFINFO, pClient, pBlob, Status );
  757. VERIFY_IRQL(dbgIrql);
  758. TRACE(PATTERN, pClient, Status, "ClientRemoveCfInfoComplete (5)");
  759. }
  760. #endif
  761. }
  762. /*
  763. ************************************************************************
  764. ClientRemoveCfInfo -
  765. Arguments
  766. Returns
  767. ************************************************************************
  768. */
  769. GPC_STATUS
  770. ClientRemoveCfInfo(
  771. IN PCLIENT_BLOCK pClient,
  772. IN PBLOB_BLOCK pBlob,
  773. IN GPC_CLIENT_HANDLE ClientCfInfoContext
  774. )
  775. {
  776. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  777. DEFINE_KIRQL(dbgIrql);
  778. TRACE(PATTERN, pClient, pBlob, "ClientRemoveCfInfo");
  779. if (pClient->State == GPC_STATE_READY) {
  780. if (pClient->FuncList.ClRemoveCfInfoNotifyHandler) {
  781. NdisInterlockedIncrement(&pBlob->ClientStatusCountDown);
  782. GET_IRQL(dbgIrql);
  783. TRACE(PATTERN, pClient, ClientCfInfoContext, "ClientRemoveCfInfo (2)");
  784. Status = (pClient->FuncList.ClRemoveCfInfoNotifyHandler)
  785. (pClient->ClientCtx,
  786. ClientCfInfoContext
  787. );
  788. VERIFY_IRQL(dbgIrql);
  789. TRACE(PATTERN, pClient, Status, "ClientRemoveCfInfo (3)");
  790. if (Status != GPC_STATUS_PENDING) {
  791. NdisInterlockedDecrement(&pBlob->ClientStatusCountDown);
  792. }
  793. } else if (IS_USERMODE_CLIENT(pClient)
  794. &&
  795. pClient == pBlob->pOwnerClient) {
  796. GET_IRQL(dbgIrql);
  797. TRACE(PATTERN, pClient, ClientCfInfoContext, "ClientRemoveCfInfo (4)");
  798. //
  799. // the notified client installed the blob
  800. // and it is a user mode client
  801. // we need to make a special call to dequeue a pending IRP
  802. // and complete it with the specified data
  803. //
  804. UMClientRemoveCfInfoNotify(pClient, pBlob);
  805. VERIFY_IRQL(dbgIrql);
  806. TRACE(PATTERN, pClient, Status, "ClientRemoveCfInfo (5)");
  807. }
  808. }
  809. return Status;
  810. }
  811. /*
  812. ************************************************************************
  813. ClearPatternLinks -
  814. Arguments
  815. Returns
  816. ************************************************************************
  817. */
  818. VOID
  819. ClearPatternLinks(
  820. IN PPATTERN_BLOCK pPattern,
  821. IN PPROTOCOL_BLOCK pProtocol,
  822. IN ULONG CfIndex
  823. )
  824. {
  825. PBLOB_BLOCK *ppBlob;
  826. //
  827. // Remove the pattern from the blob list
  828. // and NULL the pointer to the blob in the pattern block
  829. //
  830. ppBlob = & GetBlobFromPattern(pPattern, CfIndex);
  831. if (*ppBlob) {
  832. NDIS_LOCK(&(*ppBlob)->Lock);
  833. GpcRemoveEntryList(&pPattern->BlobLinkage[CfIndex]);
  834. NDIS_UNLOCK(&(*ppBlob)->Lock);
  835. *ppBlob = NULL;
  836. }
  837. }
  838. /*
  839. ************************************************************************
  840. ModifyCompleteClients -
  841. Arguments
  842. Returns
  843. ************************************************************************
  844. */
  845. VOID
  846. ModifyCompleteClients(
  847. IN PCLIENT_BLOCK pClient,
  848. IN PBLOB_BLOCK pBlob
  849. )
  850. {
  851. uint i;
  852. PCLIENT_BLOCK pNotifyClient;
  853. KIRQL irql;
  854. if (NT_SUCCESS(pBlob->LastStatus)) {
  855. //
  856. // in case of successful completion, assign the
  857. // new client data
  858. //
  859. NDIS_LOCK(&pBlob->Lock);
  860. WRITE_LOCK(&glData.ChLock, &irql);
  861. GpcFreeMem(pBlob->pClientData, CfInfoDataTag);
  862. pBlob->ClientDataSize = pBlob->NewClientDataSize;
  863. pBlob->pClientData = pBlob->pNewClientData;
  864. WRITE_UNLOCK(&glData.ChLock, irql);
  865. NDIS_UNLOCK(&pBlob->Lock);
  866. } else {
  867. GpcFreeMem(pBlob->pNewClientData, CfInfoDataTag);
  868. }
  869. pBlob->NewClientDataSize = 0;
  870. pBlob->pNewClientData = NULL;
  871. //
  872. // notify each client (except the caller) that successfully
  873. // modified the blob about the status.
  874. // it can be SUCCESS or some failure
  875. //
  876. for (i = 0; i < MAX_CLIENTS_CTX_PER_BLOB; i++) {
  877. //
  878. // only clients with none zero entries
  879. // have been succefully modified the blob
  880. //
  881. if (pNotifyClient = pBlob->arpClientStatus[i]) {
  882. //
  883. // complete here
  884. //
  885. ClientModifyCfInfoComplete(
  886. pNotifyClient,
  887. pBlob,
  888. pBlob->LastStatus
  889. );
  890. //
  891. // release the one we got earlier
  892. //
  893. //DereferenceClient(pNotifyClient);
  894. }
  895. } // for
  896. #if 0
  897. //
  898. // now, complete the call back to the calling client
  899. //
  900. ClientModifyCfInfoComplete(
  901. pBlob->pCallingClient,
  902. pBlob,
  903. pBlob->LastStatus
  904. );
  905. #endif
  906. pBlob->State = GPC_STATE_READY;
  907. }
  908. #if 0
  909. /*
  910. ************************************************************************
  911. GetClassificationHandle -
  912. Get the classification handle from the blob. If none is available
  913. creates a new one. '0' is not a valid CH!
  914. Arguments
  915. pClient - The calling client
  916. pPattern - The pattern that refers to the CH
  917. Returns
  918. A classification handle
  919. ************************************************************************
  920. */
  921. CLASSIFICATION_HANDLE
  922. GetClassificationHandle(
  923. IN PCLIENT_BLOCK pClient,
  924. IN PPATTERN_BLOCK pPattern
  925. )
  926. {
  927. HFHandle hfh;
  928. ULONG t;
  929. PCLASSIFICATION_BLOCK pCB;
  930. TRACE(CLASSIFY, pClient, pPattern, "GetClassificationHandle:");
  931. if (TEST_BIT_ON(pPattern->Flags,PATTERN_SPECIFIC)) {
  932. //
  933. // this is a specific pattern
  934. //
  935. //
  936. // get the CH from it
  937. //
  938. ASSERT(pPattern->pClassificationBlock);
  939. hfh = pPattern->pClassificationBlock->ClassificationHandle;
  940. //
  941. // check if CH is valid
  942. //
  943. t = pPattern->ProtocolTemplate;
  944. pCB = (PCLASSIFICATION_BLOCK)dereference_HF_handle(glData.pCHTable,
  945. hfh);
  946. TRACE(CLASSHAND, pCB, hfh, "GetClassificationHandle (~)");
  947. if (pCB != pPattern->pClassificationBlock) {
  948. //
  949. // the CH is invalid, release it and get a new one
  950. //
  951. NDIS_LOCK(&glData.Lock);
  952. release_HF_handle(glData.pCHTable, hfh);
  953. ProtocolStatInc(pPattern->ProtocolTemplate,
  954. RemovedCH);
  955. TRACE(CLASSHAND, glData.pCHTable, hfh, "GetClassificationHandle (-)");
  956. hfh = assign_HF_handle(glData.pCHTable,
  957. (void *)pPattern->pClassificationBlock);
  958. ProtocolStatInc(pPattern->ProtocolTemplate,
  959. InsertedCH);
  960. NDIS_UNLOCK(&glData.Lock);
  961. TRACE(CLASSIFY, pPattern, hfh, "GetClassificationHandle (+)");
  962. pPattern->pClassificationBlock->ClassificationHandle = hfh;
  963. }
  964. } else {
  965. //
  966. // this is a generic pattern
  967. //
  968. hfh = 0;
  969. }
  970. TRACE(CLASSIFY, pPattern, hfh, "GetClassificationHandle==>");
  971. return (CLASSIFICATION_HANDLE)hfh;
  972. }
  973. #endif
  974. /*
  975. ************************************************************************
  976. FreeClassificationHandle -
  977. Free the classification handle. It will invalidate the entry in the
  978. index table and make it avaiable for future use.
  979. Arguments
  980. pClient - The calling client
  981. CH - The classification handle
  982. Returns
  983. void
  984. ************************************************************************
  985. */
  986. VOID
  987. FreeClassificationHandle(
  988. IN PCLIENT_BLOCK pClient,
  989. IN CLASSIFICATION_HANDLE CH
  990. )
  991. {
  992. KIRQL CHirql;
  993. WRITE_LOCK(&glData.ChLock, &CHirql);
  994. release_HF_handle(glData.pCHTable, CH);
  995. TRACE(CLASSHAND, glData.pCHTable, CH, "FreeClassificationHandle");
  996. WRITE_UNLOCK(&glData.ChLock, CHirql);
  997. }
  998. GPC_STATUS
  999. CleanupBlobs(
  1000. IN PCLIENT_BLOCK pClient
  1001. )
  1002. {
  1003. PBLOB_BLOCK pBlob;
  1004. //PPATTERN_BLOCK pPattern;
  1005. //ULONG CfIndex = pClient->pCfBlock->AssignedIndex;
  1006. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  1007. NDIS_LOCK(&pClient->Lock);
  1008. //
  1009. // scan blobs
  1010. //
  1011. while (!IsListEmpty(&pClient->BlobList)) {
  1012. //
  1013. // get the blob
  1014. //
  1015. pBlob = CONTAINING_RECORD(pClient->BlobList.Flink, BLOB_BLOCK, ClientLinkage);
  1016. pBlob->Flags |= PATTERN_REMOVE_CB_BLOB;
  1017. NDIS_UNLOCK(&pClient->Lock);
  1018. //
  1019. // remove the blob
  1020. //
  1021. Status = GpcRemoveCfInfo((GPC_HANDLE)pClient,
  1022. (GPC_HANDLE)pBlob
  1023. );
  1024. NDIS_LOCK(&pClient->Lock);
  1025. }
  1026. NDIS_UNLOCK(&pClient->Lock);
  1027. return GPC_STATUS_SUCCESS;
  1028. }
  1029. VOID
  1030. CloseAllObjects(
  1031. IN PFILE_OBJECT FileObject,
  1032. IN PIRP Irp
  1033. )
  1034. {
  1035. PLIST_ENTRY pEntry0, pHead0;
  1036. PLIST_ENTRY pEntry, pHead;
  1037. PCLIENT_BLOCK pClient = NULL;
  1038. PCF_BLOCK pCf;
  1039. PPROTOCOL_BLOCK pProtocol;
  1040. //int i,j;
  1041. //NTSTATUS NtStatus;
  1042. //QUEUED_COMPLETION QItem;
  1043. KIRQL irql;
  1044. NDIS_LOCK(&glData.Lock);
  1045. pHead0 = &glData.CfList;
  1046. pEntry0 = pHead0->Flink;
  1047. while (pEntry0 != pHead0 && pClient == NULL) {
  1048. pCf = CONTAINING_RECORD(pEntry0, CF_BLOCK, Linkage);
  1049. pEntry0 = pEntry0->Flink;
  1050. RSC_READ_LOCK(&pCf->ClientSync, &irql);
  1051. pHead = &pCf->ClientList;
  1052. pEntry = pHead->Flink;
  1053. while (pEntry != pHead && pClient == NULL) {
  1054. pClient = CONTAINING_RECORD(pEntry,CLIENT_BLOCK,ClientLinkage);
  1055. pEntry = pEntry->Flink;
  1056. if (pClient->pFileObject == FileObject) {
  1057. REFADD(&pClient->RefCount, 'CAOB');
  1058. } else {
  1059. pClient = NULL;
  1060. }
  1061. }
  1062. RSC_READ_UNLOCK(&pCf->ClientSync, irql);
  1063. } // while (...)
  1064. NDIS_UNLOCK(&glData.Lock);
  1065. if (pClient) {
  1066. //
  1067. // clear all the blobs on the client
  1068. //
  1069. CleanupBlobs(pClient);
  1070. //
  1071. // deregister the client
  1072. //
  1073. GpcDeregisterClient((GPC_HANDLE)pClient);
  1074. //
  1075. // release the previous ref count
  1076. //
  1077. REFDEL(&pClient->RefCount, 'CAOB');
  1078. }
  1079. }
  1080. // Cool new feature - Timer Wheels [ShreeM]
  1081. // We maintain N lists of patterns, one for each "timertick". The Pattern
  1082. // Expiry routine will clean up one of the lists every time it is invoked.
  1083. // It then makes a note to cleanup the next list on the wheel, the next time
  1084. // it is invoked.
  1085. // The Timer Wheels reduces spin lock contention between inserts and deletes.
  1086. VOID
  1087. PatternTimerExpired(
  1088. IN PVOID SystemSpecific1,
  1089. IN PVOID FunctionContext,
  1090. IN PVOID SystemSpecific2,
  1091. IN PVOID SystemSpecific3
  1092. )
  1093. {
  1094. PLIST_ENTRY pEntry;
  1095. PPATTERN_BLOCK pPattern;
  1096. PCF_BLOCK pCf;
  1097. ULONG CleanupWheelIndex = 0, NewWheelIndex;
  1098. PPROTOCOL_BLOCK pProtocol = &glData.pProtocols[PtrToUlong(FunctionContext)];
  1099. TRACE(PAT_TIMER, FunctionContext, 0, "PatternTimerExpired");
  1100. DBGPRINT(PAT_TIMER, ("PatternTimerExpired: Timer expired, protocol=%d \n",
  1101. PtrToUlong(FunctionContext)));
  1102. //
  1103. // Which of the timer wheels do we want to cleanup this time?
  1104. // Remember that we Increment the current index pointer into the wheels
  1105. // All the wheel index calculations are protected by gldata->lock.
  1106. NDIS_LOCK(&glData.Lock);
  1107. CleanupWheelIndex = pProtocol->CurrentWheelIndex;
  1108. pProtocol->CurrentWheelIndex += 1;
  1109. //
  1110. // Make sure we wrap around.
  1111. //
  1112. pProtocol->CurrentWheelIndex %= NUMBER_OF_WHEELS;
  1113. NDIS_UNLOCK(&glData.Lock);
  1114. NDIS_LOCK(&pProtocol->PatternTimerLock[CleanupWheelIndex]);
  1115. while (!IsListEmpty(&pProtocol->TimerPatternList[CleanupWheelIndex])) {
  1116. pEntry = RemoveHeadList(&pProtocol->TimerPatternList[CleanupWheelIndex]);
  1117. pPattern = CONTAINING_RECORD(pEntry, PATTERN_BLOCK, TimerLinkage);
  1118. NDIS_UNLOCK(&pProtocol->PatternTimerLock[CleanupWheelIndex]);
  1119. ASSERT(pPattern->TimeToLive != 0xdeadbeef);
  1120. ASSERT(TEST_BIT_ON( pPattern->Flags, PATTERN_AUTO ));
  1121. NDIS_LOCK(&pPattern->Lock);
  1122. pPattern->Flags |= ~PATTERN_AUTO;
  1123. NDIS_UNLOCK(&pPattern->Lock);
  1124. InitializeListHead(&pPattern->TimerLinkage);
  1125. pCf = pPattern->pAutoClient->pCfBlock;
  1126. TRACE(PAT_TIMER, pPattern, pPattern->RefCount.Count, "PatternTimerExpired: del");
  1127. ProtocolStatInc(pPattern->ProtocolTemplate,
  1128. DeletedAp);
  1129. ProtocolStatDec(pPattern->ProtocolTemplate,
  1130. CurrentAp);
  1131. //
  1132. // actually remove the pattern
  1133. //
  1134. DBGPRINT(PAT_TIMER, ("PatternTimerExpired: removing pattern=%X, ref=%d, client=%X \n",
  1135. pPattern, pPattern->RefCount, pPattern->pAutoClient));
  1136. GpcRemovePattern((GPC_HANDLE)pPattern->pAutoClient,
  1137. (GPC_HANDLE)pPattern);
  1138. InterlockedDecrement(&pProtocol->AutoSpecificPatternCount);
  1139. NDIS_LOCK(&pProtocol->PatternTimerLock[CleanupWheelIndex]);
  1140. }
  1141. NDIS_UNLOCK(&pProtocol->PatternTimerLock[CleanupWheelIndex]);
  1142. //
  1143. // If there are any Auto Specific patterns around restart the timer.
  1144. //
  1145. if(InterlockedExchangeAdd(&pProtocol->AutoSpecificPatternCount, 0) > 0) {
  1146. NdisSetTimer(&pProtocol->PatternTimer, PATTERN_TIMEOUT);
  1147. DBGPRINT(PAT_TIMER, ("PatternTimer restarted\n"));
  1148. } else {
  1149. DBGPRINT(PAT_TIMER, ("Zero Auto Patterns - Timer NOT restarted\n"));
  1150. }
  1151. }
  1152. GPC_STATUS
  1153. AddSpecificPatternWithTimer(
  1154. IN PCLIENT_BLOCK pClient,
  1155. IN ULONG ProtocolTemplate,
  1156. IN PVOID PatternKey,
  1157. OUT PPATTERN_BLOCK *ppPattern,
  1158. OUT PCLASSIFICATION_HANDLE pClassificationHandle
  1159. )
  1160. {
  1161. GPC_STATUS Status;
  1162. PPATTERN_BLOCK pPattern, pCreatedPattern;
  1163. PPROTOCOL_BLOCK pProtocol = &glData.pProtocols[ProtocolTemplate];
  1164. UCHAR Mask[MAX_PATTERN_SIZE];
  1165. ULONG WheelIndex = 0;
  1166. TRACE(PAT_TIMER, pClient, PatternKey, "AddSpecificPatternWithTimer");
  1167. #if DBG
  1168. {
  1169. PGPC_IP_PATTERN pIp = (PGPC_IP_PATTERN)PatternKey;
  1170. DBGPRINT(PAT_TIMER, ("AddSpecificPatternWithTimer: Client=%X \n", pClient));
  1171. #if INTERFACE_ID
  1172. DBGPRINT(PAT_TIMER, ("IP: ifc={%d,%d} src=%08X:%04x, dst=%08X:%04x, prot=%d rsv=%x,%x,%x\n",
  1173. pIp->InterfaceId.InterfaceId,
  1174. pIp->InterfaceId.LinkId,
  1175. pIp->SrcAddr,
  1176. pIp->gpcSrcPort,
  1177. pIp->DstAddr,
  1178. pIp->gpcDstPort,
  1179. pIp->ProtocolId,
  1180. pIp->Reserved[0],
  1181. pIp->Reserved[1],
  1182. pIp->Reserved[2]
  1183. ));
  1184. #endif
  1185. }
  1186. #endif
  1187. RtlFillMemory(Mask, sizeof(Mask), 0xff);
  1188. pPattern = CreateNewPatternBlock(PATTERN_SPECIFIC);
  1189. pCreatedPattern = pPattern;
  1190. if (pPattern) {
  1191. //
  1192. // setup the pattern fields and add it
  1193. //
  1194. //pPattern->RefCount++;
  1195. pPattern->Priority = 0;
  1196. pPattern->ProtocolTemplate = ProtocolTemplate;
  1197. pPattern->Flags |= PATTERN_AUTO;
  1198. pPattern->pAutoClient = pClient;
  1199. Status = AddSpecificPattern(
  1200. pClient,
  1201. PatternKey,
  1202. Mask,
  1203. NULL,
  1204. pProtocol,
  1205. &pPattern, // output pattern pointer
  1206. pClassificationHandle
  1207. );
  1208. } else {
  1209. Status = GPC_STATUS_NO_MEMORY;
  1210. }
  1211. if (NT_SUCCESS(Status)) {
  1212. //
  1213. // we didn't get an already existing pattern
  1214. //
  1215. //ASSERT(*pClassificationHandle);
  1216. *ppPattern = pPattern;
  1217. // Figure out which wheel to stick this pattern on.
  1218. NDIS_LOCK(&glData.Lock);
  1219. WheelIndex = pProtocol->CurrentWheelIndex;
  1220. NDIS_UNLOCK(&glData.Lock);
  1221. WheelIndex += (NUMBER_OF_WHEELS -1);
  1222. WheelIndex %= NUMBER_OF_WHEELS;
  1223. //
  1224. // we must lock this pattern since we look at the timer linkage
  1225. //
  1226. NDIS_LOCK(&pPattern->Lock);
  1227. //
  1228. // set the AUTO flag again, since we might have got
  1229. // a pattern that already exist
  1230. //
  1231. pPattern->Flags |= PATTERN_AUTO;
  1232. pPattern->pAutoClient = pClient;
  1233. pPattern->WheelIndex = WheelIndex;
  1234. //
  1235. // this pattern has not been on any the timer list yet
  1236. //
  1237. if (IsListEmpty(&pPattern->TimerLinkage)) {
  1238. //
  1239. // We need to insert this in the TimerWheel which is (NUMBER_OF_WHEELS - 1)
  1240. // away from the current, so that it spends enough time on the list.
  1241. //
  1242. NDIS_DPR_LOCK(&pProtocol->PatternTimerLock[WheelIndex]);
  1243. //
  1244. // If the AutoSpecificPatternCount was zero earlier, then we need
  1245. // to a) start the timer and b) increment this count.
  1246. //
  1247. if (1 == InterlockedIncrement(&pProtocol->AutoSpecificPatternCount)) {
  1248. //
  1249. // restart the timer for the first auto pattern
  1250. //
  1251. NdisSetTimer(&pProtocol->PatternTimer, PATTERN_TIMEOUT);
  1252. TRACE(PAT_TIMER, pPattern, PATTERN_TIMEOUT, "Starting Pattern Timer\n AddSpecificPatternWithTimer: (1)");
  1253. }
  1254. GpcInsertHeadList(&pProtocol->TimerPatternList[WheelIndex], &pPattern->TimerLinkage);
  1255. //
  1256. // don't refer to pPattern after it has been placed on the timer list
  1257. // since the timer may expire any time and remove it from there...
  1258. //
  1259. NDIS_DPR_UNLOCK(&pProtocol->PatternTimerLock[WheelIndex]);
  1260. }
  1261. //
  1262. // This is a specific pattern, so lets increment the count [ShreeM].
  1263. InterlockedIncrement(&pProtocol->SpecificPatternCount);
  1264. NDIS_UNLOCK(&pPattern->Lock);
  1265. ProtocolStatInc(ProtocolTemplate,
  1266. CreatedAp);
  1267. ProtocolStatInc(ProtocolTemplate,
  1268. CurrentAp);
  1269. } else {
  1270. *ppPattern = NULL;
  1271. *pClassificationHandle = 0;
  1272. ProtocolStatInc(ProtocolTemplate,
  1273. RejectedAp);
  1274. }
  1275. if (pPattern) {
  1276. //
  1277. // release the reference count to this pattern
  1278. // in case of an error, this will also release
  1279. // the data block
  1280. //
  1281. REFDEL(&pCreatedPattern->RefCount, 'FILT');
  1282. }
  1283. TRACE(PAT_TIMER, pPattern, Status, "AddSpecificPatternWithTimer==>");
  1284. DBGPRINT(CLASSIFY, ("AddSpecificPatternWithTimer: pClient=%X Pattern=%X Status=%X\n",
  1285. pClient, pPattern, Status));
  1286. return Status;
  1287. }
  1288. NTSTATUS
  1289. InitPatternTimer(
  1290. IN ULONG ProtocolTemplate
  1291. )
  1292. {
  1293. ULONG i=0;
  1294. //
  1295. // We increase the granularity of when a "Automatic" Pattern gets cleaned
  1296. // out by using timer wheels, but they are more efficient for inserting and
  1297. // removing (in terms of locks).
  1298. //
  1299. for (i = 0; i < NUMBER_OF_WHEELS; i++) {
  1300. NDIS_INIT_LOCK(&glData.pProtocols[ProtocolTemplate].PatternTimerLock[i]);
  1301. InitializeListHead(&glData.pProtocols[ProtocolTemplate].TimerPatternList[i]);
  1302. }
  1303. glData.pProtocols[ProtocolTemplate].CurrentWheelIndex = 0;
  1304. NdisInitializeTimer(&glData.pProtocols[ProtocolTemplate].PatternTimer,
  1305. PatternTimerExpired,
  1306. (PVOID) ULongToPtr(ProtocolTemplate));
  1307. return STATUS_SUCCESS;
  1308. }
  1309. //
  1310. // Some CRT and RTL functions that cant be used at DISPATHC_LEVEL IRQL are being
  1311. // cut/paste here.
  1312. //