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.

2188 lines
60 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. void DeleteAutoPattern(PPATTERN_BLOCK pPattern,IN PPROTOCOL_BLOCK pProtocol)
  467. {
  468. NDIS_LOCK(&pPattern->Lock);
  469. pPattern->State = GPC_STATE_FORCE_REMOVE;
  470. pPattern->Flags |= ~PATTERN_AUTO;
  471. NDIS_LOCK(&pProtocol->PatternTimerLock[pPattern->WheelIndex]);
  472. if (!IsListEmpty(&pPattern->TimerLinkage))
  473. {
  474. GpcRemoveEntryList(&pPattern->TimerLinkage);
  475. InitializeListHead(&pPattern->TimerLinkage);
  476. }
  477. NDIS_UNLOCK(&pProtocol->PatternTimerLock[pPattern->WheelIndex]);
  478. ProtocolStatInc(pPattern->ProtocolTemplate,
  479. DeletedAp);
  480. ProtocolStatDec(pPattern->ProtocolTemplate,
  481. CurrentAp);
  482. NDIS_UNLOCK(&pPattern->Lock);
  483. //
  484. // actually remove the pattern
  485. //
  486. // This will try to reacquire lock on pattern. So we released the lock above.
  487. privateGpcRemovePattern((GPC_HANDLE)pPattern->pAutoClient, (GPC_HANDLE)pPattern, TRUE, TRUE);
  488. InterlockedDecrement(&pProtocol->AutoSpecificPatternCount);
  489. }
  490. /*
  491. ************************************************************************
  492. AddSpecificPattern -
  493. Add a specific pattern to the db.
  494. Arguments
  495. pClient -
  496. pPatternBits-
  497. pMaskBits -
  498. pBlob -
  499. pProtocol -
  500. ppPattern -
  501. ppCB -
  502. Returns
  503. GPC_STATUS
  504. ************************************************************************
  505. */
  506. GPC_STATUS
  507. AddSpecificPattern(
  508. IN PCLIENT_BLOCK pClient,
  509. IN PUCHAR pPatternBits,
  510. IN PUCHAR pMaskBits,
  511. IN PBLOB_BLOCK pBlob, // optional
  512. IN PPROTOCOL_BLOCK pProtocol,
  513. IN OUT PPATTERN_BLOCK *ppPattern,
  514. OUT PCLASSIFICATION_HANDLE pCH
  515. )
  516. {
  517. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  518. PSPECIFIC_PATTERN_DB pSpecificDb;
  519. PGENERIC_PATTERN_DB pGenericDb;
  520. ULONG Chyme;
  521. ULONG CfIndex, i;
  522. PPATTERN_BLOCK pPatternSave;
  523. PBLOB_BLOCK pBlobSave;
  524. SpecificPatternHandle SpHandle;
  525. PatternHandle GpHandle;
  526. PCLASSIFICATION_BLOCK pCB = NULL;
  527. PCF_BLOCK pCf = NULL;
  528. PLIST_ENTRY pHead, pEntry;
  529. KIRQL ReadIrql;
  530. KIRQL WriteIrql;
  531. KIRQL irql;
  532. //BOOLEAN bIsAuto;
  533. ASSERT(ppPattern);
  534. ASSERT(*ppPattern);
  535. TRACE(PATTERN, pClient, *ppPattern, "AddSpecificPattern");
  536. *pCH = 0;
  537. //bIsAuto = TEST_BIT_ON((*ppPattern)->Flags, PATTERN_AUTO);
  538. //
  539. // get the specific db pointer
  540. //
  541. pSpecificDb = &pProtocol->SpecificDb;
  542. ASSERT(pSpecificDb);
  543. //
  544. // get the CF index
  545. //
  546. CfIndex = pClient->pCfBlock->AssignedIndex;
  547. pCf = pClient->pCfBlock;
  548. //
  549. // Since we want to take the blob lock and specific DB lock
  550. // in the same order everywhere. Take the blob lock before the specific DB
  551. // lock. GPCEnumCfInfo does the same.
  552. //
  553. if (pBlob) {
  554. NDIS_LOCK(&pBlob->Lock);
  555. }
  556. //
  557. // lock the specific db, some other client may access it
  558. //
  559. WRITE_LOCK(&pSpecificDb->Lock, &WriteIrql);
  560. //
  561. // calculate a chyme hash value for the pat -hash
  562. //
  563. Chyme = GpcCalcHash(pProtocol->ProtocolTemplate, pPatternBits);
  564. ASSERT(Chyme != (-1));
  565. //
  566. // actually call insert directly. If the pattern already exist in the
  567. // db, the returned reference will be the one for a previously
  568. // installed pattern, so ppPattern will be different
  569. //
  570. SpHandle = insertPatHashTable(
  571. pSpecificDb->pDb,
  572. pPatternBits,
  573. Chyme,
  574. (PVOID)*ppPattern
  575. );
  576. if (SpHandle != NULL) {
  577. //
  578. // the pattern block associated with the pattern we've just
  579. // installed, we may have gotten one that has already been
  580. // installed.
  581. //
  582. pPatternSave = GetReferenceFromSpecificPatternHandle(SpHandle);
  583. if (*ppPattern != pPatternSave) {
  584. if ((TEST_BIT_ON( pPatternSave->Flags, PATTERN_AUTO))
  585. &&
  586. (!TEST_BIT_ON(pPatternSave->Flags,PATTERN_AUTO_NOT_READY)))
  587. {
  588. PCLIENT_BLOCK pClient;
  589. NDIS_LOCK(&pPatternSave->Lock);
  590. REFADD(&pPatternSave->RefCount, 'DLAP');
  591. NDIS_UNLOCK(&pPatternSave->Lock);
  592. //WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  593. pClient = pPatternSave->pAutoClient;
  594. DeleteAutoPattern(pPatternSave,pProtocol);
  595. //WRITE_LOCK(&pSpecificDb->Lock, &WriteIrql);
  596. REFDEL(&pPatternSave->RefCount, 'DLAP');
  597. REFDEL(&(pClient->RefCount),'CLNT');
  598. }
  599. SpHandle = insertPatHashTable(
  600. pSpecificDb->pDb,
  601. pPatternBits,
  602. Chyme,
  603. (PVOID)*ppPattern
  604. );
  605. }
  606. if (SpHandle!=NULL)
  607. {
  608. pPatternSave = GetReferenceFromSpecificPatternHandle(SpHandle);
  609. if (*ppPattern != pPatternSave){
  610. if (GetBlobFromPattern(pPatternSave,CfIndex) && pBlob) {
  611. //
  612. // there is a blob assigned to this entry
  613. // this is a NO NO, and will be REJECTED!
  614. //
  615. //
  616. // just a duplicate - the caller will release
  617. // one ref count in case of an error, so this
  618. // will keep the pattern around!
  619. //
  620. //NdisInterlockedIncrement(&(*ppPatternSave)->RefCount);
  621. //NDIS_UNLOCK(&pPatternSave->Lock);
  622. WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  623. //
  624. // Since we want to take the blob lock and specific DB lock
  625. // in the same order everywhere, release the blob lock after
  626. // the specific DB lock. GPCEnumCfInfo does the same.
  627. //
  628. if (pBlob) {
  629. NDIS_UNLOCK(&pBlob->Lock);
  630. }
  631. //TRACE(PATTERN, (*ppPattern)->RefCount, GPC_STATUS_CONFLICT, "AddSpecificPattern-->");
  632. return GPC_STATUS_CONFLICT;
  633. }
  634. //
  635. // get the CB pointer, since
  636. // the pattern has been already created.
  637. //
  638. pCB = pPatternSave->pClassificationBlock;
  639. TRACE(PATTERN, pCB, CfIndex, "AddSpecificPattern (1.5)");
  640. ASSERT(pCB);
  641. ASSERT(CfIndex < pCB->NumberOfElements);
  642. ASSERT(pPatternSave->DbCtx);
  643. //
  644. // increase ref count, since the caller assume there is
  645. // an extra one
  646. //
  647. REFADD(&pPatternSave->RefCount, 'ADSP');
  648. *ppPattern = pPatternSave;
  649. //
  650. // increase client ref count
  651. //
  652. NdisInterlockedIncrement(&pPatternSave->ClientRefCount);
  653. if (pBlob) {
  654. //
  655. // now assign the slot entry in the CB to the new blob
  656. //
  657. WRITE_LOCK(&glData.ChLock, &irql);
  658. pCB->arpBlobBlock[CfIndex] = pBlob;
  659. WRITE_UNLOCK(&glData.ChLock, irql);
  660. GetBlobFromPattern(pPatternSave,CfIndex) = pBlob;
  661. TRACE(PATTERN, pPatternSave, pBlob, "AddSpecificPattern(2)");
  662. //
  663. // Reasons for removing the blob->lock -
  664. // The lock is taken at teh start of this function.
  665. // (only to maintain the order in which locks are taken/released.
  666. //
  667. GpcInsertTailList
  668. (&pBlob->PatternList,
  669. &pPatternSave->BlobLinkage[CfIndex]
  670. );
  671. }
  672. *pCH = pCB->ClassificationHandle;
  673. //NDIS_UNLOCK(&pPatternSave->Lock);
  674. }
  675. else
  676. { // if (*ppPattern != pPatternSave)
  677. ProtocolStatInc(pProtocol->ProtocolTemplate,
  678. InsertedPH);
  679. //
  680. // it's a new pattern -
  681. // first we need to create a CB and update the pattern and
  682. // the blob entries
  683. //
  684. REFADD(&pPatternSave->RefCount, 'ADSP');
  685. pCB = CreateNewClassificationBlock(GPC_CF_MAX);
  686. //
  687. // This is a specific pattern, so we'll add the classification
  688. // handle for future use
  689. //
  690. WRITE_LOCK(&glData.ChLock, &irql);
  691. *pCH = (HFHandle)assign_HF_handle(
  692. glData.pCHTable,
  693. (void *)pCB
  694. );
  695. ProtocolStatInc(pProtocol->ProtocolTemplate,
  696. InsertedCH);
  697. WRITE_UNLOCK(&glData.ChLock, irql);
  698. if (pCB && *pCH) {
  699. TRACE(CLASSHAND, pCB, pCB->ClassificationHandle, "AddSpecificPattern (CH+)");
  700. //
  701. // got the CB, update the pattern
  702. //
  703. pCB->arpBlobBlock[CfIndex] = pBlob;
  704. GetBlobFromPattern(pPatternSave, CfIndex) = pBlob;
  705. pPatternSave->pClientBlock = pClient;
  706. pPatternSave->pClassificationBlock = pCB;
  707. pPatternSave->DbCtx = (PVOID)SpHandle;
  708. pCB->ClassificationHandle = *pCH;
  709. TRACE(PATTERN, pPatternSave, pBlob, "AddSpecificPattern(3)");
  710. TRACE(PATTERN, pPatternSave, SpHandle, "AddSpecificPattern: DbCtx");
  711. pPatternSave->State = GPC_STATE_READY;
  712. if (pBlob != NULL) {
  713. //
  714. // Reason for not using the Blob->Lock anymore -
  715. // The lock is taken at teh start of this function.
  716. // (only to maintain the order in which locks are taken/released.
  717. GpcInsertTailList
  718. (&pBlob->PatternList,
  719. &pPatternSave->BlobLinkage[CfIndex]
  720. );
  721. }
  722. ASSERT(pCf);
  723. if (pProtocol->GenericPatternCount) {
  724. //
  725. // a new pattern has been created in the specific db.
  726. // the CB associated with it needs to be updated for each
  727. // CF entry (except the one we've already updated now)
  728. // we'll loop through the CF enlisted and find a match
  729. // for the specific pattern in each generic db.
  730. //
  731. pHead = &glData.CfList;
  732. pEntry = pHead->Flink;
  733. while (pEntry != pHead) {
  734. //
  735. // loop through the registered CF's
  736. //
  737. pCf = CONTAINING_RECORD(pEntry, CF_BLOCK, Linkage);
  738. pEntry = pEntry->Flink;
  739. if (pCf->AssignedIndex != CfIndex || pBlob == NULL) {
  740. //
  741. // skip the current CF only if this client installed
  742. // a CfInfo
  743. //
  744. pGenericDb = pCf->arpGenericDb[pProtocol->ProtocolTemplate];
  745. ASSERT(pGenericDb);
  746. for (i = 0, pPatternSave = NULL;
  747. i < pCf->MaxPriorities && pPatternSave == NULL;
  748. i++, pGenericDb++) {
  749. //
  750. // scan each priority Rhizome
  751. //
  752. READ_LOCK(&pGenericDb->Lock, &ReadIrql);
  753. GpHandle = searchRhizome(pGenericDb->pRhizome,
  754. pPatternBits);
  755. if (GpHandle != NULL) {
  756. pPatternSave = (PPATTERN_BLOCK)GetReferenceFromPatternHandle(GpHandle);
  757. REFADD(&pPatternSave->RefCount, 'ADSP');
  758. }
  759. READ_UNLOCK(&pGenericDb->Lock, ReadIrql);
  760. }
  761. if (pPatternSave != NULL) {
  762. //
  763. // found a generic match, get the reference
  764. // which is a pointer to a pattern and get the
  765. // blob pointer from it.
  766. //
  767. pCB->arpBlobBlock[pCf->AssignedIndex] =
  768. GetBlobFromPattern(pPatternSave,pCf->AssignedIndex);
  769. REFDEL(&pPatternSave->RefCount, 'ADSP');
  770. } else {
  771. //
  772. // no generic pattern matches this specific one
  773. //
  774. pCB->arpBlobBlock[pCf->AssignedIndex] = NULL;
  775. }
  776. TRACE(PATTERN, pPatternSave, pCB->arpBlobBlock[pCf->AssignedIndex], "AddSpecificPattern(4)");
  777. }
  778. } // while (pEntry != pHead)
  779. } // if (pProtocol->GenericPatternCount)
  780. } else { // if (pCB)
  781. //
  782. // remove from pathash table!! (#321509)
  783. //
  784. removePatHashTable(
  785. pSpecificDb->pDb,
  786. SpHandle
  787. );
  788. REFDEL(&pPatternSave->RefCount, 'ADSP');
  789. if (pCB) {
  790. ReleaseClassificationBlock(pCB);
  791. }
  792. if (*pCH) {
  793. FreeClassificationHandle(pClient,
  794. *pCH
  795. );
  796. }
  797. Status = GPC_STATUS_RESOURCES;
  798. }
  799. }
  800. }
  801. else
  802. Status = GPC_STATUS_RESOURCES;
  803. }
  804. else
  805. Status=GPC_STATUS_RESOURCES;
  806. //
  807. // release the specific db lock
  808. //
  809. WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  810. //
  811. // Since we want to take the blob lock and specific DB lock
  812. // in the same order everywhere, release the blob lock after
  813. // the specific DB lock. GPCEnumCfInfo does the same.
  814. //
  815. if (pBlob) {
  816. NDIS_UNLOCK(&pBlob->Lock);
  817. }
  818. //
  819. // set output parameters:
  820. // ppPattern should have been set by now
  821. //
  822. TRACE(PATTERN, *ppPattern, Status, "AddSpecificPattern==>");
  823. return Status;
  824. }
  825. /*
  826. ************************************************************************
  827. HandleFragment -
  828. Handle an IP fragment.
  829. Arguments
  830. pClient -
  831. bFirstFrag -
  832. bLastFrag -
  833. Retu
  834. GPC_STATUS
  835. ************************************************************************
  836. */
  837. GPC_STATUS
  838. HandleFragment(
  839. IN PCLIENT_BLOCK pClient,
  840. IN PPROTOCOL_BLOCK pProtocol,
  841. IN BOOLEAN bFirstFrag,
  842. IN BOOLEAN bLastFrag,
  843. IN ULONG PacketId,
  844. IN OUT PPATTERN_BLOCK *ppPatternBlock,
  845. OUT PBLOB_BLOCK *ppBlob
  846. )
  847. {
  848. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  849. PFRAGMENT_DB pFragDb;
  850. SpecificPatternHandle SpHandle;
  851. KIRQL ReadIrql;
  852. KIRQL WriteIrql;
  853. KIRQL CHirql;
  854. ASSERT(ppPatternBlock);
  855. ASSERT(ppBlob);
  856. TRACE(CLASSIFY, PacketId, bFirstFrag, "HandleFragment: PacketId, bFirstFrag");
  857. TRACE(CLASSIFY, PacketId, bLastFrag, "HandleFragment: PacketId, bLastFrag");
  858. pFragDb = (PFRAGMENT_DB)pProtocol->pProtocolDb;
  859. if (bFirstFrag) {
  860. //
  861. // add an entry to the hash table
  862. //
  863. WRITE_LOCK(&pFragDb->Lock, &WriteIrql);
  864. SpHandle = insertPatHashTable(
  865. pFragDb->pDb,
  866. (char *)&PacketId,
  867. PacketId,
  868. (void *)*ppPatternBlock
  869. );
  870. WRITE_UNLOCK(&pFragDb->Lock, WriteIrql);
  871. ProtocolStatInc(pProtocol->ProtocolTemplate,
  872. FirstFragsCount);
  873. } else {
  874. //
  875. // search for it
  876. //
  877. READ_LOCK(&pFragDb->Lock, &ReadIrql);
  878. SpHandle = searchPatHashTable(
  879. pFragDb->pDb,
  880. (char *)&PacketId,
  881. PacketId);
  882. if (SpHandle) {
  883. *ppPatternBlock = GetReferenceFromSpecificPatternHandle(SpHandle);
  884. READ_UNLOCK(&pFragDb->Lock, ReadIrql);
  885. //NdisInterlockedIncrement(&(*ppPatternBlock)->RefCount);
  886. if (bLastFrag) {
  887. //
  888. // remove the entry from the hash table
  889. //
  890. WRITE_LOCK(&pFragDb->Lock, &WriteIrql);
  891. removePatHashTable(pFragDb->pDb, SpHandle);
  892. WRITE_UNLOCK(&pFragDb->Lock, WriteIrql);
  893. ProtocolStatInc(pProtocol->ProtocolTemplate,
  894. LastFragsCount);
  895. }
  896. } else {
  897. //
  898. // not found
  899. //
  900. READ_UNLOCK(&pFragDb->Lock, ReadIrql);
  901. *ppPatternBlock = NULL;
  902. *ppBlob = NULL;
  903. Status = GPC_STATUS_NOT_FOUND;
  904. }
  905. }
  906. if (Status == GPC_STATUS_SUCCESS) {
  907. ASSERT(*ppPatternBlock);
  908. if (TEST_BIT_ON((*ppPatternBlock)->Flags, PATTERN_SPECIFIC)) {
  909. //
  910. // specific pattern, lookup throught the CH
  911. //
  912. READ_LOCK(&glData.ChLock, &CHirql);
  913. *ppBlob = (PBLOB_BLOCK)dereference_HF_handle_with_cb(
  914. glData.pCHTable,
  915. (*ppPatternBlock)->pClassificationBlock->ClassificationHandle,
  916. pClient->pCfBlock->AssignedIndex);
  917. READ_UNLOCK(&glData.ChLock, CHirql);
  918. } else {
  919. //
  920. // generic pattern, get the blob ptr directly
  921. //
  922. *ppBlob = GetBlobFromPattern((*ppPatternBlock),
  923. pClient->pCfBlock->AssignedIndex);
  924. }
  925. DBGPRINT(CLASSIFY, ("HandleFragment: Pattern=%X Blob=%X\n",
  926. *ppPatternBlock, *ppBlob));
  927. }
  928. TRACE(CLASSIFY, *ppPatternBlock, *ppBlob, "HandleFragment==>");
  929. return Status;
  930. }
  931. /*
  932. ************************************************************************
  933. InternalSearchPattern -
  934. Arguments
  935. Returns
  936. matched pattern or NULL for none
  937. ************************************************************************
  938. */
  939. NTSTATUS
  940. InternalSearchPattern(
  941. IN PCLIENT_BLOCK pClientBlock,
  942. IN PPROTOCOL_BLOCK pProtocol,
  943. IN PVOID pPatternKey,
  944. OUT PPATTERN_BLOCK *pPatternBlock,
  945. OUT PCLASSIFICATION_HANDLE pClassificationHandle,
  946. IN BOOLEAN bNoCache
  947. )
  948. {
  949. PSPECIFIC_PATTERN_DB pSpecificDb;
  950. PGENERIC_PATTERN_DB pGenericDb;
  951. PatternHandle GpHandle;
  952. SpecificPatternHandle SpHandle;
  953. PPATTERN_BLOCK pPattern;
  954. PCF_BLOCK pCf;
  955. int i;
  956. KIRQL ReadIrql;
  957. NTSTATUS Status;
  958. TRACE(CLASSIFY, pClientBlock, pPatternKey, "InternalSearchPattern:");
  959. DBGPRINT(CLASSIFY, ("InternalSearchPattern: Client=%X \n", pClientBlock));
  960. Status = GPC_STATUS_SUCCESS;
  961. //
  962. // start with the specific db
  963. //
  964. pSpecificDb = &pProtocol->SpecificDb;
  965. READ_LOCK(&pSpecificDb->Lock, &ReadIrql);
  966. pCf = pClientBlock->pCfBlock;
  967. SpHandle = searchPatHashTable(
  968. pSpecificDb->pDb,
  969. (char *)pPatternKey,
  970. GpcCalcHash(pProtocol->ProtocolTemplate,
  971. pPatternKey)
  972. );
  973. if (SpHandle) {
  974. pPattern = (PPATTERN_BLOCK)GetReferenceFromSpecificPatternHandle(SpHandle);
  975. //NdisInterlockedIncrement(&pPattern->RefCount);
  976. *pClassificationHandle =
  977. (CLASSIFICATION_HANDLE)pPattern->pClassificationBlock->ClassificationHandle;
  978. TRACE(CLASSIFY, pClientBlock, *pClassificationHandle, "InternalSearchPattern (2)" );
  979. } else {
  980. pPattern = NULL;
  981. *pClassificationHandle = 0;
  982. }
  983. READ_UNLOCK(&pSpecificDb->Lock, ReadIrql);
  984. if (pPattern == NULL) {
  985. if (bNoCache) {
  986. Status = GPC_STATUS_FAILURE;
  987. } else {
  988. //
  989. // no specific pattern, add an automagic one
  990. //
  991. Status = AddSpecificPatternWithTimer(
  992. pClientBlock,
  993. pProtocol->ProtocolTemplate,
  994. pPatternKey,
  995. &pPattern,
  996. pClassificationHandle
  997. );
  998. DBGPRINT(CLASSIFY, ("InternalSearchPattern: Client=%X installed Pattern=%X\n",
  999. pClientBlock, pPattern));
  1000. }
  1001. if (!NT_SUCCESS(Status)) {
  1002. //
  1003. // not found, search each generic db
  1004. //
  1005. for (i = 0; i < (int)pCf->MaxPriorities && pPattern == NULL; i++) {
  1006. //
  1007. // scan each priority Rhizome
  1008. //
  1009. pGenericDb = &pCf->arpGenericDb[pProtocol->ProtocolTemplate][i];
  1010. READ_LOCK(&pGenericDb->Lock, &ReadIrql);
  1011. GpHandle = searchRhizome(pGenericDb->pRhizome, pPatternKey);
  1012. if (GpHandle != NULL) {
  1013. pPattern = (PPATTERN_BLOCK)GetReferenceFromPatternHandle(GpHandle);
  1014. //NdisInterlockedIncrement(&pPattern->RefCount);
  1015. }
  1016. READ_UNLOCK(&pGenericDb->Lock, ReadIrql);
  1017. }
  1018. // we had to search manually, make sure we know this in the main code.
  1019. *pClassificationHandle = 0;
  1020. }
  1021. DBGPRINT(CLASSIFY, ("InternalSearchPattern: Client=%X Generic Pattern=%X\n",
  1022. pClientBlock, pPattern));
  1023. }
  1024. TRACE(CLASSIFY, pPattern, *pClassificationHandle, "InternalSearchPattern==>");
  1025. DBGPRINT(CLASSIFY, ("InternalSearchPattern: Client=%X returned Pattern=%X\n",
  1026. pClientBlock, pPattern));
  1027. *pPatternBlock = pPattern;
  1028. return Status;
  1029. }
  1030. GPC_STATUS
  1031. InitFragmentDb(
  1032. IN PFRAGMENT_DB *ppFragDb
  1033. )
  1034. {
  1035. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  1036. PFRAGMENT_DB pDb;
  1037. ULONG Len, i;
  1038. TRACE(INIT, ppFragDb, 0, "InitFragmentDb");
  1039. ASSERT(ppFragDb);
  1040. //
  1041. // init the pattern db struct
  1042. // call the PH init routine
  1043. //
  1044. GpcAllocMem(ppFragDb, sizeof(FRAGMENT_DB), FragmentDbTag);
  1045. if (pDb = *ppFragDb) {
  1046. INIT_LOCK(&pDb->Lock);
  1047. AllocatePatHashTable(pDb->pDb);
  1048. if (pDb->pDb != NULL) {
  1049. constructPatHashTable(pDb->pDb,
  1050. sizeof(ULONG),
  1051. 2, // usage_ratio,
  1052. 1, // usage_histeresis,
  1053. 1, // allocation_histeresis,
  1054. 16 // max_free_list_size
  1055. );
  1056. } else {
  1057. GpcFreeMem (*ppFragDb, FragmentDbTag);
  1058. Status = GPC_STATUS_RESOURCES;
  1059. }
  1060. } else {
  1061. Status = GPC_STATUS_RESOURCES;
  1062. }
  1063. TRACE(INIT, Status, 0, "InitFragmentDb==>");
  1064. return Status;
  1065. }
  1066. GPC_STATUS
  1067. UninitFragmentDb(
  1068. IN PFRAGMENT_DB pFragDb
  1069. )
  1070. {
  1071. destructPatHashTable (pFragDb->pDb);
  1072. FreePatHashTable(pFragDb->pDb);
  1073. GpcFreeMem (pFragDb, FragmentDbTag);
  1074. return STATUS_SUCCESS;
  1075. }
  1076. /*
  1077. ************************************************************************
  1078. RemoveSpecificPattern -
  1079. Remove a specific pattern from the db.
  1080. Arguments
  1081. pClient -
  1082. pPattern -
  1083. Returns
  1084. GPC_STATUS
  1085. ************************************************************************
  1086. */
  1087. GPC_STATUS
  1088. RemoveSpecificPattern(
  1089. IN PCLIENT_BLOCK pClient,
  1090. IN PPROTOCOL_BLOCK pProtocol,
  1091. IN PPATTERN_BLOCK pPattern,
  1092. IN BOOLEAN ForceRemoval,
  1093. IN BOOLEAN DbLocked
  1094. )
  1095. {
  1096. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  1097. PSPECIFIC_PATTERN_DB pSpecificDb;
  1098. PatternHandle GpHandle;
  1099. PPATTERN_BLOCK pGp;
  1100. int i;
  1101. PBLOB_BLOCK pBlob, pNewBlob;
  1102. PGENERIC_PATTERN_DB pGenericDb;
  1103. KIRQL ReadIrql;
  1104. KIRQL WriteIrql;
  1105. ULONG ProtocolTemplate;
  1106. KIRQL irql;
  1107. LONG cClientRef;
  1108. BOOLEAN bRemoveLinks = FALSE;
  1109. GPC_HANDLE ClHandle = NULL;
  1110. TRACE(PATTERN, pClient, pPattern, "RemoveSpecificPattern");
  1111. //
  1112. // get the specific db pointer
  1113. //
  1114. pSpecificDb = &pProtocol->SpecificDb;
  1115. ASSERT(pSpecificDb);
  1116. ProtocolTemplate = pProtocol->ProtocolTemplate;
  1117. // The plan: Remove the DbCtx (from the Specific pattern structure)
  1118. // from teh Pathash table with the Specific Db Lock held. This
  1119. // will ensure that if the same pattern is being added, the pathash
  1120. // table will accept the new one instead of bumping up the ref on what
  1121. // we are trying to delete now.
  1122. //
  1123. NDIS_LOCK(&pPattern->Lock);
  1124. // If Database is not already locked
  1125. if (!DbLocked)
  1126. WRITE_LOCK(&pSpecificDb->Lock, &WriteIrql);
  1127. cClientRef = NdisInterlockedDecrement(&pPattern->ClientRefCount);
  1128. if (pPattern->State != GPC_STATE_DELETE) {
  1129. ASSERT(cClientRef >= 0);
  1130. ASSERT(pPattern->DbCtx);
  1131. if (0 == cClientRef) {
  1132. pPattern->State = GPC_STATE_DELETE;
  1133. removePatHashTable(
  1134. pSpecificDb->pDb,
  1135. (SpecificPatternHandle)pPattern->DbCtx
  1136. );
  1137. pPattern->DbCtx = NULL;
  1138. // If Database was not locked before this function was called
  1139. if (!DbLocked)
  1140. WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  1141. NDIS_UNLOCK(&pPattern->Lock);
  1142. ReadySpecificPatternForDeletion(
  1143. pClient,
  1144. pProtocol,
  1145. pPattern,
  1146. DbLocked
  1147. );
  1148. } else if (cClientRef > 0) {
  1149. if (!DbLocked)
  1150. {
  1151. // If Database was not locked before this function was called
  1152. WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  1153. }
  1154. NDIS_UNLOCK(&pPattern->Lock);
  1155. ClientRefsExistForSpecificPattern(
  1156. pClient,
  1157. pProtocol,
  1158. pPattern,
  1159. DbLocked
  1160. );
  1161. } else {
  1162. // we shouldn't be getting here - really.
  1163. // If Database was not locked before this function was called
  1164. if (!DbLocked)
  1165. WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  1166. NDIS_UNLOCK(&pPattern->Lock);
  1167. }
  1168. } else {
  1169. // If Database was not locked before this function was called
  1170. if (!DbLocked)
  1171. WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  1172. NDIS_UNLOCK(&pPattern->Lock);
  1173. }
  1174. TRACE(PATTERN, pPattern, Status, "RemoveSpecificPattern==>");
  1175. return Status;
  1176. }
  1177. /*
  1178. ************************************************************************
  1179. ReadySpecificPatternForDeletion -
  1180. Remove a specific pattern from the db.
  1181. Arguments
  1182. pClient -
  1183. pPattern -
  1184. Returns
  1185. GPC_STATUS
  1186. ************************************************************************
  1187. */
  1188. VOID
  1189. ReadySpecificPatternForDeletion(
  1190. IN PCLIENT_BLOCK pClient,
  1191. IN PPROTOCOL_BLOCK pProtocol,
  1192. IN PPATTERN_BLOCK pPattern,
  1193. IN BOOLEAN DbLocked
  1194. )
  1195. {
  1196. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  1197. PSPECIFIC_PATTERN_DB pSpecificDb;
  1198. PatternHandle GpHandle;
  1199. PPATTERN_BLOCK pGp;
  1200. PCF_BLOCK pCf;
  1201. PCLASSIFICATION_BLOCK pCB;
  1202. int i;
  1203. ULONG CfIndex;
  1204. PBLOB_BLOCK pBlob, pNewBlob;
  1205. PGENERIC_PATTERN_DB pGenericDb;
  1206. KIRQL ReadIrql;
  1207. KIRQL WriteIrql;
  1208. ULONG ProtocolTemplate;
  1209. KIRQL irql;
  1210. PVOID Key;
  1211. LONG cClientRef;
  1212. BOOLEAN bRemoveLinks = FALSE;
  1213. GPC_HANDLE ClHandle = NULL;
  1214. TRACE(PATTERN, pClient, pPattern, "ReadySpecificPatternForDeletion");
  1215. //
  1216. // get the specific db pointer
  1217. //
  1218. pSpecificDb = &pProtocol->SpecificDb;
  1219. ASSERT(pSpecificDb);
  1220. pCf = pClient->pCfBlock;
  1221. CfIndex = pCf->AssignedIndex;
  1222. pCB = pPattern->pClassificationBlock;
  1223. ProtocolTemplate = pProtocol->ProtocolTemplate;
  1224. Key = GetKeyPtrFromSpecificPatternHandle(((SpecificPatternHandle)pPattern->DbCtx));
  1225. ASSERT(pCB);
  1226. //
  1227. // Remove the ClHandle, so that if we are coming back in via a
  1228. // user mode ioctl, we wont try to remove it again.
  1229. //
  1230. ClHandle = (HANDLE) LongToPtr(InterlockedExchange((PLONG32)&pPattern->ClHandle, 0));
  1231. if (ClHandle) {
  1232. FreeHandle(ClHandle);
  1233. }
  1234. //
  1235. // Remove the pattern from the blobs linked list.
  1236. ClearPatternLinks(pPattern, pProtocol, CfIndex);
  1237. //
  1238. // We are going to access the Specific DB now, lock it NOW.
  1239. // This should fix deadlock 248352 [ShreeM]
  1240. //
  1241. // If the database is not already locked
  1242. if (!DbLocked)
  1243. WRITE_LOCK(&pSpecificDb->Lock, &WriteIrql);
  1244. //
  1245. // this is the last client that holds the pattern,
  1246. // we need to take the pattern off the specific db
  1247. //
  1248. TRACE(PATTERN, pPattern, pPattern->DbCtx, "ReadySpecificPatternForDeletion: DbCtx");
  1249. ASSERT(!pPattern->DbCtx);
  1250. ProtocolStatInc(ProtocolTemplate,
  1251. RemovedPH);
  1252. //
  1253. // free the classification handle -
  1254. // this must come *before* we free the classification block
  1255. // since it may be referenced by other clients
  1256. //
  1257. TRACE(PATTERN, pCB, CfIndex, "ReadySpecificPatternForDeletion: (2)");
  1258. FreeClassificationHandle(
  1259. pClient,
  1260. (CLASSIFICATION_HANDLE)pCB->ClassificationHandle
  1261. );
  1262. ProtocolStatInc(ProtocolTemplate,
  1263. RemovedCH);
  1264. // If the database is not already locked
  1265. if (!DbLocked)
  1266. WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  1267. //
  1268. // bye bye pattern, at least for this client
  1269. //
  1270. REFDEL(&pPattern->RefCount, 'ADSP');
  1271. TRACE(PATTERN, pClient, pPattern, "ReadySpecificPatternForDeletion--------->");
  1272. }
  1273. /*
  1274. ************************************************************************
  1275. ClientRefsExistForSpecificPattern -
  1276. Arguments
  1277. pClient -
  1278. pPattern -
  1279. Returns
  1280. GPC_STATUS
  1281. ************************************************************************
  1282. */
  1283. VOID
  1284. ClientRefsExistForSpecificPattern(
  1285. IN PCLIENT_BLOCK pClient,
  1286. IN PPROTOCOL_BLOCK pProtocol,
  1287. IN PPATTERN_BLOCK pPattern,
  1288. IN BOOLEAN dbLocked
  1289. )
  1290. {
  1291. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  1292. PSPECIFIC_PATTERN_DB pSpecificDb;
  1293. PatternHandle GpHandle;
  1294. PPATTERN_BLOCK pGp;
  1295. PCF_BLOCK pCf;
  1296. PCLASSIFICATION_BLOCK pCB;
  1297. int i;
  1298. ULONG CfIndex;
  1299. PBLOB_BLOCK pBlob, pNewBlob;
  1300. PGENERIC_PATTERN_DB pGenericDb;
  1301. KIRQL ReadIrql;
  1302. KIRQL WriteIrql;
  1303. ULONG ProtocolTemplate;
  1304. KIRQL irql;
  1305. PVOID Key;
  1306. LONG cClientRef;
  1307. BOOLEAN bRemoveLinks = FALSE;
  1308. GPC_HANDLE ClHandle = NULL;
  1309. TRACE(PATTERN, pClient, pPattern, "ClientRefsExistForSpecificPattern");
  1310. //
  1311. // get the specific db pointer
  1312. //
  1313. pSpecificDb = &pProtocol->SpecificDb;
  1314. ASSERT(pSpecificDb);
  1315. pCf = pClient->pCfBlock;
  1316. CfIndex = pCf->AssignedIndex;
  1317. pCB = pPattern->pClassificationBlock;
  1318. ProtocolTemplate = pProtocol->ProtocolTemplate;
  1319. Key = GetKeyPtrFromSpecificPatternHandle(((SpecificPatternHandle)pPattern->DbCtx));
  1320. ASSERT(pCB);
  1321. //
  1322. // reference count > 0
  1323. //
  1324. pBlob = pCB->arpBlobBlock[CfIndex];
  1325. TRACE(PATTERN, pPattern, pBlob, "ClientRefsExistForSpecificPattern (2)");
  1326. //
  1327. // We are going to access the Specific DB now, lock it NOW.
  1328. // This should fix deadlock 248352 [ShreeM]
  1329. //
  1330. if (!dbLocked)
  1331. {
  1332. WRITE_LOCK(&pSpecificDb->Lock, &WriteIrql);
  1333. }
  1334. if (pBlob
  1335. &&
  1336. ((pBlob->pOwnerClient == pClient) ||
  1337. TEST_BIT_ON(pBlob->Flags, PATTERN_REMOVE_CB_BLOB))) {
  1338. bRemoveLinks = TRUE;
  1339. pNewBlob = NULL;
  1340. TRACE(PATTERN, pCB, CfIndex, "ClientRefsExistForSpecificPattern (3)");
  1341. //
  1342. // search the generic db for the same CF, since there is an open slot,
  1343. // some other generic pattern might fill it with its own blob pointer
  1344. //
  1345. pGenericDb = pCf->arpGenericDb[ProtocolTemplate];
  1346. ASSERT(pGenericDb);
  1347. for (i = 0, pGp = NULL;
  1348. i < (int)pCf->MaxPriorities && pGp == NULL;
  1349. i++) {
  1350. //
  1351. // scan each priority Rhizome
  1352. //
  1353. READ_LOCK(&pGenericDb->Lock, &ReadIrql);
  1354. GpHandle = searchRhizome(pGenericDb->pRhizome, Key);
  1355. if (GpHandle != NULL) {
  1356. //
  1357. // found a generic pattern that match this specific one.
  1358. //
  1359. pGp = (PPATTERN_BLOCK)GetReferenceFromPatternHandle(GpHandle);
  1360. pNewBlob = GetBlobFromPattern(pGp, CfIndex);
  1361. }
  1362. READ_UNLOCK(&pGenericDb->Lock, ReadIrql);
  1363. pGenericDb++;
  1364. }
  1365. //
  1366. // update the classification block entry
  1367. //
  1368. WRITE_LOCK(&glData.ChLock, &irql);
  1369. pCB->arpBlobBlock[CfIndex] = pNewBlob;
  1370. WRITE_UNLOCK(&glData.ChLock, irql);
  1371. TRACE(PATTERN, pGp,
  1372. pCB->arpBlobBlock[CfIndex],
  1373. "ClientRefsExistForSpecificPattern (4)");
  1374. }
  1375. //
  1376. // must first release this lock to avoid dead lock
  1377. // when aquiring the Blob lock
  1378. //
  1379. if (!dbLocked)
  1380. {
  1381. WRITE_UNLOCK(&pSpecificDb->Lock, WriteIrql);
  1382. }
  1383. // For Autopatterns pBlob = NULL
  1384. // Hence bRemoveLinks = FALSE
  1385. // So we would not be acessing the client block
  1386. if (bRemoveLinks) {
  1387. //
  1388. // remove the pattern from any linked list
  1389. //
  1390. ClearPatternLinks(pPattern, pProtocol, CfIndex);
  1391. ASSERT(CfIndex == pBlob->pOwnerClient->pCfBlock->AssignedIndex);
  1392. GetBlobFromPattern(pPattern, CfIndex) = NULL;
  1393. }
  1394. REFDEL(&pPattern->RefCount, 'ADSP');
  1395. TRACE(PATTERN, pClient, pPattern, "ClientRefsExistForSpecificPattern---->");
  1396. }
  1397. /*
  1398. ************************************************************************
  1399. RemoveGenericPattern -
  1400. Remove a generic pattern from the db.
  1401. Arguments
  1402. pClient -
  1403. pPattern -
  1404. Returns
  1405. GPC_STATUS
  1406. ************************************************************************
  1407. */
  1408. GPC_STATUS
  1409. RemoveGenericPattern(
  1410. IN PCLIENT_BLOCK pClient,
  1411. IN PPROTOCOL_BLOCK pProtocol,
  1412. IN PPATTERN_BLOCK pPattern
  1413. )
  1414. {
  1415. GPC_STATUS Status = GPC_STATUS_SUCCESS;
  1416. PSPECIFIC_PATTERN_DB pSpecificDb;
  1417. PGENERIC_PATTERN_DB pGenericDb;
  1418. PCF_BLOCK pCf;
  1419. SCAN_STRUCT ScanStruct;
  1420. UCHAR PatternBits[MAX_PATTERN_SIZE];
  1421. UCHAR MaskBits[MAX_PATTERN_SIZE];
  1422. ULONG i;
  1423. KIRQL ReadIrql;
  1424. KIRQL WriteIrql;
  1425. GPC_HANDLE ClHandle = NULL;
  1426. TRACE(PATTERN, pPattern, pPattern->DbCtx, "RemoveGenericPattern");
  1427. ASSERT(MAX_PATTERN_SIZE >= sizeof(GPC_IP_PATTERN));
  1428. ASSERT(MAX_PATTERN_SIZE >= sizeof(GPC_IPX_PATTERN));
  1429. //
  1430. // Remove the ClHandle, so that if we are coming back in via a
  1431. // user mode ioctl, we wont try to remove it again.
  1432. //
  1433. ClHandle = (HANDLE) LongToPtr(InterlockedExchange((PLONG32)&pPattern->ClHandle, 0));
  1434. if (ClHandle) {
  1435. FreeHandle(ClHandle);
  1436. }
  1437. pCf = pClient->pCfBlock;
  1438. ScanStruct.Priority = pPattern->Priority;
  1439. ScanStruct.pClientBlock = pClient;
  1440. ScanStruct.pPatternBlock = pPattern;
  1441. ScanStruct.pBlobBlock = GetBlobFromPattern(pPattern, pCf->AssignedIndex);
  1442. ScanStruct.bRemove = TRUE;
  1443. //
  1444. // get the specific db pointer
  1445. //
  1446. pSpecificDb = &pProtocol->SpecificDb;
  1447. ASSERT(pSpecificDb);
  1448. pGenericDb = &pCf->arpGenericDb[pProtocol->ProtocolTemplate][pPattern->Priority];
  1449. ASSERT(pGenericDb);
  1450. // Lock the Pattern
  1451. // Check it's State
  1452. // Set the State if not set to REMOVE
  1453. // return if state already set to REMOVE
  1454. NDIS_LOCK(&pPattern->Lock);
  1455. if (pPattern->State==GPC_STATE_REMOVE)
  1456. {
  1457. NDIS_UNLOCK(&pPattern->Lock);
  1458. return Status;
  1459. }
  1460. else{
  1461. pPattern->State = GPC_STATE_REMOVE;
  1462. NDIS_UNLOCK(&pPattern->Lock);
  1463. }
  1464. //
  1465. // remove the pattern from any linked list
  1466. //
  1467. ClearPatternLinks(pPattern, pProtocol, pCf->AssignedIndex);
  1468. //
  1469. // copy the pattern key and mask for searching later
  1470. //
  1471. NDIS_LOCK(&pPattern->Lock);
  1472. WRITE_LOCK(&pGenericDb->Lock, &WriteIrql);
  1473. ASSERT(pPattern->DbCtx);
  1474. NdisMoveMemory(PatternBits,
  1475. GetKeyPtrFromPatternHandle(pGenericDb->pRhizome,
  1476. pPattern->DbCtx),
  1477. GetKeySizeBytes(pGenericDb->pRhizome)
  1478. );
  1479. NdisMoveMemory(MaskBits,
  1480. GetMaskPtrFromPatternHandle(pGenericDb->pRhizome,
  1481. pPattern->DbCtx),
  1482. GetKeySizeBytes(pGenericDb->pRhizome)
  1483. );
  1484. //
  1485. // remove the pattern from generic db
  1486. //
  1487. removeRhizome(pGenericDb->pRhizome,
  1488. (PatternHandle)pPattern->DbCtx
  1489. );
  1490. ProtocolStatInc(pProtocol->ProtocolTemplate,
  1491. RemovedRz);
  1492. //
  1493. // This is no longer valid
  1494. //
  1495. pPattern->DbCtx = NULL;
  1496. WRITE_UNLOCK(&pGenericDb->Lock, WriteIrql);
  1497. NDIS_UNLOCK(&pPattern->Lock);
  1498. //
  1499. // the generic pattern has been removed,
  1500. //
  1501. READ_LOCK(&pSpecificDb->Lock, &ReadIrql);
  1502. //
  1503. // this will do the rest of the work...
  1504. //
  1505. scanPatHashTable(
  1506. pSpecificDb->pDb,
  1507. (char *)PatternBits,
  1508. (char *)MaskBits,
  1509. (PVOID)&ScanStruct,
  1510. GpcSpecificCallback // see callback routine...
  1511. );
  1512. READ_UNLOCK(&pSpecificDb->Lock, ReadIrql);
  1513. //
  1514. // time to go to the big hunting fields....
  1515. //
  1516. REFDEL(&pPattern->RefCount, 'ADGP');
  1517. TRACE(PATTERN, pPattern, Status, "RemoveGenericPattern==>");
  1518. return Status;
  1519. }