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.

1291 lines
35 KiB

  1. /*
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. fsp_fork.c
  5. Abstract:
  6. This module contains the entry points for the AFP fork APIs queued to
  7. the FSP. These are all callable from FSP Only.
  8. Author:
  9. Jameel Hyder (microsoft!jameelh)
  10. Revision History:
  11. 25 Apr 1992 Initial Version
  12. Notes: Tab stop: 4
  13. --*/
  14. #define FILENUM FILE_FSP_FORK
  15. #include <afp.h>
  16. #include <gendisp.h>
  17. #include <fdparm.h>
  18. #include <pathmap.h>
  19. #include <forkio.h>
  20. #ifdef ALLOC_PRAGMA
  21. // #pragma alloc_text( PAGE, AfpFspDispOpenFork) // Do not page this out for perf.
  22. // #pragma alloc_text( PAGE, AfpFspDispCloseFork) // Do not page this out for perf.
  23. #pragma alloc_text( PAGE, AfpFspDispGetForkParms)
  24. #pragma alloc_text( PAGE, AfpFspDispSetForkParms)
  25. // #pragma alloc_text( PAGE, AfpFspDispRead) // Do not page this out for perf.
  26. // #pragma alloc_text( PAGE, AfpFspDispWrite) // Do not page this out for perf.
  27. #pragma alloc_text( PAGE, AfpFspDispByteRangeLock)
  28. #pragma alloc_text( PAGE, AfpFspDispFlushFork)
  29. #endif
  30. /*** AfpFspDispOpenFork
  31. *
  32. * This is the worker routine for the AfpOpenFork API.
  33. *
  34. * The request packet is represented below.
  35. *
  36. * sda_AfpSubFunc BYTE Resource/Data Flag
  37. * sda_ReqBlock PCONNDESC pConnDesc
  38. * sda_ReqBlock DWORD ParentDirId
  39. * sda_ReqBlock DWORD Bitmap
  40. * sda_ReqBlock DWORD AccessMode
  41. * sda_Name1 ANSI_STRING Path
  42. */
  43. AFPSTATUS FASTCALL
  44. AfpFspDispOpenFork(
  45. IN PSDA pSda
  46. )
  47. {
  48. DWORD Bitmap, BitmapI;
  49. AFPSTATUS RetCode = AFP_ERR_NONE, Status = AFP_ERR_PARAM;
  50. FILEDIRPARM FDParm;
  51. PVOLDESC pVolDesc;
  52. PATHMAPENTITY PME;
  53. PCONNDESC pConnDesc;
  54. POPENFORKENTRY pOpenForkEntry = NULL;
  55. BOOLEAN Resource, CleanupLock = False;
  56. BYTE OpenMode = 0;
  57. UNICODE_STRING ParentPath;
  58. struct _RequestPacket
  59. {
  60. PCONNDESC _pConnDesc;
  61. DWORD _ParentDirId;
  62. DWORD _Bitmap;
  63. DWORD _AccessMode;
  64. };
  65. struct _ResponsePacket
  66. {
  67. BYTE __Bitmap[2];
  68. BYTE __OForkRefNum[2];
  69. };
  70. #if DBG
  71. static PBYTE OpenDeny[] = { "None", "Read", "Write", "ReadWrite" };
  72. #endif
  73. PAGED_CODE( );
  74. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  75. ("AfpFspDispOpenFork: Entered - Session %ld\n", pSda->sda_SessionId));
  76. pConnDesc = pReqPkt->_pConnDesc;
  77. ASSERT(VALID_CONNDESC(pConnDesc));
  78. pVolDesc = pConnDesc->cds_pVolDesc;
  79. ASSERT(VALID_VOLDESC(pVolDesc));
  80. Bitmap = pReqPkt->_Bitmap;
  81. Resource = ((pSda->sda_AfpSubFunc & FORK_RSRC) == FORK_RSRC) ? True : False;
  82. if ((Resource && (Bitmap & FILE_BITMAP_DATALEN)) ||
  83. (!Resource && (Bitmap & FILE_BITMAP_RESCLEN)))
  84. {
  85. return AFP_ERR_BITMAP;
  86. }
  87. do
  88. {
  89. AfpInitializeFDParms(&FDParm);
  90. AfpInitializePME(&PME, 0, NULL);
  91. // We will use the PME.pme_Handle for open fork handle
  92. OpenMode = (BYTE)(pReqPkt->_AccessMode & FORK_OPEN_MASK);
  93. // Validate volume type and open modes
  94. if (!IS_CONN_NTFS(pConnDesc) && !IS_CONN_CD_HFS(pConnDesc))
  95. {
  96. // Resource fork only supported on NTFS and CD-HFS
  97. if (Resource)
  98. {
  99. Status = AFP_ERR_OBJECT_NOT_FOUND;
  100. break;
  101. }
  102. if (OpenMode & FORK_OPEN_WRITE)
  103. {
  104. Status = AFP_ERR_VOLUME_LOCKED;
  105. break;
  106. }
  107. }
  108. else if ((OpenMode & FORK_OPEN_WRITE) && IS_VOLUME_RO(pVolDesc))
  109. {
  110. Status = AFP_ERR_VOLUME_LOCKED;
  111. break;
  112. }
  113. BitmapI = FILE_BITMAP_FILENUM |
  114. FD_BITMAP_PARENT_DIRID |
  115. FD_INTERNAL_BITMAP_RETURN_PMEPATHS;
  116. // Encode the open access into the bitmap for pathmap
  117. // to use when opening the fork.
  118. if (Resource)
  119. {
  120. BitmapI |= FD_INTERNAL_BITMAP_OPENFORK_RESC;
  121. }
  122. if (OpenMode & FORK_OPEN_READ)
  123. {
  124. BitmapI |= FD_INTERNAL_BITMAP_OPENACCESS_READ;
  125. }
  126. if (OpenMode & FORK_OPEN_WRITE)
  127. {
  128. BitmapI |= FD_INTERNAL_BITMAP_OPENACCESS_WRITE;
  129. }
  130. // Encode the deny mode into the bitmap for pathmap
  131. // to use when opening the fork.
  132. BitmapI |= ((pReqPkt->_AccessMode >> FORK_DENY_SHIFT) &
  133. FORK_DENY_MASK) <<
  134. FD_INTERNAL_BITMAP_DENYMODE_SHIFT;
  135. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  136. ("AfpFspDispOpenFork: OpenMode %s, DenyMode %s\n",
  137. OpenDeny[(pReqPkt->_AccessMode & FORK_OPEN_MASK)],
  138. OpenDeny[(pReqPkt->_AccessMode >> FORK_DENY_SHIFT) & FORK_DENY_MASK]));
  139. //
  140. // Don't allow an FpExchangeFiles to occur while we are referencing
  141. // the DFE FileId -- we want to make sure we put the right ID into
  142. // the OpenForkDesc!!
  143. //
  144. AfpSwmrAcquireExclusive(&pVolDesc->vds_ExchangeFilesLock);
  145. CleanupLock = True;
  146. if ((Status = AfpMapAfpPathForLookup(pConnDesc,
  147. pReqPkt->_ParentDirId,
  148. &pSda->sda_Name1,
  149. pSda->sda_PathType,
  150. DFE_FILE,
  151. Bitmap | BitmapI |
  152. // Need these for drop folder
  153. // checking
  154. FILE_BITMAP_DATALEN | FILE_BITMAP_RESCLEN,
  155. &PME,
  156. &FDParm)) != AFP_ERR_NONE)
  157. {
  158. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  159. ("AfpFspDispOpenFork: AfpMapAfpPathForLookup %lx\n", Status));
  160. // If we got a DENY_CONFLICT error, then we still need the parameters
  161. // Do an open for nothing with no deny modes to get the parameters.
  162. PME.pme_Handle.fsh_FileHandle = NULL;
  163. if (Status == AFP_ERR_DENY_CONFLICT)
  164. {
  165. AFPSTATUS xxStatus;
  166. // Free up any path-buffer allocated
  167. if (PME.pme_FullPath.Buffer != NULL)
  168. {
  169. DBGPRINT(DBG_COMP_FORKS, DBG_LEVEL_INFO,
  170. ("AfpFspDispOpenFork: (DenyConflict) Freeing path buffer %lx\n",
  171. PME.pme_FullPath.Buffer));
  172. AfpFreeMemory(PME.pme_FullPath.Buffer);
  173. }
  174. AfpInitializePME(&PME, 0, NULL);
  175. BitmapI = FILE_BITMAP_FILENUM |
  176. FD_BITMAP_PARENT_DIRID |
  177. FD_INTERNAL_BITMAP_RETURN_PMEPATHS;
  178. if (Resource)
  179. {
  180. BitmapI |= FD_INTERNAL_BITMAP_OPENFORK_RESC;
  181. }
  182. xxStatus = AfpMapAfpPathForLookup(pConnDesc,
  183. pReqPkt->_ParentDirId,
  184. &pSda->sda_Name1,
  185. pSda->sda_PathType,
  186. DFE_FILE,
  187. Bitmap | BitmapI,
  188. &PME,
  189. &FDParm);
  190. if (!NT_SUCCESS(xxStatus))
  191. {
  192. PME.pme_Handle.fsh_FileHandle = NULL;
  193. Status = xxStatus;
  194. break;
  195. }
  196. }
  197. else break;
  198. }
  199. if (Status == AFP_ERR_NONE)
  200. {
  201. Status = AfpForkOpen(pSda,
  202. pConnDesc,
  203. &PME,
  204. &FDParm,
  205. pReqPkt->_AccessMode,
  206. Resource,
  207. &pOpenForkEntry,
  208. &CleanupLock);
  209. }
  210. // At this point we have either successfully opened the fork,
  211. // encountered a DENY_CONFLICT or some other error.
  212. if ((Status != AFP_ERR_NONE) &&
  213. (Status != AFP_ERR_DENY_CONFLICT))
  214. break;
  215. // Do drop folder sanity check if someone tries to open for Write only
  216. if ((Status == AFP_ERR_NONE) &&
  217. (OpenMode == FORK_OPEN_WRITE) &&
  218. ((FDParm._fdp_RescForkLen != 0) ||
  219. (FDParm._fdp_DataForkLen != 0)))
  220. {
  221. ASSERT (VALID_OPENFORKENTRY(pOpenForkEntry));
  222. // If either fork is not empty, and one of them is being
  223. // opened for write, the user must also have READ access
  224. // to the parent directory.
  225. ParentPath = pOpenForkEntry->ofe_pOpenForkDesc->ofd_FilePath;
  226. // adjust the length to not include the filename
  227. ParentPath.Length -= pOpenForkEntry->ofe_pOpenForkDesc->ofd_FileName.Length;
  228. if (ParentPath.Length > 0)
  229. {
  230. ParentPath.Length -= sizeof(WCHAR);
  231. }
  232. AfpSwmrAcquireExclusive(&pVolDesc->vds_IdDbAccessLock);
  233. Status = AfpCheckParentPermissions(pConnDesc,
  234. FDParm._fdp_ParentId,
  235. &ParentPath,
  236. DIR_ACCESS_READ,
  237. NULL,
  238. NULL);
  239. AfpSwmrRelease(&pVolDesc->vds_IdDbAccessLock);
  240. //
  241. // We are no longer referencing the FileId or path kept
  242. // in the OpenForkDesc. Ok for FpExchangeFiles to resume.
  243. //
  244. AfpSwmrRelease(&pVolDesc->vds_ExchangeFilesLock);
  245. CleanupLock = False;
  246. if (Status != AFP_ERR_NONE)
  247. {
  248. AfpForkClose(pOpenForkEntry);
  249. AfpForkDereference(pOpenForkEntry);
  250. // set this to null so it wont be upgraded/deref'd
  251. // in cleanup below
  252. pOpenForkEntry = NULL;
  253. // Set handle to null since it was closed in AfpForkClose
  254. // and we wont want it to be closed in cleanup below
  255. PME.pme_Handle.fsh_FileHandle = NULL;
  256. break;
  257. }
  258. }
  259. else
  260. {
  261. AfpSwmrRelease(&pVolDesc->vds_ExchangeFilesLock);
  262. CleanupLock = False;
  263. }
  264. if (RetCode == AFP_ERR_NONE)
  265. {
  266. pSda->sda_ReplySize = SIZE_RESPPKT +
  267. EVENALIGN(AfpGetFileDirParmsReplyLength(&FDParm, Bitmap));
  268. if ((RetCode = AfpAllocReplyBuf(pSda)) != AFP_ERR_NONE)
  269. {
  270. if (pOpenForkEntry != NULL)
  271. AfpForkClose(pOpenForkEntry);
  272. break;
  273. }
  274. AfpPackFileDirParms(&FDParm,
  275. Bitmap,
  276. pSda->sda_ReplyBuf + SIZE_RESPPKT);
  277. PUTDWORD2SHORT(pRspPkt->__Bitmap, Bitmap);
  278. PUTDWORD2SHORT(pRspPkt->__OForkRefNum, (pOpenForkEntry == NULL) ?
  279. 0 : pOpenForkEntry->ofe_OForkRefNum);
  280. if (Status == AFP_ERR_NONE)
  281. {
  282. INTERLOCKED_INCREMENT_LONG(&pConnDesc->cds_cOpenForks);
  283. }
  284. }
  285. else Status = RetCode;
  286. } while (False);
  287. if (CleanupLock)
  288. {
  289. AfpSwmrRelease(&pVolDesc->vds_ExchangeFilesLock);
  290. }
  291. // update the disk quota for this user
  292. if (pVolDesc->vds_Flags & VOLUME_DISKQUOTA_ENABLED)
  293. {
  294. if (AfpConnectionReferenceByPointer(pConnDesc) != NULL)
  295. {
  296. afpUpdateDiskQuotaInfo(pConnDesc);
  297. }
  298. }
  299. if (pOpenForkEntry != NULL)
  300. {
  301. if (Status == AFP_ERR_NONE)
  302. AfpUpgradeHandle(&pOpenForkEntry->ofe_FileSysHandle);
  303. AfpForkDereference(pOpenForkEntry);
  304. }
  305. if (!NT_SUCCESS(Status))
  306. {
  307. if (PME.pme_Handle.fsh_FileHandle != NULL)
  308. AfpIoClose(&PME.pme_Handle);
  309. }
  310. if (PME.pme_FullPath.Buffer != NULL)
  311. {
  312. DBGPRINT(DBG_COMP_FORKS, DBG_LEVEL_INFO,
  313. ("AfpFspDispOpenFork: Freeing path buffer %lx\n",
  314. PME.pme_FullPath.Buffer));
  315. AfpFreeMemory(PME.pme_FullPath.Buffer);
  316. }
  317. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  318. ("AfpFspDispOpenFork: Returning %ld\n", Status));
  319. return Status;
  320. }
  321. /*** AfpFspDispCloseFork
  322. *
  323. * This is the worker routine for the AfpCloseFork API.
  324. *
  325. * The request packet is represented below.
  326. *
  327. * sda_ReqBlock POPENFORKENTRY pOpenForkEntry
  328. */
  329. AFPSTATUS FASTCALL
  330. AfpFspDispCloseFork(
  331. IN PSDA pSda
  332. )
  333. {
  334. struct _RequestPacket
  335. {
  336. POPENFORKENTRY _pOpenForkEntry;
  337. };
  338. PAGED_CODE( );
  339. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  340. ("AfpFspDispCloseFork: Entered - Session %ld, Fork %ld\n",
  341. pSda->sda_SessionId, pReqPkt->_pOpenForkEntry->ofe_ForkId));
  342. ASSERT(VALID_OPENFORKENTRY(pReqPkt->_pOpenForkEntry));
  343. AfpForkClose(pReqPkt->_pOpenForkEntry);
  344. return AFP_ERR_NONE;
  345. }
  346. /*** AfpFspDispGetForkParms
  347. *
  348. * This is the worker routine for the AfpGetForkParms API.
  349. *
  350. * The request packet is represented below.
  351. *
  352. * sda_ReqBlock POPENFORKENTRY pOpenForkEntry
  353. * sda_ReqBlock DWORD Bitmap
  354. */
  355. AFPSTATUS FASTCALL
  356. AfpFspDispGetForkParms(
  357. IN PSDA pSda
  358. )
  359. {
  360. FILEDIRPARM FDParm;
  361. DWORD Bitmap;
  362. AFPSTATUS Status = AFP_ERR_PARAM;
  363. struct _RequestPacket
  364. {
  365. POPENFORKENTRY _pOpenForkEntry;
  366. DWORD _Bitmap;
  367. };
  368. struct _ResponsePacket
  369. {
  370. BYTE __Bitmap[2];
  371. };
  372. PAGED_CODE( );
  373. ASSERT(VALID_OPENFORKENTRY(pReqPkt->_pOpenForkEntry));
  374. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  375. ("AfpFspDispGetForkParms: Entered Session %ld, Fork %ld\n",
  376. pSda->sda_SessionId, pReqPkt->_pOpenForkEntry->ofe_ForkId));
  377. Bitmap = pReqPkt->_Bitmap;
  378. do
  379. {
  380. if ((RESCFORK(pReqPkt->_pOpenForkEntry) && (Bitmap & FILE_BITMAP_DATALEN)) ||
  381. (DATAFORK(pReqPkt->_pOpenForkEntry) && (Bitmap & FILE_BITMAP_RESCLEN)))
  382. {
  383. Status = AFP_ERR_BITMAP;
  384. break;
  385. }
  386. AfpInitializeFDParms(&FDParm);
  387. // Optimize for the most common case.
  388. if ((Bitmap & (FILE_BITMAP_DATALEN | FILE_BITMAP_RESCLEN)) != 0)
  389. {
  390. FORKOFFST ForkLength;
  391. Status = AfpIoQuerySize(&pReqPkt->_pOpenForkEntry->ofe_FileSysHandle,
  392. &ForkLength);
  393. ASSERT(NT_SUCCESS(Status));
  394. if (Bitmap & FILE_BITMAP_DATALEN)
  395. FDParm._fdp_DataForkLen = ForkLength.LowPart;
  396. else FDParm._fdp_RescForkLen = ForkLength.LowPart;
  397. FDParm._fdp_Flags = 0; // Take out the directory flag
  398. }
  399. // If we need more stuff, go get it
  400. if (Bitmap & ~(FILE_BITMAP_DATALEN | FILE_BITMAP_RESCLEN))
  401. {
  402. CONNDESC ConnDesc;
  403. POPENFORKDESC pOpenForkDesc = pReqPkt->_pOpenForkEntry->ofe_pOpenForkDesc;
  404. // Since the following call requires a pConnDesc and we do not
  405. // really have one, manufacture it
  406. ConnDesc.cds_pSda = pSda;
  407. ConnDesc.cds_pVolDesc = pOpenForkDesc->ofd_pVolDesc;
  408. // Don't let FpExchangeFiles come in while we are accessing
  409. // the stored FileId and its corresponding DFE
  410. AfpSwmrAcquireExclusive(&ConnDesc.cds_pVolDesc->vds_ExchangeFilesLock);
  411. Status = AfpMapAfpIdForLookup(&ConnDesc,
  412. pOpenForkDesc->ofd_FileNumber,
  413. DFE_FILE,
  414. Bitmap & ~(FILE_BITMAP_DATALEN | FILE_BITMAP_RESCLEN),
  415. NULL,
  416. &FDParm);
  417. AfpSwmrRelease(&ConnDesc.cds_pVolDesc->vds_ExchangeFilesLock);
  418. if (Status != AFP_ERR_NONE)
  419. {
  420. break;
  421. }
  422. }
  423. if (Status == AFP_ERR_NONE)
  424. {
  425. pSda->sda_ReplySize = SIZE_RESPPKT +
  426. EVENALIGN(AfpGetFileDirParmsReplyLength(&FDParm, Bitmap));
  427. if ((Status = AfpAllocReplyBuf(pSda)) == AFP_ERR_NONE)
  428. {
  429. AfpPackFileDirParms(&FDParm, Bitmap, pSda->sda_ReplyBuf + SIZE_RESPPKT);
  430. PUTDWORD2SHORT(&pRspPkt->__Bitmap, Bitmap);
  431. }
  432. }
  433. } while (False);
  434. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  435. ("AfpFspDispGetForkParms: Returning %ld\n", Status));
  436. return Status;
  437. }
  438. /*** AfpFspDispSetForkParms
  439. *
  440. * This is the worker routine for the AfpSetForkParms API.
  441. * Only thing that can be set with this API is the fork length.
  442. *
  443. * The request packet is represented below.
  444. *
  445. * sda_ReqBlock POPENFORKENTRY pOpenForkEntry
  446. * sda_ReqBlock DWORD Bitmap
  447. * sda_ReqBlock LONG ForkLength
  448. *
  449. * LOCKS: vds_IdDbAccessLock (SWMR, Exclusive)
  450. */
  451. AFPSTATUS FASTCALL
  452. AfpFspDispSetForkParms(
  453. IN PSDA pSda
  454. )
  455. {
  456. AFPSTATUS Status;
  457. DWORD Bitmap;
  458. BOOLEAN SetSize = False;
  459. PVOLDESC pVolDesc;
  460. PCONNDESC pConnDesc;
  461. struct _RequestPacket
  462. {
  463. POPENFORKENTRY _pOpenForkEntry;
  464. DWORD _Bitmap;
  465. LONG _ForkLength;
  466. };
  467. PAGED_CODE( );
  468. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  469. ("AfpFspDispSetForkParms: Entered Session %ld Fork %ld, Length %ld\n",
  470. pSda->sda_SessionId, pReqPkt->_pOpenForkEntry->ofe_ForkId,
  471. pReqPkt->_ForkLength));
  472. ASSERT(VALID_OPENFORKENTRY(pReqPkt->_pOpenForkEntry));
  473. Bitmap = pReqPkt->_Bitmap;
  474. do
  475. {
  476. if ((RESCFORK(pReqPkt->_pOpenForkEntry) &&
  477. (pReqPkt->_Bitmap & FILE_BITMAP_DATALEN)) ||
  478. (DATAFORK(pReqPkt->_pOpenForkEntry) &&
  479. (pReqPkt->_Bitmap & FILE_BITMAP_RESCLEN)))
  480. {
  481. Status = AFP_ERR_BITMAP;
  482. break;
  483. }
  484. if (!(pReqPkt->_pOpenForkEntry->ofe_OpenMode & FORK_OPEN_WRITE))
  485. {
  486. Status = AFP_ERR_ACCESS_DENIED;
  487. break;
  488. }
  489. else if (pReqPkt->_ForkLength >= 0)
  490. {
  491. FORKSIZE OldSize;
  492. // We don't try to catch our own changes for setting
  493. // forksize because we don't know how many times the mac
  494. // will set the size before closing the handle. Since
  495. // a notification will only come in once the handle is
  496. // closed, we may pile up a whole bunch of our changes
  497. // in the list, but only one of them will get satisfied.
  498. //
  499. // We also do not want to attempt a change if the current length
  500. // is same as what it is being set to (this happens a lot,
  501. // unfortunately). Catch this red-handed.
  502. Status = AfpIoQuerySize(&pReqPkt->_pOpenForkEntry->ofe_FileSysHandle,
  503. &OldSize);
  504. ASSERT (NT_SUCCESS(Status));
  505. if (!(((LONG)(OldSize.LowPart) == pReqPkt->_ForkLength) &&
  506. (OldSize.HighPart == 0)))
  507. {
  508. SetSize = True;
  509. Status = AfpIoSetSize(&pReqPkt->_pOpenForkEntry->ofe_FileSysHandle,
  510. pReqPkt->_ForkLength);
  511. // update the disk quota for this user
  512. pVolDesc = pReqPkt->_pOpenForkEntry->ofe_pConnDesc->cds_pVolDesc;
  513. if (pVolDesc->vds_Flags & VOLUME_DISKQUOTA_ENABLED)
  514. {
  515. pConnDesc = pReqPkt->_pOpenForkEntry->ofe_pConnDesc;
  516. if (AfpConnectionReferenceByPointer(pConnDesc) != NULL)
  517. {
  518. afpUpdateDiskQuotaInfo(pConnDesc);
  519. }
  520. }
  521. }
  522. // Update the Dfe view of the fork length. Don't update the cached
  523. // modified time even though it does change on NTFS immediately
  524. // (LastWriteTime for setting length of data fork, ChangeTime for
  525. // setting length of resource fork). We will let the
  526. // change notify update the modified time when the handle is closed.
  527. // Appleshare 3.0 and 4.0 do not reflect a changed modified time for
  528. // changing fork length until the fork is closed (or flushed).
  529. if (NT_SUCCESS(Status) && SetSize)
  530. {
  531. PVOLDESC pVolDesc;
  532. PDFENTRY pDfEntry;
  533. POPENFORKDESC pOpenForkDesc;
  534. pOpenForkDesc = pReqPkt->_pOpenForkEntry->ofe_pOpenForkDesc;
  535. pVolDesc = pOpenForkDesc->ofd_pVolDesc;
  536. // Don't let FpExchangeFiles come in while we are accessing
  537. // the stored FileId and its corresponding DFE
  538. AfpSwmrAcquireExclusive(&pVolDesc->vds_ExchangeFilesLock);
  539. AfpSwmrAcquireExclusive(&pVolDesc->vds_IdDbAccessLock);
  540. if ((pDfEntry = AfpFindDfEntryById(pVolDesc,
  541. pOpenForkDesc->ofd_FileNumber,
  542. DFE_FILE)) != NULL)
  543. {
  544. ASSERT (VALID_DFE(pDfEntry));
  545. if (RESCFORK(pReqPkt->_pOpenForkEntry))
  546. {
  547. // If a FlushFork occurs on resource fork, it should
  548. // update the modified time to the ChangeTime
  549. pReqPkt->_pOpenForkEntry->ofe_Flags |= OPEN_FORK_WRITTEN;
  550. pDfEntry->dfe_RescLen = pReqPkt->_ForkLength;
  551. }
  552. else
  553. {
  554. pDfEntry->dfe_DataLen = pReqPkt->_ForkLength;
  555. }
  556. }
  557. AfpSwmrRelease(&pVolDesc->vds_IdDbAccessLock);
  558. AfpSwmrRelease(&pVolDesc->vds_ExchangeFilesLock);
  559. }
  560. }
  561. else Status = AFP_ERR_PARAM;
  562. } while (False);
  563. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  564. ("AfpFspDispSetForkParms: Returning %ld\n", Status));
  565. return Status;
  566. }
  567. /*** AfpFspDispRead
  568. *
  569. * This routine implements the AfpRead API.
  570. *
  571. * The request packet is represented below.
  572. *
  573. * sda_ReqBlock POPENFORKENTRY pOpenForkEntry
  574. * sda_ReqBlock LONG Offset
  575. * sda_ReqBlock LONG Size
  576. * sda_ReqBlock DWORD NewLine Mask
  577. * sda_ReqBlock DWORD NewLine Char
  578. */
  579. AFPSTATUS FASTCALL
  580. AfpFspDispRead(
  581. IN PSDA pSda
  582. )
  583. {
  584. AFPSTATUS Status=AFP_ERR_MISC;
  585. FORKOFFST LOffset;
  586. FORKSIZE LSize;
  587. PFAST_IO_DISPATCH pFastIoDisp;
  588. IO_STATUS_BLOCK IoStsBlk;
  589. NTSTATUS NtStatus;
  590. struct _RequestPacket
  591. {
  592. POPENFORKENTRY _pOpenForkEntry;
  593. LONG _Offset;
  594. LONG _Size;
  595. DWORD _NlMask;
  596. DWORD _NlChar;
  597. };
  598. PAGED_CODE( );
  599. ASSERT(VALID_OPENFORKENTRY(pReqPkt->_pOpenForkEntry));
  600. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  601. ("AfpFspDispRead: Entered, Session %ld Fork %ld, Offset %ld, Size %ld\n",
  602. pSda->sda_SessionId, pReqPkt->_pOpenForkEntry->ofe_ForkId,
  603. pReqPkt->_Offset, pReqPkt->_Size));
  604. if ((pReqPkt->_Size < 0) ||
  605. (pReqPkt->_Offset < 0))
  606. return AFP_ERR_PARAM;
  607. if (!(pReqPkt->_pOpenForkEntry->ofe_OpenMode & FORK_OPEN_READ))
  608. {
  609. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_WARN,
  610. ("AfpFspDispRead: AfpRead on a Fork not opened for read\n"));
  611. return AFP_ERR_ACCESS_DENIED;
  612. }
  613. if (pReqPkt->_Size >= 0)
  614. {
  615. if (pReqPkt->_Size > (LONG)pSda->sda_MaxWriteSize)
  616. pReqPkt->_Size = (LONG)pSda->sda_MaxWriteSize;
  617. Status = AFP_ERR_NONE;
  618. if (pReqPkt->_Size > 0)
  619. {
  620. pSda->sda_ReadStatus = AFP_ERR_NONE;
  621. LOffset.QuadPart = pReqPkt->_Offset;
  622. LSize.QuadPart = pReqPkt->_Size;
  623. if ((pReqPkt->_pOpenForkEntry->ofe_pOpenForkDesc->ofd_UseCount == 1) ||
  624. (Status = AfpForkLockOperation( pSda,
  625. pReqPkt->_pOpenForkEntry,
  626. &LOffset,
  627. &LSize,
  628. IOCHECK,
  629. False)) == AFP_ERR_NONE)
  630. {
  631. ASSERT (LSize.HighPart == 0);
  632. ASSERT ((LONG)(LOffset.LowPart) == pReqPkt->_Offset);
  633. if ((LONG)(LSize.LowPart) != pReqPkt->_Size)
  634. pSda->sda_ReadStatus = AFP_ERR_LOCK;
  635. Status = AFP_ERR_MISC;
  636. pSda->sda_ReplySize = (USHORT)LSize.LowPart;
  637. NtStatus = STATUS_UNSUCCESSFUL;
  638. //
  639. // if Read is large enough to justify going to the cache mgr, do it
  640. //
  641. if (pSda->sda_ReplySize >= CACHEMGR_READ_THRESHOLD)
  642. {
  643. NtStatus = AfpBorrowReadMdlFromCM(pSda);
  644. }
  645. //
  646. // if we didn't go to the cache mgr, or if we did but cache mgr
  647. // couldn't satisfy our request, continue with the read
  648. //
  649. if (NtStatus != STATUS_PENDING)
  650. {
  651. Status = AfpFspDispReadContinue(pSda);
  652. }
  653. //
  654. // our attempt to get CacheMgr's mdl is pending. Return this
  655. // error code so we don't complete the api as yet
  656. //
  657. else
  658. {
  659. Status = AFP_ERR_EXTENDED;
  660. }
  661. }
  662. }
  663. }
  664. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  665. ("AfpFspDispRead: Returning %ld\n", Status));
  666. return Status;
  667. }
  668. /*** AfpFspDispReadContinue
  669. *
  670. * This routine implements the AfpRead API if our attempt to get ReadMdl directly
  671. * from the cache mgr fails.
  672. *
  673. */
  674. AFPSTATUS FASTCALL
  675. AfpFspDispReadContinue(
  676. IN PSDA pSda
  677. )
  678. {
  679. AFPSTATUS Status=AFP_ERR_MISC;
  680. FORKOFFST LOffset;
  681. FORKSIZE LSize;
  682. PFAST_IO_DISPATCH pFastIoDisp;
  683. IO_STATUS_BLOCK IoStsBlk;
  684. NTSTATUS NtStatus;
  685. struct _RequestPacket
  686. {
  687. POPENFORKENTRY _pOpenForkEntry;
  688. LONG _Offset;
  689. LONG _Size;
  690. DWORD _NlMask;
  691. DWORD _NlChar;
  692. };
  693. PAGED_CODE( );
  694. // allocate buffer for the read
  695. AfpIOAllocBackFillBuffer(pSda);
  696. if (pSda->sda_IOBuf != NULL)
  697. {
  698. #if DBG
  699. AfpPutGuardSignature(pSda);
  700. #endif
  701. LOffset.QuadPart = pReqPkt->_Offset;
  702. LSize.QuadPart = pReqPkt->_Size;
  703. // Try the fast I/O path first. If that fails, call AfpIoForkRead
  704. // to use the normal build-an-IRP path.
  705. pFastIoDisp = pReqPkt->_pOpenForkEntry->ofe_pDeviceObject->DriverObject->FastIoDispatch;
  706. if ((pFastIoDisp != NULL) &&
  707. (pFastIoDisp->FastIoRead != NULL) &&
  708. pFastIoDisp->FastIoRead(AfpGetRealFileObject(pReqPkt->_pOpenForkEntry->ofe_pFileObject),
  709. &LOffset,
  710. LSize.LowPart,
  711. True,
  712. pSda->sda_SessionId,
  713. pSda->sda_ReplyBuf,
  714. &IoStsBlk,
  715. pReqPkt->_pOpenForkEntry->ofe_pDeviceObject))
  716. {
  717. LONG i, Size;
  718. PBYTE pBuf;
  719. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  720. ("AfpFspDispRead: Fast Read Succeeded\n"));
  721. #ifdef PROFILING
  722. // The fast I/O path worked. Update statistics
  723. INTERLOCKED_INCREMENT_LONG((PLONG)(&AfpServerProfile->perf_NumFastIoSucceeded));
  724. #endif
  725. INTERLOCKED_ADD_STATISTICS(&AfpServerStatistics.stat_DataRead,
  726. (ULONG)IoStsBlk.Information,
  727. &AfpStatisticsLock);
  728. Status = pSda->sda_ReadStatus;
  729. Size = (LONG)IoStsBlk.Information;
  730. #if 0
  731. // The following code does the right thing as per the spec but
  732. // the finder seems to think otherwise.
  733. if (Size < LSize.LowPart)
  734. {
  735. pSda->sda_ReadStatus = AFP_ERR_EOF;
  736. }
  737. #endif
  738. if (Size == 0)
  739. {
  740. Status = AFP_ERR_EOF;
  741. AfpIOFreeBackFillBuffer(pSda);
  742. }
  743. else if (pReqPkt->_NlMask != 0)
  744. {
  745. for (i = 0, pBuf = pSda->sda_ReplyBuf; i < Size; i++, pBuf++)
  746. {
  747. if ((*pBuf & (BYTE)(pReqPkt->_NlMask)) == (BYTE)(pReqPkt->_NlChar))
  748. {
  749. Size = ++i;
  750. break;
  751. }
  752. }
  753. }
  754. pSda->sda_ReplySize = (USHORT)Size;
  755. ASSERT((Status != AFP_ERR_EOF) || (pSda->sda_ReplySize == 0));
  756. }
  757. else
  758. {
  759. #ifdef PROFILING
  760. INTERLOCKED_INCREMENT_LONG((PLONG)(&AfpServerProfile->perf_NumFastIoFailed));
  761. #endif
  762. Status = AfpIoForkRead(pSda,
  763. pReqPkt->_pOpenForkEntry,
  764. &LOffset,
  765. LSize.LowPart,
  766. (BYTE)pReqPkt->_NlMask,
  767. (BYTE)pReqPkt->_NlChar);
  768. }
  769. }
  770. return(Status);
  771. }
  772. /*** AfpFspDispWrite
  773. *
  774. * This routine implements the AfpWrite API.
  775. *
  776. * The request packet is represented below.
  777. *
  778. * sda_AfpSubFunc BYTE EndFlag
  779. * sda_ReqBlock POPENFORKENTRY pOpenForkEntry
  780. * sda_ReqBlock LONG Offset
  781. * sda_ReqBlock LONG Size
  782. */
  783. AFPSTATUS FASTCALL
  784. AfpFspDispWrite(
  785. IN PSDA pSda
  786. )
  787. {
  788. FORKOFFST LOffset;
  789. FORKSIZE LSize;
  790. PFAST_IO_DISPATCH pFastIoDisp;
  791. IO_STATUS_BLOCK IoStsBlk;
  792. AFPSTATUS Status = AFP_ERR_NONE;
  793. BOOLEAN EndFlag, FreeWriteBuf = True;
  794. PVOLDESC pVolDesc;
  795. PCONNDESC pConnDesc;
  796. PREQUEST pRequest;
  797. BOOLEAN fUpdateQuota=FALSE;
  798. struct _RequestPacket
  799. {
  800. POPENFORKENTRY _pOpenForkEntry;
  801. LONG _Offset;
  802. LONG _Size;
  803. };
  804. struct _ResponsePacket
  805. {
  806. BYTE __RealOffset[4];
  807. };
  808. PAGED_CODE( );
  809. EndFlag = (pSda->sda_AfpSubFunc & AFP_END_FLAG) ? True : False;
  810. ASSERT(VALID_OPENFORKENTRY(pReqPkt->_pOpenForkEntry));
  811. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  812. ("AfpFspDispWrite: Entered, Session %ld, Fork %ld, Offset %ld, Size %ld %sRelative\n",
  813. pSda->sda_SessionId, pReqPkt->_pOpenForkEntry->ofe_ForkId,
  814. pReqPkt->_Offset, pReqPkt->_Size, EndFlag ? "End" : "Begin"));
  815. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_WARN,
  816. ("AfpFspDispWrite: OForkRefNum = %d, pOpenForkEntry = %lx\n",
  817. pReqPkt->_pOpenForkEntry->ofe_ForkId,pReqPkt->_pOpenForkEntry));
  818. do
  819. {
  820. pRequest = pSda->sda_Request;
  821. //
  822. // if we got this Mdl from the Cache mgr, we must return it. Also, set
  823. // the status code such that we con't complete the request as yet, but
  824. // do so only afte cache mgr tells us that the write completed
  825. //
  826. if ((pRequest->rq_WriteMdl != NULL) &&
  827. (pRequest->rq_CacheMgrContext != NULL))
  828. {
  829. PDELAYEDALLOC pDelAlloc;
  830. pDelAlloc = pRequest->rq_CacheMgrContext;
  831. pReqPkt->_pOpenForkEntry->ofe_Flags |= OPEN_FORK_WRITTEN;
  832. ASSERT(pRequest->rq_WriteMdl == pDelAlloc->pMdl);
  833. ASSERT(!(pDelAlloc->Flags & AFP_CACHEMDL_ALLOC_ERROR));
  834. pRequest->rq_CacheMgrContext = NULL;
  835. AfpReturnWriteMdlToCM(pDelAlloc);
  836. FreeWriteBuf = False;
  837. Status = AFP_ERR_EXTENDED;
  838. break;
  839. }
  840. pConnDesc = pReqPkt->_pOpenForkEntry->ofe_pConnDesc;
  841. ASSERT(VALID_CONNDESC(pConnDesc));
  842. if ((pReqPkt->_Size < 0) ||
  843. (!EndFlag && (pReqPkt->_Offset < 0)))
  844. {
  845. Status = AFP_ERR_PARAM;
  846. break;
  847. }
  848. ASSERT((pReqPkt->_pOpenForkEntry->ofe_OpenMode & FORK_OPEN_WRITE) &&
  849. ((pReqPkt->_Size == 0) ||
  850. ((pReqPkt->_Size > 0) && (pSda->sda_IOBuf != NULL))));
  851. if (pReqPkt->_Size > (LONG)pSda->sda_MaxWriteSize)
  852. pReqPkt->_Size = (LONG)pSda->sda_MaxWriteSize;
  853. // Check if we have a lock conflict and also convert the offset &
  854. // size to absolute values if end relative
  855. LOffset.QuadPart = pReqPkt->_Offset;
  856. LSize.QuadPart = pReqPkt->_Size;
  857. if (pReqPkt->_Size == 0)
  858. {
  859. if (!(EndFlag && (pReqPkt->_Offset < 0)))
  860. {
  861. break;
  862. }
  863. }
  864. // Skip lock-check if this is the only instance of the open fork and I/O is
  865. // not end-relative.
  866. if ((!EndFlag &&
  867. (pReqPkt->_pOpenForkEntry->ofe_pOpenForkDesc->ofd_UseCount == 1)) ||
  868. (Status = AfpForkLockOperation( pSda,
  869. pReqPkt->_pOpenForkEntry,
  870. &LOffset,
  871. &LSize,
  872. IOCHECK,
  873. EndFlag)) == AFP_ERR_NONE)
  874. {
  875. ASSERT (LOffset.HighPart == 0);
  876. if ((LONG)(LSize.LowPart) != pReqPkt->_Size)
  877. {
  878. Status = AFP_ERR_LOCK;
  879. }
  880. else if (LSize.LowPart > 0)
  881. {
  882. ASSERT(VALID_CONNDESC(pReqPkt->_pOpenForkEntry->ofe_pConnDesc));
  883. // Assume write will succeed, set flag for FlushFork.
  884. // This is a one way flag, i.e. only set, never cleared
  885. pReqPkt->_pOpenForkEntry->ofe_Flags |= OPEN_FORK_WRITTEN;
  886. // Try the fast I/O path first. If that fails, call AfpIoForkWrite
  887. // to use the normal build-an-IRP path.
  888. pFastIoDisp = pReqPkt->_pOpenForkEntry->ofe_pDeviceObject->DriverObject->FastIoDispatch;
  889. if ((pFastIoDisp != NULL) &&
  890. (pFastIoDisp->FastIoWrite != NULL) &&
  891. pFastIoDisp->FastIoWrite(AfpGetRealFileObject(pReqPkt->_pOpenForkEntry->ofe_pFileObject),
  892. &LOffset,
  893. LSize.LowPart,
  894. True,
  895. pSda->sda_SessionId,
  896. pSda->sda_IOBuf,
  897. &IoStsBlk,
  898. pReqPkt->_pOpenForkEntry->ofe_pDeviceObject))
  899. {
  900. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  901. ("AfpFspDispWrite: Fast Write Succeeded\n"));
  902. #ifdef PROFILING
  903. // The fast I/O path worked. Update statistics
  904. INTERLOCKED_INCREMENT_LONG((PLONG)(&AfpServerProfile->perf_NumFastIoSucceeded));
  905. #endif
  906. INTERLOCKED_ADD_STATISTICS(&AfpServerStatistics.stat_DataWritten,
  907. (ULONG)IoStsBlk.Information,
  908. &AfpStatisticsLock);
  909. Status = AFP_ERR_NONE;
  910. }
  911. else
  912. {
  913. #ifdef PROFILING
  914. INTERLOCKED_INCREMENT_LONG((PLONG)(&AfpServerProfile->perf_NumFastIoFailed));
  915. #endif
  916. if ((Status = AfpIoForkWrite(pSda,
  917. pReqPkt->_pOpenForkEntry,
  918. &LOffset,
  919. LSize.LowPart)) == AFP_ERR_EXTENDED)
  920. {
  921. FreeWriteBuf = False;
  922. }
  923. }
  924. }
  925. }
  926. } while (False);
  927. if (FreeWriteBuf)
  928. {
  929. AfpFreeIOBuffer(pSda);
  930. }
  931. if (Status == AFP_ERR_NONE)
  932. {
  933. pSda->sda_ReplySize = SIZE_RESPPKT;
  934. if ((Status = AfpAllocReplyBuf(pSda)) == AFP_ERR_NONE)
  935. {
  936. PUTDWORD2DWORD(pRspPkt->__RealOffset, LOffset.LowPart+LSize.LowPart);
  937. }
  938. }
  939. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  940. ("AfpFspDispWrite: Returning %ld\n", Status));
  941. return Status;
  942. }
  943. /*** AfpFspDispByteRangeLock
  944. *
  945. * This routine implements the AfpByteRangeLock API.
  946. * We go ahead and call the file system to do the actual locking/unlocking.
  947. *
  948. * The request packet is represented below.
  949. *
  950. * sda_SubFunc BYTE Start/End Flag AND Lock/Unlock Flag
  951. * sda_ReqBlock POPENFORKENTRY pOpenForkEntry
  952. * sda_ReqBlock LONG Offset
  953. * sda_ReqBlock LONG Length
  954. */
  955. AFPSTATUS FASTCALL
  956. AfpFspDispByteRangeLock(
  957. IN PSDA pSda
  958. )
  959. {
  960. BOOLEAN EndFlag;
  961. LOCKOP Lock;
  962. LONG Offset;
  963. FORKOFFST LOffset;
  964. FORKSIZE LSize;
  965. AFPSTATUS Status = AFP_ERR_PARAM;
  966. struct _RequestPacket
  967. {
  968. POPENFORKENTRY _pOpenForkEntry;
  969. LONG _Offset;
  970. LONG _Length;
  971. };
  972. struct _ResponsePacket
  973. {
  974. BYTE __RangeStart[4];
  975. };
  976. ASSERT (sizeof(struct _RequestPacket) <= (MAX_REQ_ENTRIES_PLUS_1)*sizeof(DWORD));
  977. PAGED_CODE( );
  978. Lock = (pSda->sda_AfpSubFunc & AFP_UNLOCK_FLAG) ? UNLOCK : LOCK;
  979. EndFlag = (pSda->sda_AfpSubFunc & AFP_END_FLAG) ? True : False;
  980. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  981. ("AfpFspDispByteRangeLock: %sLock - Session %ld, Fork %ld Offset %ld Len %ld %sRelative\n",
  982. (Lock == LOCK) ? "":"Un", pSda->sda_SessionId,
  983. pReqPkt->_pOpenForkEntry->ofe_ForkId,
  984. pReqPkt->_Offset, pReqPkt->_Length, EndFlag ? "End" : "Begin"));
  985. ASSERT(VALID_OPENFORKENTRY(pReqPkt->_pOpenForkEntry));
  986. if ((EndFlag && (Lock == UNLOCK)) ||
  987. (pReqPkt->_Length == 0) ||
  988. (!EndFlag && (pReqPkt->_Offset < 0))||
  989. ((pReqPkt->_Length < 0) && (pReqPkt->_Length != MAXULONG)))
  990. NOTHING;
  991. else
  992. {
  993. if (pReqPkt->_Length == MAXULONG)
  994. pReqPkt->_Length = MAXLONG;
  995. LOffset.QuadPart = Offset = pReqPkt->_Offset;
  996. LSize.QuadPart = pReqPkt->_Length;
  997. Status = AfpForkLockOperation(pSda,
  998. pReqPkt->_pOpenForkEntry,
  999. &LOffset,
  1000. &LSize,
  1001. Lock,
  1002. EndFlag);
  1003. if (Status == AFP_ERR_NONE)
  1004. {
  1005. ASSERT (LOffset.HighPart == 0);
  1006. ASSERT (EndFlag ||
  1007. ((LONG)(LOffset.LowPart) == Offset));
  1008. pSda->sda_ReplySize = SIZE_RESPPKT;
  1009. if ((Status = AfpAllocReplyBuf(pSda)) == AFP_ERR_NONE)
  1010. PUTDWORD2DWORD(pRspPkt->__RangeStart, LOffset.LowPart);
  1011. }
  1012. }
  1013. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  1014. ("AfpFspDispByteRangeLock: Returning %ld\n", Status));
  1015. return Status;
  1016. }
  1017. /*** AfpFspDispFlushFork
  1018. *
  1019. * This routine implements the AfpFlushFork API. We don't actually do a
  1020. * real flush, we just query for the current forklength and modified time
  1021. * for this open fork handle and update our cached data. Note if 2
  1022. * different handles to the same file are flushed, we may end up with
  1023. * different information for each flush.
  1024. *
  1025. * The request packet is represented below.
  1026. *
  1027. * sda_ReqBlock POPENFORKENTRY pOpenForkEntry
  1028. */
  1029. AFPSTATUS FASTCALL
  1030. AfpFspDispFlushFork(
  1031. IN PSDA pSda
  1032. )
  1033. {
  1034. FORKOFFST ForkLength;
  1035. DWORD Status;
  1036. PCONNDESC pConnDesc;
  1037. struct _RequestPacket
  1038. {
  1039. POPENFORKENTRY _pOpenForkEntry;
  1040. };
  1041. PAGED_CODE( );
  1042. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  1043. ("AfpFspDispFlushFork: Entered\n"));
  1044. ASSERT(VALID_OPENFORKENTRY(pReqPkt->_pOpenForkEntry));
  1045. do
  1046. {
  1047. Status = AfpIoQuerySize(&pReqPkt->_pOpenForkEntry->ofe_FileSysHandle,
  1048. &ForkLength);
  1049. ASSERT(NT_SUCCESS(Status));
  1050. if (NT_SUCCESS(Status))
  1051. {
  1052. PVOLDESC pVolDesc;
  1053. PDFENTRY pDfEntry;
  1054. POPENFORKDESC pOpenForkDesc;
  1055. pOpenForkDesc = pReqPkt->_pOpenForkEntry->ofe_pOpenForkDesc;
  1056. pVolDesc = pOpenForkDesc->ofd_pVolDesc;
  1057. ASSERT(IS_VOLUME_NTFS(pVolDesc));
  1058. // Don't let FpExchangeFiles come in while we are accessing
  1059. // the stored FileId and its corresponding DFE
  1060. AfpSwmrAcquireExclusive(&pVolDesc->vds_ExchangeFilesLock);
  1061. AfpSwmrAcquireExclusive(&pVolDesc->vds_IdDbAccessLock);
  1062. if ((pDfEntry = AfpFindDfEntryById(pVolDesc,
  1063. pOpenForkDesc->ofd_FileNumber,
  1064. DFE_FILE)) != NULL)
  1065. {
  1066. ASSERT (VALID_DFE(pDfEntry));
  1067. AfpIoChangeNTModTime(&pReqPkt->_pOpenForkEntry->ofe_FileSysHandle,
  1068. &pDfEntry->dfe_LastModTime);
  1069. if (RESCFORK(pReqPkt->_pOpenForkEntry))
  1070. pDfEntry->dfe_RescLen = ForkLength.LowPart;
  1071. else pDfEntry->dfe_DataLen = ForkLength.LowPart;
  1072. }
  1073. AfpSwmrRelease(&pVolDesc->vds_IdDbAccessLock);
  1074. AfpSwmrRelease(&pVolDesc->vds_ExchangeFilesLock);
  1075. // update the disk quota for this user
  1076. if (pVolDesc->vds_Flags & VOLUME_DISKQUOTA_ENABLED)
  1077. {
  1078. pConnDesc = pReqPkt->_pOpenForkEntry->ofe_pConnDesc;
  1079. if (AfpConnectionReferenceByPointer(pConnDesc) != NULL)
  1080. {
  1081. afpUpdateDiskQuotaInfo(pConnDesc);
  1082. }
  1083. }
  1084. }
  1085. } while (False);
  1086. // Always return success
  1087. return AFP_ERR_NONE;
  1088. }
  1089.