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.

2044 lines
54 KiB

  1. /*
  2. ************************************************************************
  3. Copyright (c) 1996-1997 Microsoft Corporation
  4. Module Name:
  5. gpcdb.c
  6. Abstract:
  7. This file contains database routines, that includes specific patterns,
  8. and classification index table.
  9. Author:
  10. Ofer Bar - April 15, 1997
  11. Environment:
  12. Kernel mode
  13. Revision History:
  14. ************************************************************************
  15. */
  16. #include "gpcpre.h"
  17. VOID
  18. GpcSpecificCallback(
  19. IN VOID *Ctx,
  20. IN SpecificPatternHandle SpHandle);
  21. /*
  22. ************************************************************************
  23. InitSpecificPatternDb -
  24. Initialize the specific patterns database. It will allocate a table
  25. length Size.
  26. Arguments
  27. pDb - a pointer to the db to initialize
  28. Size - number of entries in the table
  29. Returns
  30. NDIS_STATUS
  31. ************************************************************************
  32. */
  33. GPC_STATUS
  34. InitSpecificPatternDb(
  35. IN PSPECIFIC_PATTERN_DB pDb,
  36. IN ULONG PatternSize
  37. )
  38. {
  39. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  40. ULONG Len, i;
  41. TRACE(INIT, pDb, PatternSize, "InitSpecificPatternDb");
  42. ASSERT(pDb);
  43. ASSERT(PatternSize);
  44. //
  45. // init the specific db struct
  46. // call the PH init routine
  47. //
  48. INIT_LOCK(&pDb->Lock);
  49. AllocatePatHashTable(pDb->pDb);
  50. if (pDb->pDb != NULL) {
  51. constructPatHashTable(pDb->pDb,
  52. PatternSize * 8,
  53. 2, // usage_ratio,
  54. 1, // usage_histeresis,
  55. 1, // allocation_histeresis,
  56. 16 // max_free_list_size
  57. );
  58. } else {
  59. Status = GPC_STATUS_RESOURCES;
  60. }
  61. TRACE(INIT, Status, 0, "InitSpecificPatternDb==>");
  62. return Status;
  63. }
  64. /*
  65. ************************************************************************
  66. UninitSpecificPatternDb -
  67. Un-Initialize the specific patterns database. It will release all
  68. allocated memory.
  69. Arguments
  70. pDb - a pointer to the db to free
  71. Returns
  72. NDIS_STATUS
  73. ************************************************************************
  74. */
  75. GPC_STATUS
  76. UninitSpecificPatternDb(
  77. IN PSPECIFIC_PATTERN_DB pDb
  78. )
  79. {
  80. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  81. TRACE(INIT, pDb, 0, "UninitSpecificPatternDb");
  82. ASSERT(pDb);
  83. destructPatHashTable(pDb->pDb);
  84. FreePatHashTable(pDb->pDb);
  85. TRACE(INIT, Status, 0, "UninitSpecificPatternDb==>");
  86. return Status;
  87. }
  88. /*
  89. ************************************************************************
  90. InitClassificationHandleTbl -
  91. Init the classification index table
  92. Arguments
  93. ppCHTable - a pointer a class handle table pointer
  94. Returns
  95. GPC_STATUS
  96. ************************************************************************
  97. */
  98. GPC_STATUS
  99. InitClassificationHandleTbl(
  100. IN HandleFactory **ppCHTable
  101. )
  102. {
  103. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  104. TRACE(INIT, ppCHTable, 0, "InitClassificationHandleTbl");
  105. ASSERT(ppCHTable);
  106. NEW_HandleFactory(*ppCHTable);
  107. if (*ppCHTable == NULL) {
  108. return GPC_STATUS_RESOURCES;
  109. }
  110. if (0 != constructHandleFactory(*ppCHTable)) {
  111. return GPC_STATUS_RESOURCES;
  112. }
  113. TRACE(INIT, Status, 0, "InitClassificationIndexTbl==>");
  114. return Status;
  115. }
  116. /*
  117. ************************************************************************
  118. UninitClassificationHandleTbl -
  119. Uninit the classification index table
  120. Arguments
  121. pCHTable - a pointer a class handle table
  122. Returns
  123. void
  124. ************************************************************************
  125. */
  126. VOID
  127. UninitClassificationHandleTbl(
  128. IN HandleFactory *pCHTable
  129. )
  130. {
  131. destructHandleFactory(pCHTable);
  132. FreeHandleFactory(pCHTable);
  133. }
  134. /*
  135. ************************************************************************
  136. InitializeGenericDb -
  137. Init the generic db. This is called by per CF.
  138. Arguments
  139. pGenericDb - a pointer to the generic db
  140. NumEntries - number of entries, one per rhizome
  141. PatternSize - pattern size in bytes
  142. Returns
  143. GPC_STATUS: no memory resources
  144. ************************************************************************
  145. */
  146. GPC_STATUS
  147. InitializeGenericDb(
  148. IN PGENERIC_PATTERN_DB *ppGenericDb,
  149. IN ULONG NumEntries,
  150. IN ULONG PatternSize
  151. )
  152. {
  153. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  154. ULONG i;
  155. PGENERIC_PATTERN_DB pDb;
  156. *ppGenericDb = NULL;
  157. ASSERT(PatternSize);
  158. GpcAllocMem(&pDb,
  159. sizeof(GENERIC_PATTERN_DB) * NumEntries,
  160. GenPatternDbTag);
  161. if (pDb == NULL)
  162. return GPC_STATUS_RESOURCES;
  163. *ppGenericDb = pDb;
  164. for (i = 0; i < NumEntries; i++, pDb++) {
  165. INIT_LOCK(&pDb->Lock);
  166. AllocateRhizome(pDb->pRhizome);
  167. if (pDb->pRhizome == NULL) {
  168. //
  169. // failed, release all allocated resources
  170. //
  171. while (i > 0) {
  172. NdisFreeSpinLock(&pDb->Lock);
  173. i--;
  174. pDb--;
  175. destructRhizome(pDb->pRhizome);
  176. FreeRhizome(pDb->pRhizome);
  177. }
  178. GpcFreeMem((*ppGenericDb), GenPatternDbTag);
  179. Status = GPC_STATUS_RESOURCES;
  180. *ppGenericDb = NULL;
  181. break;
  182. }
  183. //
  184. // init the rhizome
  185. //
  186. constructRhizome(pDb->pRhizome, PatternSize*8);
  187. }
  188. return Status;
  189. }
  190. /*
  191. ************************************************************************
  192. UninitializeGenericDb -
  193. Uninit the generic db.
  194. Arguments
  195. pGenericDb - a pointer to the generic db
  196. NumEntries - number of entries, one per rhizome
  197. PatternSize - pattern size in bytes
  198. Returns
  199. void
  200. ************************************************************************
  201. */
  202. VOID
  203. UninitializeGenericDb(
  204. IN PGENERIC_PATTERN_DB *ppGenericDb,
  205. IN ULONG NumEntries
  206. )
  207. {
  208. ULONG i;
  209. PGENERIC_PATTERN_DB pDb;
  210. pDb = *ppGenericDb;
  211. ASSERT(pDb);
  212. for (i = 0; i < NumEntries; i++, pDb++) {
  213. NdisFreeSpinLock(&pDb->Lock);
  214. destructRhizome(pDb->pRhizome);
  215. FreeRhizome(pDb->pRhizome);
  216. }
  217. GpcFreeMem(*ppGenericDb, GenPatternDbTag);
  218. *ppGenericDb = NULL;
  219. }
  220. /*
  221. ************************************************************************
  222. GpcSpecificCallback -
  223. Call back routine given when calling scanPatHashTable and getting called
  224. by the pathash scanning routine.
  225. Arguments
  226. Ctx - a pointer to a SCAN_STRUCT to hold context info
  227. SpHandle - the specific pattern handle that matches
  228. Returns
  229. void
  230. ************************************************************************
  231. */
  232. VOID
  233. GpcSpecificCallback(
  234. IN VOID *Ctx,
  235. IN SpecificPatternHandle SpHandle)
  236. {
  237. PSCAN_STRUCT pScan = (PSCAN_STRUCT)Ctx;
  238. PPATTERN_BLOCK pSpPattern;
  239. PPATTERN_BLOCK pGpPattern;
  240. PGENERIC_PATTERN_DB pGenericDb;
  241. PatternHandle GpHandle;
  242. PBLOB_BLOCK pSpBlob, *ppSpCbBlob, OldBlob;
  243. ULONG CfIndex;
  244. PCF_BLOCK pCf;
  245. KIRQL ReadIrql;
  246. KIRQL CBirql;
  247. PCLASSIFICATION_BLOCK pCB;
  248. PGPC_IP_PATTERN pIp;
  249. BOOLEAN bBetterFound = FALSE;
  250. UINT i;
  251. TRACE(PATTERN, Ctx, SpHandle, "GpcSpecificCallback");
  252. pSpPattern = (PPATTERN_BLOCK)GetReferenceFromSpecificPatternHandle(SpHandle);
  253. pCB = pSpPattern->pClassificationBlock;
  254. pIp = (PGPC_IP_PATTERN) GetKeyPtrFromSpecificPatternHandle(SpHandle);
  255. ASSERT(pCB);
  256. ASSERT(pScan);
  257. //
  258. // get the CF index
  259. //
  260. CfIndex = pScan->pClientBlock->pCfBlock->AssignedIndex;
  261. pCf = pScan->pClientBlock->pCfBlock;
  262. //
  263. // the blob that actually belongs to the SP
  264. //
  265. pSpBlob = GetBlobFromPattern(pSpPattern,CfIndex);
  266. //
  267. // the blob that currently exist in the CfIndex entry of the the CB
  268. //
  269. ppSpCbBlob = &pCB->arpBlobBlock[CfIndex];
  270. TRACE(PATTERN, pSpBlob, *ppSpCbBlob, "GpcSpecificCallback (2)");
  271. TRACE(PATTERN, pCB, CfIndex, "GpcSpecificCallback (2.5)");
  272. if (pSpBlob != *ppSpCbBlob || pSpBlob == NULL) {
  273. if (!pScan->bRemove) {
  274. //
  275. // we just added the generic pattern, so we should set the
  276. // CB pointer for that CF point to the new blob
  277. //
  278. for (i = 0; i <= pScan->pPatternBlock->Priority; i++) {
  279. pGenericDb = &pScan->pClientBlock->pCfBlock->arpGenericDb[pSpPattern->ProtocolTemplate][i];
  280. READ_LOCK(&pGenericDb->Lock, &ReadIrql);
  281. GpHandle = searchRhizome(pGenericDb->pRhizome,
  282. GetKeyPtrFromSpecificPatternHandle(SpHandle)
  283. );
  284. TRACE(PATTERN, pGenericDb, GpHandle, "GpcSpecificCallback (3.5)");
  285. if (GpHandle != NULL) {
  286. WRITE_LOCK(&glData.ChLock, &CBirql);
  287. bBetterFound = TRUE;
  288. pGpPattern = (PPATTERN_BLOCK)GetReferenceFromPatternHandle(GpHandle);
  289. *ppSpCbBlob = GetBlobFromPattern(pGpPattern, CfIndex);
  290. WRITE_UNLOCK(&glData.ChLock, CBirql);
  291. READ_UNLOCK(&pGenericDb->Lock, ReadIrql);
  292. break;
  293. }
  294. READ_UNLOCK(&pGenericDb->Lock, ReadIrql);
  295. }
  296. if (!bBetterFound) {
  297. WRITE_LOCK(&glData.ChLock, &CBirql);
  298. *ppSpCbBlob = pScan->pBlobBlock;
  299. WRITE_UNLOCK(&glData.ChLock, CBirql);
  300. }
  301. } else {
  302. //
  303. // The CfIndex slot in the CB points to a blob that doesn't belong
  304. // to the specific pattern we have just found. There is a chance
  305. // that there is another generic pattern somewhere, that may
  306. // or may not be more specific, thus resulting in updating the blob
  307. // pointer in the CB. So we need to search the generic db for a
  308. // match (to the specific pattern).
  309. //
  310. for (i = 0; i <= pScan->pPatternBlock->Priority; i++) {
  311. pGenericDb = &pScan->pClientBlock->pCfBlock->arpGenericDb[pSpPattern->ProtocolTemplate][i];
  312. READ_LOCK(&pGenericDb->Lock, &ReadIrql);
  313. GpHandle = searchRhizome(pGenericDb->pRhizome,
  314. GetKeyPtrFromSpecificPatternHandle(SpHandle)
  315. );
  316. TRACE(PATTERN, pGenericDb, GpHandle, "GpcSpecificCallback (3.5)");
  317. if (GpHandle != NULL) {
  318. //
  319. // we found a generic pattern in the rhizoe that can also be
  320. // the same one that is currently being installed, but
  321. // that's fine, since we want the most specific one, and
  322. // the search guarantees that.
  323. // all we need to do is to update the CB of the SP with
  324. // the blob of the GP we've just found.
  325. //
  326. bBetterFound = TRUE;
  327. WRITE_LOCK(&glData.ChLock, &CBirql);
  328. OldBlob = *ppSpCbBlob;
  329. pGpPattern = (PPATTERN_BLOCK)GetReferenceFromPatternHandle(GpHandle);
  330. *ppSpCbBlob = GetBlobFromPattern(pGpPattern, CfIndex);
  331. TRACE(PATTERN, pGpPattern, pCB->arpBlobBlock[CfIndex], "GpcSpecificCallback (4)");
  332. WRITE_UNLOCK(&glData.ChLock, CBirql);
  333. READ_UNLOCK(&pGenericDb->Lock, ReadIrql);
  334. break;
  335. }
  336. READ_UNLOCK(&pGenericDb->Lock, ReadIrql);
  337. }
  338. if (!bBetterFound) {
  339. //
  340. // non was found
  341. //
  342. WRITE_LOCK(&glData.ChLock, &CBirql);
  343. *ppSpCbBlob = NULL;
  344. WRITE_UNLOCK(&glData.ChLock, CBirql);
  345. TRACE(PATTERN, *ppSpCbBlob, pCB->arpBlobBlock[CfIndex], "GpcSpecificCallback (5)");
  346. }
  347. }
  348. }
  349. TRACE(PATTERN, pCB, CfIndex, "GpcSpecificCallback==>");
  350. }
  351. /*
  352. ************************************************************************
  353. AddGenericPattern -
  354. Add a generic pattern to the db.
  355. Arguments
  356. pClient -
  357. Pattern -
  358. Mask -
  359. Priority -
  360. pBlob -
  361. ppPatter -
  362. Returns
  363. GPC_STATUS
  364. ************************************************************************
  365. */
  366. GPC_STATUS
  367. AddGenericPattern(
  368. IN PCLIENT_BLOCK pClient,
  369. IN PUCHAR pPatternBits,
  370. IN PUCHAR pMaskBits,
  371. IN ULONG Priority,
  372. IN PBLOB_BLOCK pBlob,
  373. IN PPROTOCOL_BLOCK pProtocol,
  374. IN OUT PPATTERN_BLOCK *ppPattern
  375. )
  376. {
  377. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  378. PatternHandle GpHandle;
  379. PPATTERN_BLOCK pPattern = *ppPattern;
  380. PGENERIC_PATTERN_DB pGenericDb;
  381. PSPECIFIC_PATTERN_DB pSpecificDb;
  382. SCAN_STRUCT ScanStruct;
  383. ULONG i;
  384. ULONG CfIndex = pClient->pCfBlock->AssignedIndex;
  385. KIRQL ReadIrql;
  386. KIRQL WriteIrql;
  387. PGPC_IP_PATTERN pIp, pMask;
  388. TRACE(PATTERN, pClient, pPatternBits, "AddGenericPattern");
  389. // This is impossible with a good client (320705)
  390. if (!pBlob) {
  391. return GPC_STATUS_INVALID_PARAMETER;
  392. }
  393. pIp = (PGPC_IP_PATTERN)pPatternBits;
  394. pMask = (PGPC_IP_PATTERN)pMaskBits;
  395. //
  396. // get the specific db pointer
  397. //
  398. pSpecificDb = &pProtocol->SpecificDb;
  399. ASSERT(pSpecificDb);
  400. //
  401. // Add to the Rhizome tree, according to priority value
  402. //
  403. pGenericDb = &pClient->pCfBlock->arpGenericDb[pProtocol->ProtocolTemplate][Priority];
  404. //
  405. // Lock the generic db for insertion
  406. //
  407. WRITE_LOCK(&pGenericDb->Lock, &WriteIrql);
  408. GpHandle = insertRhizome(pGenericDb->pRhizome,
  409. pPatternBits,
  410. pMaskBits,
  411. (PVOID)*ppPattern,
  412. (PULONG)&Status
  413. );
  414. WRITE_UNLOCK(&pGenericDb->Lock, WriteIrql);
  415. if (NT_SUCCESS(Status)) {
  416. //
  417. // add one ref count
  418. //
  419. REFADD(&(*ppPattern)->RefCount, 'ADGP');
  420. //
  421. // we managed to insert the pattern, no conflicts.
  422. // now we need to scan the specific db for a match,
  423. // since the insertion might affect CB entries for
  424. // patterns which are subsets of the installed pattern
  425. //
  426. ProtocolStatInc(pProtocol->ProtocolTemplate,
  427. InsertedRz);
  428. //
  429. // lock the specific db, some other client may access it
  430. //
  431. ScanStruct.Priority = Priority;
  432. ScanStruct.pClientBlock = pClient;
  433. ScanStruct.pPatternBlock = *ppPattern;
  434. ScanStruct.pBlobBlock = pBlob;
  435. ScanStruct.bRemove = FALSE;
  436. //
  437. // update the pattern
  438. //
  439. GetBlobFromPattern(pPattern,CfIndex) = pBlob;
  440. pPattern->pClientBlock = pClient;
  441. ASSERT(GpHandle);
  442. pPattern->DbCtx = (PVOID)GpHandle;
  443. TRACE(PATTERN, pPattern, GpHandle, "AddGenericPattern: DbCtx");
  444. pPattern->State = GPC_STATE_READY;
  445. GpcInterlockedInsertTailList
  446. (&pBlob->PatternList,
  447. &pPattern->BlobLinkage[CfIndex],
  448. &pBlob->Lock
  449. );
  450. //
  451. // this will do the rest of the work...
  452. //
  453. READ_LOCK(&pSpecificDb->Lock, &ReadIrql);
  454. scanPatHashTable(
  455. pSpecificDb->pDb,
  456. pPatternBits,
  457. pMaskBits,
  458. (PVOID)&ScanStruct,
  459. GpcSpecificCallback // see callback routine...
  460. );
  461. READ_UNLOCK(&pSpecificDb->Lock, ReadIrql);
  462. }
  463. TRACE(PATTERN, Status, 0, "AddGenericPattern==>");
  464. return Status;
  465. }
  466. /*
  467. ************************************************************************
  468. AddSpecificPattern -
  469. Add a specific pattern to the db.
  470. Arguments
  471. pClient -
  472. pPatternBits-
  473. pMaskBits -
  474. pBlob -
  475. pProtocol -
  476. ppPattern -
  477. ppCB -
  478. Returns
  479. GPC_STATUS
  480. ************************************************************************
  481. */
  482. GPC_STATUS
  483. AddSpecificPattern(
  484. IN PCLIENT_BLOCK pClient,
  485. IN PUCHAR pPatternBits,
  486. IN PUCHAR pMaskBits,
  487. IN PBLOB_BLOCK pBlob, // optional
  488. IN PPROTOCOL_BLOCK pProtocol,
  489. IN OUT PPATTERN_BLOCK *ppPattern,
  490. OUT PCLASSIFICATION_HANDLE pCH
  491. )
  492. {
  493. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  494. PSPECIFIC_PATTERN_DB pSpecificDb;
  495. PGENERIC_PATTERN_DB pGenericDb;
  496. ULONG Chyme;
  497. ULONG CfIndex, i;
  498. PPATTERN_BLOCK pPatternSave;
  499. PBLOB_BLOCK pBlobSave;
  500. SpecificPatternHandle SpHandle;
  501. PatternHandle GpHandle;
  502. PCLASSIFICATION_BLOCK pCB = NULL;
  503. PCF_BLOCK pCf = NULL;
  504. PLIST_ENTRY pHead, pEntry;
  505. KIRQL ReadIrql;
  506. KIRQL WriteIrql;
  507. KIRQL irql;
  508. //BOOLEAN bIsAuto;
  509. ASSERT(ppPattern);
  510. ASSERT(*ppPattern);
  511. TRACE(PATTERN, pClient, *ppPattern, "AddSpecificPattern");
  512. *pCH = 0;
  513. //bIsAuto = TEST_BIT_ON((*ppPattern)->Flags, PATTERN_AUTO);
  514. //
  515. // get the specific db pointer
  516. //
  517. pSpecificDb = &pProtocol->SpecificDb;
  518. ASSERT(pSpecificDb);
  519. //
  520. // get the CF index
  521. //
  522. CfIndex = pClient->pCfBlock->AssignedIndex;
  523. pCf = pClient->pCfBlock;
  524. //
  525. // Since we want to take the blob lock and specific DB lock
  526. // in the same order everywhere. Take the blob lock before the specific DB
  527. // lock. GPCEnumCfInfo does the same.
  528. //
  529. if (pBlob) {
  530. NDIS_LOCK(&pBlob->Lock);
  531. }
  532. //
  533. // lock the specific db, some other client may access it
  534. //
  535. WRITE_LOCK(&pSpecificDb->Lock, &WriteIrql);
  536. //
  537. // calculate a chyme hash value for the pat -hash
  538. //
  539. Chyme = GpcCalcHash(pProtocol->ProtocolTemplate, pPatternBits);
  540. ASSERT(Chyme != (-1));
  541. //
  542. // actually call insert directly. If the pattern already exist in the
  543. // db, the returned reference will be the one for a previously
  544. // installed pattern, so ppPattern will be different
  545. //
  546. SpHandle = insertPatHashTable(
  547. pSpecificDb->pDb,
  548. pPatternBits,
  549. Chyme,
  550. (PVOID)*ppPattern
  551. );
  552. if (SpHandle != NULL) {
  553. //
  554. // the pattern block associated with the pattern we've just
  555. // installed, we may have gotten one that has already been
  556. // installed.
  557. //
  558. pPatternSave = GetReferenceFromSpecificPatternHandle(SpHandle);
  559. if (*ppPattern != pPatternSave) {
  560. //NDIS_LOCK(&pPatternSave->Lock);
  561. if (GetBlobFromPattern(pPatternSave,CfIndex) && pBlob) {
  562. //
  563. // there is a blob assigned to this entry
  564. // this is a NO NO, and will be REJECTED!
  565. //
  566. //
  567. // just a duplicate - the caller will release
  568. // one ref count in case of an error, so this
  569. // will keep the pattern around!
  570. //
  571. //NdisInterlockedIncrement(&(*ppPatternSave)->RefCount);
  572. //NDIS_UNLOCK(&pPatternSave->Lock);
  573. WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  574. //
  575. // Since we want to take the blob lock and specific DB lock
  576. // in the same order everywhere, release the blob lock after
  577. // the specific DB lock. GPCEnumCfInfo does the same.
  578. //
  579. if (pBlob) {
  580. NDIS_UNLOCK(&pBlob->Lock);
  581. }
  582. //TRACE(PATTERN, (*ppPattern)->RefCount, GPC_STATUS_CONFLICT, "AddSpecificPattern-->");
  583. return GPC_STATUS_CONFLICT;
  584. }
  585. //
  586. // get the CB pointer, since
  587. // the pattern has been already created.
  588. //
  589. pCB = pPatternSave->pClassificationBlock;
  590. TRACE(PATTERN, pCB, CfIndex, "AddSpecificPattern (1.5)");
  591. ASSERT(pCB);
  592. ASSERT(CfIndex < pCB->NumberOfElements);
  593. ASSERT(pPatternSave->DbCtx);
  594. //
  595. // increase ref count, since the caller assume there is
  596. // an extra one
  597. //
  598. REFADD(&pPatternSave->RefCount, 'ADSP');
  599. *ppPattern = pPatternSave;
  600. //
  601. // increase client ref count
  602. //
  603. NdisInterlockedIncrement(&pPatternSave->ClientRefCount);
  604. if (pBlob) {
  605. //
  606. // now assign the slot entry in the CB to the new blob
  607. //
  608. WRITE_LOCK(&glData.ChLock, &irql);
  609. pCB->arpBlobBlock[CfIndex] = pBlob;
  610. WRITE_UNLOCK(&glData.ChLock, irql);
  611. GetBlobFromPattern(pPatternSave,CfIndex) = pBlob;
  612. TRACE(PATTERN, pPatternSave, pBlob, "AddSpecificPattern(2)");
  613. //
  614. // Reasons for removing the blob->lock -
  615. // The lock is taken at teh start of this function.
  616. // (only to maintain the order in which locks are taken/released.
  617. //
  618. GpcInsertTailList
  619. (&pBlob->PatternList,
  620. &pPatternSave->BlobLinkage[CfIndex]
  621. );
  622. }
  623. *pCH = pCB->ClassificationHandle;
  624. //NDIS_UNLOCK(&pPatternSave->Lock);
  625. } else { // if (*ppPattern != pPatternSave)
  626. ProtocolStatInc(pProtocol->ProtocolTemplate,
  627. InsertedPH);
  628. //
  629. // it's a new pattern -
  630. // first we need to create a CB and update the pattern and
  631. // the blob entries
  632. //
  633. REFADD(&pPatternSave->RefCount, 'ADSP');
  634. pCB = CreateNewClassificationBlock(GPC_CF_MAX);
  635. //
  636. // This is a specific pattern, so we'll add the classification
  637. // handle for future use
  638. //
  639. WRITE_LOCK(&glData.ChLock, &irql);
  640. *pCH = (HFHandle)assign_HF_handle(
  641. glData.pCHTable,
  642. (void *)pCB
  643. );
  644. ProtocolStatInc(pProtocol->ProtocolTemplate,
  645. InsertedCH);
  646. WRITE_UNLOCK(&glData.ChLock, irql);
  647. if (pCB && *pCH) {
  648. TRACE(CLASSHAND, pCB, pCB->ClassificationHandle, "AddSpecificPattern (CH+)");
  649. //
  650. // got the CB, update the pattern
  651. //
  652. pCB->arpBlobBlock[CfIndex] = pBlob;
  653. GetBlobFromPattern(pPatternSave, CfIndex) = pBlob;
  654. pPatternSave->pClientBlock = pClient;
  655. pPatternSave->pClassificationBlock = pCB;
  656. pPatternSave->DbCtx = (PVOID)SpHandle;
  657. pCB->ClassificationHandle = *pCH;
  658. TRACE(PATTERN, pPatternSave, pBlob, "AddSpecificPattern(3)");
  659. TRACE(PATTERN, pPatternSave, SpHandle, "AddSpecificPattern: DbCtx");
  660. pPatternSave->State = GPC_STATE_READY;
  661. if (pBlob != NULL) {
  662. //
  663. // Reason for not using the Blob->Lock anymore -
  664. // The lock is taken at teh start of this function.
  665. // (only to maintain the order in which locks are taken/released.
  666. GpcInsertTailList
  667. (&pBlob->PatternList,
  668. &pPatternSave->BlobLinkage[CfIndex]
  669. );
  670. }
  671. ASSERT(pCf);
  672. if (pProtocol->GenericPatternCount) {
  673. //
  674. // a new pattern has been created in the specific db.
  675. // the CB associated with it needs to be updated for each
  676. // CF entry (except the one we've already updated now)
  677. // we'll loop through the CF enlisted and find a match
  678. // for the specific pattern in each generic db.
  679. //
  680. pHead = &glData.CfList;
  681. pEntry = pHead->Flink;
  682. while (pEntry != pHead) {
  683. //
  684. // loop through the registered CF's
  685. //
  686. pCf = CONTAINING_RECORD(pEntry, CF_BLOCK, Linkage);
  687. pEntry = pEntry->Flink;
  688. if (pCf->AssignedIndex != CfIndex || pBlob == NULL) {
  689. //
  690. // skip the current CF only if this client installed
  691. // a CfInfo
  692. //
  693. pGenericDb = pCf->arpGenericDb[pProtocol->ProtocolTemplate];
  694. ASSERT(pGenericDb);
  695. for (i = 0, pPatternSave = NULL;
  696. i < pCf->MaxPriorities && pPatternSave == NULL;
  697. i++, pGenericDb++) {
  698. //
  699. // scan each priority Rhizome
  700. //
  701. READ_LOCK(&pGenericDb->Lock, &ReadIrql);
  702. GpHandle = searchRhizome(pGenericDb->pRhizome,
  703. pPatternBits);
  704. if (GpHandle != NULL) {
  705. pPatternSave = (PPATTERN_BLOCK)GetReferenceFromPatternHandle(GpHandle);
  706. REFADD(&pPatternSave->RefCount, 'ADSP');
  707. }
  708. READ_UNLOCK(&pGenericDb->Lock, ReadIrql);
  709. }
  710. if (pPatternSave != NULL) {
  711. //
  712. // found a generic match, get the reference
  713. // which is a pointer to a pattern and get the
  714. // blob pointer from it.
  715. //
  716. pCB->arpBlobBlock[pCf->AssignedIndex] =
  717. GetBlobFromPattern(pPatternSave,pCf->AssignedIndex);
  718. REFDEL(&pPatternSave->RefCount, 'ADSP');
  719. } else {
  720. //
  721. // no generic pattern matches this specific one
  722. //
  723. pCB->arpBlobBlock[pCf->AssignedIndex] = NULL;
  724. }
  725. TRACE(PATTERN, pPatternSave, pCB->arpBlobBlock[pCf->AssignedIndex], "AddSpecificPattern(4)");
  726. }
  727. } // while (pEntry != pHead)
  728. } // if (pProtocol->GenericPatternCount)
  729. } else { // if (pCB)
  730. //
  731. // remove from pathash table!! (#321509)
  732. //
  733. removePatHashTable(
  734. pSpecificDb->pDb,
  735. SpHandle
  736. );
  737. REFDEL(&pPatternSave->RefCount, 'ADSP');
  738. if (pCB) {
  739. ReleaseClassificationBlock(pCB);
  740. }
  741. if (*pCH) {
  742. FreeClassificationHandle(pClient,
  743. *pCH
  744. );
  745. }
  746. Status = GPC_STATUS_RESOURCES;
  747. }
  748. }
  749. } else { // if (SpHandle != NULL)
  750. Status = GPC_STATUS_RESOURCES;
  751. }
  752. //
  753. // release the specific db lock
  754. //
  755. WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  756. //
  757. // Since we want to take the blob lock and specific DB lock
  758. // in the same order everywhere, release the blob lock after
  759. // the specific DB lock. GPCEnumCfInfo does the same.
  760. //
  761. if (pBlob) {
  762. NDIS_UNLOCK(&pBlob->Lock);
  763. }
  764. //
  765. // set output parameters:
  766. // ppPattern should have been set by now
  767. //
  768. TRACE(PATTERN, *ppPattern, Status, "AddSpecificPattern==>");
  769. return Status;
  770. }
  771. /*
  772. ************************************************************************
  773. HandleFragment -
  774. Handle an IP fragment.
  775. Arguments
  776. pClient -
  777. bFirstFrag -
  778. bLastFrag -
  779. Retu
  780. GPC_STATUS
  781. ************************************************************************
  782. */
  783. GPC_STATUS
  784. HandleFragment(
  785. IN PCLIENT_BLOCK pClient,
  786. IN PPROTOCOL_BLOCK pProtocol,
  787. IN BOOLEAN bFirstFrag,
  788. IN BOOLEAN bLastFrag,
  789. IN ULONG PacketId,
  790. IN OUT PPATTERN_BLOCK *ppPatternBlock,
  791. OUT PBLOB_BLOCK *ppBlob
  792. )
  793. {
  794. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  795. PFRAGMENT_DB pFragDb;
  796. SpecificPatternHandle SpHandle;
  797. KIRQL ReadIrql;
  798. KIRQL WriteIrql;
  799. KIRQL CHirql;
  800. ASSERT(ppPatternBlock);
  801. ASSERT(ppBlob);
  802. TRACE(CLASSIFY, PacketId, bFirstFrag, "HandleFragment: PacketId, bFirstFrag");
  803. TRACE(CLASSIFY, PacketId, bLastFrag, "HandleFragment: PacketId, bLastFrag");
  804. pFragDb = (PFRAGMENT_DB)pProtocol->pProtocolDb;
  805. if (bFirstFrag) {
  806. //
  807. // add an entry to the hash table
  808. //
  809. WRITE_LOCK(&pFragDb->Lock, &WriteIrql);
  810. SpHandle = insertPatHashTable(
  811. pFragDb->pDb,
  812. (char *)&PacketId,
  813. PacketId,
  814. (void *)*ppPatternBlock
  815. );
  816. WRITE_UNLOCK(&pFragDb->Lock, WriteIrql);
  817. ProtocolStatInc(pProtocol->ProtocolTemplate,
  818. FirstFragsCount);
  819. } else {
  820. //
  821. // search for it
  822. //
  823. READ_LOCK(&pFragDb->Lock, &ReadIrql);
  824. SpHandle = searchPatHashTable(
  825. pFragDb->pDb,
  826. (char *)&PacketId,
  827. PacketId);
  828. if (SpHandle) {
  829. *ppPatternBlock = GetReferenceFromSpecificPatternHandle(SpHandle);
  830. READ_UNLOCK(&pFragDb->Lock, ReadIrql);
  831. //NdisInterlockedIncrement(&(*ppPatternBlock)->RefCount);
  832. if (bLastFrag) {
  833. //
  834. // remove the entry from the hash table
  835. //
  836. WRITE_LOCK(&pFragDb->Lock, &WriteIrql);
  837. removePatHashTable(pFragDb->pDb, SpHandle);
  838. WRITE_UNLOCK(&pFragDb->Lock, WriteIrql);
  839. ProtocolStatInc(pProtocol->ProtocolTemplate,
  840. LastFragsCount);
  841. }
  842. } else {
  843. //
  844. // not found
  845. //
  846. READ_UNLOCK(&pFragDb->Lock, ReadIrql);
  847. *ppPatternBlock = NULL;
  848. *ppBlob = NULL;
  849. Status = GPC_STATUS_NOT_FOUND;
  850. }
  851. }
  852. if (Status == GPC_STATUS_SUCCESS) {
  853. ASSERT(*ppPatternBlock);
  854. if (TEST_BIT_ON((*ppPatternBlock)->Flags, PATTERN_SPECIFIC)) {
  855. //
  856. // specific pattern, lookup throught the CH
  857. //
  858. READ_LOCK(&glData.ChLock, &CHirql);
  859. *ppBlob = (PBLOB_BLOCK)dereference_HF_handle_with_cb(
  860. glData.pCHTable,
  861. (*ppPatternBlock)->pClassificationBlock->ClassificationHandle,
  862. pClient->pCfBlock->AssignedIndex);
  863. READ_UNLOCK(&glData.ChLock, CHirql);
  864. } else {
  865. //
  866. // generic pattern, get the blob ptr directly
  867. //
  868. *ppBlob = GetBlobFromPattern((*ppPatternBlock),
  869. pClient->pCfBlock->AssignedIndex);
  870. }
  871. DBGPRINT(CLASSIFY, ("HandleFragment: Pattern=%X Blob=%X\n",
  872. *ppPatternBlock, *ppBlob));
  873. }
  874. TRACE(CLASSIFY, *ppPatternBlock, *ppBlob, "HandleFragment==>");
  875. return Status;
  876. }
  877. /*
  878. ************************************************************************
  879. InternalSearchPattern -
  880. Arguments
  881. Returns
  882. matched pattern or NULL for none
  883. ************************************************************************
  884. */
  885. NTSTATUS
  886. InternalSearchPattern(
  887. IN PCLIENT_BLOCK pClientBlock,
  888. IN PPROTOCOL_BLOCK pProtocol,
  889. IN PVOID pPatternKey,
  890. OUT PPATTERN_BLOCK *pPatternBlock,
  891. OUT PCLASSIFICATION_HANDLE pClassificationHandle,
  892. IN BOOLEAN bNoCache
  893. )
  894. {
  895. PSPECIFIC_PATTERN_DB pSpecificDb;
  896. PGENERIC_PATTERN_DB pGenericDb;
  897. PatternHandle GpHandle;
  898. SpecificPatternHandle SpHandle;
  899. PPATTERN_BLOCK pPattern;
  900. PCF_BLOCK pCf;
  901. int i;
  902. KIRQL ReadIrql;
  903. NTSTATUS Status;
  904. TRACE(CLASSIFY, pClientBlock, pPatternKey, "InternalSearchPattern:");
  905. DBGPRINT(CLASSIFY, ("InternalSearchPattern: Client=%X \n", pClientBlock));
  906. Status = GPC_STATUS_SUCCESS;
  907. //
  908. // start with the specific db
  909. //
  910. pSpecificDb = &pProtocol->SpecificDb;
  911. READ_LOCK(&pSpecificDb->Lock, &ReadIrql);
  912. pCf = pClientBlock->pCfBlock;
  913. SpHandle = searchPatHashTable(
  914. pSpecificDb->pDb,
  915. (char *)pPatternKey,
  916. GpcCalcHash(pProtocol->ProtocolTemplate,
  917. pPatternKey)
  918. );
  919. if (SpHandle) {
  920. pPattern = (PPATTERN_BLOCK)GetReferenceFromSpecificPatternHandle(SpHandle);
  921. //NdisInterlockedIncrement(&pPattern->RefCount);
  922. *pClassificationHandle =
  923. (CLASSIFICATION_HANDLE)pPattern->pClassificationBlock->ClassificationHandle;
  924. TRACE(CLASSIFY, pClientBlock, *pClassificationHandle, "InternalSearchPattern (2)" );
  925. } else {
  926. pPattern = NULL;
  927. *pClassificationHandle = 0;
  928. }
  929. READ_UNLOCK(&pSpecificDb->Lock, ReadIrql);
  930. if (pPattern == NULL) {
  931. if (bNoCache) {
  932. Status = GPC_STATUS_FAILURE;
  933. } else {
  934. //
  935. // no specific pattern, add an automagic one
  936. //
  937. Status = AddSpecificPatternWithTimer(
  938. pClientBlock,
  939. pProtocol->ProtocolTemplate,
  940. pPatternKey,
  941. &pPattern,
  942. pClassificationHandle
  943. );
  944. DBGPRINT(CLASSIFY, ("InternalSearchPattern: Client=%X installed Pattern=%X\n",
  945. pClientBlock, pPattern));
  946. }
  947. if (!NT_SUCCESS(Status)) {
  948. //
  949. // not found, search each generic db
  950. //
  951. for (i = 0; i < (int)pCf->MaxPriorities && pPattern == NULL; i++) {
  952. //
  953. // scan each priority Rhizome
  954. //
  955. pGenericDb = &pCf->arpGenericDb[pProtocol->ProtocolTemplate][i];
  956. READ_LOCK(&pGenericDb->Lock, &ReadIrql);
  957. GpHandle = searchRhizome(pGenericDb->pRhizome, pPatternKey);
  958. if (GpHandle != NULL) {
  959. pPattern = (PPATTERN_BLOCK)GetReferenceFromPatternHandle(GpHandle);
  960. //NdisInterlockedIncrement(&pPattern->RefCount);
  961. }
  962. READ_UNLOCK(&pGenericDb->Lock, ReadIrql);
  963. }
  964. // we had to search manually, make sure we know this in the main code.
  965. *pClassificationHandle = 0;
  966. }
  967. DBGPRINT(CLASSIFY, ("InternalSearchPattern: Client=%X Generic Pattern=%X\n",
  968. pClientBlock, pPattern));
  969. }
  970. TRACE(CLASSIFY, pPattern, *pClassificationHandle, "InternalSearchPattern==>");
  971. DBGPRINT(CLASSIFY, ("InternalSearchPattern: Client=%X returned Pattern=%X\n",
  972. pClientBlock, pPattern));
  973. *pPatternBlock = pPattern;
  974. return Status;
  975. }
  976. GPC_STATUS
  977. InitFragmentDb(
  978. IN PFRAGMENT_DB *ppFragDb
  979. )
  980. {
  981. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  982. PFRAGMENT_DB pDb;
  983. ULONG Len, i;
  984. TRACE(INIT, ppFragDb, 0, "InitFragmentDb");
  985. ASSERT(ppFragDb);
  986. //
  987. // init the pattern db struct
  988. // call the PH init routine
  989. //
  990. GpcAllocMem(ppFragDb, sizeof(FRAGMENT_DB), FragmentDbTag);
  991. if (pDb = *ppFragDb) {
  992. INIT_LOCK(&pDb->Lock);
  993. AllocatePatHashTable(pDb->pDb);
  994. if (pDb->pDb != NULL) {
  995. constructPatHashTable(pDb->pDb,
  996. sizeof(ULONG),
  997. 2, // usage_ratio,
  998. 1, // usage_histeresis,
  999. 1, // allocation_histeresis,
  1000. 16 // max_free_list_size
  1001. );
  1002. } else {
  1003. GpcFreeMem (*ppFragDb, FragmentDbTag);
  1004. Status = GPC_STATUS_RESOURCES;
  1005. }
  1006. } else {
  1007. Status = GPC_STATUS_RESOURCES;
  1008. }
  1009. TRACE(INIT, Status, 0, "InitFragmentDb==>");
  1010. return Status;
  1011. }
  1012. GPC_STATUS
  1013. UninitFragmentDb(
  1014. IN PFRAGMENT_DB pFragDb
  1015. )
  1016. {
  1017. destructPatHashTable (pFragDb->pDb);
  1018. FreePatHashTable(pFragDb->pDb);
  1019. GpcFreeMem (pFragDb, FragmentDbTag);
  1020. return STATUS_SUCCESS;
  1021. }
  1022. /*
  1023. ************************************************************************
  1024. RemoveSpecificPattern -
  1025. Remove a specific pattern from the db.
  1026. Arguments
  1027. pClient -
  1028. pPattern -
  1029. Returns
  1030. GPC_STATUS
  1031. ************************************************************************
  1032. */
  1033. GPC_STATUS
  1034. RemoveSpecificPattern(
  1035. IN PCLIENT_BLOCK pClient,
  1036. IN PPROTOCOL_BLOCK pProtocol,
  1037. IN PPATTERN_BLOCK pPattern,
  1038. IN BOOLEAN ForceRemoval
  1039. )
  1040. {
  1041. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  1042. PSPECIFIC_PATTERN_DB pSpecificDb;
  1043. PatternHandle GpHandle;
  1044. PPATTERN_BLOCK pGp;
  1045. PCF_BLOCK pCf;
  1046. int i;
  1047. ULONG CfIndex;
  1048. PBLOB_BLOCK pBlob, pNewBlob;
  1049. PGENERIC_PATTERN_DB pGenericDb;
  1050. KIRQL ReadIrql;
  1051. KIRQL WriteIrql;
  1052. ULONG ProtocolTemplate;
  1053. KIRQL irql;
  1054. LONG cClientRef;
  1055. BOOLEAN bRemoveLinks = FALSE;
  1056. GPC_HANDLE ClHandle = NULL;
  1057. TRACE(PATTERN, pClient, pPattern, "RemoveSpecificPattern");
  1058. //
  1059. // get the specific db pointer
  1060. //
  1061. pSpecificDb = &pProtocol->SpecificDb;
  1062. ASSERT(pSpecificDb);
  1063. pCf = pClient->pCfBlock;
  1064. CfIndex = pCf->AssignedIndex;
  1065. ProtocolTemplate = pProtocol->ProtocolTemplate;
  1066. // The plan: Remove the DbCtx (from the Specific pattern structure)
  1067. // from teh Pathash table with the Specific Db Lock held. This
  1068. // will ensure that if the same pattern is being added, the pathash
  1069. // table will accept the new one instead of bumping up the ref on what
  1070. // we are trying to delete now.
  1071. //
  1072. NDIS_LOCK(&pPattern->Lock);
  1073. WRITE_LOCK(&pSpecificDb->Lock, &WriteIrql);
  1074. cClientRef = NdisInterlockedDecrement(&pPattern->ClientRefCount);
  1075. if (pPattern->State != GPC_STATE_DELETE) {
  1076. ASSERT(cClientRef >= 0);
  1077. ASSERT(pPattern->DbCtx);
  1078. if (0 == cClientRef) {
  1079. pPattern->State = GPC_STATE_DELETE;
  1080. removePatHashTable(
  1081. pSpecificDb->pDb,
  1082. (SpecificPatternHandle)pPattern->DbCtx
  1083. );
  1084. pPattern->DbCtx = NULL;
  1085. WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  1086. NDIS_UNLOCK(&pPattern->Lock);
  1087. ReadySpecificPatternForDeletion(
  1088. pClient,
  1089. pProtocol,
  1090. pPattern
  1091. );
  1092. } else if (cClientRef > 0) {
  1093. WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  1094. NDIS_UNLOCK(&pPattern->Lock);
  1095. ClientRefsExistForSpecificPattern(
  1096. pClient,
  1097. pProtocol,
  1098. pPattern
  1099. );
  1100. } else {
  1101. // we shouldn't be getting here - really.
  1102. WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  1103. NDIS_UNLOCK(&pPattern->Lock);
  1104. }
  1105. } else {
  1106. WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  1107. NDIS_UNLOCK(&pPattern->Lock);
  1108. }
  1109. TRACE(PATTERN, pPattern, Status, "RemoveSpecificPattern==>");
  1110. return Status;
  1111. }
  1112. /*
  1113. ************************************************************************
  1114. ReadySpecificPatternForDeletion -
  1115. Remove a specific pattern from the db.
  1116. Arguments
  1117. pClient -
  1118. pPattern -
  1119. Returns
  1120. GPC_STATUS
  1121. ************************************************************************
  1122. */
  1123. VOID
  1124. ReadySpecificPatternForDeletion(
  1125. IN PCLIENT_BLOCK pClient,
  1126. IN PPROTOCOL_BLOCK pProtocol,
  1127. IN PPATTERN_BLOCK pPattern
  1128. )
  1129. {
  1130. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  1131. PSPECIFIC_PATTERN_DB pSpecificDb;
  1132. PatternHandle GpHandle;
  1133. PPATTERN_BLOCK pGp;
  1134. PCF_BLOCK pCf;
  1135. PCLASSIFICATION_BLOCK pCB;
  1136. int i;
  1137. ULONG CfIndex;
  1138. PBLOB_BLOCK pBlob, pNewBlob;
  1139. PGENERIC_PATTERN_DB pGenericDb;
  1140. KIRQL ReadIrql;
  1141. KIRQL WriteIrql;
  1142. ULONG ProtocolTemplate;
  1143. KIRQL irql;
  1144. PVOID Key;
  1145. LONG cClientRef;
  1146. BOOLEAN bRemoveLinks = FALSE;
  1147. GPC_HANDLE ClHandle = NULL;
  1148. TRACE(PATTERN, pClient, pPattern, "ReadySpecificPatternForDeletion");
  1149. //
  1150. // get the specific db pointer
  1151. //
  1152. pSpecificDb = &pProtocol->SpecificDb;
  1153. ASSERT(pSpecificDb);
  1154. pCf = pClient->pCfBlock;
  1155. CfIndex = pCf->AssignedIndex;
  1156. pCB = pPattern->pClassificationBlock;
  1157. ProtocolTemplate = pProtocol->ProtocolTemplate;
  1158. Key = GetKeyPtrFromSpecificPatternHandle(((SpecificPatternHandle)pPattern->DbCtx));
  1159. ASSERT(pCB);
  1160. //
  1161. // Remove the ClHandle, so that if we are coming back in via a
  1162. // user mode ioctl, we wont try to remove it again.
  1163. //
  1164. ClHandle = (HANDLE) LongToPtr(InterlockedExchange((PLONG32)&pPattern->ClHandle, 0));
  1165. if (ClHandle) {
  1166. FreeHandle(ClHandle);
  1167. }
  1168. //
  1169. // remove the pattern from any linked list
  1170. //
  1171. ClearPatternLinks(pPattern, pProtocol, CfIndex);
  1172. //
  1173. // We are going to access the Specific DB now, lock it NOW.
  1174. // This should fix deadlock 248352 [ShreeM]
  1175. //
  1176. WRITE_LOCK(&pSpecificDb->Lock, &WriteIrql);
  1177. //
  1178. // this is the last client that holds the pattern,
  1179. // we need to take the pattern off the specific db
  1180. //
  1181. TRACE(PATTERN, pPattern, pPattern->DbCtx, "ReadySpecificPatternForDeletion: DbCtx");
  1182. ASSERT(!pPattern->DbCtx);
  1183. ProtocolStatInc(ProtocolTemplate,
  1184. RemovedPH);
  1185. //
  1186. // free the classification handle -
  1187. // this must come *before* we free the classification block
  1188. // since it may be referenced by other clients
  1189. //
  1190. TRACE(PATTERN, pCB, CfIndex, "ReadySpecificPatternForDeletion: (2)");
  1191. FreeClassificationHandle(
  1192. pClient,
  1193. (CLASSIFICATION_HANDLE)pCB->ClassificationHandle
  1194. );
  1195. ProtocolStatInc(ProtocolTemplate,
  1196. RemovedCH);
  1197. WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  1198. //
  1199. // bye bye pattern, at least for this client
  1200. //
  1201. REFDEL(&pPattern->RefCount, 'ADSP');
  1202. TRACE(PATTERN, pClient, pPattern, "ReadySpecificPatternForDeletion--------->");
  1203. }
  1204. /*
  1205. ************************************************************************
  1206. ClientRefsExistForSpecificPattern -
  1207. Arguments
  1208. pClient -
  1209. pPattern -
  1210. Returns
  1211. GPC_STATUS
  1212. ************************************************************************
  1213. */
  1214. VOID
  1215. ClientRefsExistForSpecificPattern(
  1216. IN PCLIENT_BLOCK pClient,
  1217. IN PPROTOCOL_BLOCK pProtocol,
  1218. IN PPATTERN_BLOCK pPattern
  1219. )
  1220. {
  1221. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  1222. PSPECIFIC_PATTERN_DB pSpecificDb;
  1223. PatternHandle GpHandle;
  1224. PPATTERN_BLOCK pGp;
  1225. PCF_BLOCK pCf;
  1226. PCLASSIFICATION_BLOCK pCB;
  1227. int i;
  1228. ULONG CfIndex;
  1229. PBLOB_BLOCK pBlob, pNewBlob;
  1230. PGENERIC_PATTERN_DB pGenericDb;
  1231. KIRQL ReadIrql;
  1232. KIRQL WriteIrql;
  1233. ULONG ProtocolTemplate;
  1234. KIRQL irql;
  1235. PVOID Key;
  1236. LONG cClientRef;
  1237. BOOLEAN bRemoveLinks = FALSE;
  1238. GPC_HANDLE ClHandle = NULL;
  1239. TRACE(PATTERN, pClient, pPattern, "ClientRefsExistForSpecificPattern");
  1240. //
  1241. // get the specific db pointer
  1242. //
  1243. pSpecificDb = &pProtocol->SpecificDb;
  1244. ASSERT(pSpecificDb);
  1245. pCf = pClient->pCfBlock;
  1246. CfIndex = pCf->AssignedIndex;
  1247. pCB = pPattern->pClassificationBlock;
  1248. ProtocolTemplate = pProtocol->ProtocolTemplate;
  1249. Key = GetKeyPtrFromSpecificPatternHandle(((SpecificPatternHandle)pPattern->DbCtx));
  1250. ASSERT(pCB);
  1251. //
  1252. // reference count > 0
  1253. //
  1254. pBlob = pCB->arpBlobBlock[CfIndex];
  1255. TRACE(PATTERN, pPattern, pBlob, "ClientRefsExistForSpecificPattern (2)");
  1256. //
  1257. // We are going to access the Specific DB now, lock it NOW.
  1258. // This should fix deadlock 248352 [ShreeM]
  1259. //
  1260. WRITE_LOCK(&pSpecificDb->Lock, &WriteIrql);
  1261. if (pBlob
  1262. &&
  1263. ((pBlob->pOwnerClient == pClient) ||
  1264. TEST_BIT_ON(pBlob->Flags, PATTERN_REMOVE_CB_BLOB))) {
  1265. bRemoveLinks = TRUE;
  1266. pNewBlob = NULL;
  1267. TRACE(PATTERN, pCB, CfIndex, "ClientRefsExistForSpecificPattern (3)");
  1268. //
  1269. // search the generic db for the same CF, since there is an open slot,
  1270. // some other generic pattern might fill it with its own blob pointer
  1271. //
  1272. pGenericDb = pCf->arpGenericDb[ProtocolTemplate];
  1273. ASSERT(pGenericDb);
  1274. for (i = 0, pGp = NULL;
  1275. i < (int)pCf->MaxPriorities && pGp == NULL;
  1276. i++) {
  1277. //
  1278. // scan each priority Rhizome
  1279. //
  1280. READ_LOCK(&pGenericDb->Lock, &ReadIrql);
  1281. GpHandle = searchRhizome(pGenericDb->pRhizome, Key);
  1282. if (GpHandle != NULL) {
  1283. //
  1284. // found a generic pattern that match this specific one.
  1285. //
  1286. pGp = (PPATTERN_BLOCK)GetReferenceFromPatternHandle(GpHandle);
  1287. pNewBlob = GetBlobFromPattern(pGp, CfIndex);
  1288. }
  1289. READ_UNLOCK(&pGenericDb->Lock, ReadIrql);
  1290. pGenericDb++;
  1291. }
  1292. //
  1293. // update the classification block entry
  1294. //
  1295. WRITE_LOCK(&glData.ChLock, &irql);
  1296. pCB->arpBlobBlock[CfIndex] = pNewBlob;
  1297. WRITE_UNLOCK(&glData.ChLock, irql);
  1298. TRACE(PATTERN, pGp,
  1299. pCB->arpBlobBlock[CfIndex],
  1300. "ClientRefsExistForSpecificPattern (4)");
  1301. }
  1302. //
  1303. // must first release this lock to avoid dead lock
  1304. // when aquiring the Blob lock
  1305. //
  1306. WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  1307. if (bRemoveLinks) {
  1308. //
  1309. // remove the pattern from any linked list
  1310. //
  1311. ClearPatternLinks(pPattern, pProtocol, CfIndex);
  1312. ASSERT(CfIndex == pBlob->pOwnerClient->pCfBlock->AssignedIndex);
  1313. GetBlobFromPattern(pPattern, CfIndex) = NULL;
  1314. }
  1315. REFDEL(&pPattern->RefCount, 'ADSP');
  1316. TRACE(PATTERN, pClient, pPattern, "ClientRefsExistForSpecificPattern---->");
  1317. }
  1318. /*
  1319. ************************************************************************
  1320. RemoveGenericPattern -
  1321. Remove a generic pattern from the db.
  1322. Arguments
  1323. pClient -
  1324. pPattern -
  1325. Returns
  1326. GPC_STATUS
  1327. ************************************************************************
  1328. */
  1329. GPC_STATUS
  1330. RemoveGenericPattern(
  1331. IN PCLIENT_BLOCK pClient,
  1332. IN PPROTOCOL_BLOCK pProtocol,
  1333. IN PPATTERN_BLOCK pPattern
  1334. )
  1335. {
  1336. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  1337. PSPECIFIC_PATTERN_DB pSpecificDb;
  1338. PGENERIC_PATTERN_DB pGenericDb;
  1339. PCF_BLOCK pCf;
  1340. SCAN_STRUCT ScanStruct;
  1341. UCHAR PatternBits[MAX_PATTERN_SIZE];
  1342. UCHAR MaskBits[MAX_PATTERN_SIZE];
  1343. ULONG i;
  1344. KIRQL ReadIrql;
  1345. KIRQL WriteIrql;
  1346. GPC_HANDLE ClHandle = NULL;
  1347. TRACE(PATTERN, pPattern, pPattern->DbCtx, "RemoveGenericPattern");
  1348. ASSERT(MAX_PATTERN_SIZE >= sizeof(GPC_IP_PATTERN));
  1349. ASSERT(MAX_PATTERN_SIZE >= sizeof(GPC_IPX_PATTERN));
  1350. //
  1351. // Remove the ClHandle, so that if we are coming back in via a
  1352. // user mode ioctl, we wont try to remove it again.
  1353. //
  1354. ClHandle = (HANDLE) LongToPtr(InterlockedExchange((PLONG32)&pPattern->ClHandle, 0));
  1355. if (ClHandle) {
  1356. FreeHandle(ClHandle);
  1357. }
  1358. pPattern->State = GPC_STATE_REMOVE;
  1359. pCf = pClient->pCfBlock;
  1360. ScanStruct.Priority = pPattern->Priority;
  1361. ScanStruct.pClientBlock = pClient;
  1362. ScanStruct.pPatternBlock = pPattern;
  1363. ScanStruct.pBlobBlock = GetBlobFromPattern(pPattern, pCf->AssignedIndex);
  1364. ScanStruct.bRemove = TRUE;
  1365. //
  1366. // get the specific db pointer
  1367. //
  1368. pSpecificDb = &pProtocol->SpecificDb;
  1369. ASSERT(pSpecificDb);
  1370. pGenericDb = &pCf->arpGenericDb[pProtocol->ProtocolTemplate][pPattern->Priority];
  1371. ASSERT(pGenericDb);
  1372. //
  1373. // remove the pattern from any linked list
  1374. //
  1375. ClearPatternLinks(pPattern, pProtocol, pCf->AssignedIndex);
  1376. //
  1377. // copy the pattern key and mask for searching later
  1378. //
  1379. NDIS_LOCK(&pPattern->Lock);
  1380. WRITE_LOCK(&pGenericDb->Lock, &WriteIrql);
  1381. ASSERT(pPattern->DbCtx);
  1382. NdisMoveMemory(PatternBits,
  1383. GetKeyPtrFromPatternHandle(pGenericDb->pRhizome,
  1384. pPattern->DbCtx),
  1385. GetKeySizeBytes(pGenericDb->pRhizome)
  1386. );
  1387. NdisMoveMemory(MaskBits,
  1388. GetMaskPtrFromPatternHandle(pGenericDb->pRhizome,
  1389. pPattern->DbCtx),
  1390. GetKeySizeBytes(pGenericDb->pRhizome)
  1391. );
  1392. //
  1393. // remove the pattern from generic db
  1394. //
  1395. removeRhizome(pGenericDb->pRhizome,
  1396. (PatternHandle)pPattern->DbCtx
  1397. );
  1398. ProtocolStatInc(pProtocol->ProtocolTemplate,
  1399. RemovedRz);
  1400. //
  1401. // This is no longer valid
  1402. //
  1403. pPattern->DbCtx = NULL;
  1404. WRITE_UNLOCK(&pGenericDb->Lock, WriteIrql);
  1405. NDIS_UNLOCK(&pPattern->Lock);
  1406. //
  1407. // the generic pattern has been removed,
  1408. //
  1409. READ_LOCK(&pSpecificDb->Lock, &ReadIrql);
  1410. //
  1411. // this will do the rest of the work...
  1412. //
  1413. scanPatHashTable(
  1414. pSpecificDb->pDb,
  1415. (char *)PatternBits,
  1416. (char *)MaskBits,
  1417. (PVOID)&ScanStruct,
  1418. GpcSpecificCallback // see callback routine...
  1419. );
  1420. READ_UNLOCK(&pSpecificDb->Lock, ReadIrql);
  1421. //
  1422. // time to go to the big hunting fields....
  1423. //
  1424. REFDEL(&pPattern->RefCount, 'ADGP');
  1425. TRACE(PATTERN, pPattern, Status, "RemoveGenericPattern==>");
  1426. return Status;
  1427. }