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.

698 lines
18 KiB

  1. /*
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. forkio.c
  5. Abstract:
  6. This module contains the routines for performing fork reads and writes
  7. directly by building IRPs and not using NtReadFile/NtWriteFile. This
  8. should be used only by the FpRead and FpWrite Apis.
  9. Author:
  10. Jameel Hyder (microsoft!jameelh)
  11. Revision History:
  12. 15 Jan 1993 Initial Version
  13. Notes: Tab stop: 4
  14. --*/
  15. #define FILENUM FILE_FORKIO
  16. #define FORKIO_LOCALS
  17. #include <afp.h>
  18. #include <forkio.h>
  19. #include <gendisp.h>
  20. #if DBG
  21. PCHAR AfpIoForkFunc[] =
  22. {
  23. "",
  24. "READ",
  25. "WRITE",
  26. "LOCK",
  27. "UNLOCK"
  28. };
  29. #endif
  30. #ifdef ALLOC_PRAGMA
  31. #pragma alloc_text( PAGE, AfpIoForkRead)
  32. #pragma alloc_text( PAGE, AfpIoForkWrite)
  33. #pragma alloc_text( PAGE, AfpIoForkLockUnlock)
  34. #endif
  35. /*** afpIoGenericComplete
  36. *
  37. * This is the generic completion routine for a posted io request.
  38. */
  39. NTSTATUS
  40. afpIoGenericComplete(
  41. IN PDEVICE_OBJECT pDeviceObject,
  42. IN PIRP pIrp,
  43. IN PCMPLCTXT pCmplCtxt
  44. )
  45. {
  46. PSDA pSda; // Not valid for Unlock
  47. struct _ResponsePacket // For lock/unlock request
  48. {
  49. union
  50. {
  51. BYTE __RangeStart[4];
  52. BYTE __LastWritten[4];
  53. };
  54. };
  55. ASSERT(VALID_CTX(pCmplCtxt));
  56. if (pCmplCtxt->cc_Func != FUNC_UNLOCK)
  57. {
  58. pSda = (PSDA)(pCmplCtxt->cc_pSda);
  59. ASSERT(VALID_SDA(pSda));
  60. if (pCmplCtxt->cc_Func == FUNC_WRITE)
  61. {
  62. AfpFreeIOBuffer(pSda);
  63. }
  64. else if (!NT_SUCCESS(pIrp->IoStatus.Status) &&
  65. (pCmplCtxt->cc_Func == FUNC_READ))
  66. {
  67. AfpIOFreeBackFillBuffer(pSda);
  68. }
  69. }
  70. if (!NT_SUCCESS(pIrp->IoStatus.Status))
  71. {
  72. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_WARN,
  73. ("afpIoGenericComplete: %s ERROR %lx\n",
  74. AfpIoForkFunc[pCmplCtxt->cc_Func], pIrp->IoStatus.Status));
  75. if (pCmplCtxt->cc_Func != FUNC_UNLOCK)
  76. {
  77. if (pIrp->IoStatus.Status == STATUS_FILE_LOCK_CONFLICT)
  78. pCmplCtxt->cc_SavedStatus = AFP_ERR_LOCK;
  79. else if (pIrp->IoStatus.Status == STATUS_END_OF_FILE)
  80. {
  81. pCmplCtxt->cc_SavedStatus = AFP_ERR_NONE;
  82. if (pIrp->IoStatus.Information == 0)
  83. pCmplCtxt->cc_SavedStatus = AFP_ERR_EOF;
  84. }
  85. else if (pIrp->IoStatus.Status == STATUS_DISK_FULL)
  86. pCmplCtxt->cc_SavedStatus = AFP_ERR_DISK_FULL;
  87. else pCmplCtxt->cc_SavedStatus = AFP_ERR_MISC;
  88. }
  89. else
  90. {
  91. AFPLOG_ERROR(AFPSRVMSG_CANT_UNLOCK,
  92. pIrp->IoStatus.Status,
  93. NULL,
  94. 0,
  95. NULL);
  96. }
  97. if (pCmplCtxt->cc_Func == FUNC_LOCK)
  98. {
  99. DBGPRINT(DBG_COMP_FORKS, DBG_LEVEL_ERR,
  100. ("afpIoGenericComplete: ForkLock failed %lx, aborting for range %ld,%ld\n",
  101. pIrp->IoStatus.Status,
  102. pCmplCtxt->cc_pForkLock->flo_Offset,
  103. pCmplCtxt->cc_pForkLock->flo_Offset+pCmplCtxt->cc_pForkLock->flo_Size-1));
  104. AfpForkLockUnlink(pCmplCtxt->cc_pForkLock);
  105. }
  106. }
  107. else switch (pCmplCtxt->cc_Func)
  108. {
  109. case FUNC_WRITE:
  110. INTERLOCKED_ADD_STATISTICS(&AfpServerStatistics.stat_DataWritten,
  111. pCmplCtxt->cc_Offst,
  112. &AfpStatisticsLock);
  113. pSda->sda_ReplySize = SIZE_RESPPKT;
  114. if (AfpAllocReplyBuf(pSda) == AFP_ERR_NONE)
  115. {
  116. PUTDWORD2DWORD(pRspPkt->__LastWritten,
  117. pCmplCtxt->cc_Offst + pCmplCtxt->cc_ReqCount);
  118. }
  119. else pCmplCtxt->cc_SavedStatus = AFP_ERR_MISC;
  120. break;
  121. case FUNC_READ:
  122. {
  123. LONG i, Size;
  124. PBYTE pBuf;
  125. BYTE NlChar = pCmplCtxt->cc_NlChar;
  126. BYTE NlMask = pCmplCtxt->cc_NlMask;
  127. INTERLOCKED_ADD_STATISTICS(&AfpServerStatistics.stat_DataRead,
  128. (ULONG)pIrp->IoStatus.Information,
  129. &AfpStatisticsLock);
  130. Size = (LONG)pIrp->IoStatus.Information;
  131. #if 0
  132. // The following code does the right thing as per the spec but
  133. // the finder seems to think otherwise.
  134. if (Size < pCmplCtxt->cc_ReqCount)
  135. pCmplCtxt->cc_SavedStatus = AFP_ERR_EOF;
  136. #endif
  137. if (Size == 0)
  138. {
  139. pCmplCtxt->cc_SavedStatus = AFP_ERR_EOF;
  140. AfpIOFreeBackFillBuffer(pSda);
  141. }
  142. else if (pCmplCtxt->cc_NlMask != 0)
  143. {
  144. for (i = 0, pBuf = pSda->sda_ReplyBuf; i < Size; i++, pBuf++)
  145. {
  146. if ((*pBuf & NlMask) == NlChar)
  147. {
  148. Size = ++i;
  149. pCmplCtxt->cc_SavedStatus = AFP_ERR_NONE;
  150. break;
  151. }
  152. }
  153. }
  154. pSda->sda_ReplySize = (USHORT)Size;
  155. }
  156. ASSERT((pCmplCtxt->cc_SavedStatus != AFP_ERR_EOF) ||
  157. (pSda->sda_ReplySize == 0));
  158. break;
  159. case FUNC_LOCK:
  160. INTERLOCKED_ADD_ULONG(&AfpServerStatistics.stat_CurrentFileLocks,
  161. 1,
  162. &AfpStatisticsLock);
  163. pSda->sda_ReplySize = SIZE_RESPPKT;
  164. if (AfpAllocReplyBuf(pSda) == AFP_ERR_NONE)
  165. PUTDWORD2DWORD(pRspPkt->__RangeStart, pCmplCtxt->cc_pForkLock->flo_Offset);
  166. else pCmplCtxt->cc_SavedStatus = AFP_ERR_MISC;
  167. break;
  168. case FUNC_UNLOCK:
  169. INTERLOCKED_ADD_ULONG(
  170. &AfpServerStatistics.stat_CurrentFileLocks,
  171. (ULONG)-1,
  172. &AfpStatisticsLock);
  173. break;
  174. default:
  175. ASSERTMSG(0, "afpIoGenericComplete: Invalid function\n");
  176. KeBugCheck(0);
  177. break;
  178. }
  179. if (pIrp->MdlAddress != NULL)
  180. AfpFreeMdl(pIrp->MdlAddress);
  181. AfpFreeIrp(pIrp);
  182. if (pCmplCtxt->cc_Func != FUNC_UNLOCK)
  183. {
  184. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  185. ("afpIoGenericComplete: %s Returning %ld\n",
  186. AfpIoForkFunc[pCmplCtxt->cc_Func], pCmplCtxt->cc_SavedStatus));
  187. AfpCompleteApiProcessing(pSda, pCmplCtxt->cc_SavedStatus);
  188. }
  189. AfpFreeCmplCtxtBuf(pCmplCtxt);
  190. // Return STATUS_MORE_PROCESSING_REQUIRED so that IoCompleteRequest
  191. // will stop working on the IRP.
  192. return STATUS_MORE_PROCESSING_REQUIRED;
  193. }
  194. /*** AfpIoForkRead
  195. *
  196. * Read a chunk of data from the open fork. The read buffer is always the
  197. * the reply buffer in the sda (sda_ReplyBuf).
  198. */
  199. AFPSTATUS
  200. AfpIoForkRead(
  201. IN PSDA pSda, // The session requesting read
  202. IN POPENFORKENTRY pOpenForkEntry, // The open fork in question
  203. IN PFORKOFFST pOffset, // Pointer to fork offset
  204. IN LONG ReqCount, // Size of read request
  205. IN BYTE NlMask,
  206. IN BYTE NlChar
  207. )
  208. {
  209. PIRP pIrp = NULL;
  210. PIO_STACK_LOCATION pIrpSp;
  211. NTSTATUS Status;
  212. PMDL pMdl = NULL;
  213. PCMPLCTXT pCmplCtxt;
  214. PAGED_CODE( );
  215. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  216. ASSERT(VALID_OPENFORKENTRY(pOpenForkEntry));
  217. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  218. ("AfpIoForkRead: Session %ld, Offset %ld, Size %ld, Fork %ld\n",
  219. pSda->sda_SessionId, pOffset->LowPart, ReqCount, pOpenForkEntry->ofe_ForkId));
  220. do
  221. {
  222. // Allocate and initialize the completion context
  223. pCmplCtxt = AfpAllocCmplCtxtBuf(pSda);
  224. if (pCmplCtxt == NULL)
  225. {
  226. AfpFreeIOBuffer(pSda);
  227. Status = AFP_ERR_MISC;
  228. break;
  229. }
  230. afpInitializeCmplCtxt(pCmplCtxt,
  231. FUNC_READ,
  232. pSda->sda_ReadStatus,
  233. pSda,
  234. NULL,
  235. ReqCount,
  236. pOffset->LowPart);
  237. pCmplCtxt->cc_NlChar = NlChar;
  238. pCmplCtxt->cc_NlMask = NlMask;
  239. // Allocate and initialize the IRP for this operation.
  240. if ((pIrp = AfpAllocIrp(pOpenForkEntry->ofe_pDeviceObject->StackSize)) == NULL)
  241. {
  242. AfpFreeIOBuffer(pSda);
  243. Status = AFP_ERR_MISC;
  244. break;
  245. }
  246. if ((pOpenForkEntry->ofe_pDeviceObject->Flags & DO_BUFFERED_IO) == 0)
  247. {
  248. // Allocate an Mdl to describe the read buffer
  249. if ((pMdl = AfpAllocMdl(pSda->sda_ReplyBuf, ReqCount, pIrp)) == NULL)
  250. {
  251. Status = AFP_ERR_MISC;
  252. break;
  253. }
  254. }
  255. // Set up the completion routine.
  256. IoSetCompletionRoutine( pIrp,
  257. (PIO_COMPLETION_ROUTINE)afpIoGenericComplete,
  258. pCmplCtxt,
  259. True,
  260. True,
  261. True);
  262. pIrpSp = IoGetNextIrpStackLocation(pIrp);
  263. pIrp->Tail.Overlay.OriginalFileObject = AfpGetRealFileObject(pOpenForkEntry->ofe_pFileObject);
  264. pIrp->Tail.Overlay.Thread = AfpThread;
  265. pIrp->RequestorMode = KernelMode;
  266. // Get a pointer to the stack location for the first driver.
  267. // This will be used to pass the original function codes and
  268. // parameters.
  269. pIrpSp->MajorFunction = IRP_MJ_READ;
  270. pIrpSp->MinorFunction = IRP_MN_NORMAL;
  271. pIrpSp->FileObject = AfpGetRealFileObject(pOpenForkEntry->ofe_pFileObject);
  272. pIrpSp->DeviceObject = pOpenForkEntry->ofe_pDeviceObject;
  273. // Copy the caller's parameters to the service-specific portion of the
  274. // IRP.
  275. pIrpSp->Parameters.Read.Length = ReqCount;
  276. pIrpSp->Parameters.Read.Key = pSda->sda_SessionId;
  277. pIrpSp->Parameters.Read.ByteOffset = *pOffset;
  278. if ((pOpenForkEntry->ofe_pDeviceObject->Flags & DO_BUFFERED_IO) != 0)
  279. {
  280. pIrp->AssociatedIrp.SystemBuffer = pSda->sda_ReplyBuf;
  281. pIrp->Flags = IRP_BUFFERED_IO | IRP_INPUT_OPERATION;
  282. }
  283. else if ((pOpenForkEntry->ofe_pDeviceObject->Flags & DO_DIRECT_IO) != 0)
  284. {
  285. pIrp->MdlAddress = pMdl;
  286. }
  287. else
  288. {
  289. pIrp->UserBuffer = pSda->sda_ReplyBuf;
  290. pIrp->MdlAddress = pMdl;
  291. }
  292. // Now simply invoke the driver at its dispatch entry with the IRP.
  293. IoCallDriver(pOpenForkEntry->ofe_pDeviceObject, pIrp);
  294. Status = AFP_ERR_EXTENDED; // This makes the caller do nothing and
  295. } while (False); // the completion routine handles everything
  296. if (Status != AFP_ERR_EXTENDED)
  297. {
  298. if (pIrp != NULL)
  299. AfpFreeIrp(pIrp);
  300. if (pMdl != NULL)
  301. AfpFreeMdl(pMdl);
  302. if (pCmplCtxt)
  303. {
  304. AfpFreeCmplCtxtBuf(pCmplCtxt);
  305. }
  306. }
  307. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  308. ("AfpIoForkRead: Returning %ld\n", Status));
  309. return Status;
  310. }
  311. /*** AfpIoForkWrite
  312. *
  313. * Write a chunk of data to the open fork. The write buffer is always the
  314. * the write buffer in the sda (sda_IOBuf).
  315. */
  316. AFPSTATUS
  317. AfpIoForkWrite(
  318. IN PSDA pSda, // The session requesting read
  319. IN POPENFORKENTRY pOpenForkEntry, // The open fork in question
  320. IN PFORKOFFST pOffset, // Pointer to fork offset
  321. IN LONG ReqCount // Size of write request
  322. )
  323. {
  324. PIRP pIrp = NULL;
  325. PIO_STACK_LOCATION pIrpSp;
  326. NTSTATUS Status;
  327. PMDL pMdl = NULL;
  328. PCMPLCTXT pCmplCtxt;
  329. PAGED_CODE( );
  330. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  331. ASSERT(VALID_OPENFORKENTRY(pOpenForkEntry));
  332. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  333. ("AfpIoForkWrite: Session %ld, Offset %ld, Size %ld, Fork %ld\n",
  334. pSda->sda_SessionId, pOffset->LowPart, ReqCount, pOpenForkEntry->ofe_ForkId));
  335. do
  336. {
  337. // Allocate and initialize the completion context
  338. pCmplCtxt = AfpAllocCmplCtxtBuf(pSda);
  339. if (pCmplCtxt == NULL)
  340. {
  341. Status = AFP_ERR_MISC;
  342. break;
  343. }
  344. afpInitializeCmplCtxt(pCmplCtxt,
  345. FUNC_WRITE,
  346. AFP_ERR_NONE,
  347. pSda,
  348. NULL,
  349. ReqCount,
  350. pOffset->LowPart);
  351. // Allocate and initialize the IRP for this operation.
  352. if ((pIrp = AfpAllocIrp(pOpenForkEntry->ofe_pDeviceObject->StackSize)) == NULL)
  353. {
  354. Status = AFP_ERR_MISC;
  355. break;
  356. }
  357. if ((pOpenForkEntry->ofe_pDeviceObject->Flags & DO_BUFFERED_IO) == 0)
  358. {
  359. // Allocate an Mdl to describe the write buffer
  360. if ((pMdl = AfpAllocMdl(pSda->sda_IOBuf, ReqCount, pIrp)) == NULL)
  361. {
  362. Status = AFP_ERR_MISC;
  363. break;
  364. }
  365. }
  366. // Set up the completion routine.
  367. IoSetCompletionRoutine( pIrp,
  368. (PIO_COMPLETION_ROUTINE)afpIoGenericComplete,
  369. pCmplCtxt,
  370. True,
  371. True,
  372. True);
  373. pIrpSp = IoGetNextIrpStackLocation(pIrp);
  374. pIrp->Tail.Overlay.OriginalFileObject = AfpGetRealFileObject(pOpenForkEntry->ofe_pFileObject);
  375. pIrp->Tail.Overlay.Thread = AfpThread;
  376. pIrp->RequestorMode = KernelMode;
  377. // Get a pointer to the stack location for the first driver.
  378. // This will be used to pass the original function codes and
  379. // parameters.
  380. pIrpSp->MajorFunction = IRP_MJ_WRITE;
  381. pIrpSp->MinorFunction = IRP_MN_NORMAL;
  382. pIrpSp->FileObject = AfpGetRealFileObject(pOpenForkEntry->ofe_pFileObject);
  383. pIrpSp->DeviceObject = pOpenForkEntry->ofe_pDeviceObject;
  384. // Copy the caller's parameters to the service-specific portion of the
  385. // IRP.
  386. pIrpSp->Parameters.Write.Length = ReqCount;
  387. pIrpSp->Parameters.Write.Key = pSda->sda_SessionId;
  388. pIrpSp->Parameters.Write.ByteOffset = *pOffset;
  389. if ((pOpenForkEntry->ofe_pDeviceObject->Flags & DO_BUFFERED_IO) != 0)
  390. {
  391. pIrp->AssociatedIrp.SystemBuffer = pSda->sda_IOBuf;
  392. pIrp->Flags = IRP_BUFFERED_IO;
  393. }
  394. else if ((pOpenForkEntry->ofe_pDeviceObject->Flags & DO_DIRECT_IO) != 0)
  395. {
  396. pIrp->MdlAddress = pMdl;
  397. }
  398. else
  399. {
  400. pIrp->UserBuffer = pSda->sda_IOBuf;
  401. pIrp->MdlAddress = pMdl;
  402. }
  403. // Now simply invoke the driver at its dispatch entry with the IRP.
  404. IoCallDriver(pOpenForkEntry->ofe_pDeviceObject, pIrp);
  405. Status = AFP_ERR_EXTENDED; // This makes the caller do nothing and
  406. } while (False); // the completion routine handles everything
  407. if (Status != AFP_ERR_EXTENDED)
  408. {
  409. if (pIrp != NULL)
  410. AfpFreeIrp(pIrp);
  411. if (pMdl != NULL)
  412. AfpFreeMdl(pMdl);
  413. if (pCmplCtxt)
  414. {
  415. AfpFreeCmplCtxtBuf(pCmplCtxt);
  416. }
  417. }
  418. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  419. ("AfpIoForkWrite: Returning %ld\n", Status));
  420. return Status;
  421. }
  422. /*** AfpIoForkLock
  423. *
  424. * Lock/Unlock a section of the open fork.
  425. */
  426. AFPSTATUS
  427. AfpIoForkLockUnlock(
  428. IN PSDA pSda,
  429. IN PFORKLOCK pForkLock,
  430. IN PFORKOFFST pForkOffset,
  431. IN PFORKSIZE pLockSize,
  432. IN BYTE Func
  433. )
  434. {
  435. PIRP pIrp = NULL;
  436. PIO_STACK_LOCATION pIrpSp;
  437. POPENFORKENTRY pOpenForkEntry = pForkLock->flo_pOpenForkEntry;
  438. NTSTATUS Status;
  439. PCMPLCTXT pCmplCtxt;
  440. PAGED_CODE( );
  441. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  442. ASSERT(VALID_OPENFORKENTRY(pOpenForkEntry));
  443. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  444. ("AfpIoForkLockUnlock: %sLOCK Session %ld, Offset %ld, Size %ld, Fork %ld\n",
  445. (Func == FUNC_LOCK) ? "" : "UN", pSda->sda_SessionId,
  446. pForkOffset->LowPart, pLockSize->LowPart, pOpenForkEntry->ofe_ForkId));
  447. do
  448. {
  449. // Allocate and initialize the completion context
  450. pCmplCtxt = AfpAllocCmplCtxtBuf(pSda);
  451. if (pCmplCtxt == NULL)
  452. {
  453. Status = AFP_ERR_MISC;
  454. break;
  455. }
  456. afpInitializeCmplCtxt(pCmplCtxt,
  457. Func,
  458. AFP_ERR_NONE,
  459. pSda,
  460. pForkLock,
  461. pForkOffset->LowPart,
  462. pLockSize->LowPart);
  463. // Allocate and initialize the IRP for this operation.
  464. if ((pIrp = AfpAllocIrp(pOpenForkEntry->ofe_pDeviceObject->StackSize)) == NULL)
  465. {
  466. Status = AFP_ERR_MISC;
  467. break;
  468. }
  469. // Set up the completion routine.
  470. IoSetCompletionRoutine( pIrp,
  471. (PIO_COMPLETION_ROUTINE)afpIoGenericComplete,
  472. pCmplCtxt,
  473. True,
  474. True,
  475. True);
  476. pIrpSp = IoGetNextIrpStackLocation(pIrp);
  477. pIrp->Tail.Overlay.OriginalFileObject = AfpGetRealFileObject(pOpenForkEntry->ofe_pFileObject);
  478. pIrp->Tail.Overlay.Thread = AfpThread;
  479. pIrp->RequestorMode = KernelMode;
  480. // Get a pointer to the stack location for the first driver.
  481. // This will be used to pass the original function codes and parameters.
  482. pIrpSp->MajorFunction = IRP_MJ_LOCK_CONTROL;
  483. pIrpSp->MinorFunction = (Func == FUNC_LOCK) ? IRP_MN_LOCK : IRP_MN_UNLOCK_SINGLE;
  484. pIrpSp->FileObject = AfpGetRealFileObject(pOpenForkEntry->ofe_pFileObject);
  485. pIrpSp->DeviceObject = pOpenForkEntry->ofe_pDeviceObject;
  486. // Copy the caller's parameters to the service-specific portion of the IRP.
  487. pIrpSp->Parameters.LockControl.Length = pLockSize;
  488. pIrpSp->Parameters.LockControl.Key = pSda->sda_SessionId;
  489. pIrpSp->Parameters.LockControl.ByteOffset = *pForkOffset;
  490. pIrp->MdlAddress = NULL;
  491. pIrpSp->Flags = SL_FAIL_IMMEDIATELY | SL_EXCLUSIVE_LOCK;
  492. // Now simply invoke the driver at its dispatch entry with the IRP.
  493. IoCallDriver(pOpenForkEntry->ofe_pDeviceObject, pIrp);
  494. // For lock operation this makes the caller do nothing
  495. // and the completion routine handles everything
  496. // For unlock operation we complete the request here.
  497. Status = (Func == FUNC_LOCK) ? AFP_ERR_EXTENDED : AFP_ERR_NONE;
  498. } while (False);
  499. if ((Status != AFP_ERR_EXTENDED) && (Status != AFP_ERR_NONE))
  500. {
  501. if (pIrp != NULL)
  502. AfpFreeIrp(pIrp);
  503. if (pCmplCtxt)
  504. {
  505. AfpFreeCmplCtxtBuf(pCmplCtxt);
  506. }
  507. }
  508. DBGPRINT(DBG_COMP_AFPAPI_FORK, DBG_LEVEL_INFO,
  509. ("AfpIoForkLock: Returning %ld\n", Status));
  510. return Status;
  511. }
  512. PCMPLCTXT
  513. AfpAllocCmplCtxtBuf(
  514. IN PSDA pSda
  515. )
  516. {
  517. KIRQL OldIrql;
  518. PBYTE pRetBuffer;
  519. ACQUIRE_SPIN_LOCK(&pSda->sda_Lock, &OldIrql);
  520. ASSERT (sizeof(CMPLCTXT) <= pSda->sda_SizeNameXSpace);
  521. if (((pSda->sda_Flags & SDA_NAMEXSPACE_IN_USE) == 0) &&
  522. (sizeof(CMPLCTXT) <= pSda->sda_SizeNameXSpace))
  523. {
  524. pRetBuffer = pSda->sda_NameXSpace;
  525. pSda->sda_Flags |= SDA_NAMEXSPACE_IN_USE;
  526. }
  527. else
  528. {
  529. pRetBuffer = AfpAllocNonPagedMemory(sizeof(CMPLCTXT));
  530. }
  531. RELEASE_SPIN_LOCK(&pSda->sda_Lock, OldIrql);
  532. return ((PCMPLCTXT)(pRetBuffer));
  533. }
  534. VOID
  535. AfpFreeCmplCtxtBuf(
  536. IN PCMPLCTXT pCmplCtxt
  537. )
  538. {
  539. KIRQL OldIrql;
  540. PSDA pSda;
  541. ASSERT(VALID_CTX(pCmplCtxt));
  542. pSda = pCmplCtxt->cc_pSda;
  543. ASSERT(VALID_SDA(pSda));
  544. ACQUIRE_SPIN_LOCK(&pSda->sda_Lock, &OldIrql);
  545. #if DBG
  546. pCmplCtxt->Signature = 0x12341234;
  547. pCmplCtxt->cc_Func = 0xff;
  548. pCmplCtxt->cc_pSda = (PSDA)0x12341234;
  549. pCmplCtxt->cc_pForkLock = (PFORKLOCK)0x12341234;
  550. pCmplCtxt->cc_SavedStatus = 0x12341234;
  551. pCmplCtxt->cc_ReqCount = 0x12341234;
  552. pCmplCtxt->cc_Offst = 0x12341234;
  553. #endif
  554. if (((PBYTE)pCmplCtxt) == pSda->sda_NameXSpace)
  555. {
  556. ASSERT(pSda->sda_Flags & SDA_NAMEXSPACE_IN_USE);
  557. pSda->sda_Flags &= ~SDA_NAMEXSPACE_IN_USE;
  558. }
  559. else
  560. {
  561. AfpFreeMemory((PBYTE)(pCmplCtxt));
  562. }
  563. RELEASE_SPIN_LOCK(&pSda->sda_Lock, OldIrql);
  564. }