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.

956 lines
24 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. read.c
  5. Abstract:
  6. This module contains the code that is very specific to initialization
  7. and unload operations in the irenum driver
  8. Author:
  9. Brian Lieuallen, 7-13-2000
  10. Environment:
  11. Kernel mode
  12. Revision History :
  13. --*/
  14. #include "internal.h"
  15. VOID
  16. ReadCancelRoutine(
  17. PDEVICE_OBJECT DeviceObject,
  18. PIRP Irp
  19. );
  20. VOID
  21. MoveDataFromBufferToIrp(
  22. PFDO_DEVICE_EXTENSION DeviceExtension
  23. );
  24. VOID
  25. SeeIfIrpShouldBeCompleted(
  26. PFDO_DEVICE_EXTENSION DeviceExtension
  27. );
  28. NTSTATUS
  29. IrCommRead(
  30. PDEVICE_OBJECT DeviceObject,
  31. PIRP Irp
  32. )
  33. {
  34. PFDO_DEVICE_EXTENSION DeviceExtension=(PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
  35. NTSTATUS Status=STATUS_SUCCESS;
  36. D_TRACE1(DbgPrint("IRCOMM: IrCommRead\n");)
  37. if (DeviceExtension->Removing) {
  38. //
  39. // the device has been removed, no more irps
  40. //
  41. Irp->IoStatus.Status=STATUS_DEVICE_REMOVED;
  42. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  43. return STATUS_DEVICE_REMOVED;
  44. }
  45. #if DBG
  46. {
  47. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  48. RtlFillMemory(
  49. Irp->AssociatedIrp.SystemBuffer,
  50. IrpSp->Parameters.Read.Length,
  51. 0xf1
  52. );
  53. }
  54. #endif
  55. IoMarkIrpPending(Irp);
  56. Irp->IoStatus.Information=0;
  57. QueuePacket(&DeviceExtension->Read.Queue,Irp,FALSE);
  58. return STATUS_PENDING;
  59. }
  60. VOID
  61. ReadStartRoutine(
  62. PVOID Context,
  63. PIRP Irp
  64. )
  65. {
  66. PFDO_DEVICE_EXTENSION DeviceExtension=(PFDO_DEVICE_EXTENSION)Context;
  67. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  68. KIRQL OldIrql;
  69. KIRQL CancelIrql;
  70. Irp->IoStatus.Information=0;
  71. Irp->IoStatus.Status=STATUS_TIMEOUT;
  72. KeAcquireSpinLock(
  73. &DeviceExtension->Read.ReadLock,
  74. &OldIrql
  75. );
  76. ASSERT(!DeviceExtension->Read.TotalTimerSet);
  77. ASSERT(!DeviceExtension->Read.IntervalTimerSet);
  78. //
  79. // add one refcount for this routine.
  80. //
  81. DeviceExtension->Read.IrpRefCount=1;
  82. DeviceExtension->Read.CurrentIrp=Irp;
  83. DeviceExtension->Read.IrpShouldBeCompleted=FALSE;
  84. DeviceExtension->Read.IrpShouldBeCompletedWithAnyData=FALSE;
  85. IoAcquireCancelSpinLock(&CancelIrql);
  86. if (Irp->Cancel) {
  87. //
  88. // it has already been canceled, just mark it to complete
  89. //
  90. DeviceExtension->Read.IrpShouldBeCompleted=FALSE;
  91. }
  92. DeviceExtension->Read.IrpRefCount++;
  93. IoSetCancelRoutine(Irp,ReadCancelRoutine);
  94. IoReleaseCancelSpinLock(CancelIrql);
  95. if ((DeviceExtension->TimeOuts.ReadIntervalTimeout == MAXULONG)
  96. &&
  97. (DeviceExtension->TimeOuts.ReadTotalTimeoutMultiplier == 0)
  98. &&
  99. (DeviceExtension->TimeOuts.ReadTotalTimeoutConstant == 0)) {
  100. //
  101. // The set of timeouts means that the request should simply return with
  102. // whatever data is availible
  103. //
  104. DeviceExtension->Read.IrpShouldBeCompleted=TRUE;
  105. Irp->IoStatus.Status=STATUS_SUCCESS;
  106. }
  107. if ((DeviceExtension->TimeOuts.ReadTotalTimeoutMultiplier != 0) || (DeviceExtension->TimeOuts.ReadTotalTimeoutConstant != 0)) {
  108. //
  109. // need a total timeout
  110. //
  111. LARGE_INTEGER DueTime;
  112. ULONG TimeoutMultiplier=DeviceExtension->TimeOuts.ReadTotalTimeoutMultiplier;
  113. if ((TimeoutMultiplier == MAXULONG) && (DeviceExtension->TimeOuts.ReadIntervalTimeout == MAXULONG)) {
  114. //
  115. // this means that the read should complete as soon as any data is read, or the constant timeout
  116. // expires.
  117. //
  118. DeviceExtension->Read.IrpShouldBeCompletedWithAnyData=TRUE;
  119. TimeoutMultiplier=0;
  120. }
  121. DueTime.QuadPart= ((LONGLONG)(DeviceExtension->TimeOuts.ReadTotalTimeoutConstant +
  122. (TimeoutMultiplier * IrpSp->Parameters.Read.Length)))
  123. * -10000;
  124. KeSetTimer(
  125. &DeviceExtension->Read.TotalTimer,
  126. DueTime,
  127. &DeviceExtension->Read.TotalTimerDpc
  128. );
  129. DeviceExtension->Read.TotalTimerSet=TRUE;
  130. DeviceExtension->Read.IrpRefCount++;
  131. }
  132. DeviceExtension->Read.IntervalTimeOut=0;
  133. if ((DeviceExtension->TimeOuts.ReadIntervalTimeout != 0) && (DeviceExtension->TimeOuts.ReadIntervalTimeout != MAXULONG)) {
  134. //
  135. // capture the interval timer we will use for this irp
  136. //
  137. DeviceExtension->Read.IntervalTimeOut=DeviceExtension->TimeOuts.ReadIntervalTimeout;
  138. }
  139. KeReleaseSpinLock(
  140. &DeviceExtension->Read.ReadLock,
  141. OldIrql
  142. );
  143. MoveDataFromBufferToIrp(
  144. DeviceExtension
  145. );
  146. SeeIfIrpShouldBeCompleted(
  147. DeviceExtension
  148. );
  149. return;
  150. }
  151. BOOLEAN
  152. CopyMemoryAndCheckForChar(
  153. PUCHAR Destination,
  154. PUCHAR Source,
  155. ULONG Length,
  156. UCHAR CharacterToCheck
  157. )
  158. {
  159. PUCHAR EndPoint=Destination+Length;
  160. BOOLEAN ReturnValue=FALSE;
  161. while (Destination < EndPoint) {
  162. *Destination = *Source;
  163. if (*Destination == CharacterToCheck) {
  164. // DbgPrint("Got event char\n");
  165. ReturnValue=TRUE;
  166. }
  167. Destination++;
  168. Source++;
  169. }
  170. return ReturnValue;
  171. }
  172. NTSTATUS
  173. DataAvailibleHandler(
  174. PVOID Context,
  175. PUCHAR Buffer,
  176. ULONG BytesAvailible,
  177. PULONG BytesUsed
  178. )
  179. {
  180. PFDO_DEVICE_EXTENSION DeviceExtension=(PFDO_DEVICE_EXTENSION)Context;
  181. ULONG BytesToCopy;
  182. ULONG BytesToCopyInFirstPass;
  183. BOOLEAN FoundEventCharacter;
  184. BOOLEAN FoundEventCharacter2=FALSE;
  185. BOOLEAN EightyPercentFull=FALSE;
  186. KIRQL OldIrql;
  187. *BytesUsed = 0;
  188. ASSERT(BytesAvailible <= INPUT_BUFFER_SIZE);
  189. KeAcquireSpinLock(
  190. &DeviceExtension->Read.ReadLock,
  191. &OldIrql
  192. );
  193. //
  194. // find out how many bytes can be copied
  195. //
  196. BytesToCopy = min(BytesAvailible , INPUT_BUFFER_SIZE - DeviceExtension->Read.BytesInBuffer);
  197. if (BytesToCopy < BytesAvailible) {
  198. if (DeviceExtension->Read.DtrState) {
  199. //
  200. // only take the whole packet, so we don't have to worry about how to figure out if
  201. // the ircomm control info in on the front of the buffer
  202. //
  203. DeviceExtension->Read.RefusedDataIndication=TRUE;
  204. D_TRACE1(DbgPrint("IRCOMM: data refused\n");)
  205. KeReleaseSpinLock(
  206. &DeviceExtension->Read.ReadLock,
  207. OldIrql
  208. );
  209. *BytesUsed=0;
  210. return STATUS_DATA_NOT_ACCEPTED;
  211. } else {
  212. //
  213. // dtr is low, just throw the data away as we are probably trying to hangup
  214. //
  215. D_TRACE1(DbgPrint("IRCOMM: overflow data thrown away because dtr low - %d\n",BytesAvailible);)
  216. KeReleaseSpinLock(
  217. &DeviceExtension->Read.ReadLock,
  218. OldIrql
  219. );
  220. *BytesUsed=BytesAvailible;
  221. return STATUS_SUCCESS;
  222. }
  223. }
  224. //
  225. // see how much more is left before we wrap the buffer
  226. //
  227. BytesToCopyInFirstPass= (ULONG)(&DeviceExtension->Read.InputBuffer[INPUT_BUFFER_SIZE] - DeviceExtension->Read.NextEmptyByte);
  228. //
  229. // only can copy as many as are actually availible
  230. //
  231. BytesToCopyInFirstPass= min( BytesToCopy , BytesToCopyInFirstPass );
  232. FoundEventCharacter=CopyMemoryAndCheckForChar(
  233. DeviceExtension->Read.NextEmptyByte,
  234. Buffer,
  235. BytesToCopyInFirstPass,
  236. DeviceExtension->SerialChars.EventChar
  237. );
  238. DeviceExtension->Read.NextEmptyByte += BytesToCopyInFirstPass;
  239. *BytesUsed += BytesToCopyInFirstPass;
  240. DeviceExtension->Read.BytesInBuffer += BytesToCopyInFirstPass;
  241. if (BytesToCopyInFirstPass < BytesToCopy) {
  242. //
  243. // must have wrapped, copy the rest
  244. //
  245. ULONG BytesToCopyInSecondPass=BytesToCopy-BytesToCopyInFirstPass;
  246. ASSERT(DeviceExtension->Read.NextEmptyByte == &DeviceExtension->Read.InputBuffer[INPUT_BUFFER_SIZE]);
  247. //
  248. // back to the beggining
  249. //
  250. DeviceExtension->Read.NextEmptyByte=&DeviceExtension->Read.InputBuffer[0];
  251. FoundEventCharacter2 =CopyMemoryAndCheckForChar(
  252. DeviceExtension->Read.NextEmptyByte,
  253. Buffer+BytesToCopyInFirstPass,
  254. BytesToCopyInSecondPass,
  255. DeviceExtension->SerialChars.EventChar
  256. );
  257. DeviceExtension->Read.NextEmptyByte += BytesToCopyInSecondPass;
  258. *BytesUsed += BytesToCopyInSecondPass;
  259. DeviceExtension->Read.BytesInBuffer += BytesToCopyInSecondPass;
  260. }
  261. if (DeviceExtension->Read.CurrentIrp != NULL) {
  262. //
  263. // there is currently a read irp, Check to see if we should set an interval timeout
  264. //
  265. if (DeviceExtension->Read.IntervalTimerSet) {
  266. //
  267. // the time is already set, cancel it first
  268. //
  269. BOOLEAN Canceled;
  270. Canceled=KeCancelTimer(
  271. &DeviceExtension->Read.IntervalTimer
  272. );
  273. if (Canceled) {
  274. //
  275. // the timer had not fired yet, reset these since they will be changed below
  276. //
  277. DeviceExtension->Read.IntervalTimerSet=FALSE;
  278. DeviceExtension->Read.IrpRefCount--;
  279. } else {
  280. //
  281. // the time has already expired. it will complete the current irp
  282. //
  283. }
  284. }
  285. //
  286. // either this is the first time we are setting the timer, or we tried to
  287. // cancel a previous version of it. If we did cancel it this is the same as
  288. // it not being set. If it was set before and we did not cancel it, then we
  289. // won't set a new one since the timer DPC is queued to run and will complete
  290. // the irp
  291. //
  292. if ((DeviceExtension->Read.IntervalTimeOut != 0) && !DeviceExtension->Read.IntervalTimerSet) {
  293. //
  294. // we need an interval timer
  295. //
  296. LARGE_INTEGER DueTime;
  297. DueTime.QuadPart= (LONGLONG)DeviceExtension->Read.IntervalTimeOut * -10000;
  298. KeSetTimer(
  299. &DeviceExtension->Read.IntervalTimer,
  300. DueTime,
  301. &DeviceExtension->Read.IntervalTimerDpc
  302. );
  303. DeviceExtension->Read.IntervalTimerSet=TRUE;
  304. DeviceExtension->Read.IrpRefCount++;
  305. }
  306. }
  307. EightyPercentFull= DeviceExtension->Read.BytesInBuffer > (INPUT_BUFFER_SIZE * 8)/10;
  308. KeReleaseSpinLock(
  309. &DeviceExtension->Read.ReadLock,
  310. OldIrql
  311. );
  312. //
  313. // try to move the buffered data to a read irp
  314. //
  315. MoveDataFromBufferToIrp(
  316. DeviceExtension
  317. );
  318. SeeIfIrpShouldBeCompleted(
  319. DeviceExtension
  320. );
  321. EventNotification(
  322. DeviceExtension,
  323. SERIAL_EV_RXCHAR |
  324. ((FoundEventCharacter || FoundEventCharacter) ? SERIAL_EV_RXFLAG : 0) |
  325. ((EightyPercentFull) ? SERIAL_EV_RX80FULL : 0)
  326. );
  327. ASSERT(*BytesUsed == BytesAvailible);
  328. return STATUS_SUCCESS;
  329. }
  330. #if 0
  331. VOID
  332. DebugCopyMemory(
  333. PUCHAR Destination,
  334. PUCHAR Source,
  335. ULONG Length
  336. )
  337. {
  338. PUCHAR EndPoint=Destination+Length;
  339. while (Destination < EndPoint) {
  340. *Destination = *Source;
  341. if ((*Source == 0xe1) || (*Source == 0xe2)) {
  342. DbgPrint("IRCOMM: bad data at %p\n",Source);
  343. DbgBreakPoint();
  344. }
  345. Destination++;
  346. Source++;
  347. }
  348. return;
  349. }
  350. #endif
  351. VOID
  352. MoveDataFromBufferToIrp(
  353. PFDO_DEVICE_EXTENSION DeviceExtension
  354. )
  355. {
  356. KIRQL OldIrql;
  357. BOOLEAN RequestDataIndications=FALSE;
  358. KeAcquireSpinLock(
  359. &DeviceExtension->Read.ReadLock,
  360. &OldIrql
  361. );
  362. if (DeviceExtension->Read.CurrentIrp != NULL) {
  363. PIRP Irp = DeviceExtension->Read.CurrentIrp;
  364. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  365. ULONG TotalBytesToCopy;
  366. ULONG BytesToCopyInFirstPass;
  367. ULONG BytesToCopyInSecondPass;
  368. ULONG BytesToEndOfBuffer;
  369. //
  370. // find the max number of bytes that can be copied
  371. //
  372. TotalBytesToCopy = min(DeviceExtension->Read.BytesInBuffer , IrpSp->Parameters.Read.Length - (ULONG)Irp->IoStatus.Information );
  373. //
  374. // Find out how many bytes are between the first filled byte and the end of the buffer
  375. //
  376. BytesToEndOfBuffer= (ULONG)(&DeviceExtension->Read.InputBuffer[INPUT_BUFFER_SIZE] - DeviceExtension->Read.NextFilledByte);
  377. //
  378. // If the buffer wraps, the bytes to the end will be the limiting factor, otherwise
  379. // it does not wrap and in that case the total bytes will be the limiting factor
  380. //
  381. BytesToCopyInFirstPass= min(TotalBytesToCopy , BytesToEndOfBuffer);
  382. RtlCopyMemory(
  383. (PUCHAR)Irp->AssociatedIrp.SystemBuffer + Irp->IoStatus.Information,
  384. DeviceExtension->Read.NextFilledByte,
  385. BytesToCopyInFirstPass
  386. );
  387. #if DBG
  388. RtlFillMemory(
  389. DeviceExtension->Read.NextFilledByte,
  390. BytesToCopyInFirstPass,
  391. 0xe1
  392. );
  393. #endif
  394. DeviceExtension->Read.NextFilledByte += BytesToCopyInFirstPass;
  395. DeviceExtension->Read.BytesInBuffer -= BytesToCopyInFirstPass;
  396. Irp->IoStatus.Information+= BytesToCopyInFirstPass;
  397. BytesToCopyInSecondPass= TotalBytesToCopy - BytesToCopyInFirstPass;
  398. if (BytesToCopyInSecondPass > 0) {
  399. //
  400. // back to the begining of the buffer
  401. //
  402. ASSERT( DeviceExtension->Read.NextFilledByte == &DeviceExtension->Read.InputBuffer[INPUT_BUFFER_SIZE]);
  403. DeviceExtension->Read.NextFilledByte=&DeviceExtension->Read.InputBuffer[0];
  404. RtlCopyMemory(
  405. (PUCHAR)Irp->AssociatedIrp.SystemBuffer + Irp->IoStatus.Information,
  406. DeviceExtension->Read.NextFilledByte,
  407. BytesToCopyInSecondPass
  408. );
  409. #if DBG
  410. RtlFillMemory(
  411. DeviceExtension->Read.NextFilledByte,
  412. BytesToCopyInSecondPass,
  413. 0xe2
  414. );
  415. #endif
  416. DeviceExtension->Read.NextFilledByte += BytesToCopyInSecondPass;
  417. DeviceExtension->Read.BytesInBuffer -= BytesToCopyInSecondPass;
  418. Irp->IoStatus.Information+= BytesToCopyInSecondPass;
  419. }
  420. if (Irp->IoStatus.Information == IrpSp->Parameters.Read.Length) {
  421. //
  422. // the irp is full, set status to success
  423. //
  424. Irp->IoStatus.Status=STATUS_SUCCESS;
  425. //
  426. // since it is now full, it can complete now
  427. //
  428. DeviceExtension->Read.IrpShouldBeCompleted=TRUE;
  429. }
  430. if (DeviceExtension->Read.IrpShouldBeCompletedWithAnyData && (Irp->IoStatus.Information > 0)) {
  431. //
  432. // the client wants the irp to complete when any data is present
  433. //
  434. Irp->IoStatus.Status=STATUS_SUCCESS;
  435. //
  436. // make complete
  437. //
  438. DeviceExtension->Read.IrpShouldBeCompleted=TRUE;
  439. }
  440. }
  441. if ((DeviceExtension->Read.BytesInBuffer == 0) && DeviceExtension->Read.RefusedDataIndication) {
  442. //
  443. // the buffer is empty now and we previous refused some indicated data
  444. //
  445. DbgPrint("IRCOMM: requesting data\n");
  446. DeviceExtension->Read.RefusedDataIndication=FALSE;
  447. RequestDataIndications=TRUE;
  448. }
  449. KeReleaseSpinLock(
  450. &DeviceExtension->Read.ReadLock,
  451. OldIrql
  452. );
  453. if (RequestDataIndications) {
  454. IndicateReceiveBufferSpaceAvailible(
  455. DeviceExtension->ConnectionHandle
  456. );
  457. }
  458. return;
  459. }
  460. VOID
  461. ReadCancelRoutine(
  462. PDEVICE_OBJECT DeviceObject,
  463. PIRP Irp
  464. )
  465. {
  466. PFDO_DEVICE_EXTENSION DeviceExtension=DeviceObject->DeviceExtension;
  467. KIRQL OldIrql;
  468. IoReleaseCancelSpinLock(Irp->CancelIrql);
  469. KeAcquireSpinLock(
  470. &DeviceExtension->Read.ReadLock,
  471. &OldIrql
  472. );
  473. DeviceExtension->Read.IrpRefCount--;
  474. DeviceExtension->Read.IrpShouldBeCompleted=TRUE;
  475. KeReleaseSpinLock(
  476. &DeviceExtension->Read.ReadLock,
  477. OldIrql
  478. );
  479. SeeIfIrpShouldBeCompleted(
  480. DeviceExtension
  481. );
  482. return;
  483. }
  484. VOID
  485. IntervalTimeProc(
  486. PKDPC Dpc,
  487. PVOID Context,
  488. PVOID SystemParam1,
  489. PVOID SystemParam2
  490. )
  491. {
  492. PFDO_DEVICE_EXTENSION DeviceExtension=Context;
  493. KIRQL OldIrql;
  494. PIRP Irp=NULL;
  495. D_ERROR(DbgPrint("IRCOMM: Interval timeout expired\n");)
  496. MoveDataFromBufferToIrp(
  497. DeviceExtension
  498. );
  499. KeAcquireSpinLock(
  500. &DeviceExtension->Read.ReadLock,
  501. &OldIrql
  502. );
  503. ASSERT(DeviceExtension->Read.IntervalTimerSet);
  504. //
  505. // this timer is not set anymore
  506. //
  507. DeviceExtension->Read.IntervalTimerSet=FALSE;
  508. DeviceExtension->Read.IrpRefCount--;
  509. DeviceExtension->Read.IrpShouldBeCompleted=TRUE;
  510. KeReleaseSpinLock(
  511. &DeviceExtension->Read.ReadLock,
  512. OldIrql
  513. );
  514. SeeIfIrpShouldBeCompleted(
  515. DeviceExtension
  516. );
  517. return;
  518. }
  519. VOID
  520. TotalTimerProc(
  521. PKDPC Dpc,
  522. PVOID Context,
  523. PVOID SystemParam1,
  524. PVOID SystemParam2
  525. )
  526. {
  527. PFDO_DEVICE_EXTENSION DeviceExtension=Context;
  528. KIRQL OldIrql;
  529. D_TRACE1(DbgPrint("IRCOMM: Total timeout expired\n");)
  530. MoveDataFromBufferToIrp(
  531. DeviceExtension
  532. );
  533. KeAcquireSpinLock(
  534. &DeviceExtension->Read.ReadLock,
  535. &OldIrql
  536. );
  537. ASSERT(DeviceExtension->Read.TotalTimerSet);
  538. //
  539. // this timer is not set anymore
  540. //
  541. DeviceExtension->Read.TotalTimerSet=FALSE;
  542. DeviceExtension->Read.IrpRefCount--;
  543. DeviceExtension->Read.IrpShouldBeCompleted=TRUE;
  544. KeReleaseSpinLock(
  545. &DeviceExtension->Read.ReadLock,
  546. OldIrql
  547. );
  548. SeeIfIrpShouldBeCompleted(
  549. DeviceExtension
  550. );
  551. return;
  552. }
  553. VOID
  554. SeeIfIrpShouldBeCompleted(
  555. PFDO_DEVICE_EXTENSION DeviceExtension
  556. )
  557. {
  558. KIRQL OldIrql;
  559. PIRP Irp=NULL;
  560. KeAcquireSpinLock(
  561. &DeviceExtension->Read.ReadLock,
  562. &OldIrql
  563. );
  564. if (DeviceExtension->Read.CurrentIrp != NULL) {
  565. //
  566. // There is an irp present
  567. //
  568. if (DeviceExtension->Read.IrpShouldBeCompleted) {
  569. //
  570. // either the irp is full, or a timer has expired. We are done with this irp in anycase.
  571. //
  572. PVOID OldCancelRoutine;
  573. //
  574. // try to cancel the timers, since we want to complete the irp now.
  575. //
  576. if (DeviceExtension->Read.IntervalTimerSet) {
  577. BOOLEAN Canceled;
  578. Canceled=KeCancelTimer(
  579. &DeviceExtension->Read.IntervalTimer
  580. );
  581. if (Canceled) {
  582. //
  583. // We ended up canceling the timer
  584. //
  585. DeviceExtension->Read.IrpRefCount--;
  586. DeviceExtension->Read.IntervalTimerSet=FALSE;
  587. } else {
  588. //
  589. // The timer is already running, we will just let it complete
  590. // and do the clean up.
  591. //
  592. }
  593. }
  594. if (DeviceExtension->Read.TotalTimerSet) {
  595. BOOLEAN Canceled;
  596. Canceled=KeCancelTimer(
  597. &DeviceExtension->Read.TotalTimer
  598. );
  599. if (Canceled) {
  600. //
  601. // We ended up canceling the timer
  602. //
  603. DeviceExtension->Read.IrpRefCount--;
  604. DeviceExtension->Read.TotalTimerSet=FALSE;
  605. } else {
  606. //
  607. // The timer is already running, we will just let it complete
  608. // and do the clean up.
  609. //
  610. }
  611. }
  612. OldCancelRoutine=IoSetCancelRoutine(DeviceExtension->Read.CurrentIrp,NULL);
  613. if (OldCancelRoutine != NULL) {
  614. //
  615. // the irp has not been canceled yet, and will not be now
  616. //
  617. DeviceExtension->Read.IrpRefCount--;
  618. } else {
  619. //
  620. // the cancel routine has run and decremented the ref count for us
  621. //
  622. }
  623. ASSERT(DeviceExtension->Read.IrpRefCount > 0);
  624. if (DeviceExtension->Read.IrpRefCount == 1) {
  625. //
  626. // We can complete the irp now
  627. //
  628. ASSERT(!DeviceExtension->Read.TotalTimerSet);
  629. ASSERT(!DeviceExtension->Read.IntervalTimerSet);
  630. #if DBG
  631. DeviceExtension->Read.IrpRefCount=0;
  632. #endif
  633. Irp=DeviceExtension->Read.CurrentIrp;
  634. DeviceExtension->Read.CurrentIrp=NULL;
  635. InterlockedExchangeAdd(&DeviceExtension->Read.BytesRead,(LONG)Irp->IoStatus.Information);
  636. }
  637. }
  638. }
  639. KeReleaseSpinLock(
  640. &DeviceExtension->Read.ReadLock,
  641. OldIrql
  642. );
  643. if (Irp != NULL) {
  644. //
  645. // we should complete this irp now
  646. //
  647. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  648. StartNextPacket(&DeviceExtension->Read.Queue);
  649. }
  650. return;
  651. }
  652. VOID
  653. ReadPurge(
  654. PFDO_DEVICE_EXTENSION DeviceExtension,
  655. ULONG Flags
  656. )
  657. {
  658. KIRQL OldIrql;
  659. BOOLEAN RequestDataIndications=FALSE;
  660. if (Flags == READ_PURGE_CLEAR_BUFFER) {
  661. //
  662. // the caller wants the buffer cleared
  663. //
  664. KeAcquireSpinLock(
  665. &DeviceExtension->Read.ReadLock,
  666. &OldIrql
  667. );
  668. DeviceExtension->Read.BytesInBuffer=0;
  669. DeviceExtension->Read.NextFilledByte=&DeviceExtension->Read.InputBuffer[0];
  670. DeviceExtension->Read.NextEmptyByte=&DeviceExtension->Read.InputBuffer[0];
  671. #if DBG
  672. RtlFillMemory(
  673. &DeviceExtension->Read.InputBuffer[0],
  674. sizeof(DeviceExtension->Read.InputBuffer),
  675. 0xf7
  676. );
  677. #endif
  678. if (DeviceExtension->Read.RefusedDataIndication) {
  679. //
  680. // the buffer is empty now and we previous refused some indicated data
  681. //
  682. DbgPrint("IRCOMM: requesting data from purge\n");
  683. DeviceExtension->Read.RefusedDataIndication=FALSE;
  684. RequestDataIndications=TRUE;
  685. }
  686. KeReleaseSpinLock(
  687. &DeviceExtension->Read.ReadLock,
  688. OldIrql
  689. );
  690. }
  691. if (Flags == READ_PURGE_ABORT_IRP) {
  692. //
  693. // the caller wants the current irp to complete
  694. //
  695. DeviceExtension->Read.IrpShouldBeCompleted=TRUE;
  696. SeeIfIrpShouldBeCompleted(
  697. DeviceExtension
  698. );
  699. }
  700. if (RequestDataIndications) {
  701. IndicateReceiveBufferSpaceAvailible(
  702. DeviceExtension->ConnectionHandle
  703. );
  704. }
  705. return;
  706. }