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.

1881 lines
53 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. openclos.c
  5. Abstract:
  6. This module implements the name cache for file basic and standard information.
  7. Author:
  8. Yun Lin [YunLin] 2-Octorber-1998
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #include "smbce.h"
  13. #pragma hdrstop
  14. #ifdef ALLOC_PRAGMA
  15. #pragma alloc_text(PAGE, MRxSmbIsStreamFile)
  16. #pragma alloc_text(PAGE, MRxSmbCacheFileNotFound)
  17. #pragma alloc_text(PAGE, MRxSmbCreateFileInfoCache)
  18. #pragma alloc_text(PAGE, MRxSmbIsFileInfoCacheFound)
  19. #pragma alloc_text(PAGE, MRxSmbInvalidateFileInfoCache)
  20. #pragma alloc_text(PAGE, MRxSmbUpdateBasicFileInfoCache)
  21. #pragma alloc_text(PAGE, MRxSmbCreateBasicFileInfoCache)
  22. #pragma alloc_text(PAGE, MRxSmbUpdateFileInfoCacheStatus)
  23. #pragma alloc_text(PAGE, MRxSmbCreateStandardFileInfoCache)
  24. #pragma alloc_text(PAGE, MRxSmbUpdateFileInfoCacheFileSize)
  25. #pragma alloc_text(PAGE, MRxSmbUpdateStandardFileInfoCache)
  26. #pragma alloc_text(PAGE, MRxSmbInvalidateFileNotFoundCache)
  27. #pragma alloc_text(PAGE, MRxSmbUpdateBasicFileInfoCacheAll)
  28. #pragma alloc_text(PAGE, MRxSmbInvalidateBasicFileInfoCache)
  29. #pragma alloc_text(PAGE, MRxSmbUpdateBasicFileInfoCacheStatus)
  30. #pragma alloc_text(PAGE, MRxSmbInvalidateStandardFileInfoCache)
  31. #pragma alloc_text(PAGE, MRxSmbInvalidateInternalFileInfoCache)
  32. #pragma alloc_text(PAGE, MRxSmbUpdateStandardFileInfoCacheStatus)
  33. #endif
  34. extern FAST_MUTEX MRxSmbFileInfoCacheLock;
  35. VOID
  36. MRxSmbCreateFileInfoCache(
  37. PRX_CONTEXT RxContext,
  38. PSMBPSE_FILEINFO_BUNDLE FileInfo,
  39. PSMBCEDB_SERVER_ENTRY pServerEntry,
  40. NTSTATUS Status
  41. )
  42. /*++
  43. Routine Description:
  44. This routine creates name cache entry for both file basic and standard information.
  45. Arguments:
  46. RxContext - the RDBSS context
  47. FileInfo - the file information package including basic and standard information
  48. Status - the status returned from server response of query file information
  49. Return Value:
  50. none
  51. --*/
  52. {
  53. PAGED_CODE();
  54. if (!pServerEntry->Server.IsLoopBack) {
  55. MRxSmbCreateBasicFileInfoCache(RxContext,&FileInfo->Basic,pServerEntry,Status);
  56. MRxSmbCreateStandardFileInfoCache(RxContext,&FileInfo->Standard,pServerEntry,Status);
  57. }
  58. }
  59. VOID
  60. MRxSmbCreateBasicFileInfoCache(
  61. PRX_CONTEXT RxContext,
  62. PFILE_BASIC_INFORMATION Basic,
  63. PSMBCEDB_SERVER_ENTRY pServerEntry,
  64. NTSTATUS Status
  65. )
  66. /*++
  67. Routine Description:
  68. This routine creates name cache entry for the file basic information.
  69. Arguments:
  70. RxContext - the RDBSS context
  71. Basic - the file basic information package
  72. Status - the status returned from server response of query file information
  73. Return Value:
  74. none
  75. --*/
  76. {
  77. RxCaptureFcb;
  78. PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  79. PNAME_CACHE NameCache = NULL;
  80. PMRX_NET_ROOT NetRoot;
  81. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  82. PNAME_CACHE_CONTROL NameCacheCtl;
  83. RX_NC_CHECK_STATUS NameCacheStatus;
  84. PFILE_BASIC_INFORMATION FileInfoCache = NULL;
  85. PAGED_CODE();
  86. if (pServerEntry->Server.IsLoopBack ||
  87. (MRxSmbIsLongFileName(RxContext) &&
  88. pServerEntry->Server.Dialect != LANMAN21_DIALECT)) {
  89. return;
  90. }
  91. if (RxContext->MajorFunction == IRP_MJ_CREATE) {
  92. NetRoot = RxContext->Create.pNetRoot;
  93. } else {
  94. ASSERT(capFcb != NULL);
  95. NetRoot = capFcb->pNetRoot;
  96. }
  97. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  98. NameCacheCtl = &pNetRootEntry->NameCacheCtlGFABasic;
  99. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  100. NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
  101. if (NameCache == NULL) {
  102. NameCache = RxNameCacheCreateEntry (
  103. NameCacheCtl,
  104. OriginalFileName,
  105. TRUE); // case insensitive match
  106. }
  107. if (NameCache != NULL) {
  108. FileInfoCache = (PFILE_BASIC_INFORMATION)NameCache->ContextExtension;
  109. *FileInfoCache = *Basic;
  110. NameCache->PriorStatus = Status;
  111. RxNameCacheActivateEntry(
  112. NameCacheCtl,
  113. NameCache,
  114. NAME_CACHE_OBJ_GET_FILE_ATTRIB_LIFETIME,
  115. MRxSmbStatistics.SmbsReceived.LowPart);
  116. //DbgPrint(" Create File Attrib cache : %x %wZ\n",Basic->FileAttributes,OriginalFileName);
  117. //DbgPrint(" Create File Attrib cache : %I64X %I64X %wZ\n",Basic->CreationTime,Basic->LastAccessTime,OriginalFileName);
  118. }
  119. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  120. }
  121. VOID
  122. MRxSmbCreateStandardFileInfoCache(
  123. PRX_CONTEXT RxContext,
  124. PFILE_STANDARD_INFORMATION Standard,
  125. PSMBCEDB_SERVER_ENTRY pServerEntry,
  126. NTSTATUS Status
  127. )
  128. /*++
  129. Routine Description:
  130. This routine creates name cache entry for the file standard information.
  131. Arguments:
  132. RxContext - the RDBSS context
  133. Standard - the file standard information package
  134. Status - the status returned from server response of query file information
  135. Return Value:
  136. none
  137. --*/
  138. {
  139. RxCaptureFcb;
  140. PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  141. PNAME_CACHE NameCache = NULL;
  142. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  143. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  144. PNAME_CACHE_CONTROL NameCacheCtl = &pNetRootEntry->NameCacheCtlGFAStandard;
  145. PFILE_STANDARD_INFORMATION FileInfoCache = NULL;
  146. PAGED_CODE();
  147. if (pServerEntry->Server.IsLoopBack ||
  148. (MRxSmbIsLongFileName(RxContext) &&
  149. pServerEntry->Server.Dialect != LANMAN21_DIALECT)) {
  150. return;
  151. }
  152. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  153. NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
  154. if (NameCache == NULL) {
  155. NameCache = RxNameCacheCreateEntry (
  156. NameCacheCtl,
  157. OriginalFileName,
  158. TRUE); // case insensitive match
  159. }
  160. if (NameCache != NULL) {
  161. FileInfoCache = (PFILE_STANDARD_INFORMATION)NameCache->ContextExtension;
  162. *FileInfoCache = *Standard;
  163. NameCache->PriorStatus = Status;
  164. RxNameCacheActivateEntry(
  165. NameCacheCtl,
  166. NameCache,
  167. NAME_CACHE_OBJ_GET_FILE_ATTRIB_LIFETIME,
  168. MRxSmbStatistics.SmbsReceived.LowPart);
  169. //DbgPrint(" Create Standard cache : %I64x %wZ\n",((PFILE_STANDARD_INFORMATION)NameCache->ContextExtension)->EndOfFile,OriginalFileName);
  170. }
  171. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  172. }
  173. VOID
  174. MRxSmbCreateInternalFileInfoCache(
  175. PRX_CONTEXT RxContext,
  176. PFILE_INTERNAL_INFORMATION Internal,
  177. PSMBCEDB_SERVER_ENTRY pServerEntry,
  178. NTSTATUS Status
  179. )
  180. /*++
  181. Routine Description:
  182. This routine creates name cache entry for the file internal information.
  183. Arguments:
  184. RxContext - the RDBSS context
  185. Standard - the file standard information package
  186. Status - the status returned from server response of query file information
  187. Return Value:
  188. none
  189. --*/
  190. {
  191. RxCaptureFcb;
  192. PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  193. PNAME_CACHE NameCache = NULL;
  194. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  195. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  196. PNAME_CACHE_CONTROL NameCacheCtl = &pNetRootEntry->NameCacheCtlGFAInternal;
  197. PFILE_INTERNAL_INFORMATION FileInfoCache = NULL;
  198. PAGED_CODE();
  199. if (pServerEntry->Server.IsLoopBack) {
  200. return;
  201. }
  202. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  203. NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
  204. if (NameCache == NULL) {
  205. NameCache = RxNameCacheCreateEntry (
  206. NameCacheCtl,
  207. OriginalFileName,
  208. TRUE); // case insensitive match
  209. }
  210. if (NameCache != NULL) {
  211. FileInfoCache = (PFILE_INTERNAL_INFORMATION)NameCache->ContextExtension;
  212. *FileInfoCache = *Internal;
  213. NameCache->PriorStatus = Status;
  214. RxNameCacheActivateEntry(
  215. NameCacheCtl,
  216. NameCache,
  217. NAME_CACHE_OBJ_GET_FILE_ATTRIB_LIFETIME,
  218. MRxSmbStatistics.SmbsReceived.LowPart);
  219. //DbgPrint(" Create Internal cache : %I64x %wZ\n",((PFILE_INTERNAL_INFORMATION)NameCache->ContextExtension)->IndexNumber,OriginalFileName);
  220. }
  221. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  222. }
  223. VOID
  224. MRxSmbUpdateFileInfoCacheFromDelete(
  225. PRX_CONTEXT RxContext
  226. )
  227. /*++
  228. Routine Description:
  229. This routine updates the status of the name cache entry as STATUS_OBJECT_NAME_NOT_FOUND
  230. for both file basic and standard information.
  231. Arguments:
  232. RxContext - the RDBSS context
  233. Return Value:
  234. none
  235. --*/
  236. {
  237. MRxSmbUpdateBasicFileInfoCacheStatus(RxContext,STATUS_OBJECT_NAME_NOT_FOUND);
  238. MRxSmbUpdateStandardFileInfoCacheStatus(RxContext,STATUS_OBJECT_NAME_NOT_FOUND);
  239. }
  240. VOID
  241. MRxSmbUpdateFileInfoCacheStatus(
  242. PRX_CONTEXT RxContext,
  243. NTSTATUS Status
  244. )
  245. /*++
  246. Routine Description:
  247. This routine updates the status of the name cache entry for both file basic and standard information.
  248. Arguments:
  249. RxContext - the RDBSS context
  250. Status - the status needs to be put on the cache
  251. Return Value:
  252. none
  253. --*/
  254. {
  255. MRxSmbUpdateBasicFileInfoCacheStatus(RxContext,Status);
  256. MRxSmbUpdateStandardFileInfoCacheStatus(RxContext,Status);
  257. }
  258. VOID
  259. MRxSmbUpdateBasicFileInfoCacheStatus(
  260. PRX_CONTEXT RxContext,
  261. NTSTATUS Status
  262. )
  263. /*++
  264. Routine Description:
  265. This routine updates the status of the name cache entry for the file basic information.
  266. Arguments:
  267. RxContext - the RDBSS context
  268. Status - the status needs to be put on the cache
  269. Return Value:
  270. none
  271. --*/
  272. {
  273. RxCaptureFcb;
  274. PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  275. UNICODE_STRING FileName;
  276. PNAME_CACHE NameCache = NULL;
  277. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  278. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  279. PNAME_CACHE_CONTROL NameCacheCtl = &pNetRootEntry->NameCacheCtlGFABasic;
  280. PAGED_CODE();
  281. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  282. NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
  283. if (NameCache != NULL) {
  284. NameCache->PriorStatus = Status;
  285. RxNameCacheActivateEntry(NameCacheCtl,
  286. NameCache,
  287. 0,
  288. 0);
  289. //DbgPrint("Update status basic : %x %wZ\n",Status,OriginalFileName);
  290. RxLog(("Update status basic : %x %wZ\n",Status,OriginalFileName));
  291. } else {
  292. RxLog(("Update status basic fails: %x %wZ\n",Status,OriginalFileName));
  293. }
  294. if (MRxSmbIsStreamFile(OriginalFileName,&FileName)) {
  295. // if it is a stream file, we invalid the root file name cache needs since we are not
  296. // sure what could happen to the root file on the server
  297. NameCache = RxNameCacheFetchEntry(NameCacheCtl,&FileName);
  298. if (NameCache != NULL) {
  299. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  300. }
  301. //DbgPrint("Update status basic : %x %wZ\n",Status,&FileName);
  302. }
  303. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  304. }
  305. VOID
  306. MRxSmbUpdateStandardFileInfoCacheStatus(
  307. PRX_CONTEXT RxContext,
  308. NTSTATUS Status
  309. )
  310. /*++
  311. Routine Description:
  312. This routine updates the status of the name cache entry for the file standard information.
  313. Arguments:
  314. RxContext - the RDBSS context
  315. Status - the status needs to be put on the cache
  316. Return Value:
  317. none
  318. --*/
  319. {
  320. RxCaptureFcb;
  321. PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  322. UNICODE_STRING FileName;
  323. PNAME_CACHE NameCache = NULL;
  324. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  325. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  326. PNAME_CACHE_CONTROL NameCacheCtl = &pNetRootEntry->NameCacheCtlGFAStandard;
  327. PAGED_CODE();
  328. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  329. NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
  330. if (NameCache != NULL) {
  331. NameCache->PriorStatus = Status;
  332. RxNameCacheActivateEntry(NameCacheCtl,
  333. NameCache,
  334. 0,
  335. 0);
  336. }
  337. /*
  338. if (MRxSmbIsStreamFile(OriginalFileName,&FileName)) {
  339. NameCache = RxNameCacheFetchEntry(NameCacheCtl,&FileName);
  340. if (NameCache != NULL) {
  341. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  342. }
  343. } */
  344. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  345. }
  346. VOID
  347. MRxSmbInvalidateFileInfoCache(
  348. PRX_CONTEXT RxContext
  349. )
  350. /*++
  351. Routine Description:
  352. This routine invalidates the name cache entry for both file basic and standard information.
  353. Arguments:
  354. RxContext - the RDBSS context
  355. Return Value:
  356. none
  357. --*/
  358. {
  359. PAGED_CODE();
  360. MRxSmbInvalidateBasicFileInfoCache(RxContext);
  361. MRxSmbInvalidateStandardFileInfoCache(RxContext);
  362. }
  363. VOID
  364. MRxSmbInvalidateBasicFileInfoCache(
  365. PRX_CONTEXT RxContext
  366. )
  367. /*++
  368. Routine Description:
  369. This routine invalidates the name cache entry for file basic information.
  370. Arguments:
  371. RxContext - the RDBSS context
  372. Return Value:
  373. none
  374. --*/
  375. {
  376. RxCaptureFcb;
  377. PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  378. UNICODE_STRING FileName;
  379. PNAME_CACHE NameCache = NULL;
  380. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  381. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  382. PNAME_CACHE_CONTROL NameCacheCtl = &pNetRootEntry->NameCacheCtlGFABasic;
  383. PAGED_CODE();
  384. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  385. NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
  386. if (NameCache != NULL) {
  387. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  388. //DbgPrint("Invalid Baisc cache : %wZ\n",OriginalFileName);
  389. RxLog(("Invalid Baisc cache : %wZ\n",OriginalFileName));
  390. }
  391. if (MRxSmbIsStreamFile(OriginalFileName,&FileName)) {
  392. NameCache = RxNameCacheFetchEntry(NameCacheCtl,&FileName);
  393. if (NameCache != NULL) {
  394. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  395. }
  396. }
  397. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  398. }
  399. VOID
  400. MRxSmbInvalidateStandardFileInfoCache(
  401. PRX_CONTEXT RxContext
  402. )
  403. /*++
  404. Routine Description:
  405. This routine invalidates the name cache entry for the file standard information.
  406. Arguments:
  407. RxContext - the RDBSS context
  408. Return Value:
  409. none
  410. --*/
  411. {
  412. RxCaptureFcb;
  413. PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  414. UNICODE_STRING FileName;
  415. PNAME_CACHE NameCache = NULL;
  416. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  417. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  418. PNAME_CACHE_CONTROL NameCacheCtl = &pNetRootEntry->NameCacheCtlGFAStandard;
  419. PAGED_CODE();
  420. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  421. NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
  422. if (NameCache != NULL) {
  423. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  424. //DbgPrint("Invalid Standard cache : %I64x %wZ\n",((PFILE_STANDARD_INFORMATION)NameCache->ContextExtension)->EndOfFile,OriginalFileName);
  425. }
  426. if (MRxSmbIsStreamFile(OriginalFileName,&FileName)) {
  427. NameCache = RxNameCacheFetchEntry(NameCacheCtl,&FileName);
  428. if (NameCache != NULL) {
  429. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  430. }
  431. }
  432. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  433. }
  434. VOID
  435. MRxSmbInvalidateInternalFileInfoCache(
  436. PRX_CONTEXT RxContext
  437. )
  438. /*++
  439. Routine Description:
  440. This routine invalidates the name cache entry for file internal information.
  441. Arguments:
  442. RxContext - the RDBSS context
  443. Return Value:
  444. none
  445. --*/
  446. {
  447. RxCaptureFcb;
  448. PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  449. UNICODE_STRING FileName;
  450. PNAME_CACHE NameCache = NULL;
  451. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  452. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  453. PNAME_CACHE_CONTROL NameCacheCtl = &pNetRootEntry->NameCacheCtlGFAInternal;
  454. PAGED_CODE();
  455. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  456. NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
  457. if (NameCache != NULL) {
  458. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  459. //DbgPrint("Invalid Internal cache : %wZ\n",OriginalFileName);
  460. RxLog(("Invalid Internal cache : %wZ\n",OriginalFileName));
  461. }
  462. if (MRxSmbIsStreamFile(OriginalFileName,&FileName)) {
  463. NameCache = RxNameCacheFetchEntry(NameCacheCtl,&FileName);
  464. if (NameCache != NULL) {
  465. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  466. }
  467. }
  468. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  469. }
  470. VOID
  471. MRxSmbUpdateFileInfoCacheFileSize(
  472. PRX_CONTEXT RxContext,
  473. PLARGE_INTEGER FileSize
  474. )
  475. /*++
  476. Routine Description:
  477. This routine updates file size on the name cache entry for the file standard information.
  478. Arguments:
  479. RxContext - the RDBSS context
  480. Return Value:
  481. none
  482. --*/
  483. {
  484. RxCaptureFcb;
  485. PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  486. UNICODE_STRING FileName;
  487. PNAME_CACHE NameCache = NULL;
  488. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  489. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  490. PNAME_CACHE_CONTROL NameCacheCtl = &pNetRootEntry->NameCacheCtlGFAStandard;
  491. PFILE_STANDARD_INFORMATION FileInfoCache = NULL;
  492. PAGED_CODE();
  493. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  494. NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
  495. if (NameCache != NULL) {
  496. FileInfoCache = (PFILE_STANDARD_INFORMATION)NameCache->ContextExtension;
  497. FileInfoCache->AllocationSize.QuadPart = FileSize->QuadPart;
  498. FileInfoCache->EndOfFile.QuadPart = FileSize->QuadPart;
  499. RxNameCacheActivateEntry(NameCacheCtl,
  500. NameCache,
  501. 0,
  502. 0);
  503. //DbgPrint("Update File size cache : %I64x %wZ\n",((PFILE_STANDARD_INFORMATION)NameCache->ContextExtension)->EndOfFile,OriginalFileName);
  504. }
  505. /*
  506. if (MRxSmbIsStreamFile(OriginalFileName,&FileName)) {
  507. NameCache = RxNameCacheFetchEntry(NameCacheCtl,&FileName);
  508. if (NameCache != NULL) {
  509. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  510. }
  511. }*/
  512. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  513. }
  514. VOID
  515. MRxSmbUpdateBasicFileInfoCache(
  516. PRX_CONTEXT RxContext,
  517. ULONG FileAttributes,
  518. PLARGE_INTEGER pLastWriteTime
  519. )
  520. /*++
  521. Routine Description:
  522. This routine updates file attributs and last write time on the name cache entry
  523. for the file basic information.
  524. Arguments:
  525. RxContext - the RDBSS context
  526. FileAttributes - new file attributes
  527. pLastWriteTime - address of file last write time
  528. Return Value:
  529. none
  530. --*/
  531. {
  532. FILE_BASIC_INFORMATION Basic;
  533. Basic.ChangeTime.QuadPart = 0;
  534. Basic.CreationTime.QuadPart = 0;
  535. Basic.LastWriteTime.QuadPart = 0;
  536. Basic.LastAccessTime.QuadPart = 0;
  537. if (pLastWriteTime != NULL && pLastWriteTime->QuadPart != 0) {
  538. Basic.LastWriteTime = *pLastWriteTime;
  539. }
  540. Basic.FileAttributes = FileAttributes;
  541. MRxSmbUpdateBasicFileInfoCacheAll(RxContext,&Basic);
  542. }
  543. VOID
  544. MRxSmbUpdateBasicFileInfoCacheAll(
  545. PRX_CONTEXT RxContext,
  546. PFILE_BASIC_INFORMATION Basic
  547. )
  548. /*++
  549. Routine Description:
  550. This routine updates the name cache entry for the file basic information.
  551. Arguments:
  552. RxContext - the RDBSS context
  553. Basic - file basic information
  554. Return Value:
  555. none
  556. --*/
  557. {
  558. RxCaptureFcb;
  559. PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  560. UNICODE_STRING FileName;
  561. PNAME_CACHE NameCache = NULL;
  562. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  563. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  564. PNAME_CACHE_CONTROL NameCacheCtl = &pNetRootEntry->NameCacheCtlGFABasic;
  565. PFILE_BASIC_INFORMATION BasicFileInfoCache = NULL;
  566. PAGED_CODE();
  567. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  568. NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
  569. if (NameCache != NULL) {
  570. ULONG SavedAttributes = 0;
  571. BasicFileInfoCache = (PFILE_BASIC_INFORMATION)NameCache->ContextExtension;
  572. if (Basic->CreationTime.QuadPart != 0) {
  573. BasicFileInfoCache->CreationTime = Basic->CreationTime;
  574. }
  575. if (Basic->LastAccessTime.QuadPart != 0) {
  576. BasicFileInfoCache->LastAccessTime = Basic->LastAccessTime;
  577. }
  578. if (Basic->LastWriteTime.QuadPart != 0) {
  579. BasicFileInfoCache->LastWriteTime = Basic->LastWriteTime;
  580. }
  581. SavedAttributes = BasicFileInfoCache->FileAttributes &
  582. ( FILE_ATTRIBUTE_DIRECTORY |
  583. FILE_ATTRIBUTE_ENCRYPTED |
  584. FILE_ATTRIBUTE_COMPRESSED |
  585. FILE_ATTRIBUTE_SPARSE_FILE |
  586. FILE_ATTRIBUTE_REPARSE_POINT );
  587. //DbgPrint("Update File Attrib cache 1: %x %wZ\n",FileAttributes,OriginalFileName);
  588. //DbgPrint("Update File Attrib cache 2: %x %wZ\n",BasicFileInfoCache->FileAttributes,OriginalFileName);
  589. BasicFileInfoCache->FileAttributes = Basic->FileAttributes;
  590. BasicFileInfoCache->FileAttributes |= SavedAttributes;
  591. if (BasicFileInfoCache->FileAttributes & ~FILE_ATTRIBUTE_NORMAL) {
  592. BasicFileInfoCache->FileAttributes &= ~FILE_ATTRIBUTE_NORMAL;
  593. }
  594. RxNameCacheActivateEntry(NameCacheCtl,
  595. NameCache,
  596. 0,
  597. 0);
  598. //DbgPrint("Update File Attrib cache 3: %x %wZ\n",BasicFileInfoCache->FileAttributes,OriginalFileName);
  599. //DbgPrint("Update File Attrib cache : %I64X %I64X %wZ\n",BasicFileInfoCache->CreationTime,BasicFileInfoCache->LastAccessTime,OriginalFileName);
  600. }
  601. if (MRxSmbIsStreamFile(OriginalFileName,&FileName)) {
  602. // if it is a stream file, we need to invalid the root file since we are not sure how this
  603. // could affect the root file.
  604. NameCache = RxNameCacheFetchEntry(NameCacheCtl,&FileName);
  605. if (NameCache != NULL) {
  606. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  607. }
  608. }
  609. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  610. }
  611. VOID
  612. MRxSmbUpdateStandardFileInfoCache(
  613. PRX_CONTEXT RxContext,
  614. PFILE_STANDARD_INFORMATION Standard,
  615. BOOLEAN IsDirectory
  616. )
  617. /*++
  618. Routine Description:
  619. This routine updates the name cache entry for the file standard information.
  620. Arguments:
  621. RxContext - the RDBSS context
  622. Standard - file standard information
  623. IsDirectory - file is a directory
  624. Return Value:
  625. none
  626. --*/
  627. {
  628. RxCaptureFcb;
  629. PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  630. UNICODE_STRING FileName;
  631. PNAME_CACHE NameCache = NULL;
  632. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  633. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  634. PNAME_CACHE_CONTROL NameCacheCtl = &pNetRootEntry->NameCacheCtlGFAStandard;
  635. PFILE_STANDARD_INFORMATION StandardFileInfoCache = NULL;
  636. PAGED_CODE();
  637. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  638. NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
  639. if (NameCache != NULL) {
  640. StandardFileInfoCache = (PFILE_STANDARD_INFORMATION)NameCache->ContextExtension;
  641. if (Standard != NULL) {
  642. *StandardFileInfoCache = *Standard;
  643. } else {
  644. StandardFileInfoCache->Directory = IsDirectory;
  645. }
  646. RxNameCacheActivateEntry(NameCacheCtl,
  647. NameCache,
  648. 0,
  649. 0);
  650. //DbgPrint(" Update Standard cache : %I64x %wZ\n",((PFILE_STANDARD_INFORMATION)NameCache->ContextExtension)->EndOfFile,OriginalFileName);
  651. }
  652. /*
  653. if (MRxSmbIsStreamFile(OriginalFileName,&FileName)) {
  654. NameCache = RxNameCacheFetchEntry(NameCacheCtl,&FileName);
  655. if (NameCache != NULL) {
  656. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  657. }
  658. } */
  659. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  660. }
  661. BOOLEAN
  662. MRxSmbIsFileInfoCacheFound(
  663. PRX_CONTEXT RxContext,
  664. PSMBPSE_FILEINFO_BUNDLE FileInfo,
  665. NTSTATUS *Status,
  666. PUNICODE_STRING OriginalFileName
  667. )
  668. /*++
  669. Routine Description:
  670. This routine looks for the name cache entry of both file basic and standard information.
  671. Arguments:
  672. RxContext - the RDBSS context
  673. FileInfo - buffer to return file basic and standard information
  674. Status - status retured on the last reponse from server
  675. Return Value:
  676. BOOLEAN - name cache found
  677. --*/
  678. {
  679. PFILE_BASIC_INFORMATION Basic;
  680. PFILE_STANDARD_INFORMATION Standard;
  681. BOOLEAN CacheFound = FALSE;
  682. if (MRxSmbIsBasicFileInfoCacheFound(RxContext,&FileInfo->Basic,Status,OriginalFileName)) {
  683. if (*Status == STATUS_SUCCESS) {
  684. if (MRxSmbIsStandardFileInfoCacheFound(RxContext,&FileInfo->Standard,Status,OriginalFileName)) {
  685. CacheFound = TRUE;
  686. }
  687. } else {
  688. // if an error stored on the file basic information cache, return cache found
  689. CacheFound = TRUE;
  690. }
  691. }
  692. return CacheFound;
  693. }
  694. // these file attributes may be different between streams on a file
  695. ULONG StreamAttributes = FILE_ATTRIBUTE_COMPRESSED |
  696. FILE_ATTRIBUTE_DIRECTORY |
  697. FILE_ATTRIBUTE_SPARSE_FILE;
  698. BOOLEAN
  699. MRxSmbIsBasicFileInfoCacheFound(
  700. PRX_CONTEXT RxContext,
  701. PFILE_BASIC_INFORMATION Basic,
  702. NTSTATUS *Status,
  703. PUNICODE_STRING OriginalFileName
  704. )
  705. /*++
  706. Routine Description:
  707. This routine looks for the name cache entry of the file basic information.
  708. Arguments:
  709. RxContext - the RDBSS context
  710. Basic - buffer to return file basic information
  711. Status - status retured on the last reponse from server
  712. Return Value:
  713. BOOLEAN - name cache found
  714. --*/
  715. {
  716. RxCaptureFcb;
  717. UNICODE_STRING FileName;
  718. PNAME_CACHE NameCache = NULL;
  719. PMRX_NET_ROOT NetRoot;
  720. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  721. PNAME_CACHE_CONTROL NameCacheCtl;
  722. RX_NC_CHECK_STATUS NameCacheStatus;
  723. BOOLEAN CacheFound = FALSE;
  724. BOOLEAN RootFound = FALSE;
  725. ULONG RootAttributes = 0;
  726. NTSTATUS RootStatus = STATUS_SUCCESS;
  727. PAGED_CODE();
  728. if (OriginalFileName == NULL) {
  729. OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  730. }
  731. if (RxContext->MajorFunction == IRP_MJ_CREATE) {
  732. NetRoot = RxContext->Create.pNetRoot;
  733. } else {
  734. ASSERT(capFcb != NULL);
  735. NetRoot = capFcb->pNetRoot;
  736. }
  737. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  738. NameCacheCtl = &pNetRootEntry->NameCacheCtlGFABasic;
  739. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  740. if (MRxSmbIsStreamFile(OriginalFileName,&FileName)) {
  741. // check for stream file attribute changes
  742. NameCache = RxNameCacheFetchEntry(NameCacheCtl,&FileName);
  743. if (NameCache != NULL) {
  744. NameCacheStatus = RxNameCacheCheckEntry(
  745. NameCache,
  746. NameCache->Context);
  747. if (NameCacheStatus == RX_NC_SUCCESS) {
  748. RootFound = TRUE;
  749. RootStatus = NameCache->PriorStatus;
  750. RootAttributes = ((PFILE_BASIC_INFORMATION)NameCache->ContextExtension)->FileAttributes & ~StreamAttributes;
  751. RxNameCacheActivateEntry(NameCacheCtl, NameCache, 0, 0);
  752. } else {
  753. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  754. }
  755. }
  756. }
  757. NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
  758. if (NameCache != NULL) {
  759. //
  760. // Found it. Now check entry for not expired.
  761. // Note - The NameCache entry has been pulled off the active list.
  762. //
  763. NameCacheStatus = RxNameCacheCheckEntry(
  764. NameCache,
  765. NameCache->Context);
  766. if (NameCacheStatus == RX_NC_SUCCESS &&
  767. (!RootFound ||
  768. (*Status == RootStatus &&
  769. (Basic->FileAttributes & ~StreamAttributes) == RootAttributes))) {
  770. // The name cache matches if it is not expired and the attributes matches the one of
  771. // the root file if it is a stream file. If this is a match, return the old status,
  772. // file info and reactivate the entry but leave expiration time unchanged.
  773. *Status = NameCache->PriorStatus;
  774. RxNameCacheOpSaved(NameCacheCtl);
  775. *Basic = *((PFILE_BASIC_INFORMATION)NameCache->ContextExtension);
  776. CacheFound = TRUE;
  777. // put the entry back to the active list without changing the expire time
  778. RxNameCacheActivateEntry(NameCacheCtl, NameCache, 0, 0);
  779. //DbgPrint(" Found Basic cache : %x %wZ\n",Basic->FileAttributes,OriginalFileName);
  780. //DbgPrint(" Get File Attrib cache : %I64X %I64X %wZ\n",Basic->CreationTime,Basic->LastAccessTime,OriginalFileName);
  781. } else {
  782. // put the entry back to the expire list
  783. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  784. }
  785. } else {
  786. //DbgPrint(" No Basic cache : %wZ\n",OriginalFileName);
  787. }
  788. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  789. return CacheFound;
  790. }
  791. BOOLEAN
  792. MRxSmbIsStandardFileInfoCacheFound(
  793. PRX_CONTEXT RxContext,
  794. PFILE_STANDARD_INFORMATION Standard,
  795. NTSTATUS *Status,
  796. PUNICODE_STRING OriginalFileName
  797. )
  798. /*++
  799. Routine Description:
  800. This routine looks for the name cache entry of the file standard information.
  801. Arguments:
  802. RxContext - the RDBSS context
  803. Standard - buffer to return file standard information
  804. Status - status retured on the last reponse from server
  805. Return Value:
  806. BOOLEAN - name cache found
  807. --*/
  808. {
  809. RxCaptureFcb;
  810. RxCaptureFobx;
  811. UNICODE_STRING FileName;
  812. PNAME_CACHE NameCache = NULL;
  813. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  814. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  815. PNAME_CACHE_CONTROL NameCacheCtl = &pNetRootEntry->NameCacheCtlGFAStandard;
  816. RX_NC_CHECK_STATUS NameCacheStatus;
  817. BOOLEAN CacheFound = FALSE;
  818. BOOLEAN RootFound = FALSE;
  819. NTSTATUS RootStatus = STATUS_SUCCESS;
  820. PMRX_SMB_SRV_OPEN smbSrvOpen;
  821. PAGED_CODE();
  822. if (OriginalFileName == NULL) {
  823. OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  824. }
  825. if (RxContext->MajorFunction == IRP_MJ_CREATE) {
  826. smbSrvOpen = MRxSmbGetSrvOpenExtension(RxContext->pRelevantSrvOpen);
  827. } else {
  828. smbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  829. }
  830. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  831. if (MRxSmbIsStreamFile(OriginalFileName,&FileName)) {
  832. // check for stream file attribute changes
  833. NameCache = RxNameCacheFetchEntry(NameCacheCtl,&FileName);
  834. if (NameCache != NULL) {
  835. NameCacheStatus = RxNameCacheCheckEntry(
  836. NameCache,
  837. NameCache->Context);
  838. if (NameCacheStatus == RX_NC_SUCCESS) {
  839. RootFound = TRUE;
  840. RootStatus = NameCache->PriorStatus;
  841. RxNameCacheActivateEntry(NameCacheCtl, NameCache, 0, 0);
  842. } else {
  843. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  844. }
  845. }
  846. }
  847. NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
  848. if (NameCache != NULL) {
  849. //
  850. // Found it. Now check entry for not expired.
  851. // Note - The NameCache entry has been pulled off the active list.
  852. //
  853. NameCacheStatus = RxNameCacheCheckEntry(
  854. NameCache,
  855. NameCache->Context);
  856. if (NameCacheStatus == RX_NC_SUCCESS &&
  857. (!RootFound || *Status == RootStatus)) {
  858. // The name cache matches if it is not expired and the status matches the one of
  859. // the root file if it is a stream file. If this is a match, return the old status,
  860. // file info and reactivate the entry but leave expiration time unchanged.
  861. *Status = NameCache->PriorStatus;
  862. RxNameCacheOpSaved(NameCacheCtl);
  863. *Standard = *((PFILE_STANDARD_INFORMATION)NameCache->ContextExtension);
  864. if (FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_SUCCESSFUL_OPEN) &&
  865. !FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN)) {
  866. RxGetFileSizeWithLock((PFCB)capFcb,&Standard->EndOfFile.QuadPart);
  867. }
  868. CacheFound = TRUE;
  869. // put the entry back to the active list without changing the expire time
  870. RxNameCacheActivateEntry(NameCacheCtl, NameCache, 0, 0);
  871. //DbgPrint(" Get Standard cache : %I64x %wZ\n",((PFILE_STANDARD_INFORMATION)NameCache->ContextExtension)->EndOfFile,OriginalFileName);
  872. } else {
  873. // put the entry back to the expire list
  874. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  875. }
  876. }
  877. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  878. return CacheFound;
  879. }
  880. BOOLEAN
  881. MRxSmbIsInternalFileInfoCacheFound(
  882. PRX_CONTEXT RxContext,
  883. PFILE_INTERNAL_INFORMATION Internal,
  884. NTSTATUS *Status,
  885. PUNICODE_STRING OriginalFileName
  886. )
  887. /*++
  888. Routine Description:
  889. This routine looks for the name cache entry of the file basic information.
  890. Arguments:
  891. RxContext - the RDBSS context
  892. Basic - buffer to return file basic information
  893. Status - status retured on the last reponse from server
  894. Return Value:
  895. BOOLEAN - name cache found
  896. --*/
  897. {
  898. RxCaptureFcb;
  899. UNICODE_STRING FileName;
  900. PNAME_CACHE NameCache = NULL;
  901. PMRX_NET_ROOT NetRoot;
  902. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  903. PNAME_CACHE_CONTROL NameCacheCtl;
  904. RX_NC_CHECK_STATUS NameCacheStatus;
  905. BOOLEAN CacheFound = FALSE;
  906. PAGED_CODE();
  907. if (OriginalFileName == NULL) {
  908. OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  909. }
  910. //DbgPrint(" Query Internal cache : %wZ\n",OriginalFileName);
  911. if (RxContext->MajorFunction == IRP_MJ_CREATE) {
  912. NetRoot = RxContext->Create.pNetRoot;
  913. } else {
  914. ASSERT(capFcb != NULL);
  915. NetRoot = capFcb->pNetRoot;
  916. }
  917. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  918. NameCacheCtl = &pNetRootEntry->NameCacheCtlGFAInternal;
  919. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  920. NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
  921. if (NameCache != NULL) {
  922. //
  923. // Found it. Now check entry for not expired.
  924. // Note - The NameCache entry has been pulled off the active list.
  925. //
  926. NameCacheStatus = RxNameCacheCheckEntry(
  927. NameCache,
  928. NameCache->Context);
  929. if (NameCacheStatus == RX_NC_SUCCESS) {
  930. // The name cache matches if it is not expired and the attributes matches the one of
  931. // the root file if it is a stream file. If this is a match, return the old status,
  932. // file info and reactivate the entry but leave expiration time unchanged.
  933. *Status = NameCache->PriorStatus;
  934. RxNameCacheOpSaved(NameCacheCtl);
  935. *Internal = *((PFILE_INTERNAL_INFORMATION)NameCache->ContextExtension);
  936. CacheFound = TRUE;
  937. // put the entry back to the active list without changing the expire time
  938. RxNameCacheActivateEntry(NameCacheCtl, NameCache, 0, 0);
  939. //DbgPrint(" Found Internal cache : %I64x %wZ\n",Internal->IndexNumber,OriginalFileName);
  940. } else {
  941. // put the entry back to the expire list
  942. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  943. //DbgPrint("Internal cache expired : %wZ\n",OriginalFileName);
  944. }
  945. } else {
  946. //DbgPrint(" No Internal cache : %wZ\n",OriginalFileName);
  947. }
  948. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  949. return CacheFound;
  950. }
  951. NTSTATUS
  952. MRxSmbGetFileInfoCacheStatus(
  953. PRX_CONTEXT RxContext
  954. )
  955. /*++
  956. Routine Description:
  957. This routine looks for the status of the name cache entry of either file basic or standard information.
  958. Arguments:
  959. RxContext - the RDBSS context
  960. Return Value:
  961. NTSTATUS - statu of the name cache if found, otherwise, STATUS_SUCCESS
  962. --*/
  963. {
  964. RxCaptureFcb;
  965. PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  966. PNAME_CACHE NameCache = NULL;
  967. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  968. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  969. PNAME_CACHE_CONTROL NameCacheCtlBasic = &pNetRootEntry->NameCacheCtlGFABasic;
  970. PNAME_CACHE_CONTROL NameCacheCtlStandard = &pNetRootEntry->NameCacheCtlGFAStandard;
  971. NTSTATUS Status = STATUS_MORE_PROCESSING_REQUIRED;
  972. PAGED_CODE();
  973. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  974. NameCache = RxNameCacheFetchEntry(NameCacheCtlBasic,OriginalFileName);
  975. if (NameCache != NULL) {
  976. RX_NC_CHECK_STATUS NameCacheStatus;
  977. //
  978. // Found it. Now check entry for not expired
  979. //
  980. NameCacheStatus = RxNameCacheCheckEntry(NameCache,NameCache->Context);
  981. if (NameCacheStatus == RX_NC_SUCCESS) {
  982. //
  983. // If the cache has not expired, return the previous status.
  984. //
  985. Status = NameCache->PriorStatus;
  986. RxNameCacheOpSaved(NameCacheCtlBasic);
  987. // put the entry back to the active list without changing the expire time
  988. RxNameCacheActivateEntry(NameCacheCtlBasic, NameCache, 0, 0);
  989. //DbgPrint(" Get Basic Status : %x %wZ\n",Status,OriginalFileName);
  990. RxLog((" Get Basic Status : %x %wZ\n",Status,OriginalFileName));
  991. } else {
  992. // put the entry back to the expire list
  993. RxNameCacheExpireEntry(NameCacheCtlBasic, NameCache);
  994. }
  995. } else {
  996. NameCache = RxNameCacheFetchEntry(NameCacheCtlStandard,OriginalFileName);
  997. if (NameCache != NULL) {
  998. RX_NC_CHECK_STATUS NameCacheStatus;
  999. //
  1000. // Found it. Now check entry for not expired
  1001. //
  1002. NameCacheStatus = RxNameCacheCheckEntry(NameCache,NameCache->Context);
  1003. if (NameCacheStatus == RX_NC_SUCCESS) {
  1004. //
  1005. // If the cache has not expired, return the previous status.
  1006. //
  1007. Status = NameCache->PriorStatus;
  1008. RxNameCacheOpSaved(NameCacheCtlStandard);
  1009. // put the entry back to the active list without changing the expire time
  1010. RxNameCacheActivateEntry(NameCacheCtlStandard, NameCache, 0, 0);
  1011. } else {
  1012. // put the entry back to the expire list
  1013. RxNameCacheExpireEntry(NameCacheCtlStandard, NameCache);
  1014. }
  1015. }
  1016. }
  1017. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  1018. return Status;
  1019. }
  1020. BOOLEAN
  1021. MRxSmbIsFileNotFoundCached(
  1022. PRX_CONTEXT RxContext
  1023. )
  1024. /*++
  1025. Routine Description:
  1026. This routine checks if the name cache entry exists as File Not Found.
  1027. Arguments:
  1028. RxContext - the RDBSS context
  1029. Return Value:
  1030. BOOLEAN - name cache found
  1031. --*/
  1032. {
  1033. RxCaptureFcb;
  1034. PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  1035. UNICODE_STRING StreamlessName;
  1036. PNAME_CACHE NameCache = NULL;
  1037. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  1038. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  1039. PNAME_CACHE_CONTROL NameCacheCtl = &pNetRootEntry->NameCacheCtlFNF;
  1040. BOOLEAN CacheFound = FALSE;
  1041. PAGED_CODE();
  1042. // If a file does not exist, its stream doesn't either
  1043. MRxSmbIsStreamFile( OriginalFileName, &StreamlessName );
  1044. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  1045. NameCache = RxNameCacheFetchEntry(NameCacheCtl,&StreamlessName);
  1046. if (NameCache != NULL) {
  1047. RX_NC_CHECK_STATUS NameCacheStatus;
  1048. //
  1049. // Found it. Now check entry for not expired.
  1050. // Note - The NameCache entry has been pulled off the active list.
  1051. //
  1052. NameCacheStatus = RxNameCacheCheckEntry(
  1053. NameCache,
  1054. //MRxSmbStatistics.SmbsReceived.LowPart
  1055. NameCache->Context);
  1056. if ((NameCacheStatus == RX_NC_SUCCESS) &&
  1057. (NameCache->PriorStatus == STATUS_OBJECT_NAME_NOT_FOUND)) {
  1058. //
  1059. // This is a match. Return the old status, file info and
  1060. // reactivate the entry but leave expiration time unchanged.
  1061. //
  1062. CacheFound = TRUE;
  1063. // put the entry back to the active list without changing the expire time
  1064. RxNameCacheActivateEntry(NameCacheCtl, NameCache, 0, 0);
  1065. } else {
  1066. // put the entry back to the expire list
  1067. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  1068. }
  1069. }
  1070. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  1071. return CacheFound;
  1072. }
  1073. VOID
  1074. MRxSmbCacheFileNotFound(
  1075. PRX_CONTEXT RxContext
  1076. )
  1077. /*++
  1078. Routine Description:
  1079. This routine creates the name cache entry for File Not Found.
  1080. Arguments:
  1081. RxContext - the RDBSS context
  1082. Return Value:
  1083. BOOLEAN - name cache found
  1084. --*/
  1085. {
  1086. RxCaptureFcb;
  1087. PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  1088. PNAME_CACHE NameCache = NULL;
  1089. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  1090. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  1091. PNAME_CACHE_CONTROL NameCacheCtl = &pNetRootEntry->NameCacheCtlFNF;
  1092. PAGED_CODE();
  1093. // Never cache stream file opens
  1094. if( MRxSmbIsStreamFile( OriginalFileName, NULL ) )
  1095. {
  1096. return;
  1097. }
  1098. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  1099. NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
  1100. if (NameCache != NULL) {
  1101. NameCache->PriorStatus = STATUS_OBJECT_NAME_NOT_FOUND;
  1102. RxNameCacheActivateEntry(
  1103. NameCacheCtl,
  1104. NameCache,
  1105. NAME_CACHE_OBJ_NAME_NOT_FOUND_LIFETIME,
  1106. MRxSmbStatistics.SmbsReceived.LowPart);
  1107. } else {
  1108. if (FlagOn(NetRoot->Flags,NETROOT_FLAG_UNIQUE_FILE_NAME)) {
  1109. NameCache = RxNameCacheCreateEntry (
  1110. NameCacheCtl,
  1111. OriginalFileName,
  1112. TRUE); // case insensitive match
  1113. if (NameCache != NULL) {
  1114. NameCache->PriorStatus = STATUS_OBJECT_NAME_NOT_FOUND;
  1115. RxNameCacheActivateEntry(
  1116. NameCacheCtl,
  1117. NameCache,
  1118. 1,
  1119. MRxSmbStatistics.SmbsReceived.LowPart);
  1120. }
  1121. }
  1122. }
  1123. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  1124. }
  1125. VOID
  1126. MRxSmbCacheFileNotFoundFromQueryDirectory(
  1127. PRX_CONTEXT RxContext
  1128. )
  1129. /*++
  1130. Routine Description:
  1131. This routine creates the name cache entry for File Not Found.
  1132. Arguments:
  1133. RxContext - the RDBSS context
  1134. Return Value:
  1135. BOOLEAN - name cache found
  1136. --*/
  1137. {
  1138. RxCaptureFcb;
  1139. RxCaptureFobx;
  1140. PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  1141. PUNICODE_STRING Template = &capFobx->UnicodeQueryTemplate;
  1142. UNICODE_STRING FileName;
  1143. PNAME_CACHE NameCache = NULL;
  1144. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  1145. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  1146. PNAME_CACHE_CONTROL NameCacheCtl = &pNetRootEntry->NameCacheCtlFNF;
  1147. PAGED_CODE();
  1148. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  1149. NameCache = RxNameCacheFetchEntry(NameCacheCtl,&FileName);
  1150. if (NameCache != NULL) {
  1151. if ((NameCache == NULL) &&
  1152. (OriginalFileName->Length > sizeof(WCHAR))) {
  1153. //
  1154. // Do lookup now since we may have skipped it at entry.
  1155. //
  1156. NameCache = RxNameCacheFetchEntry(NameCacheCtl,&FileName);
  1157. if (NameCache == NULL) {
  1158. NameCache = RxNameCacheCreateEntry (
  1159. NameCacheCtl,
  1160. OriginalFileName,
  1161. TRUE); // case insensitive match
  1162. }
  1163. }
  1164. if (NameCache != NULL) {
  1165. NameCache->PriorStatus = STATUS_OBJECT_NAME_NOT_FOUND;
  1166. RxNameCacheActivateEntry(
  1167. NameCacheCtl,
  1168. NameCache,
  1169. NAME_CACHE_OBJ_NAME_NOT_FOUND_LIFETIME,
  1170. MRxSmbStatistics.SmbsReceived.LowPart);
  1171. }
  1172. }
  1173. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  1174. }
  1175. VOID
  1176. MRxSmbInvalidateFileNotFoundCache(
  1177. PRX_CONTEXT RxContext
  1178. )
  1179. /*++
  1180. Routine Description:
  1181. This routine invalidates the name cache entry as File Not Found.
  1182. Arguments:
  1183. RxContext - the RDBSS context
  1184. Return Value:
  1185. BOOLEAN - name cache found
  1186. --*/
  1187. {
  1188. RxCaptureFcb;
  1189. PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  1190. UNICODE_STRING StreamlessName;
  1191. PNAME_CACHE NameCache = NULL;
  1192. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  1193. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  1194. PNAME_CACHE_CONTROL NameCacheCtl = &pNetRootEntry->NameCacheCtlFNF;
  1195. PAGED_CODE();
  1196. // If we invalidate a stream, this invalidates the associated file entry
  1197. MRxSmbIsStreamFile( OriginalFileName, &StreamlessName );
  1198. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  1199. NameCache = RxNameCacheFetchEntry(NameCacheCtl, &StreamlessName);
  1200. if (NameCache != NULL) {
  1201. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  1202. }
  1203. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  1204. }
  1205. VOID
  1206. MRxSmbInvalidateFileNotFoundCacheForRename(
  1207. PRX_CONTEXT RxContext
  1208. )
  1209. /*++
  1210. Routine Description:
  1211. This routine invalidates the name cache entry as File Not Found.
  1212. Arguments:
  1213. RxContext - the RDBSS context
  1214. Return Value:
  1215. BOOLEAN - name cache found
  1216. --*/
  1217. {
  1218. RxCaptureFcb;
  1219. UNICODE_STRING RenameName;
  1220. UNICODE_STRING StreamlessName;
  1221. PNAME_CACHE NameCache = NULL;
  1222. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  1223. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  1224. PNAME_CACHE_CONTROL NameCacheCtl = &pNetRootEntry->NameCacheCtlFNF;
  1225. PFILE_RENAME_INFORMATION RenameInformation = RxContext->Info.Buffer;
  1226. RenameName.Buffer = &RenameInformation->FileName[0];
  1227. RenameName.Length = (USHORT)RenameInformation->FileNameLength;
  1228. //DbgPrint("Invalidate FNF cache %wZ\n", &RenameName);
  1229. PAGED_CODE();
  1230. // If we rename a stream, invalidate the name without the stream
  1231. MRxSmbIsStreamFile( &RenameName, &StreamlessName );
  1232. ExAcquireFastMutex(&MRxSmbFileInfoCacheLock);
  1233. NameCache = RxNameCacheFetchEntry(NameCacheCtl,&StreamlessName);
  1234. if (NameCache != NULL) {
  1235. RxNameCacheExpireEntry(NameCacheCtl, NameCache);
  1236. }
  1237. ExReleaseFastMutex(&MRxSmbFileInfoCacheLock);
  1238. }
  1239. BOOLEAN
  1240. MRxSmbIsStreamFile(
  1241. PUNICODE_STRING FileName,
  1242. PUNICODE_STRING AdjustFileName
  1243. )
  1244. /*++
  1245. Routine Description:
  1246. This routine checks if it is a stream file and return the root file name if true.
  1247. Arguments:
  1248. FileName - the file name needs to be parsed
  1249. AdjustFileName - the file name contains only root name of the stream
  1250. Return Value:
  1251. BOOLEAN - stream file
  1252. --*/
  1253. {
  1254. USHORT i;
  1255. BOOLEAN IsStream = FALSE;
  1256. NTSTATUS Status = STATUS_SUCCESS;
  1257. for (i=0;i<FileName->Length/sizeof(WCHAR);i++) {
  1258. if (FileName->Buffer[i] == L':') {
  1259. IsStream = TRUE;
  1260. break;
  1261. }
  1262. }
  1263. if (AdjustFileName != NULL) {
  1264. if (IsStream) {
  1265. AdjustFileName->Length =
  1266. AdjustFileName->MaximumLength = i * sizeof(WCHAR);
  1267. AdjustFileName->Buffer = FileName->Buffer;
  1268. } else {
  1269. AdjustFileName->Length =
  1270. AdjustFileName->MaximumLength = FileName->Length;
  1271. AdjustFileName->Buffer = FileName->Buffer;
  1272. }
  1273. }
  1274. return IsStream;
  1275. }
  1276. BOOLEAN EnableInfoCache = TRUE;
  1277. BOOLEAN
  1278. MRxSmbIsLongFileName(
  1279. PRX_CONTEXT RxContext
  1280. )
  1281. /*++
  1282. Routine Description:
  1283. This routine checks if it is a short file name and return the first part of short name if true.
  1284. Arguments:
  1285. FileName - the file name needs to be parsed
  1286. AdjustFileName - the file name contains only root name of the stream
  1287. Return Value:
  1288. BOOLEAN - stream file
  1289. --*/
  1290. {
  1291. RxCaptureFcb;
  1292. RxCaptureFobx;
  1293. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  1294. BOOLEAN IsLongName = FALSE;
  1295. if (!EnableInfoCache) {
  1296. return TRUE;
  1297. }
  1298. if (FlagOn(smbFcb->MFlags, SMB_FCB_FLAG_LONG_FILE_NAME)) {
  1299. IsLongName = TRUE;
  1300. } else {
  1301. USHORT i;
  1302. USHORT Left = 0;
  1303. USHORT Right = 0;
  1304. OEM_STRING OemString;
  1305. BOOLEAN RightPart = FALSE;
  1306. WCHAR LastChar = 0;
  1307. WCHAR CurrentChar = 0;
  1308. PUNICODE_STRING FileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  1309. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext = NULL;
  1310. PSMBCE_NET_ROOT pSmbNetRoot = NULL;
  1311. if (RxContext->MajorFunction == IRP_MJ_CREATE) {
  1312. pVNetRootContext = RxContext->Create.pVNetRoot->Context;
  1313. pSmbNetRoot = &pVNetRootContext->pNetRootEntry->NetRoot;
  1314. } else {
  1315. ASSERT(capFobx != NULL);
  1316. pVNetRootContext = (PSMBCE_V_NET_ROOT_CONTEXT)capFobx->pSrvOpen->pVNetRoot->Context;
  1317. pSmbNetRoot = &pVNetRootContext->pNetRootEntry->NetRoot;
  1318. }
  1319. for (i=0;i<FileName->Length/sizeof(WCHAR);i++) {
  1320. LastChar = CurrentChar;
  1321. CurrentChar = FileName->Buffer[i];
  1322. if (CurrentChar == L'\\') {
  1323. RightPart = FALSE;
  1324. Left = 0;
  1325. Right = 0;
  1326. continue;
  1327. }
  1328. if (CurrentChar == L'.') {
  1329. if (RightPart) {
  1330. IsLongName = TRUE;
  1331. break;
  1332. } else {
  1333. RightPart = TRUE;
  1334. Right = 0;
  1335. continue;
  1336. }
  1337. }
  1338. if (CurrentChar >= L'0' && CurrentChar <= L'9' ||
  1339. CurrentChar >= L'a' && CurrentChar <= L'z' ||
  1340. CurrentChar >= L'A' && CurrentChar <= L'Z' ||
  1341. CurrentChar == L'~' ||
  1342. CurrentChar == L'_' ||
  1343. CurrentChar == L'$' ||
  1344. CurrentChar == L'@') {
  1345. if (RightPart) {
  1346. if (++Right > 3) {
  1347. IsLongName = TRUE;
  1348. break;
  1349. }
  1350. } else {
  1351. if (++Left > 8) {
  1352. IsLongName = TRUE;
  1353. break;
  1354. }
  1355. }
  1356. if (pSmbNetRoot->NetRootFileSystem != NET_ROOT_FILESYSTEM_NTFS) {
  1357. if (CurrentChar >= L'A' && CurrentChar <= L'Z' &&
  1358. LastChar >= L'a' && LastChar <= L'z' ||
  1359. CurrentChar >= L'a' && CurrentChar <= L'z' &&
  1360. LastChar >= L'A' && LastChar <= L'Z') {
  1361. // On FAT volume, name with mixture of cases will be treated as long name
  1362. IsLongName = TRUE;
  1363. break;
  1364. }
  1365. }
  1366. } else {
  1367. // if not, an alternate name may be created by the server which will
  1368. // be different from this name.
  1369. IsLongName = TRUE;
  1370. break;
  1371. }
  1372. }
  1373. }
  1374. if (IsLongName) {
  1375. SetFlag(smbFcb->MFlags, SMB_FCB_FLAG_LONG_FILE_NAME);
  1376. }
  1377. return IsLongName;
  1378. }