Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2280 lines
55 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. BOOLEAN fChargeQuota // Should I charge Quota?
  191. )
  192. {
  193. // Quota Charging should be done only if we have a proces context
  194. PBLOB_BLOCK pBlob;
  195. if (fChargeQuota){
  196. GpcAllocMemWithQuota(&pBlob,CfInfoLLSize,CfInfoTag);
  197. }
  198. else{
  199. GpcAllocMem(&pBlob,CfInfoLLSize,CfInfoTag);
  200. }
  201. if (pBlob) {
  202. //
  203. // reset all
  204. //
  205. NdisZeroMemory(pBlob, sizeof(BLOB_BLOCK));
  206. if (fChargeQuota){
  207. GpcAllocMemWithQuota(&pBlob->pClientData,
  208. ClientDataSize, CfInfoDataTag);
  209. }
  210. else{
  211. GpcAllocMem(&pBlob->pClientData,
  212. ClientDataSize, CfInfoDataTag);
  213. }
  214. if (pBlob->pClientData) {
  215. pBlob->ObjectType = GPC_ENUM_CFINFO_TYPE;
  216. pBlob->ClHandle = NULL;
  217. InitializeListHead(&pBlob->ClientLinkage);
  218. InitializeListHead(&pBlob->PatternList);
  219. InitializeListHead(&pBlob->CfLinkage);
  220. pBlob->State = GPC_STATE_INIT;
  221. pBlob->Flags = 0;
  222. ReferenceInit(&pBlob->RefCount, pBlob, DereferenceBlob);
  223. REFADD(&pBlob->RefCount, 'BLOB');
  224. pBlob->ClientDataSize = ClientDataSize;
  225. pBlob->LastStatus = GPC_STATUS_SUCCESS;
  226. NdisMoveMemory(pBlob->pClientData, pClientData, ClientDataSize);
  227. NDIS_INIT_LOCK(&pBlob->Lock);
  228. //
  229. // that's for the notified client about the CfInfo Add
  230. //
  231. pBlob->pNotifiedClient = NULL;
  232. pBlob->NotifiedClientCtx = NULL;
  233. } else {
  234. //GpcFreeToLL(pBlob, &CfInfoLL, CfInfoTag);
  235. GpcFreeMem(pBlob,CfInfoTag);
  236. pBlob = NULL;
  237. }
  238. }
  239. return pBlob;
  240. }
  241. /*
  242. ************************************************************************
  243. AssignNewClientIndex -
  244. Finds and returns a new index for a client on the CF. It also sets
  245. the index as busy in the CF block.
  246. Arguments
  247. pClient - poinetr to the client block
  248. Returns
  249. a client index or (-1) for none
  250. ************************************************************************
  251. */
  252. ULONG
  253. AssignNewClientIndex(
  254. IN PCF_BLOCK pCfBlock
  255. )
  256. {
  257. ULONG i;
  258. for (i = 0; i < MAX_CLIENTS_CTX_PER_BLOB; i++) {
  259. if (TEST_BIT_OFF(pCfBlock->ClientIndexes, (1 << i)))
  260. break;
  261. }
  262. if (i < MAX_CLIENTS_CTX_PER_BLOB) {
  263. //
  264. // found a zero bit, set it on
  265. //
  266. pCfBlock->ClientIndexes |= (1 << i);
  267. } else {
  268. i = (-1);
  269. }
  270. return i;
  271. }
  272. /*
  273. ************************************************************************
  274. ReleaseClientBlock -
  275. Release the client block
  276. Arguments
  277. pClientBlock - the client block to release
  278. Returns
  279. void
  280. ************************************************************************
  281. */
  282. VOID
  283. ReleaseClientBlock(
  284. IN PCLIENT_BLOCK pClientBlock
  285. )
  286. {
  287. NdisFreeSpinLock(&pClientBlock->Lock);
  288. //
  289. // just free the memory
  290. //
  291. GpcFreeToLL(pClientBlock, &ClientLL, ClientTag);
  292. }
  293. /*
  294. ************************************************************************
  295. ReleasePatternBlock -
  296. Release the pattern block
  297. Arguments
  298. pPatternBlock - the pattern block to release
  299. Returns
  300. void
  301. ************************************************************************
  302. */
  303. VOID
  304. ReleasePatternBlock(
  305. IN PPATTERN_BLOCK pPatternBlock
  306. )
  307. {
  308. #if DBG
  309. pPatternBlock->TimeToLive = 0xdeadbeef;
  310. #endif
  311. //
  312. // just free the memory
  313. //
  314. GpcFreeToLL(pPatternBlock, &PatternLL, PatternTag);
  315. }
  316. /*
  317. ************************************************************************
  318. ReleaseBlobBlock -
  319. Release the blob block
  320. Arguments
  321. pBlobBlock - the blob block to release
  322. Returns
  323. void
  324. ************************************************************************
  325. */
  326. VOID
  327. ReleaseBlobBlock(
  328. IN PBLOB_BLOCK pBlobBlock
  329. )
  330. {
  331. //
  332. // just free the memory
  333. //
  334. GpcFreeMem(pBlobBlock->pClientData, CfInfoDataTag);
  335. ASSERT(pBlobBlock->pNewClientData == NULL);
  336. //GpcFreeToLL(pBlobBlock, &CfInfoLL, CfInfoTag);
  337. GpcFreeMem(pBlobBlock,CfInfoTag);
  338. }
  339. /*
  340. ************************************************************************
  341. CreateNewClassificationBlock -
  342. create and return a new classification block for internal use
  343. Arguments
  344. NumEntries - number of entries
  345. Returns
  346. pointer to the new classification block or NULL for no memory resources
  347. ************************************************************************
  348. */
  349. PCLASSIFICATION_BLOCK
  350. CreateNewClassificationBlock(
  351. IN ULONG NumEntries
  352. )
  353. {
  354. PCLASSIFICATION_BLOCK pClassification;
  355. ULONG l;
  356. l = sizeof(CLASSIFICATION_BLOCK) + sizeof(PBLOB_BLOCK) * (NumEntries-1);
  357. GpcAllocMem(&pClassification, l, ClassificationBlockTag);
  358. if (pClassification) {
  359. //
  360. // reset all
  361. //
  362. NdisZeroMemory(pClassification, l);
  363. pClassification->NumberOfElements = NumEntries;
  364. }
  365. return pClassification;
  366. }
  367. /*
  368. ************************************************************************
  369. ReleaseClassificationBlock -
  370. Release the Classification block
  371. Arguments
  372. pClassificationBlock - the Classification block to release
  373. Returns
  374. void
  375. ************************************************************************
  376. */
  377. VOID
  378. ReleaseClassificationBlock(
  379. IN PCLASSIFICATION_BLOCK pClassificationBlock
  380. )
  381. {
  382. if (pClassificationBlock) {
  383. //
  384. // release the memory block
  385. //
  386. GpcFreeMem(pClassificationBlock, ClassificationBlockTag);
  387. }
  388. }
  389. /*
  390. ************************************************************************
  391. GpcCalcHash -
  392. Calculate the hash table key for a specific pattern
  393. Arguments
  394. ProtocolTempId - The protocol template
  395. pPattern - a pointer to the pattern
  396. Returns
  397. ULONG - the hash key, (-1) if Protocol value is illegal
  398. ************************************************************************
  399. */
  400. ULONG
  401. GpcCalcHash(
  402. IN ULONG ProtocolTempId,
  403. IN PUCHAR pPattern
  404. )
  405. {
  406. ULONG Key = (-1);
  407. ULONG temp;
  408. PULONG Cheat;
  409. PGPC_IP_PATTERN pIpPatt;
  410. PGPC_IPX_PATTERN pIpxPatt;
  411. const ULONG MagicNumber = 0x9e4155b9; // magic number - hocus pocus
  412. TRACE(LOOKUP, ProtocolTempId, pPattern, "GpcClacHash");
  413. ASSERT(pPattern);
  414. switch (ProtocolTempId) {
  415. case GPC_PROTOCOL_TEMPLATE_IP:
  416. //
  417. // the IP protocol template, this function was contributed by
  418. // JohnDo
  419. //
  420. pIpPatt = (PGPC_IP_PATTERN)pPattern;
  421. temp = (pIpPatt->SrcAddr << 16) ^ (pIpPatt->SrcAddr >> 16)
  422. ^ pIpPatt->DstAddr ^ pIpPatt->ProtocolId ^ pIpPatt->gpcSpi;
  423. Key = temp * MagicNumber;
  424. break;
  425. case GPC_PROTOCOL_TEMPLATE_IPX:
  426. //
  427. // the IPX protocol template, this function was contributed by
  428. // JohnDo
  429. //
  430. Cheat = (PULONG)pPattern;
  431. temp =
  432. (Cheat[0] << 16) ^ (Cheat[0] >> 16) ^
  433. (Cheat[1] << 16) ^ (Cheat[1] >> 16) ^
  434. (Cheat[2] << 16) ^ (Cheat[2] >> 16) ^
  435. Cheat[3] ^ Cheat[4] ^ Cheat[5];
  436. Key = temp * MagicNumber;
  437. break;
  438. default:
  439. //
  440. // illegal value
  441. //
  442. ASSERT(0);
  443. }
  444. //
  445. // -1 is a bad key
  446. //
  447. if (Key == (-1))
  448. Key = 0;
  449. TRACE(LOOKUP, Key, 0, "GpcClacHash==>");
  450. return Key;
  451. }
  452. /*
  453. ************************************************************************
  454. DereferencePattern -
  455. Decrement the RefCount and deletes the pattern block if the count reaches
  456. zero.
  457. Arguments
  458. pPattern - a pointer to the pattern
  459. Returns
  460. void
  461. ************************************************************************
  462. */
  463. VOID
  464. DereferencePattern(
  465. IN PPATTERN_BLOCK pPattern
  466. )
  467. {
  468. ASSERT(pPattern);
  469. //ASSERT(pPattern->RefCount.Count > 0);
  470. TRACE(PATTERN, pPattern, pPattern->DbCtx, "DereferencePattern");
  471. ProtocolStatInc(pPattern->ProtocolTemplate,
  472. DerefPattern2Zero);
  473. ASSERT(IsListEmpty(&pPattern->TimerLinkage));
  474. //
  475. // no longer do we need this CB
  476. //
  477. ReleaseClassificationBlock(pPattern->pClassificationBlock);
  478. //
  479. // time to remove the pattern
  480. //
  481. ReleasePatternBlock(pPattern);
  482. }
  483. /*
  484. ************************************************************************
  485. DereferenceBlob -
  486. Decrement the RefCount and deletes the blob block if the count reaches
  487. zero.
  488. Arguments
  489. pBlob - a pointer to the blob
  490. Returns
  491. void
  492. ************************************************************************
  493. */
  494. VOID
  495. DereferenceBlob(
  496. IN PBLOB_BLOCK pBlob
  497. )
  498. {
  499. ASSERT(pBlob);
  500. //
  501. // If there is a File Object, dereference it.
  502. //
  503. if (pBlob->FileObject) {
  504. ObDereferenceObject(pBlob->FileObject);
  505. pBlob->FileObject = NULL;
  506. }
  507. if (pBlob->Pattern) {
  508. GpcFreeMem(pBlob->Pattern,TcpPatternTag);
  509. pBlob->Pattern = NULL;
  510. }
  511. //ASSERT(*ppBlob);
  512. //TRACE(BLOB, *ppBlob, (*ppBlob)->RefCount, "DereferenceBlob");
  513. //ASSERT((*ppBlob)->RefCount.Count > 0);
  514. CfStatInc(pBlob->pOwnerClient->pCfBlock->AssignedIndex,DerefBlobs2Zero);
  515. //
  516. // time to remove the blob
  517. //
  518. ReleaseBlobBlock(pBlob);
  519. }
  520. /*
  521. ************************************************************************
  522. DereferenceClient -
  523. Decrement the RefCount and deletes the client block if the count reaches
  524. zero.
  525. Arguments
  526. pClient - pointer to the client block
  527. Returns
  528. void
  529. ************************************************************************
  530. */
  531. VOID
  532. DereferenceClient(
  533. IN PCLIENT_BLOCK pClient
  534. )
  535. {
  536. PCF_BLOCK pCf;
  537. KIRQL irql;
  538. ASSERT(pClient);
  539. //TRACE(CLIENT, pClient, pClient->RefCount, "DereferenceClient");
  540. //ASSERT(pClient->RefCount.Count > 0);
  541. pCf = pClient->pCfBlock;
  542. RSC_WRITE_LOCK(&pCf->ClientSync, &irql);
  543. //
  544. // time to remove the client
  545. //
  546. GpcRemoveEntryList(&pClient->ClientLinkage);
  547. ReleaseClientIndex(pCf->ClientIndexes, pClient->AssignedIndex);
  548. ReleaseClientBlock(pClient);
  549. RSC_WRITE_UNLOCK(&pCf->ClientSync, irql);
  550. }
  551. /*
  552. ************************************************************************
  553. ClientAddCfInfo -
  554. Arguments
  555. Returns
  556. ************************************************************************
  557. */
  558. GPC_STATUS
  559. ClientAddCfInfo(
  560. IN PCLIENT_BLOCK pClient,
  561. IN PBLOB_BLOCK pBlob,
  562. OUT PGPC_CLIENT_HANDLE pClientCfInfoContext
  563. )
  564. {
  565. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  566. DEFINE_KIRQL(dbgIrql);
  567. TRACE(PATTERN, pClient, pBlob, "ClientAddCfInfo");
  568. *pClientCfInfoContext = NULL;
  569. if (pClient->State == GPC_STATE_READY) {
  570. if (pClient->FuncList.ClAddCfInfoNotifyHandler) {
  571. NdisInterlockedIncrement(&pBlob->ClientStatusCountDown);
  572. GET_IRQL(dbgIrql);
  573. TRACE(PATTERN, pClient, dbgIrql, "ClientAddCfInfo (2)");
  574. // Pass in link id if a client of the new interface registers
  575. if (IS_USERMODE_CLIENT_EX(pBlob->pOwnerClient)){
  576. Status = (pClient->FuncList.ClAddCfInfoNotifyHandler)
  577. (
  578. pClient->ClientCtx,
  579. (GPC_HANDLE)pBlob,
  580. &(pBlob->Pattern->InterfaceId),
  581. pBlob->ClientDataSize,
  582. pBlob->pClientData,
  583. pClientCfInfoContext
  584. );
  585. }
  586. else{
  587. Status = (pClient->FuncList.ClAddCfInfoNotifyHandler)
  588. (
  589. pClient->ClientCtx,
  590. (GPC_HANDLE)pBlob,
  591. NULL,
  592. pBlob->ClientDataSize,
  593. pBlob->pClientData,
  594. pClientCfInfoContext
  595. );
  596. }
  597. VERIFY_IRQL(dbgIrql);
  598. TRACE(PATTERN, *pClientCfInfoContext, Status, "ClientAddCfInfo (3)");
  599. if (Status != GPC_STATUS_PENDING) {
  600. NdisInterlockedDecrement(&pBlob->ClientStatusCountDown);
  601. }
  602. }
  603. }
  604. return Status;
  605. }
  606. /*
  607. ************************************************************************
  608. ClientAddCfInfoComplete -
  609. Arguments
  610. Returns
  611. ************************************************************************
  612. */
  613. VOID
  614. ClientAddCfInfoComplete(
  615. IN PCLIENT_BLOCK pClient,
  616. IN PBLOB_BLOCK pBlob,
  617. IN GPC_STATUS Status
  618. )
  619. {
  620. ULONG CfIndex;
  621. DEFINE_KIRQL(dbgIrql);
  622. TRACE(PATTERN, pClient, pBlob, "ClientAddCfInfoComplete");
  623. ASSERT(Status != GPC_STATUS_PENDING);
  624. ASSERT(pClient);
  625. ASSERT(pBlob);
  626. if (pClient->State == GPC_STATE_READY) {
  627. #if NO_USER_PENDING
  628. //
  629. // the user is blocking on this call
  630. //
  631. CTESignal(&pBlob->WaitBlock, Status);
  632. #else
  633. CfIndex = pClient->pCfBlock->AssignedIndex;
  634. if (NT_SUCCESS(Status)) {
  635. CfStatInc(CfIndex,CreatedBlobs);
  636. CfStatInc(CfIndex,CurrentBlobs);
  637. } else {
  638. CfStatInc(CfIndex,RejectedBlobs);
  639. }
  640. if (pClient->FuncList.ClAddCfInfoCompleteHandler) {
  641. GET_IRQL(dbgIrql);
  642. TRACE(PATTERN, pClient, dbgIrql, "ClientAddCfInfoComplete (2)");
  643. TRACE(PATTERN, pClient, pBlob->arClientCtx[pClient->AssignedIndex], "ClientAddCfInfoComplete (3)");
  644. (pClient->FuncList.ClAddCfInfoCompleteHandler)
  645. (
  646. pClient->ClientCtx,
  647. pBlob->arClientCtx[pClient->AssignedIndex],
  648. Status
  649. );
  650. VERIFY_IRQL(dbgIrql);
  651. TRACE(PATTERN, pClient, Status, "ClientAddCfInfoComplete (4)");
  652. } else if (IS_USERMODE_CLIENT(pClient)
  653. &&
  654. pClient == pBlob->pOwnerClient ) {
  655. GET_IRQL(dbgIrql);
  656. TRACE(PATTERN, pClient, dbgIrql, "ClientAddCfInfoComplete (5)");
  657. //
  658. // this is a user mode client - call the specific routine
  659. // to complete a pending IRP, but only if the client is the
  660. // blob owner
  661. //
  662. UMCfInfoComplete( OP_ADD_CFINFO, pClient, pBlob, Status );
  663. VERIFY_IRQL(dbgIrql);
  664. TRACE(PATTERN, pClient, Status, "ClientAddCfInfoComplete (6)");
  665. }
  666. if (NT_SUCCESS(Status)) {
  667. pBlob->State = GPC_STATE_READY;
  668. } else {
  669. //
  670. // remove the blob
  671. //
  672. REFDEL(&pBlob->RefCount, 'BLOB');
  673. }
  674. #endif
  675. }
  676. }
  677. /*
  678. ************************************************************************
  679. ClientModifyCfInfoComplete -
  680. Arguments
  681. Returns
  682. ************************************************************************
  683. */
  684. VOID
  685. ClientModifyCfInfoComplete(
  686. IN PCLIENT_BLOCK pClient,
  687. IN PBLOB_BLOCK pBlob,
  688. IN GPC_STATUS Status
  689. )
  690. {
  691. DEFINE_KIRQL(dbgIrql);
  692. TRACE(PATTERN, pClient, pBlob, "ClientModifyCfInfoComplete");
  693. ASSERT(Status != GPC_STATUS_PENDING);
  694. if (pClient->State == GPC_STATE_READY) {
  695. if (pClient->FuncList.ClModifyCfInfoCompleteHandler) {
  696. GET_IRQL(dbgIrql);
  697. TRACE(PATTERN, pClient, dbgIrql, "ClientModifyCfInfoComplete (2)");
  698. (pClient->FuncList.ClModifyCfInfoCompleteHandler)
  699. (
  700. pClient->ClientCtx,
  701. pBlob->arClientCtx[pClient->AssignedIndex],
  702. Status
  703. );
  704. VERIFY_IRQL(dbgIrql);
  705. TRACE(PATTERN, pBlob->arClientCtx[pClient->AssignedIndex], Status, "ClientModifyCfInfoComplete (3)");
  706. } else if (IS_USERMODE_CLIENT(pClient)) {
  707. GET_IRQL(dbgIrql);
  708. TRACE(PATTERN, pClient, dbgIrql, "ClientModifyCfInfoComplete (4)");
  709. UMCfInfoComplete( OP_MODIFY_CFINFO, pClient, pBlob, Status );
  710. VERIFY_IRQL(dbgIrql);
  711. TRACE(PATTERN, pBlob->arClientCtx[pClient->AssignedIndex], Status, "ClientModifyCfInfoComplete (5)");
  712. }
  713. }
  714. }
  715. /*
  716. ************************************************************************
  717. ClientModifyCfInfo -
  718. Arguments
  719. Returns
  720. ************************************************************************
  721. */
  722. GPC_STATUS
  723. ClientModifyCfInfo(
  724. IN PCLIENT_BLOCK pClient,
  725. IN PBLOB_BLOCK pBlob,
  726. IN ULONG CfInfoSize,
  727. IN PVOID pClientData
  728. )
  729. {
  730. GPC_STATUS Status = GPC_STATUS_IGNORED;
  731. DEFINE_KIRQL(dbgIrql);
  732. TRACE(PATTERN, pClient, pBlob, "ClientModifyCfInfo");
  733. if (pClient->State == GPC_STATE_READY) {
  734. if (pClient->FuncList.ClModifyCfInfoNotifyHandler) {
  735. NdisInterlockedIncrement(&pBlob->ClientStatusCountDown);
  736. GET_IRQL(dbgIrql);
  737. TRACE(PATTERN, pClient, dbgIrql, "ClientModifyCfInfo (2)");
  738. Status = (pClient->FuncList.ClModifyCfInfoNotifyHandler)
  739. (pClient->ClientCtx,
  740. pBlob->arClientCtx[pClient->AssignedIndex],
  741. CfInfoSize,
  742. pClientData
  743. );
  744. VERIFY_IRQL(dbgIrql);
  745. TRACE(PATTERN, pBlob->arClientCtx[pClient->AssignedIndex], Status, "ClientModifyCfInfo (3)");
  746. if (Status != GPC_STATUS_PENDING) {
  747. NdisInterlockedDecrement(&pBlob->ClientStatusCountDown);
  748. }
  749. }
  750. }
  751. return Status;
  752. }
  753. /*
  754. ************************************************************************
  755. ClientRemoveCfInfoComplete -
  756. Arguments
  757. Returns
  758. ************************************************************************
  759. */
  760. VOID
  761. ClientRemoveCfInfoComplete(
  762. IN PCLIENT_BLOCK pClient,
  763. IN PBLOB_BLOCK pBlob,
  764. IN GPC_STATUS Status
  765. )
  766. {
  767. ULONG CfIndex;
  768. DEFINE_KIRQL(dbgIrql);
  769. TRACE(PATTERN, pClient, pBlob, "ClientRemoveCfInfoComplete");
  770. ASSERT(Status != GPC_STATUS_PENDING);
  771. ASSERT(pClient);
  772. ASSERT(pBlob);
  773. #if NO_USER_PENDING
  774. //
  775. // the user is blocking on this call
  776. //
  777. CTESignal(&pBlob->WaitBlock, Status);
  778. #else
  779. CfIndex = pClient->pCfBlock->AssignedIndex;
  780. if (NT_SUCCESS(Status)) {
  781. CfStatInc(CfIndex,DeletedBlobs);
  782. CfStatDec(CfIndex,CurrentBlobs);
  783. }
  784. if (pClient->FuncList.ClRemoveCfInfoCompleteHandler) {
  785. GET_IRQL(dbgIrql);
  786. TRACE(PATTERN, pClient, pBlob->arClientCtx[pClient->AssignedIndex], "ClientRemoveCfInfoComplete (2)");
  787. (pClient->FuncList.ClRemoveCfInfoCompleteHandler)
  788. (
  789. pClient->ClientCtx,
  790. pBlob->arClientCtx[pClient->AssignedIndex],
  791. Status
  792. );
  793. VERIFY_IRQL(dbgIrql);
  794. TRACE(PATTERN, pClient, Status, "ClientRemoveCfInfoComplete (3)");
  795. } else if (IS_USERMODE_CLIENT(pClient)) {
  796. GET_IRQL(dbgIrql);
  797. TRACE(PATTERN, pClient, pBlob->arClientCtx[pClient->AssignedIndex], "ClientRemoveCfInfoComplete (4)");
  798. UMCfInfoComplete( OP_REMOVE_CFINFO, pClient, pBlob, Status );
  799. VERIFY_IRQL(dbgIrql);
  800. TRACE(PATTERN, pClient, Status, "ClientRemoveCfInfoComplete (5)");
  801. }
  802. #endif
  803. }
  804. /*
  805. ************************************************************************
  806. ClientRemoveCfInfo -
  807. Arguments
  808. Returns
  809. ************************************************************************
  810. */
  811. GPC_STATUS
  812. ClientRemoveCfInfo(
  813. IN PCLIENT_BLOCK pClient,
  814. IN PBLOB_BLOCK pBlob,
  815. IN GPC_CLIENT_HANDLE ClientCfInfoContext
  816. )
  817. {
  818. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  819. DEFINE_KIRQL(dbgIrql);
  820. TRACE(PATTERN, pClient, pBlob, "ClientRemoveCfInfo");
  821. if (pClient->State == GPC_STATE_READY) {
  822. if (pClient->FuncList.ClRemoveCfInfoNotifyHandler) {
  823. NdisInterlockedIncrement(&pBlob->ClientStatusCountDown);
  824. GET_IRQL(dbgIrql);
  825. TRACE(PATTERN, pClient, ClientCfInfoContext, "ClientRemoveCfInfo (2)");
  826. Status = (pClient->FuncList.ClRemoveCfInfoNotifyHandler)
  827. (pClient->ClientCtx,
  828. ClientCfInfoContext
  829. );
  830. VERIFY_IRQL(dbgIrql);
  831. TRACE(PATTERN, pClient, Status, "ClientRemoveCfInfo (3)");
  832. if (Status != GPC_STATUS_PENDING) {
  833. NdisInterlockedDecrement(&pBlob->ClientStatusCountDown);
  834. }
  835. } else if
  836. (IS_USERMODE_CLIENT(pClient) //For client using IOCTL interface
  837. &&
  838. !IS_USERMODE_CLIENT_EX(pClient)//But Not for new IOCTL interfaces
  839. &&
  840. pClient == pBlob->pOwnerClient) {// If the client owns the Blob
  841. GET_IRQL(dbgIrql);
  842. TRACE(PATTERN, pClient, ClientCfInfoContext, "ClientRemoveCfInfo (4)");
  843. //
  844. // the notified client installed the blob
  845. // and it is a user mode client
  846. // we need to make a special call to dequeue a pending IRP
  847. // and complete it with the specified data
  848. //
  849. UMClientRemoveCfInfoNotify(pClient, pBlob);
  850. VERIFY_IRQL(dbgIrql);
  851. TRACE(PATTERN, pClient, Status, "ClientRemoveCfInfo (5)");
  852. }
  853. }
  854. return Status;
  855. }
  856. /*
  857. ************************************************************************
  858. ClearPatternLinks -
  859. Arguments
  860. Returns
  861. ************************************************************************
  862. */
  863. VOID
  864. ClearPatternLinks(
  865. IN PPATTERN_BLOCK pPattern,
  866. IN PPROTOCOL_BLOCK pProtocol,
  867. IN ULONG CfIndex
  868. )
  869. {
  870. PBLOB_BLOCK *ppBlob;
  871. //
  872. // Remove the pattern from the blob list
  873. // and NULL the pointer to the blob in the pattern block
  874. //
  875. ppBlob = & GetBlobFromPattern(pPattern, CfIndex);
  876. if (*ppBlob) {
  877. NDIS_LOCK(&(*ppBlob)->Lock);
  878. GpcRemoveEntryList(&pPattern->BlobLinkage[CfIndex]);
  879. NDIS_UNLOCK(&(*ppBlob)->Lock);
  880. *ppBlob = NULL;
  881. }
  882. }
  883. /*
  884. ************************************************************************
  885. ModifyCompleteClients -
  886. Arguments
  887. Returns
  888. ************************************************************************
  889. */
  890. VOID
  891. ModifyCompleteClients(
  892. IN PCLIENT_BLOCK pClient,
  893. IN PBLOB_BLOCK pBlob
  894. )
  895. {
  896. uint i;
  897. PCLIENT_BLOCK pNotifyClient;
  898. KIRQL irql;
  899. if (NT_SUCCESS(pBlob->LastStatus)) {
  900. //
  901. // in case of successful completion, assign the
  902. // new client data
  903. //
  904. NDIS_LOCK(&pBlob->Lock);
  905. WRITE_LOCK(&glData.ChLock, &irql);
  906. GpcFreeMem(pBlob->pClientData, CfInfoDataTag);
  907. pBlob->ClientDataSize = pBlob->NewClientDataSize;
  908. pBlob->pClientData = pBlob->pNewClientData;
  909. WRITE_UNLOCK(&glData.ChLock, irql);
  910. NDIS_UNLOCK(&pBlob->Lock);
  911. } else {
  912. GpcFreeMem(pBlob->pNewClientData, CfInfoDataTag);
  913. }
  914. pBlob->NewClientDataSize = 0;
  915. pBlob->pNewClientData = NULL;
  916. //
  917. // notify each client (except the caller) that successfully
  918. // modified the blob about the status.
  919. // it can be SUCCESS or some failure
  920. //
  921. for (i = 0; i < MAX_CLIENTS_CTX_PER_BLOB; i++) {
  922. //
  923. // only clients with none zero entries
  924. // have been succefully modified the blob
  925. //
  926. if (pNotifyClient = pBlob->arpClientStatus[i]) {
  927. //
  928. // complete here
  929. //
  930. ClientModifyCfInfoComplete(
  931. pNotifyClient,
  932. pBlob,
  933. pBlob->LastStatus
  934. );
  935. //
  936. // release the one we got earlier
  937. //
  938. //DereferenceClient(pNotifyClient);
  939. }
  940. } // for
  941. #if 0
  942. //
  943. // now, complete the call back to the calling client
  944. //
  945. ClientModifyCfInfoComplete(
  946. pBlob->pCallingClient,
  947. pBlob,
  948. pBlob->LastStatus
  949. );
  950. #endif
  951. pBlob->State = GPC_STATE_READY;
  952. }
  953. #if 0
  954. /*
  955. ************************************************************************
  956. GetClassificationHandle -
  957. Get the classification handle from the blob. If none is available
  958. creates a new one. '0' is not a valid CH!
  959. Arguments
  960. pClient - The calling client
  961. pPattern - The pattern that refers to the CH
  962. Returns
  963. A classification handle
  964. ************************************************************************
  965. */
  966. CLASSIFICATION_HANDLE
  967. GetClassificationHandle(
  968. IN PCLIENT_BLOCK pClient,
  969. IN PPATTERN_BLOCK pPattern
  970. )
  971. {
  972. HFHandle hfh;
  973. ULONG t;
  974. PCLASSIFICATION_BLOCK pCB;
  975. TRACE(CLASSIFY, pClient, pPattern, "GetClassificationHandle:");
  976. if (TEST_BIT_ON(pPattern->Flags,PATTERN_SPECIFIC)) {
  977. //
  978. // this is a specific pattern
  979. //
  980. //
  981. // get the CH from it
  982. //
  983. ASSERT(pPattern->pClassificationBlock);
  984. hfh = pPattern->pClassificationBlock->ClassificationHandle;
  985. //
  986. // check if CH is valid
  987. //
  988. t = pPattern->ProtocolTemplate;
  989. pCB = (PCLASSIFICATION_BLOCK)dereference_HF_handle(glData.pCHTable,
  990. hfh);
  991. TRACE(CLASSHAND, pCB, hfh, "GetClassificationHandle (~)");
  992. if (pCB != pPattern->pClassificationBlock) {
  993. //
  994. // the CH is invalid, release it and get a new one
  995. //
  996. NDIS_LOCK(&glData.Lock);
  997. release_HF_handle(glData.pCHTable, hfh);
  998. ProtocolStatInc(pPattern->ProtocolTemplate,
  999. RemovedCH);
  1000. TRACE(CLASSHAND, glData.pCHTable, hfh, "GetClassificationHandle (-)");
  1001. hfh = assign_HF_handle(glData.pCHTable,
  1002. (void *)pPattern->pClassificationBlock);
  1003. ProtocolStatInc(pPattern->ProtocolTemplate,
  1004. InsertedCH);
  1005. NDIS_UNLOCK(&glData.Lock);
  1006. TRACE(CLASSIFY, pPattern, hfh, "GetClassificationHandle (+)");
  1007. pPattern->pClassificationBlock->ClassificationHandle = hfh;
  1008. }
  1009. } else {
  1010. //
  1011. // this is a generic pattern
  1012. //
  1013. hfh = 0;
  1014. }
  1015. TRACE(CLASSIFY, pPattern, hfh, "GetClassificationHandle==>");
  1016. return (CLASSIFICATION_HANDLE)hfh;
  1017. }
  1018. #endif
  1019. /*
  1020. ************************************************************************
  1021. FreeClassificationHandle -
  1022. Free the classification handle. It will invalidate the entry in the
  1023. index table and make it avaiable for future use.
  1024. Arguments
  1025. pClient - The calling client
  1026. CH - The classification handle
  1027. Returns
  1028. void
  1029. ************************************************************************
  1030. */
  1031. VOID
  1032. FreeClassificationHandle(
  1033. IN PCLIENT_BLOCK pClient,
  1034. IN CLASSIFICATION_HANDLE CH
  1035. )
  1036. {
  1037. KIRQL CHirql;
  1038. WRITE_LOCK(&glData.ChLock, &CHirql);
  1039. release_HF_handle(glData.pCHTable, CH);
  1040. TRACE(CLASSHAND, glData.pCHTable, CH, "FreeClassificationHandle");
  1041. WRITE_UNLOCK(&glData.ChLock, CHirql);
  1042. }
  1043. GPC_STATUS
  1044. CleanupBlobs(
  1045. IN PCLIENT_BLOCK pClient
  1046. )
  1047. {
  1048. PBLOB_BLOCK pBlob;
  1049. //PPATTERN_BLOCK pPattern;
  1050. //ULONG CfIndex = pClient->pCfBlock->AssignedIndex;
  1051. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  1052. NDIS_LOCK(&pClient->Lock);
  1053. //
  1054. // scan blobs
  1055. //
  1056. while (!IsListEmpty(&pClient->BlobList)) {
  1057. //
  1058. // get the blob
  1059. //
  1060. pBlob = CONTAINING_RECORD(pClient->BlobList.Flink, BLOB_BLOCK, ClientLinkage);
  1061. pBlob->Flags |= PATTERN_REMOVE_CB_BLOB;
  1062. NDIS_UNLOCK(&pClient->Lock);
  1063. //
  1064. // remove the blob
  1065. //
  1066. Status = GpcRemoveCfInfo((GPC_HANDLE)pClient,
  1067. (GPC_HANDLE)pBlob
  1068. );
  1069. NDIS_LOCK(&pClient->Lock);
  1070. }
  1071. NDIS_UNLOCK(&pClient->Lock);
  1072. return GPC_STATUS_SUCCESS;
  1073. }
  1074. VOID
  1075. CloseAllObjects(
  1076. IN PFILE_OBJECT FileObject,
  1077. IN PIRP Irp
  1078. )
  1079. {
  1080. PLIST_ENTRY pEntry0, pHead0;
  1081. PLIST_ENTRY pEntry, pHead;
  1082. PCLIENT_BLOCK pClient = NULL;
  1083. PCF_BLOCK pCf;
  1084. PPROTOCOL_BLOCK pProtocol;
  1085. //int i,j;
  1086. //NTSTATUS NtStatus;
  1087. //QUEUED_COMPLETION QItem;
  1088. KIRQL irql;
  1089. NDIS_LOCK(&glData.Lock);
  1090. pHead0 = &glData.CfList;
  1091. pEntry0 = pHead0->Flink;
  1092. while (pEntry0 != pHead0 && pClient == NULL) {
  1093. pCf = CONTAINING_RECORD(pEntry0, CF_BLOCK, Linkage);
  1094. pEntry0 = pEntry0->Flink;
  1095. RSC_READ_LOCK(&pCf->ClientSync, &irql);
  1096. pHead = &pCf->ClientList;
  1097. pEntry = pHead->Flink;
  1098. while (pEntry != pHead && pClient == NULL) {
  1099. pClient = CONTAINING_RECORD(pEntry,CLIENT_BLOCK,ClientLinkage);
  1100. pEntry = pEntry->Flink;
  1101. if (pClient->pFileObject == FileObject) {
  1102. REFADD(&pClient->RefCount, 'CAOB');
  1103. } else {
  1104. pClient = NULL;
  1105. }
  1106. }
  1107. RSC_READ_UNLOCK(&pCf->ClientSync, irql);
  1108. } // while (...)
  1109. NDIS_UNLOCK(&glData.Lock);
  1110. if (pClient) {
  1111. //
  1112. // clear all the blobs on the client
  1113. //
  1114. CleanupBlobs(pClient);
  1115. //
  1116. // deregister the client
  1117. //
  1118. GpcDeregisterClient((GPC_HANDLE)pClient);
  1119. //
  1120. // release the previous ref count
  1121. //
  1122. REFDEL(&pClient->RefCount, 'CAOB');
  1123. }
  1124. }
  1125. // Cool new feature - Timer Wheels [ShreeM]
  1126. // We maintain N lists of patterns, one for each "timertick". The Pattern
  1127. // Expiry routine will clean up one of the lists every time it is invoked.
  1128. // It then makes a note to cleanup the next list on the wheel, the next time
  1129. // it is invoked.
  1130. // The Timer Wheels reduces spin lock contention between inserts and deletes.
  1131. VOID
  1132. PatternTimerExpired(
  1133. IN PVOID SystemSpecific1,
  1134. IN PVOID FunctionContext,
  1135. IN PVOID SystemSpecific2,
  1136. IN PVOID SystemSpecific3
  1137. )
  1138. {
  1139. PLIST_ENTRY pEntry;
  1140. PPATTERN_BLOCK pPattern;
  1141. ULONG CleanupWheelIndex = 0, NewWheelIndex;
  1142. PPROTOCOL_BLOCK pProtocol = &glData.pProtocols[PtrToUlong(FunctionContext)];
  1143. TRACE(PAT_TIMER, FunctionContext, 0, "PatternTimerExpired");
  1144. DBGPRINT(PAT_TIMER, ("PatternTimerExpired: Timer expired, protocol=%d \n",
  1145. PtrToUlong(FunctionContext)));
  1146. //
  1147. // Which of the timer wheels do we want to cleanup this time?
  1148. // Remember that we Increment the current index pointer into the wheels
  1149. // All the wheel index calculations are protected by gldata->lock.
  1150. NDIS_LOCK(&glData.Lock);
  1151. CleanupWheelIndex = pProtocol->CurrentWheelIndex;
  1152. pProtocol->CurrentWheelIndex += 1;
  1153. //
  1154. // Make sure we wrap around.
  1155. //
  1156. pProtocol->CurrentWheelIndex %= NUMBER_OF_WHEELS;
  1157. NDIS_UNLOCK(&glData.Lock);
  1158. NDIS_LOCK(&pProtocol->PatternTimerLock[CleanupWheelIndex]);
  1159. while (!IsListEmpty(&pProtocol->TimerPatternList[CleanupWheelIndex])) {
  1160. PCLIENT_BLOCK pClient;
  1161. pEntry = RemoveHeadList(&pProtocol->TimerPatternList[CleanupWheelIndex]);
  1162. pPattern = CONTAINING_RECORD(pEntry, PATTERN_BLOCK, TimerLinkage);
  1163. InitializeListHead(&pPattern->TimerLinkage);
  1164. NDIS_UNLOCK(&pProtocol->PatternTimerLock[CleanupWheelIndex]);
  1165. ASSERT(pPattern->TimeToLive != 0xdeadbeef);
  1166. ASSERT(TEST_BIT_ON( pPattern->Flags, PATTERN_AUTO ));
  1167. NDIS_LOCK(&pPattern->Lock);
  1168. pPattern->Flags |= ~PATTERN_AUTO;
  1169. NDIS_UNLOCK(&pPattern->Lock);
  1170. TRACE(PAT_TIMER, pPattern, pPattern->RefCount.Count, "PatternTimerExpired: del");
  1171. ProtocolStatInc(pPattern->ProtocolTemplate,
  1172. DeletedAp);
  1173. ProtocolStatDec(pPattern->ProtocolTemplate,
  1174. CurrentAp);
  1175. //
  1176. // actually remove the pattern
  1177. //
  1178. DBGPRINT(PAT_TIMER, ("PatternTimerExpired: removing pattern=%X, ref=%d, client=%X \n",
  1179. pPattern, pPattern->RefCount, pPattern->pAutoClient));
  1180. pClient = pPattern->pAutoClient;
  1181. GpcRemovePattern((GPC_HANDLE)pPattern->pAutoClient,
  1182. (GPC_HANDLE)pPattern);
  1183. REFDEL(&(pClient->RefCount), 'CLNT');
  1184. InterlockedDecrement(&pProtocol->AutoSpecificPatternCount);
  1185. NDIS_LOCK(&pProtocol->PatternTimerLock[CleanupWheelIndex]);
  1186. }
  1187. NDIS_UNLOCK(&pProtocol->PatternTimerLock[CleanupWheelIndex]);
  1188. //
  1189. // If there are any Auto Specific patterns around restart the timer.
  1190. //
  1191. if(InterlockedExchangeAdd(&pProtocol->AutoSpecificPatternCount, 0) > 0) {
  1192. NdisSetTimer(&pProtocol->PatternTimer, PATTERN_TIMEOUT);
  1193. DBGPRINT(PAT_TIMER, ("PatternTimer restarted\n"));
  1194. } else {
  1195. DBGPRINT(PAT_TIMER, ("Zero Auto Patterns - Timer NOT restarted\n"));
  1196. }
  1197. }
  1198. GPC_STATUS
  1199. AddSpecificPatternWithTimer(
  1200. IN PCLIENT_BLOCK pClient,
  1201. IN ULONG ProtocolTemplate,
  1202. IN PVOID PatternKey,
  1203. OUT PPATTERN_BLOCK *ppPattern,
  1204. OUT PCLASSIFICATION_HANDLE pClassificationHandle
  1205. )
  1206. {
  1207. GPC_STATUS Status=GPC_STATUS_SUCCESS;
  1208. PPATTERN_BLOCK pPattern=NULL, pCreatedPattern=NULL;
  1209. PPROTOCOL_BLOCK pProtocol = &glData.pProtocols[ProtocolTemplate];
  1210. UCHAR Mask[MAX_PATTERN_SIZE];
  1211. ULONG WheelIndex = 0;
  1212. ULONG ulCurrentAutoPatternCount=0;
  1213. ulCurrentAutoPatternCount=InterlockedExchangeAdd(&pProtocol->AutoSpecificPatternCount,0);
  1214. DBGPRINT(PAT_TIMER,("MSGPC:Creating New AutoPattern: Number of AutoPatterns"
  1215. "Before Creation = %ul \n", ulCurrentAutoPatternCount));
  1216. if (ulCurrentAutoPatternCount > glData.AutoPatternLimit) {
  1217. DBGPRINT(PAT_TIMER,("MSGPCHit AutoPatternLimit : Num AutoPatterns = %ul :"
  1218. "Limit =%ul \n",ulCurrentAutoPatternCount, glData.AutoPatternLimit));
  1219. Status = GPC_STATUS_NO_MEMORY;
  1220. goto exit;
  1221. }
  1222. TRACE(PAT_TIMER, pClient, PatternKey, "AddSpecificPatternWithTimer");
  1223. #if DBG
  1224. {
  1225. PGPC_IP_PATTERN pIp = (PGPC_IP_PATTERN)PatternKey;
  1226. DBGPRINT(PAT_TIMER, ("AddSpecificPatternWithTimer: Client=%X \n", pClient));
  1227. #if INTERFACE_ID
  1228. DBGPRINT(PAT_TIMER, ("IP: ifc={%d,%d} src=%08X:%04x, dst=%08X:%04x, prot=%d rsv=%x,%x,%x\n",
  1229. pIp->InterfaceId.InterfaceId,
  1230. pIp->InterfaceId.LinkId,
  1231. pIp->SrcAddr,
  1232. pIp->gpcSrcPort,
  1233. pIp->DstAddr,
  1234. pIp->gpcDstPort,
  1235. pIp->ProtocolId,
  1236. pIp->Reserved[0],
  1237. pIp->Reserved[1],
  1238. pIp->Reserved[2]
  1239. ));
  1240. #endif
  1241. }
  1242. #endif
  1243. RtlFillMemory(Mask, sizeof(Mask), 0xff);
  1244. pPattern = CreateNewPatternBlock(PATTERN_SPECIFIC);
  1245. pCreatedPattern = pPattern;
  1246. if (pPattern) {
  1247. //
  1248. // setup the pattern fields and add it
  1249. //
  1250. //pPattern->RefCount++;
  1251. pPattern->Priority = 0;
  1252. pPattern->ProtocolTemplate = ProtocolTemplate;
  1253. pPattern->Flags |= PATTERN_AUTO;
  1254. // This flag indicates that the auto pattern is not on
  1255. // timer list yet . This means
  1256. // the pattern is not ready yet though it may or may
  1257. // not have been inserted into the patternhashtable
  1258. pPattern->Flags |= PATTERN_AUTO_NOT_READY;
  1259. pPattern->pAutoClient = pClient;
  1260. Status = AddSpecificPattern(
  1261. pClient,
  1262. PatternKey,
  1263. Mask,
  1264. NULL,
  1265. pProtocol,
  1266. &pPattern, // output pattern pointer
  1267. pClassificationHandle
  1268. );
  1269. } else {
  1270. Status = GPC_STATUS_NO_MEMORY;
  1271. }
  1272. if (NT_SUCCESS(Status)) {
  1273. //
  1274. // we didn't get an already existing pattern
  1275. //
  1276. //ASSERT(*pClassificationHandle);
  1277. *ppPattern = pPattern;
  1278. // Figure out which wheel to stick this pattern on.
  1279. NDIS_LOCK(&glData.Lock);
  1280. WheelIndex = pProtocol->CurrentWheelIndex;
  1281. NDIS_UNLOCK(&glData.Lock);
  1282. WheelIndex += (NUMBER_OF_WHEELS -1);
  1283. WheelIndex %= NUMBER_OF_WHEELS;
  1284. //
  1285. // we must lock this pattern since we look at the timer linkage
  1286. //
  1287. NDIS_LOCK(&pPattern->Lock);
  1288. //
  1289. // set the AUTO flag again, since we might have got
  1290. // a pattern that already exist
  1291. //
  1292. pPattern->Flags |= PATTERN_AUTO;
  1293. pPattern->pAutoClient = pClient;
  1294. pPattern->WheelIndex = WheelIndex;
  1295. //
  1296. // this pattern has not been on any the timer list yet
  1297. //
  1298. if (IsListEmpty(&pPattern->TimerLinkage)) {
  1299. //
  1300. // We need to insert this in the TimerWheel which is (NUMBER_OF_WHEELS - 1)
  1301. // away from the current, so that it spends enough time on the list.
  1302. //
  1303. NDIS_DPR_LOCK(&pProtocol->PatternTimerLock[WheelIndex]);
  1304. //
  1305. // If the AutoSpecificPatternCount was zero earlier, then we need
  1306. // to a) start the timer and b) increment this count.
  1307. //
  1308. if (1 == InterlockedIncrement(&pProtocol->AutoSpecificPatternCount)) {
  1309. //
  1310. // restart the timer for the first auto pattern
  1311. //
  1312. NdisSetTimer(&pProtocol->PatternTimer, PATTERN_TIMEOUT);
  1313. TRACE(PAT_TIMER, pPattern, PATTERN_TIMEOUT, "Starting Pattern Timer\n AddSpecificPatternWithTimer: (1)");
  1314. }
  1315. GpcInsertHeadList(&pProtocol->TimerPatternList[WheelIndex], &pPattern->TimerLinkage);
  1316. //
  1317. // don't refer to pPattern after it has been placed on the timer list
  1318. // since the timer may expire any time and remove it from there...
  1319. //
  1320. NDIS_DPR_UNLOCK(&pProtocol->PatternTimerLock[WheelIndex]);
  1321. }
  1322. //
  1323. // This is a specific pattern, so lets increment the count [ShreeM].
  1324. InterlockedIncrement(&pProtocol->SpecificPatternCount);
  1325. // Pattern is now ready. It has been inserted
  1326. // into the hash table and has been put into the
  1327. // timer list.
  1328. pPattern->Flags &= ~PATTERN_AUTO_NOT_READY;
  1329. NDIS_UNLOCK(&pPattern->Lock);
  1330. ProtocolStatInc(ProtocolTemplate,
  1331. CreatedAp);
  1332. ProtocolStatInc(ProtocolTemplate,
  1333. CurrentAp);
  1334. } else {
  1335. goto exit;
  1336. }
  1337. exit:
  1338. if (!NT_SUCCESS(Status)){
  1339. *ppPattern = NULL;
  1340. *pClassificationHandle = 0;
  1341. ProtocolStatInc(ProtocolTemplate,
  1342. RejectedAp);
  1343. }
  1344. else{
  1345. REFADD(&pClient->RefCount, 'CLNT');
  1346. }
  1347. if (pPattern) {
  1348. //
  1349. // release the reference count to this pattern
  1350. // in case of an error, this will also release
  1351. // the data block
  1352. //
  1353. REFDEL(&pCreatedPattern->RefCount, 'FILT');
  1354. }
  1355. TRACE(PAT_TIMER, pPattern, Status, "AddSpecificPatternWithTimer==>");
  1356. DBGPRINT(CLASSIFY, ("AddSpecificPatternWithTimer: pClient=%X Pattern=%X Status=%X\n",
  1357. pClient, pPattern, Status));
  1358. return Status;
  1359. }
  1360. // SS202 CR
  1361. //
  1362. NTSTATUS
  1363. InitPatternTimer(
  1364. IN ULONG ProtocolTemplate
  1365. )
  1366. {
  1367. ULONG i=0;
  1368. //
  1369. // We increase the granularity of when a "Automatic" Pattern gets cleaned
  1370. // out by using timer wheels, but they are more efficient for inserting and
  1371. // removing (in terms of locks).
  1372. //
  1373. for (i = 0; i < NUMBER_OF_WHEELS; i++) {
  1374. NDIS_INIT_LOCK(&glData.pProtocols[ProtocolTemplate].PatternTimerLock[i]);
  1375. InitializeListHead(&glData.pProtocols[ProtocolTemplate].TimerPatternList[i]);
  1376. }
  1377. glData.pProtocols[ProtocolTemplate].CurrentWheelIndex = 0;
  1378. NdisInitializeTimer(&glData.pProtocols[ProtocolTemplate].PatternTimer,
  1379. PatternTimerExpired,
  1380. (PVOID) ULongToPtr(ProtocolTemplate));
  1381. return STATUS_SUCCESS;
  1382. }
  1383. //
  1384. // Some CRT and RTL functions that cant be used at DISPATHC_LEVEL IRQL are being
  1385. // cut/paste here.
  1386. //
  1387. NTSTATUS
  1388. OpenRegKey(
  1389. PHANDLE HandlePtr,
  1390. PWCHAR KeyName
  1391. )
  1392. /*++
  1393. Routine Description:
  1394. Opens a Registry key and returns a handle to it.
  1395. Arguments:
  1396. HandlePtr - The varible into which to write the opened handle.
  1397. KeyName - The name of the Registry key to open.
  1398. Return Value:
  1399. STATUS_SUCCESS or an appropriate failure code.
  1400. --*/
  1401. {
  1402. NTSTATUS Status;
  1403. OBJECT_ATTRIBUTES ObjectAttributes;
  1404. UNICODE_STRING UKeyName;
  1405. PAGED_CODE();
  1406. RtlInitUnicodeString(&UKeyName, KeyName);
  1407. memset(&ObjectAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
  1408. InitializeObjectAttributes(&ObjectAttributes,
  1409. &UKeyName,
  1410. OBJ_CASE_INSENSITIVE,
  1411. NULL,
  1412. NULL);
  1413. Status = ZwOpenKey(HandlePtr,
  1414. KEY_READ,
  1415. &ObjectAttributes);
  1416. return Status;
  1417. }
  1418. NTSTATUS
  1419. GetRegDWORDValue(
  1420. HANDLE KeyHandle,
  1421. PWCHAR ValueName,
  1422. PULONG ValueData
  1423. )
  1424. /*++
  1425. Routine Description:
  1426. Reads a REG_DWORD value from the registry into the supplied variable.
  1427. Arguments:
  1428. KeyHandle - Open handle to the parent key of the value to read.
  1429. ValueName - The name of the value to read.
  1430. ValueData - The variable into which to read the data.
  1431. Return Value:
  1432. STATUS_SUCCESS or an appropriate failure code.
  1433. --*/
  1434. {
  1435. NTSTATUS status;
  1436. ULONG resultLength;
  1437. PKEY_VALUE_FULL_INFORMATION keyValueFullInformation;
  1438. UCHAR keybuf[WORK_BUFFER_SIZE];
  1439. UNICODE_STRING UValueName;
  1440. PAGED_CODE();
  1441. RtlInitUnicodeString(&UValueName, ValueName);
  1442. keyValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)keybuf;
  1443. RtlZeroMemory(keyValueFullInformation, sizeof(keyValueFullInformation));
  1444. status = ZwQueryValueKey(KeyHandle,
  1445. &UValueName,
  1446. KeyValueFullInformation,
  1447. keyValueFullInformation,
  1448. WORK_BUFFER_SIZE,
  1449. &resultLength);
  1450. if (NT_SUCCESS(status)) {
  1451. if (keyValueFullInformation->Type != REG_DWORD) {
  1452. status = STATUS_INVALID_PARAMETER_MIX;
  1453. } else {
  1454. *ValueData = *((ULONG UNALIGNED *)((PCHAR)keyValueFullInformation +
  1455. keyValueFullInformation->DataOffset));
  1456. }
  1457. }
  1458. return status;
  1459. }
  1460. /*++
  1461. Routine Description:
  1462. Reads a REG_DWORD value from registry and init the variable passed in..
  1463. Arguments:
  1464. - Open handle to the parent key of the value to read.
  1465. param - The name of the value to read.
  1466. ValueData - The variable into which to read the data.
  1467. Return Value:
  1468. STATUS_SUCCESS or an appropriate failure code.
  1469. --*/
  1470. VOID
  1471. GPC_REG_READ_DWORD(HANDLE hRegKey, PWCHAR pwcName, PULONG pulData, ULONG ulDefault,ULONG ulMax, ULONG ulMin) {
  1472. NTSTATUS status;
  1473. status = GetRegDWORDValue(hRegKey,
  1474. pwcName,
  1475. (pulData));
  1476. if (!NT_SUCCESS(status)) {
  1477. *(pulData) = ulDefault;
  1478. } else if (*(pulData) > ulMax) {
  1479. *(pulData) = ulMax;
  1480. } else if (*(pulData) < ulMin) {
  1481. *(pulData) = ulMin;
  1482. }
  1483. }
  1484. VOID
  1485. GpcReadRegistry()
  1486. /*++
  1487. Routine Description:
  1488. Reads config info from registry into glData
  1489. Arguments:
  1490. Return Value:
  1491. status of the read.
  1492. --*/
  1493. {
  1494. NTSTATUS status;
  1495. HANDLE hRegKey;
  1496. WCHAR GpcParametersRegistryKey[] = GPC_REG_KEY;
  1497. glData.SystemSizeHint = MmQuerySystemSize();
  1498. switch (glData.SystemSizeHint)
  1499. {
  1500. case MmSmallSystem:
  1501. glData.AutoPatternLimit = DEFAULT_SMALL_SYSTEM_AUTO_PATTERN_LIMIT;
  1502. break;
  1503. case MmMediumSystem:
  1504. glData.AutoPatternLimit = DEFAULT_MEDIUM_SYSTEM_AUTO_PATTERN_LIMIT;
  1505. break;
  1506. case MmLargeSystem:
  1507. glData.AutoPatternLimit = DEFAULT_LARGE_SYSTEM_AUTO_PATTERN_LIMIT;
  1508. break;
  1509. default: break;
  1510. }
  1511. status = OpenRegKey(&hRegKey,
  1512. GpcParametersRegistryKey);
  1513. if (NT_SUCCESS(status)) {
  1514. //
  1515. // Expected configuration values. We use reasonable defaults if they
  1516. // aren't available for some reason.
  1517. //
  1518. GPC_REG_READ_DWORD( hRegKey,
  1519. GPC_REG_AUTO_PATTERN_LIMIT,
  1520. &glData.AutoPatternLimit,
  1521. glData.AutoPatternLimit,
  1522. GPC_AUTO_PATTERN_MAX,
  1523. GPC_AUTO_PATTERN_MIN);
  1524. }
  1525. ZwClose(hRegKey);
  1526. }