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.

777 lines
20 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1997, Microsoft Corporation.
  4. //
  5. // File: ipsup.c
  6. //
  7. // Contents: Support routines for managing DFS_IP_INFO entries and
  8. // DFS_IP_PENDING_INFO entries
  9. //
  10. // Functions: DfsInitIp - Initialize the hash table for DFS_IP_INFO lookup
  11. // DfsLookupIpInfo - Lookup a DFS_IP_INFO
  12. // DfsAllocateIpInfo - Allocate a DFS_IP_INFO
  13. // DfsInsertIpInfo - Put a DFS_IP_INFO into the table
  14. // DfsDeleteIpInfo - Remove a DFS_IP_INFO from the table
  15. // DfsReleaseIpInfo - Stop using a DFS_IP_INFO
  16. //
  17. // DfsFsctrlCreateIpInfo - Load an IpInfo table entry
  18. // DfsFsctrlDeleteIpInfo - Remove an IpInfo table entry
  19. //
  20. // History: 16 Dec 1997 Jharper Created
  21. //
  22. //--------------------------------------------------------------------------
  23. #include "dfsprocs.h"
  24. #include "attach.h"
  25. #include "ipsup.h"
  26. #include "fsctrl.h"
  27. #include "dfslpc.h"
  28. #include "registry.h"
  29. #include "regkeys.h"
  30. #define Dbg 0x1000
  31. //
  32. // Manifest constants
  33. //
  34. #define IP_DEFAULT_HASH_SIZE 16 // default size of hash table
  35. #define IP_DEFAULT_NUMBER_ENTRIES 250 // default max # of entries
  36. #define IP_DEFAULT_TIMEOUT (60 * 60 * 24) // default time entry can live (in sec)
  37. NTSTATUS
  38. DfsInitIpInfoHashTable(
  39. IN ULONG cHash,
  40. OUT PIP_HASH_TABLE *ppHashTable
  41. );
  42. NTSTATUS
  43. DfsAllocateIpInfo(
  44. IN PDFS_IPADDRESS pDfsIpAddress,
  45. IN PUNICODE_STRING pSiteName,
  46. OUT PDFS_IP_INFO *ppIpInfo
  47. );
  48. VOID
  49. DfsInsertIpInfo(
  50. IN PDFS_IPADDRESS pDfsIpAddress,
  51. IN PDFS_IP_INFO pIpInfo
  52. );
  53. VOID
  54. DfsDeleteIpInfo(
  55. PDFS_IP_INFO pIpInfo
  56. );
  57. ULONG
  58. DfsHashIpAddress(
  59. IN PDFS_IPADDRESS pDfsIpAddress,
  60. IN DWORD HashMask
  61. );
  62. PDFS_IP_INFO
  63. DfsLookupIpInfo(
  64. IN PIP_HASH_TABLE pHashTable,
  65. IN PDFS_IPADDRESS pDfsIpAddress
  66. );
  67. #ifdef ALLOC_PRAGMA
  68. #pragma alloc_text(INIT, DfsInitIp)
  69. #pragma alloc_text(PAGE, DfsUninitIp)
  70. #pragma alloc_text(PAGE, DfsInitIpInfoHashTable)
  71. #pragma alloc_text(PAGE, DfsAllocateIpInfo)
  72. #pragma alloc_text(PAGE, DfsLookupIpInfo)
  73. #pragma alloc_text(PAGE, DfsInsertIpInfo)
  74. #pragma alloc_text(PAGE, DfsDeleteIpInfo)
  75. #pragma alloc_text(PAGE, DfsReleaseIpInfo)
  76. #pragma alloc_text(PAGE, DfsHashIpAddress)
  77. #pragma alloc_text(PAGE, DfsFsctrlCreateIpInfo)
  78. #pragma alloc_text(PAGE, DfsFsctrlDeleteIpInfo)
  79. #endif
  80. #ifdef DBG
  81. VOID
  82. DfsDumpIpTable(void);
  83. #endif
  84. //+-------------------------------------------------------------------------
  85. //
  86. // Function: DfsInitIpHashTable - Initialize the DFS_IP_INFO lookup hash table
  87. //
  88. // Synopsis: This function initializes data structures which are
  89. // used for looking up a DFS_IP_INFO associated with some IP address
  90. //
  91. // Arguments: [cHash] -- Size of the hash table to be allocated. Must be
  92. // a power of two. If zero, a default size is used.
  93. //
  94. // Returns: NTSTATUS -- STATUS_SUCCESS, unless memory allocation
  95. // fails.
  96. //
  97. // Note: The hash buckets are initialized to zero, then later
  98. // initialized to a list head when used. This is a debugging
  99. // aid to determine if some hash buckets are never used.
  100. //
  101. //--------------------------------------------------------------------------
  102. NTSTATUS
  103. DfsInitIpHashTable(
  104. ULONG cHash,
  105. ULONG cEntries,
  106. PIP_HASH_TABLE *ppHashTable)
  107. {
  108. PIP_HASH_TABLE pHashTable;
  109. ULONG cbHashTable;
  110. ULONG Timeout;
  111. NTSTATUS status;
  112. PBYTE pData;
  113. if (cHash == 0) {
  114. cHash = IP_DEFAULT_HASH_SIZE;
  115. }
  116. ASSERT ((cHash & (cHash-1)) == 0); // Assure cHash is a power of two
  117. if (cEntries == 0) {
  118. cEntries = IP_DEFAULT_NUMBER_ENTRIES;
  119. }
  120. cbHashTable = sizeof(IP_HASH_TABLE) + (cHash-1) * sizeof(LIST_ENTRY);
  121. pHashTable = ExAllocatePoolWithTag(NonPagedPool, cbHashTable, ' sfD');
  122. if (pHashTable == NULL) {
  123. return STATUS_NO_MEMORY;
  124. }
  125. pHashTable->NodeTypeCode = DFS_NTC_IP_HASH;
  126. pHashTable->NodeByteSize = (NODE_BYTE_SIZE) cbHashTable;
  127. pHashTable->MaxEntries = cEntries;
  128. pHashTable->EntryCount = 0;
  129. InitializeListHead(&pHashTable->LRUChain);
  130. pHashTable->HashMask = (cHash-1);
  131. ExInitializeFastMutex( &pHashTable->HashListMutex );
  132. RtlZeroMemory(&pHashTable->HashBuckets[0], cHash * sizeof(LIST_ENTRY));
  133. //
  134. // If there is a timeout override in the registry, get it
  135. //
  136. Timeout = IP_DEFAULT_TIMEOUT;
  137. status = KRegSetRoot(wszRegDfsDriver);
  138. if (NT_SUCCESS(status)) {
  139. status = KRegGetValue(
  140. L"",
  141. wszIpCacheTimeout,
  142. (PVOID ) &pData);
  143. KRegCloseRoot();
  144. if (NT_SUCCESS(status)) {
  145. Timeout = *((ULONG*)pData);
  146. ExFreePool(pData);
  147. }
  148. }
  149. pHashTable->Timeout.QuadPart = UInt32x32To64(
  150. Timeout,
  151. 10 * 1000 * 1000
  152. );
  153. *ppHashTable = pHashTable;
  154. return(STATUS_SUCCESS);
  155. }
  156. NTSTATUS
  157. DfsInitIp(
  158. ULONG cHash,
  159. ULONG cEntries)
  160. {
  161. NTSTATUS status;
  162. status = DfsInitIpHashTable( cHash, cEntries, &DfsData.IpHashTable );
  163. return status;
  164. }
  165. VOID
  166. DfsUninitIp(
  167. VOID
  168. )
  169. {
  170. ExFreePool (DfsData.IpHashTable);
  171. }
  172. //+-------------------------------------------------------------------------
  173. //
  174. // Function: DfsLookupIpInfo - Lookup a DFS_IP_INFO in the hash table
  175. //
  176. // Synopsis: This function will lookup a DFS_IP_INFO.
  177. // It will increment the UseCount on the DFS_IP_INFO.
  178. //
  179. // Arguments: [pDfsIpAddress] -- Ip address being looked up.
  180. //
  181. // Returns: PVOID -- pointer to the DFS_IP_INFO found, or NULL if none
  182. //
  183. //--------------------------------------------------------------------------
  184. PDFS_IP_INFO
  185. DfsLookupIpInfo(
  186. PIP_HASH_TABLE pHashTable,
  187. PDFS_IPADDRESS pDfsIpAddress)
  188. {
  189. PLIST_ENTRY pListHead, pLink;
  190. PDFS_IP_INFO pIpInfo;
  191. ExAcquireFastMutex( &pHashTable->HashListMutex);
  192. pListHead = &pHashTable->HashBuckets[DfsHashIpAddress(pDfsIpAddress,pHashTable->HashMask)];
  193. if ((pListHead->Flink == NULL) || // list not initialized
  194. (pListHead->Flink == pListHead)) { // list empty
  195. ExReleaseFastMutex( &pHashTable->HashListMutex );
  196. return NULL;
  197. }
  198. for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) {
  199. pIpInfo = CONTAINING_RECORD(pLink, DFS_IP_INFO, HashChain);
  200. if (pDfsIpAddress->IpFamily == pIpInfo->IpAddress.IpFamily
  201. &&
  202. pDfsIpAddress->IpLen == pIpInfo->IpAddress.IpLen
  203. &&
  204. RtlCompareMemory(
  205. pDfsIpAddress->IpData,
  206. pIpInfo->IpAddress.IpData,
  207. pDfsIpAddress->IpLen) == pDfsIpAddress->IpLen
  208. ) {
  209. RemoveEntryList(&pIpInfo->LRUChain);
  210. InsertHeadList(&pHashTable->LRUChain, &pIpInfo->LRUChain);
  211. pIpInfo->UseCount++;
  212. ExReleaseFastMutex( &pHashTable->HashListMutex );
  213. return pIpInfo;
  214. }
  215. }
  216. ExReleaseFastMutex( &pHashTable->HashListMutex);
  217. return NULL;
  218. }
  219. //+-------------------------------------------------------------------------
  220. //
  221. // Function: DfsInsertIpInfo - Inserts a DFS_IP_INFO into the hash table
  222. //
  223. // Synopsis: This function associates a DFS_IP_INFO with an Ip address. This
  224. // involves removing any existing entry, and adding the new.
  225. //
  226. // Arguments: [pDfsIpAddress] -- Pointer to the corresponding IpAddress, used
  227. // as the hash key.
  228. // [pIpInfo] -- Pointer to the DFS_IP_INFO to be inserted.
  229. //
  230. // Returns: -nothing-
  231. //
  232. //--------------------------------------------------------------------------
  233. VOID
  234. DfsInsertIpInfo(
  235. PDFS_IPADDRESS pDfsIpAddress,
  236. PDFS_IP_INFO pIpInfo)
  237. {
  238. PIP_HASH_TABLE pHashTable = (PIP_HASH_TABLE) DfsData.IpHashTable;
  239. PLIST_ENTRY pListHead;
  240. PDFS_IP_INFO pExistingIpInfo;
  241. PDFS_IP_INFO pTailIpInfo;
  242. LARGE_INTEGER now;
  243. pExistingIpInfo = DfsLookupIpInfo(pHashTable, &pIpInfo->IpAddress);
  244. //
  245. // Put the new one in
  246. //
  247. ExAcquireFastMutex( &pHashTable->HashListMutex);
  248. pListHead = &pHashTable->HashBuckets[DfsHashIpAddress(pDfsIpAddress,pHashTable->HashMask)];
  249. if (pListHead->Flink == NULL) {
  250. InitializeListHead(pListHead);
  251. }
  252. KeQuerySystemTime(&now);
  253. pIpInfo->Timeout.QuadPart = now.QuadPart + pHashTable->Timeout.QuadPart;
  254. InsertHeadList(pListHead, &pIpInfo->HashChain);
  255. InsertHeadList(&pHashTable->LRUChain, &pIpInfo->LRUChain);
  256. pHashTable->EntryCount++;
  257. //
  258. // If adding this entry causes the number of entries to exceed the maximum,
  259. // then remove entries from the tail of the LRU list.
  260. //
  261. pListHead = &pHashTable->LRUChain;
  262. if (pHashTable->EntryCount > pHashTable->MaxEntries && pListHead->Blink != pListHead) {
  263. pTailIpInfo = CONTAINING_RECORD(pListHead->Blink, DFS_IP_INFO, LRUChain);
  264. if (pTailIpInfo != pIpInfo) {
  265. pTailIpInfo->Flags |= IP_INFO_DELETE_PENDING;
  266. RemoveEntryList(&pTailIpInfo->HashChain);
  267. RemoveEntryList(&pTailIpInfo->LRUChain);
  268. if (pTailIpInfo->UseCount == 0) {
  269. ExFreePool(pTailIpInfo);
  270. }
  271. pHashTable->EntryCount--;
  272. }
  273. }
  274. ExReleaseFastMutex( &pHashTable->HashListMutex );
  275. if (pExistingIpInfo != NULL) {
  276. DfsDeleteIpInfo(
  277. pExistingIpInfo);
  278. DfsReleaseIpInfo(
  279. pExistingIpInfo);
  280. }
  281. DebugTrace(0, Dbg, "Added pIpInfo %08lx ", pIpInfo);
  282. DebugTrace(0, Dbg, "For Site %wZ ", &pIpInfo->SiteName);
  283. }
  284. //+-------------------------------------------------------------------------
  285. //
  286. // Function: DfsDeleteIpInfo - Delete a DFS_IP_INFO from the lookup hash table
  287. //
  288. // Synopsis: This function Deletes a DFS_IP_INFO from the hash table.
  289. //
  290. // Arguments: [pIpInfo] -- Pointer to the DFS_IP_INFO to delete
  291. //
  292. // Returns: -nothing-
  293. //
  294. //--------------------------------------------------------------------------
  295. VOID
  296. DfsDeleteIpInfo(
  297. PDFS_IP_INFO pIpInfo)
  298. {
  299. PIP_HASH_TABLE pHashTable = (PIP_HASH_TABLE) DfsData.IpHashTable;
  300. ExAcquireFastMutex( &pHashTable->HashListMutex);
  301. pIpInfo->Flags |= IP_INFO_DELETE_PENDING;
  302. RemoveEntryList(&pIpInfo->HashChain);
  303. RemoveEntryList(&pIpInfo->LRUChain);
  304. pHashTable->EntryCount--;
  305. ExReleaseFastMutex( &pHashTable->HashListMutex);
  306. DebugTrace(0, Dbg, "deleted pIpInfo %08lx ", pIpInfo);
  307. DebugTrace(0, Dbg, "For site %wZ ", &pIpInfo->SiteName);
  308. }
  309. //+----------------------------------------------------------------------------
  310. //
  311. // Function: DfsAllocateIpInfo - Allocate a DFS_IP_INFO
  312. //
  313. // Synopsis: This function allocates a contiguous DFS_IP_INFO struct. The
  314. // strings are stored in the allocated buffer after the DFS_IP_INFO
  315. // structure.
  316. //
  317. // Arguments: [pSiteName] -- The site name
  318. // [pDfsIpAddress -- The Ip address of the client
  319. // [ppIpInfo] -- On successful return, has pointer to newly allocated
  320. // DFS_IP_INFO.
  321. //
  322. // Returns: [STATUS_SUCCESS] -- Successfully allocated DFS_IP_INFO
  323. //
  324. // [STATUS_INSUFFICIENT_RESOURCES] -- Out of memory condition
  325. //
  326. //-----------------------------------------------------------------------------
  327. NTSTATUS
  328. DfsAllocateIpInfo(
  329. PDFS_IPADDRESS pDfsIpAddress,
  330. PUNICODE_STRING pSiteName,
  331. PDFS_IP_INFO *ppIpInfo)
  332. {
  333. NTSTATUS status;
  334. PDFS_IP_INFO pIpInfo;
  335. ULONG Size;
  336. ULONG i;
  337. LPWSTR pwCh;
  338. PUNICODE_STRING pustr;
  339. DebugTrace(0, Dbg, "DfsAllocateIpInfo(%wZ)\n", pSiteName);
  340. //
  341. // Size the buffer - include storage for the unicode string after the
  342. // DFS_IP_INFO structure.
  343. //
  344. Size = sizeof(DFS_IP_INFO) + pSiteName->Length;
  345. pIpInfo = (PDFS_IP_INFO) ExAllocatePoolWithTag( PagedPool, Size, ' sfD' );
  346. if (pIpInfo != NULL) {
  347. RtlZeroMemory( pIpInfo, Size );
  348. pIpInfo->NodeTypeCode = DFS_NTC_IP_INFO;
  349. pIpInfo->NodeByteSize = (USHORT)Size;
  350. pIpInfo->IpAddress = *pDfsIpAddress;
  351. pwCh = (LPWSTR) &pIpInfo[1];
  352. pustr = &pIpInfo->SiteName;
  353. pustr->Length = pustr->MaximumLength = pSiteName->Length;
  354. pustr->Buffer = pwCh;
  355. RtlCopyMemory(pwCh, pSiteName->Buffer, pSiteName->Length);
  356. pwCh += pustr->Length / sizeof(WCHAR);
  357. *ppIpInfo = pIpInfo;
  358. status = STATUS_SUCCESS;
  359. DebugTrace(0, Dbg, "DfsAllocateIpInfo pIpInfo = %d\n", pIpInfo);
  360. } else {
  361. status = STATUS_INSUFFICIENT_RESOURCES;
  362. }
  363. return( status );
  364. }
  365. //+----------------------------------------------------------------------------
  366. //
  367. // Function: DfsReleaseIpInfo
  368. //
  369. // Synopsis: Decrements UseCount of and possibly frees a DFS_IP_INFO
  370. //
  371. // Arguments: [pIpInfo] -- The DFS_IP_INFO to release
  372. //
  373. // Returns: Nothing
  374. //
  375. //-----------------------------------------------------------------------------
  376. VOID
  377. DfsReleaseIpInfo(
  378. PDFS_IP_INFO pIpInfo)
  379. {
  380. PIP_HASH_TABLE pHashTable = (PIP_HASH_TABLE) DfsData.IpHashTable;
  381. if (pIpInfo == NULL) {
  382. return;
  383. }
  384. //
  385. // There's a potential race with DfsDeleteIpInfo/DfsInsertIpInfo w.r.t.
  386. // DELETE_PENDING and the test below of DELETE_PENDING, so we still have
  387. // to acquire the Mutex to safely test the DELETE_PENDING bit.
  388. //
  389. ExAcquireFastMutex( &pHashTable->HashListMutex);
  390. pIpInfo->UseCount--;
  391. if ((pIpInfo->Flags & IP_INFO_DELETE_PENDING) != 0 && pIpInfo->UseCount == 0) {
  392. ExFreePool(pIpInfo);
  393. }
  394. ExReleaseFastMutex( &pHashTable->HashListMutex);
  395. }
  396. //+----------------------------------------------------------------------------
  397. //
  398. // Function: DfsHashIpAddress
  399. //
  400. // Synopsis: Generates a hash 0-N
  401. //
  402. // Arguments: [pDfsIpAddress] -- Ip address to hash
  403. //
  404. // Returns: Nothing
  405. //
  406. //-----------------------------------------------------------------------------
  407. ULONG
  408. DfsHashIpAddress(
  409. PDFS_IPADDRESS pDfsAddress,
  410. DWORD HashMask)
  411. {
  412. ULONG BucketNo = 0;
  413. CHAR *pBuffer = pDfsAddress->IpData;
  414. CHAR *pBufferEnd = &pBuffer[pDfsAddress->IpLen];
  415. ULONG Ch;
  416. BucketNo = 0;
  417. while (pBuffer != pBufferEnd) {
  418. Ch = *pBuffer & 0xff;
  419. BucketNo *= 131;
  420. BucketNo += Ch;
  421. pBuffer++;
  422. }
  423. BucketNo = BucketNo & HashMask;
  424. return BucketNo;
  425. }
  426. //+-------------------------------------------------------------------------
  427. //
  428. // Function: DfsFsctrlCreateIpInfo, public
  429. //
  430. // Synopsis:
  431. //
  432. // Arguments:
  433. //
  434. // Returns:
  435. //
  436. //--------------------------------------------------------------------------
  437. NTSTATUS
  438. DfsFsctrlCreateIpInfo(
  439. PIRP Irp,
  440. PVOID InputBuffer,
  441. ULONG InputBufferLength)
  442. {
  443. NTSTATUS status = STATUS_SUCCESS;
  444. PDFS_CREATE_IP_INFO_ARG arg;
  445. PDFS_IP_INFO pIpInfo;
  446. ULONG i;
  447. DebugTrace(+1, Dbg, "DfsFsctrlCreateIpInfo()\n", 0);
  448. STD_FSCTRL_PROLOGUE(DfsFsctrlCreateIpInfo, TRUE, FALSE);
  449. if (InputBufferLength < sizeof(DFS_CREATE_IP_INFO_ARG)) {
  450. status = STATUS_INVALID_PARAMETER;
  451. goto exit_with_status;
  452. }
  453. //
  454. // unmarshal the arguments...
  455. //
  456. arg = (PDFS_CREATE_IP_INFO_ARG) InputBuffer;
  457. OFFSET_TO_POINTER(arg->SiteName.Buffer, arg);
  458. if (!UNICODESTRING_IS_VALID(arg->SiteName, InputBuffer, InputBufferLength)
  459. ||
  460. arg->IpAddress.IpLen > sizeof(arg->IpAddress.IpData)
  461. ) {
  462. status = STATUS_INVALID_PARAMETER;
  463. goto exit_with_status;
  464. }
  465. status = DfsAllocateIpInfo(
  466. &arg->IpAddress,
  467. &arg->SiteName,
  468. &pIpInfo);
  469. if (NT_SUCCESS(status)) {
  470. DfsInsertIpInfo(
  471. &arg->IpAddress,
  472. pIpInfo);
  473. }
  474. exit_with_status:
  475. DfsCompleteRequest( Irp, status );
  476. DebugTrace(-1, Dbg,
  477. "DfsFsctrlCreateIpInfo: Exit -> %08lx\n", ULongToPtr( status ) );
  478. return status;
  479. }
  480. //+-------------------------------------------------------------------------
  481. //
  482. // Function: DfsFsctrlDeleteIpInfo, public
  483. //
  484. // Synopsis:
  485. //
  486. // Arguments:
  487. //
  488. // Returns:
  489. //
  490. //--------------------------------------------------------------------------
  491. NTSTATUS
  492. DfsFsctrlDeleteIpInfo(
  493. PIRP Irp,
  494. PVOID InputBuffer,
  495. ULONG InputBufferLength)
  496. {
  497. NTSTATUS status = STATUS_SUCCESS;
  498. PDFS_DELETE_IP_INFO_ARG arg;
  499. PDFS_IP_INFO pIpInfo;
  500. PIP_HASH_TABLE pHashTable = DfsData.IpHashTable;
  501. DebugTrace(+1, Dbg, "DfsFsctrlDeleteIpInfo()\n", 0);
  502. STD_FSCTRL_PROLOGUE(DfsFsctrlDeleteIpInfo, TRUE, FALSE);
  503. if (InputBufferLength < sizeof(DFS_DELETE_IP_INFO_ARG)) {
  504. status = STATUS_INVALID_PARAMETER;
  505. goto exit_with_status;
  506. }
  507. //
  508. // unmarshal the arguments...
  509. //
  510. arg = (PDFS_DELETE_IP_INFO_ARG) InputBuffer;
  511. if ( arg->IpAddress.IpLen > sizeof(arg->IpAddress.IpData)) {
  512. status = STATUS_INVALID_PARAMETER;
  513. goto exit_with_status;
  514. }
  515. pIpInfo = DfsLookupIpInfo(
  516. pHashTable,
  517. &arg->IpAddress);
  518. //
  519. // The DfsLookupIpInfo() call bumped the usecount, so we're sure pIpInfo
  520. // won't become invalid as we're using it.
  521. //
  522. if (pIpInfo != NULL) {
  523. //
  524. // Removes from the table, but doesn't free the memory
  525. //
  526. DfsDeleteIpInfo(
  527. pIpInfo);
  528. //
  529. // This will decrement the usecount, and if it goes to zero, frees the memory
  530. //
  531. DfsReleaseIpInfo(
  532. pIpInfo);
  533. }
  534. exit_with_status:
  535. DfsCompleteRequest( Irp, status );
  536. DebugTrace(-1, Dbg,
  537. "DfsFsctrlDeleteIpInfo: Exit -> %08lx\n", ULongToPtr( status ) );
  538. return status;
  539. }
  540. PDFS_IP_INFO
  541. DfsLookupSiteByIpaddress(
  542. PDFS_IPADDRESS pDfsIpAddress,
  543. BOOLEAN UseForce)
  544. {
  545. PDFS_IP_INFO pIpInfo;
  546. LARGE_INTEGER now;
  547. NTSTATUS status;
  548. PIP_HASH_TABLE pHashTable = DfsData.IpHashTable;
  549. if (pDfsIpAddress == NULL) {
  550. return NULL;
  551. }
  552. KeQuerySystemTime(&now);
  553. pIpInfo = DfsLookupIpInfo(pHashTable, pDfsIpAddress);
  554. if (pIpInfo == NULL || now.QuadPart > pIpInfo->Timeout.QuadPart) {
  555. //
  556. // Entry is not in cache, or is old
  557. //
  558. if (pIpInfo != NULL) {
  559. // Old entry - try for a new one
  560. if (UseForce == TRUE) {
  561. ExAcquireFastMutex( &pHashTable->HashListMutex);
  562. pIpInfo->Timeout.QuadPart = now.QuadPart + UInt32x32To64(
  563. 10 * 60,
  564. 10 * 1000 * 1000);
  565. ExReleaseFastMutex( &pHashTable->HashListMutex);
  566. DfsLpcIpRequest(pDfsIpAddress);
  567. pIpInfo = DfsLookupIpInfo(pHashTable, pDfsIpAddress);
  568. }
  569. } else {
  570. if (UseForce == TRUE) {
  571. DfsLpcIpRequest(pDfsIpAddress);
  572. pIpInfo = DfsLookupIpInfo(pHashTable, pDfsIpAddress);
  573. }
  574. }
  575. }
  576. return pIpInfo;
  577. }
  578. #ifdef DBG
  579. VOID
  580. DfsDumpIpTable(void)
  581. {
  582. PLIST_ENTRY pListHead, pLink;
  583. PDFS_IP_INFO pIpInfo;
  584. PIP_HASH_TABLE pHashTable = DfsData.IpHashTable;
  585. ULONG i, j;
  586. DbgPrint("%d entries total\n", pHashTable->EntryCount);
  587. for (i = 0; i <= pHashTable->HashMask; i++) {
  588. pListHead = &pHashTable->HashBuckets[i];
  589. if ((pListHead->Flink == NULL) || // list not initialized
  590. (pListHead->Flink == pListHead)) { // list empty
  591. continue;
  592. }
  593. for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) {
  594. pIpInfo = CONTAINING_RECORD(pLink, DFS_IP_INFO, HashChain);
  595. DbgPrint("B:%02d Ip:0x%x N:%wZ C=%d\n",
  596. i,
  597. *((ULONG *)&pIpInfo->IpAddress.IpData),
  598. &pIpInfo->SiteName,
  599. pIpInfo->UseCount);
  600. }
  601. }
  602. }
  603. #endif