ReactOS  0.4.15-dev-3173-g40ee59d
scratch.c
Go to the documentation of this file.
1 /*--
2 
3 Copyright (C) Microsoft Corporation. All rights reserved.
4 
5 Module Name:
6 
7  scratch.c
8 
9 Abstract:
10 
11  Functions for using common scratch buffer
12 
13 Environment:
14 
15  kernel mode only
16 
17 Notes:
18 
19 
20 Revision History:
21 
22 --*/
23 
24 #include "stddef.h"
25 #include "string.h"
26 
27 #include "ntddk.h"
28 #include "ntddstor.h"
29 #include "cdrom.h"
30 #include "ioctl.h"
31 #include "scratch.h"
32 #include "mmc.h"
33 
34 #ifdef DEBUG_USE_WPP
35 #include "scratch.tmh"
36 #endif
37 
38 // Forward declarations
39 EVT_WDF_REQUEST_COMPLETION_ROUTINE ScratchBuffer_ReadWriteCompletionRoutine;
40 
41 #ifdef ALLOC_PRAGMA
42 
43 #pragma alloc_text(PAGE, ScratchBuffer_Deallocate)
44 #pragma alloc_text(PAGE, ScratchBuffer_Allocate)
45 #pragma alloc_text(PAGE, ScratchBuffer_SetupSrb)
46 #pragma alloc_text(PAGE, ScratchBuffer_ExecuteCdbEx)
47 
48 #endif
49 
51 VOID
52 ScratchBuffer_Deallocate(
53  _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension
54  )
55 /*++
56 
57 Routine Description:
58 
59  release all resources allocated for scratch.
60 
61 Arguments:
62 
63  DeviceExtension - device extension
64 
65 Return Value:
66 
67  none
68 
69 --*/
70 {
71  PAGED_CODE ();
72 
73  NT_ASSERT(DeviceExtension->ScratchContext.ScratchInUse == 0);
74 
75  if (DeviceExtension->ScratchContext.ScratchHistory != NULL)
76  {
77  ExFreePool(DeviceExtension->ScratchContext.ScratchHistory);
78  DeviceExtension->ScratchContext.ScratchHistory = NULL;
79  }
80  if (DeviceExtension->ScratchContext.ScratchSense != NULL)
81  {
82  ExFreePool(DeviceExtension->ScratchContext.ScratchSense);
83  DeviceExtension->ScratchContext.ScratchSense = NULL;
84  }
85  if (DeviceExtension->ScratchContext.ScratchSrb != NULL)
86  {
87  ExFreePool(DeviceExtension->ScratchContext.ScratchSrb);
88  DeviceExtension->ScratchContext.ScratchSrb = NULL;
89  }
90  if (DeviceExtension->ScratchContext.ScratchBufferSize != 0)
91  {
92  DeviceExtension->ScratchContext.ScratchBufferSize = 0;
93  }
94  if (DeviceExtension->ScratchContext.ScratchBufferMdl != NULL)
95  {
96  IoFreeMdl(DeviceExtension->ScratchContext.ScratchBufferMdl);
97  DeviceExtension->ScratchContext.ScratchBufferMdl = NULL;
98  }
99  if (DeviceExtension->ScratchContext.ScratchBuffer != NULL)
100  {
101  ExFreePool(DeviceExtension->ScratchContext.ScratchBuffer);
102  DeviceExtension->ScratchContext.ScratchBuffer = NULL;
103  }
104 
105  if (DeviceExtension->ScratchContext.PartialMdl != NULL)
106  {
107  IoFreeMdl(DeviceExtension->ScratchContext.PartialMdl);
108  DeviceExtension->ScratchContext.PartialMdl = NULL;
109  }
110 
111  if (DeviceExtension->ScratchContext.ScratchRequest != NULL)
112  {
113  PIRP irp = WdfRequestWdmGetIrp(DeviceExtension->ScratchContext.ScratchRequest);
114  if (irp->MdlAddress)
115  {
116  irp->MdlAddress = NULL;
117  }
118  WdfObjectDelete(DeviceExtension->ScratchContext.ScratchRequest);
119  DeviceExtension->ScratchContext.ScratchRequest = NULL;
120  }
121 
122  return;
123 }
124 
126 BOOLEAN
127 ScratchBuffer_Allocate(
128  _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension
129  )
130 /*++
131 
132 Routine Description:
133 
134  allocate resources allocated for scratch.
135 
136 Arguments:
137 
138  DeviceExtension - device extension
139 
140 Return Value:
141 
142  none
143 
144 --*/
145 {
147 
148  PAGED_CODE ();
149 
150  NT_ASSERT(DeviceExtension->ScratchContext.ScratchInUse == 0);
151 
152  // quick-exit if already allocated
153  if ((DeviceExtension->ScratchContext.ScratchBuffer != NULL) &&
154  (DeviceExtension->ScratchContext.ScratchBufferMdl != NULL) &&
155  (DeviceExtension->ScratchContext.ScratchBufferSize != 0) &&
156  (DeviceExtension->ScratchContext.ScratchRequest != NULL) &&
157  (DeviceExtension->ScratchContext.ScratchSrb != NULL) &&
158  (DeviceExtension->ScratchContext.ScratchHistory != NULL) &&
159  (DeviceExtension->ScratchContext.PartialMdl != NULL)
160  )
161  {
162  return TRUE;
163  }
164 
165  // validate max transfer already determined
166  NT_ASSERT(DeviceExtension->DeviceAdditionalData.MaxPageAlignedTransferBytes != 0);
167 
168  // validate no partially-saved state
169  NT_ASSERT(DeviceExtension->ScratchContext.ScratchBuffer == NULL);
170  NT_ASSERT(DeviceExtension->ScratchContext.ScratchBufferMdl == NULL);
171  NT_ASSERT(DeviceExtension->ScratchContext.ScratchBufferSize == 0);
172  NT_ASSERT(DeviceExtension->ScratchContext.ScratchRequest == NULL);
173  NT_ASSERT(DeviceExtension->ScratchContext.PartialMdl == NULL);
174 
175  // limit the scratch buffer to between 4k and 64k (so data length fits into USHORT -- req'd for many commands)
176  DeviceExtension->ScratchContext.ScratchBufferSize = min(DeviceExtension->DeviceAdditionalData.MaxPageAlignedTransferBytes, (64*1024));
177 
178  // allocate the buffer
179  if (NT_SUCCESS(status))
180  {
181  DeviceExtension->ScratchContext.ScratchBuffer = ExAllocatePoolWithTag(NonPagedPoolNx,
182  DeviceExtension->ScratchContext.ScratchBufferSize,
184  if (DeviceExtension->ScratchContext.ScratchBuffer == NULL)
185  {
187  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
188  "Failed to allocate scratch buffer of %x bytes\n",
189  DeviceExtension->ScratchContext.ScratchBufferSize
190  ));
191  }
192  else if (BYTE_OFFSET(DeviceExtension->ScratchContext.ScratchBuffer) != 0)
193  {
195  TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_INIT,
196  "Allocation of %x bytes non-paged pool was not "
197  "allocated on page boundary? STATUS_INTERNAL_ERROR\n",
198  DeviceExtension->ScratchContext.ScratchBufferSize
199  ));
200  }
201  }
202 
203  // allocate the MDL
204  if (NT_SUCCESS(status))
205  {
206  DeviceExtension->ScratchContext.ScratchBufferMdl = IoAllocateMdl(DeviceExtension->ScratchContext.ScratchBuffer,
207  DeviceExtension->ScratchContext.ScratchBufferSize,
208  FALSE, FALSE, NULL);
209  if (DeviceExtension->ScratchContext.ScratchBufferMdl == NULL)
210  {
212  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
213  "Failed to allocate MDL for %x byte buffer\n",
214  DeviceExtension->ScratchContext.ScratchBufferSize
215  ));
216  }
217  else
218  {
219  MmBuildMdlForNonPagedPool(DeviceExtension->ScratchContext.ScratchBufferMdl);
220  }
221  }
222 
223  // create the request
224  if (NT_SUCCESS(status))
225  {
226  WDF_OBJECT_ATTRIBUTES attributes;
229 
230  status = WdfRequestCreate(&attributes,
231  DeviceExtension->IoTarget,
232  &DeviceExtension->ScratchContext.ScratchRequest);
233 
234  if ((!NT_SUCCESS(status)) ||
235  (DeviceExtension->ScratchContext.ScratchRequest == NULL))
236  {
238  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
239  "Failed to allocate scratch MDL \n"));
240  }
241  }
242 
243  // allocate the srb
244  if (NT_SUCCESS(status))
245  {
246  DeviceExtension->ScratchContext.ScratchSrb = ExAllocatePoolWithTag(NonPagedPoolNx,
247  sizeof(SCSI_REQUEST_BLOCK),
249 
250  if (DeviceExtension->ScratchContext.ScratchSrb == NULL)
251  {
253  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
254  "Failed to allocate scratch SRB\n"));
255  }
256  }
257 
258  // allocate the sense buffer
259  if (NT_SUCCESS(status))
260  {
261  DeviceExtension->ScratchContext.ScratchSense = ExAllocatePoolWithTag(NonPagedPoolNx,
262  sizeof(SENSE_DATA),
264 
265  if (DeviceExtension->ScratchContext.ScratchSense == NULL)
266  {
268  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
269  "Failed to allocate scratch sense data\n"
270  ));
271  }
272  }
273 
274  // allocate the SRB history data
275  if (NT_SUCCESS(status))
276  {
277  size_t allocationSize = sizeof(SRB_HISTORY) - sizeof(SRB_HISTORY_ITEM);
278  allocationSize += 20 * sizeof(SRB_HISTORY_ITEM);
279 
280  DeviceExtension->ScratchContext.ScratchHistory = ExAllocatePoolWithTag(NonPagedPoolNx,
281  allocationSize,
283  if (DeviceExtension->ScratchContext.ScratchHistory == NULL)
284  {
286  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
287  "Failed to allocate scratch history buffer\n"
288  ));
289  }
290  else
291  {
292  // must be initialized here...
293  RtlZeroMemory(DeviceExtension->ScratchContext.ScratchHistory, allocationSize);
294  DeviceExtension->ScratchContext.ScratchHistory->TotalHistoryCount = 20;
295  }
296  }
297 
298  // allocate the MDL
299  if (NT_SUCCESS(status))
300  {
301  ULONG transferLength = 0;
302 
303  status = RtlULongAdd(DeviceExtension->DeviceAdditionalData.MaxPageAlignedTransferBytes, PAGE_SIZE, &transferLength);
304  if (NT_SUCCESS(status))
305  {
306  DeviceExtension->ScratchContext.PartialMdlIsBuilt = FALSE;
307  DeviceExtension->ScratchContext.PartialMdl = IoAllocateMdl(NULL,
308  transferLength,
309  FALSE,
310  FALSE,
311  NULL);
312  if (DeviceExtension->ScratchContext.PartialMdl == NULL)
313  {
315  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
316  "Failed to allocate MDL for %x byte buffer\n",
317  DeviceExtension->ScratchContext.ScratchBufferSize
318  ));
319  }
320  else
321  {
322  NT_ASSERT(DeviceExtension->ScratchContext.PartialMdl->Size >=
323  (CSHORT)(sizeof(MDL) + BYTES_TO_PAGES(DeviceExtension->DeviceAdditionalData.MaxPageAlignedTransferBytes) * sizeof(PFN_NUMBER)));
324  }
325  }
326  else
327  {
329  }
330  }
331 
332  // cleanup on failure
333  if (!NT_SUCCESS(status))
334  {
335  ScratchBuffer_Deallocate(DeviceExtension);
336  }
337 
338  return NT_SUCCESS(status);
339 }
340 
341 
342 VOID
344  _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
345  _In_ BOOLEAN ResetRequestHistory
346  )
347 /*++
348 
349 Routine Description:
350 
351  reset scratch items for reuse.
352 
353 Arguments:
354 
355  DeviceExtension - device extension
356  ResetRequestHistory - reset history fields or not
357 
358 Return Value:
359 
360  none
361 
362 --*/
363 {
365  WDF_REQUEST_REUSE_PARAMS reuseParams;
366  PIRP irp = NULL;
367 
368  NT_ASSERT(DeviceExtension->ScratchContext.ScratchHistory != NULL);
369  NT_ASSERT(DeviceExtension->ScratchContext.ScratchSense != NULL);
370  NT_ASSERT(DeviceExtension->ScratchContext.ScratchSrb != NULL);
371  NT_ASSERT(DeviceExtension->ScratchContext.ScratchRequest != NULL);
372  NT_ASSERT(DeviceExtension->ScratchContext.ScratchBufferSize != 0);
373  NT_ASSERT(DeviceExtension->ScratchContext.ScratchBuffer != NULL);
374  NT_ASSERT(DeviceExtension->ScratchContext.ScratchBufferMdl != NULL);
375  NT_ASSERT(DeviceExtension->ScratchContext.ScratchInUse != 0);
376 
377  irp = WdfRequestWdmGetIrp(DeviceExtension->ScratchContext.ScratchRequest);
378 
379  if (ResetRequestHistory)
380  {
381  PSRB_HISTORY history = DeviceExtension->ScratchContext.ScratchHistory;
382  RtlZeroMemory(history->History, sizeof(SRB_HISTORY_ITEM) * history->TotalHistoryCount);
383  history->ClassDriverUse[0] = 0;
384  history->ClassDriverUse[1] = 0;
385  history->ClassDriverUse[2] = 0;
386  history->ClassDriverUse[3] = 0;
387  history->UsedHistoryCount = 0;
388  }
389 
390  // re-use the KMDF request object
391 
392  // deassign the MdlAddress, this is the value we assign explicitly.
393  // this is to prevent WdfRequestReuse to release the Mdl unexpectly.
394  if (irp->MdlAddress)
395  {
396  irp->MdlAddress = NULL;
397  }
398 
400  status = WdfRequestReuse(DeviceExtension->ScratchContext.ScratchRequest, &reuseParams);
401  // WDF request to format the request befor sending it
402  if (NT_SUCCESS(status))
403  {
404  // clean up completion routine.
405  WdfRequestSetCompletionRoutine(DeviceExtension->ScratchContext.ScratchRequest, NULL, NULL);
406 
407  status = WdfIoTargetFormatRequestForInternalIoctlOthers(DeviceExtension->IoTarget,
408  DeviceExtension->ScratchContext.ScratchRequest,
410  NULL, NULL,
411  NULL, NULL,
412  NULL, NULL);
413  if (!NT_SUCCESS(status))
414  {
415  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
416  "ScratchBuffer_ResetItems: WdfIoTargetFormatRequestForInternalIoctlOthers failed, %!STATUS!\n",
417  status));
418  }
419  }
420 
421  RtlZeroMemory(DeviceExtension->ScratchContext.ScratchSense, sizeof(SENSE_DATA));
422  RtlZeroMemory(DeviceExtension->ScratchContext.ScratchSrb, sizeof(SCSI_REQUEST_BLOCK));
423 
424  return;
425 }
426 
427 
428 NTSTATUS
430  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
432  )
433 /*++
434 
435 Routine Description:
436 
437  This function asynchronously sends the next read/write SRB down the stack.
438 
439 Arguments:
440 
441  DeviceExtension - Device extension
442 
443 Return Value:
444 
445  none
446 
447 --*/
448 {
449  PCDROM_SCRATCH_READ_WRITE_CONTEXT readWriteContext = &DeviceExtension->ScratchContext.ScratchReadWriteContext;
450  PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(DeviceExtension->ScratchContext.ScratchRequest);
451  WDFREQUEST originalRequest = requestContext->OriginalRequest;
453 
454  ULONG transferSize;
455  BOOLEAN usePartialMdl;
456 
457  transferSize = min((readWriteContext->EntireXferLen - readWriteContext->TransferedBytes), readWriteContext->MaxLength);
458 
459  if (FirstTry)
460  {
461  DeviceExtension->ScratchContext.NumRetries = 0;
462  }
463 
464  ScratchBuffer_ResetItems(DeviceExtension, FALSE);
465 
466  usePartialMdl = (readWriteContext->PacketsCount > 1 || readWriteContext->TransferedBytes > 0);
467 
468  ScratchBuffer_SetupReadWriteSrb(DeviceExtension,
469  originalRequest,
470  readWriteContext->StartingOffset,
471  transferSize,
472  readWriteContext->DataBuffer,
473  readWriteContext->IsRead,
474  usePartialMdl
475  );
476 
477  WdfRequestSetCompletionRoutine(DeviceExtension->ScratchContext.ScratchRequest,
479 
480  status = ScratchBuffer_SendSrb(DeviceExtension, FALSE, (FirstTry ? &readWriteContext->SrbHistoryItem : NULL));
481 
482  return status;
483 }
484 
485 
486 VOID
487 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
489  struct _KDPC *Dpc,
493  )
494 /*++
495 
496 Routine Description:
497 
498  Timer routine for retrying read and write requests.
499 
500 Arguments:
501 
502  Timer - WDF timer
503 
504 Return Value:
505 
506  none
507 
508 --*/
509 {
510  PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
511  PCDROM_SCRATCH_READ_WRITE_CONTEXT readWriteContext = NULL;
512  WDFREQUEST originalRequest = NULL;
513  PCDROM_REQUEST_CONTEXT requestContext = NULL;
515  KIRQL oldIrql;
516 
520 
521  if (DeferredContext == NULL)
522  {
523  // This is impossible, but definition of KDEFERRED_ROUTINE allows optional argument,
524  // and thus OACR will complain.
525 
526  return;
527  }
528 
529  originalRequest = (WDFREQUEST) DeferredContext;
530  requestContext = RequestGetContext(originalRequest);
531 
532  KeAcquireSpinLock(&requestContext->ReadWriteCancelSpinLock, &oldIrql);
533 
534  if (!requestContext->ReadWriteIsCompleted)
535  {
536  // As the first step, unregister the cancellation routine
537  status = WdfRequestUnmarkCancelable(originalRequest);
538  }
539  else
540  {
542  }
543 
544  KeReleaseSpinLock(&requestContext->ReadWriteCancelSpinLock, oldIrql);
545 
546  if (status != STATUS_CANCELLED)
547  {
548  deviceExtension = requestContext->DeviceExtension;
549  readWriteContext = &deviceExtension->ScratchContext.ScratchReadWriteContext;
550 
551  // We use timer only for retries, that's why the second parameter is always FALSE
552  status = ScratchBuffer_PerformNextReadWrite(deviceExtension, FALSE);
553 
554  if (!NT_SUCCESS(status))
555  {
556  ScratchBuffer_EndUse(deviceExtension);
557  RequestCompletion(deviceExtension, originalRequest, status, readWriteContext->TransferedBytes);
558  }
559  }
560 
561  //
562  // Drop the extra reference
563  //
564  WdfObjectDereference(originalRequest);
565 }
566 
567 
569 
570 VOID
571 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
573  _In_ WDFREQUEST Request
574  )
575 /*++
576 
577 Routine Description:
578 
579  Cancels a request waiting for the read/write timer to expire. This function does not
580  support cancellation of requests that have already been sent down.
581 
582 Arguments:
583 
584  Request - WDF request
585 
586 Return Value:
587 
588  none
589 
590 --*/
591 {
592  PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
593  PCDROM_DEVICE_EXTENSION deviceExtension = requestContext->DeviceExtension;
594  PCDROM_SCRATCH_READ_WRITE_CONTEXT readWriteContext = &deviceExtension->ScratchContext.ScratchReadWriteContext;
595  KIRQL oldIrql;
596 
597  KeAcquireSpinLock(&requestContext->ReadWriteCancelSpinLock, &oldIrql);
598 
599  if (KeCancelTimer(&requestContext->ReadWriteTimer))
600  {
601  //
602  // Timer is canceled, we own the request. Drop the reference we took before
603  // queueing the timer.
604  //
606  }
607  else
608  {
609  //
610  // Timer will run and drop the reference but it won't complete the request
611  // because we set IsCompleted to TRUE
612  //
613  }
614 
615  requestContext->ReadWriteIsCompleted = TRUE;
616 
617  KeReleaseSpinLock(&requestContext->ReadWriteCancelSpinLock, oldIrql);
618 
619  ScratchBuffer_EndUse(deviceExtension);
620 
621  // If WdfTimerStop returned TRUE, it means this request was scheduled for a retry
622  // and the retry has not happened yet. We just need to cancel it and release the scratch buffer.
623  RequestCompletion(deviceExtension, Request, STATUS_CANCELLED, readWriteContext->TransferedBytes);
624 }
625 
626 VOID
627 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
629  _In_ WDFREQUEST Request,
630  _In_ WDFIOTARGET Target,
633  )
634 /*++
635 
636 Routine Description:
637 
638  Read/write request completion routine.
639 
640 Arguments:
641  Request - WDF request
642  Target - The IO target the request was completed by.
643  Params - the request completion parameters
644  Context - context
645 
646 Return Value:
647 
648  none
649 
650 --*/
651 {
653  PCDROM_SCRATCH_READ_WRITE_CONTEXT readWriteContext = &deviceExtension->ScratchContext.ScratchReadWriteContext;
655  PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(deviceExtension->ScratchContext.ScratchRequest);
656  WDFREQUEST originalRequest = requestContext->OriginalRequest;
657 
658  if (!NT_SUCCESS(WdfRequestGetStatus(Request)))
659  {
660  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
661  "WdfRequestSend: %lx\n",
662  WdfRequestGetStatus(Request)
663  ));
664  }
665 
668 
669  // We are not calling ScratchBuffer_BeginUse / ScratchBuffer_EndUse in this function, because we already own
670  // the scratch buffer if this function is being called.
671 
672  if ((deviceExtension->ScratchContext.ScratchSrb->SrbStatus == SRB_STATUS_ABORTED) &&
674  {
675  // The request has been cancelled, just need to complete it
676  }
677  else if (SRB_STATUS(deviceExtension->ScratchContext.ScratchSrb->SrbStatus) != SRB_STATUS_SUCCESS)
678  {
679  // The SCSI command that we sent down has failed, retry it if necessary
680  BOOLEAN shouldRetry = TRUE;
681  LONGLONG retryIn100nsUnits = 0;
682 
683  shouldRetry = RequestSenseInfoInterpretForScratchBuffer(deviceExtension,
684  deviceExtension->ScratchContext.NumRetries,
685  &status,
686  &retryIn100nsUnits);
687 
688  if (shouldRetry)
689  {
690  deviceExtension->ScratchContext.NumRetries++;
691 
692  if (retryIn100nsUnits == 0)
693  {
694  // We take a shortcut here by calling ScratchBuffer_PerformNextReadWrite directly:
695  // this helps to avoid unnecessary context switch.
696  status = ScratchBuffer_PerformNextReadWrite(deviceExtension, FALSE);
697 
698  if (NT_SUCCESS(status))
699  {
700  // We're not done with the request yet, no need to complete it now
701  return;
702  }
703  }
704  else
705  {
706  PCDROM_REQUEST_CONTEXT originalRequestContext = RequestGetContext(originalRequest);
707  KIRQL oldIrql;
708 
709  //
710  // Initialize the spin lock and timer local to the original request.
711  //
712  if (!originalRequestContext->ReadWriteRetryInitialized)
713  {
714  KeInitializeSpinLock(&originalRequestContext->ReadWriteCancelSpinLock);
715  KeInitializeTimer(&originalRequestContext->ReadWriteTimer);
716  KeInitializeDpc(&originalRequestContext->ReadWriteDpc, ScratchBuffer_ReadWriteTimerRoutine, originalRequest);
717  originalRequestContext->ReadWriteRetryInitialized = TRUE;
718  }
719 
720  KeAcquireSpinLock(&requestContext->ReadWriteCancelSpinLock, &oldIrql);
721 
722  status = WdfRequestMarkCancelableEx(originalRequest, ScratchBuffer_ReadWriteEvtRequestCancel);
723 
724  if (status == STATUS_CANCELLED)
725  {
726  requestContext->ReadWriteIsCompleted = TRUE;
727 
728  KeReleaseSpinLock(&requestContext->ReadWriteCancelSpinLock, oldIrql);
729  }
730  else
731  {
733 
734  t.QuadPart = -retryIn100nsUnits;
735 
736  WdfObjectReference(originalRequest);
737 
738  // Use negative time to indicate that we want a relative delay
739  KeSetTimer(&originalRequestContext->ReadWriteTimer,
740  t,
741  &originalRequestContext->ReadWriteDpc
742  );
743 
744  KeReleaseSpinLock(&requestContext->ReadWriteCancelSpinLock, oldIrql);
745 
746  return;
747  }
748  }
749  }
750  }
751  else
752  {
753  // The SCSI command has succeeded
754  readWriteContext->DataBuffer += deviceExtension->ScratchContext.ScratchSrb->DataTransferLength;
755  readWriteContext->StartingOffset.QuadPart += deviceExtension->ScratchContext.ScratchSrb->DataTransferLength;
756  readWriteContext->TransferedBytes += deviceExtension->ScratchContext.ScratchSrb->DataTransferLength;
757  readWriteContext->PacketsCount--;
758 
759  // Update the SRB history item
760  if (readWriteContext->SrbHistoryItem)
761  {
762  ULONG senseSize;
763 
764  // Query the tick count and store in the history
766 
767  // Copy the SRB Status...
768  readWriteContext->SrbHistoryItem->SrbStatus = deviceExtension->ScratchContext.ScratchSrb->SrbStatus;
769 
770  // Determine the amount of valid sense data
771  if (deviceExtension->ScratchContext.ScratchSrb->SenseInfoBufferLength >=
772  RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength))
773  {
775  senseSize = RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength) +
776  sense->AdditionalSenseLength;
777  senseSize = min(senseSize, sizeof(SENSE_DATA));
778  }
779  else
780  {
781  senseSize = deviceExtension->ScratchContext.ScratchSrb->SenseInfoBufferLength;
782  }
783 
784  // Normalize the sense data copy in the history
785  RtlZeroMemory(&(readWriteContext->SrbHistoryItem->NormalizedSenseData), sizeof(SENSE_DATA));
786  RtlCopyMemory(&(readWriteContext->SrbHistoryItem->NormalizedSenseData),
787  deviceExtension->ScratchContext.ScratchSrb->SenseInfoBuffer, senseSize);
788  }
789 
790  // Check whether we need to send more SCSI commands to complete the request
791  if (readWriteContext->PacketsCount > 0)
792  {
793  status = ScratchBuffer_PerformNextReadWrite(deviceExtension, TRUE);
794 
795  if (NT_SUCCESS(status))
796  {
797  // We're not done with the request yet, no need to complete it now
798  return;
799  }
800  }
801  }
802 
803  ScratchBuffer_EndUse(deviceExtension);
804 
805 
806  RequestCompletion(deviceExtension, originalRequest, status, readWriteContext->TransferedBytes);
807 }
808 
810 VOID
811 ScratchBuffer_SetupSrb(
812  _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
813  _In_opt_ WDFREQUEST OriginalRequest,
816  )
817 /*++
818 
819 Routine Description:
820 
821  setup scratch SRB for sending out.
822 
823 Arguments:
824 
825  DeviceExtension - device extension
826  OriginalRequest - original request delivered by WDF
827  MaximumTransferLength - transfer length
828  GetDataFromDevice - TRUE (get data from device); FALSE (send data to device)
829 
830 Return Value:
831 
832  none
833 
834 --*/
835 {
836  WDFREQUEST request = DeviceExtension->ScratchContext.ScratchRequest;
837  PIRP irp = WdfRequestWdmGetIrp(request);
838  PSCSI_REQUEST_BLOCK srb = DeviceExtension->ScratchContext.ScratchSrb;
839  PIO_STACK_LOCATION irpStack = NULL;
840  PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(request);
841 
842  PAGED_CODE ();
843 
844  requestContext->OriginalRequest = OriginalRequest;
845 
846  // set to use the full scratch buffer via the scratch SRB
847  irpStack = IoGetNextIrpStackLocation(irp);
848  irpStack->MajorFunction = IRP_MJ_SCSI;
849  if (MaximumTransferLength == 0)
850  {
851  irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_NONE;
852  }
853  else if (GetDataFromDevice)
854  {
855  irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN;
856  }
857  else
858  {
859  irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_OUT;
860  }
861  irpStack->Parameters.Scsi.Srb = srb;
862 
863  if (MaximumTransferLength > 0)
864  {
865  // the Irp must show the MDL's address for the transfer
866  irp->MdlAddress = DeviceExtension->ScratchContext.ScratchBufferMdl;
867 
868  srb->DataBuffer = DeviceExtension->ScratchContext.ScratchBuffer;
869  }
870 
871  // prepare the SRB with default values
875  srb->SrbStatus = 0;
876  srb->ScsiStatus = 0;
877  srb->NextSrb = NULL;
878  srb->OriginalRequest = irp;
880  srb->SenseInfoBuffer = DeviceExtension->ScratchContext.ScratchSense;
881 
882  srb->CdbLength = 16; // to cause failures if not set correctly -- CD devices limited to 12 bytes for now...
883 
884  srb->DataTransferLength = min(DeviceExtension->ScratchContext.ScratchBufferSize, MaximumTransferLength);
885  srb->TimeOutValue = DeviceExtension->TimeOutValue;
886  srb->SrbFlags = DeviceExtension->SrbFlags;
889 
890  if (MaximumTransferLength == 0)
891  {
893  }
894  else if (GetDataFromDevice)
895  {
897  }
898  else
899  {
901  }
902 }
903 
904 
905 NTSTATUS
907  _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
908  _In_ BOOLEAN SynchronousSrb,
909  _When_(SynchronousSrb, _Pre_null_)
910  _When_(!SynchronousSrb, _In_opt_)
911  PSRB_HISTORY_ITEM *SrbHistoryItem
912  )
913 /*++
914 
915 Routine Description:
916 
917  Send the command from the scratch SRB to lower driver and retry if necessary.
918 
919 Arguments:
920 
921  DeviceExtension - device extension
922  SynchronousSrb - indicates whether the SRB needs to be sent synchronously or nor
923  SrbHistoryItem - storage for SRB history item, if this is an asynchronous request
924 
925 Return Value:
926 
927  none
928 
929 --*/
930 {
932  PSCSI_REQUEST_BLOCK srb = DeviceExtension->ScratchContext.ScratchSrb;
933  PSRB_HISTORY history = DeviceExtension->ScratchContext.ScratchHistory;
935  BOOLEAN requestCancelled = FALSE;
936 
937  srb->InternalStatus = 0;
938  srb->SrbStatus = 0;
939 
940  // allocate/update history pre-command, if it is a synchronous request or we were supplied
941  // with a storage for the history item
942  if (SynchronousSrb || SrbHistoryItem != NULL)
943  {
944  // sending a packet implies a new history unit is to be used.
945  NT_ASSERT( history->UsedHistoryCount <= history->TotalHistoryCount );
946 
947  // if already all used up, remove at least one history unit
948  if (history->UsedHistoryCount == history->TotalHistoryCount )
949  {
950  CompressSrbHistoryData(history);
951  NT_ASSERT( history->UsedHistoryCount < history->TotalHistoryCount );
952  }
953 
954  // thus, since we are about to increment the count, it must now be less...
955  NT_ASSERT( history->UsedHistoryCount < history->TotalHistoryCount );
956 
957  // increment the number of history units in use
958  history->UsedHistoryCount++;
959 
960  // determine index to use
961  item = &( history->History[ history->UsedHistoryCount-1 ] );
962 
963  if (SrbHistoryItem != NULL)
964  {
965  *SrbHistoryItem = item;
966  }
967 
968  // zero out the history item
970 
971  // Query the tick count and store in the history
972  KeQueryTickCount(&item->TickCountSent);
973  }
974 
975  // get cancellation status;
976  {
977  PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(DeviceExtension->ScratchContext.ScratchRequest);
978 
979  if (requestContext->OriginalRequest != NULL)
980  {
981  requestCancelled = WdfRequestIsCanceled(requestContext->OriginalRequest);
982  }
983  }
984 
985  if (!requestCancelled)
986  {
987  status = RequestSend(DeviceExtension,
988  DeviceExtension->ScratchContext.ScratchRequest,
989  DeviceExtension->IoTarget,
990  SynchronousSrb ? WDF_REQUEST_SEND_OPTION_SYNCHRONOUS : 0,
991  NULL);
992 
993  // If this is a synchronous request, update the history item immediately, including "normalized" sense data
994  if (SynchronousSrb)
995  {
996  ULONG senseSize;
997 
998  // Query the tick count and store in the history
999  KeQueryTickCount(&item->TickCountCompleted);
1000 
1001  // Copy the SRB Status
1002  item->SrbStatus = srb->SrbStatus;
1003 
1004  // Determine the amount of valid sense data
1005  if (srb->SenseInfoBufferLength >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength))
1006  {
1007  PSENSE_DATA sense = (PSENSE_DATA)srb->SenseInfoBuffer;
1008  senseSize = RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength) +
1009  sense->AdditionalSenseLength;
1010  senseSize = min(senseSize, sizeof(SENSE_DATA));
1011  }
1012  else
1013  {
1014  senseSize = srb->SenseInfoBufferLength;
1015  }
1016 
1017  // Normalize the sense data copy in the history
1018  RtlZeroMemory(&(item->NormalizedSenseData), sizeof(SENSE_DATA));
1019  RtlCopyMemory(&(item->NormalizedSenseData), srb->SenseInfoBuffer, senseSize);
1020  }
1021  }
1022  else
1023  {
1024  DeviceExtension->ScratchContext.ScratchSrb->SrbStatus = SRB_STATUS_ABORTED;
1025  DeviceExtension->ScratchContext.ScratchSrb->InternalStatus = (ULONG)STATUS_CANCELLED;
1027  }
1028 
1029  return status;
1030 }
1031 
1032 VOID
1035  )
1036 /*++
1037 
1038 Routine Description:
1039 
1040  compress the SRB history data.
1041 
1042 Arguments:
1043 
1044  RequestHistory - SRB history data
1045 
1046 Return Value:
1047 
1048  RequestHistory - compressed history data
1049 
1050 --*/
1051 {
1052  ULONG i;
1053  NT_ASSERT( RequestHistory->UsedHistoryCount == RequestHistory->TotalHistoryCount );
1055 
1056  for (i=0; i < RequestHistory->UsedHistoryCount; i++)
1057  {
1058  // for each item...
1059  PSRB_HISTORY_ITEM toMatch = &( RequestHistory->History[i] );
1060  // hint: read const qualifiers backwards. i.e. srbstatus is a const UCHAR
1061  // so, "UCHAR const * const x" is read "x is a const pointer to a const UCHAR"
1062  // unfortunately, "const UCHAR" is equivalent to "UCHAR const", which causes
1063  // people no end of confusion due to its widespread use.
1064  UCHAR const srbStatus = toMatch->SrbStatus;
1065  UCHAR const sense = toMatch->NormalizedSenseData.SenseKey;
1066  UCHAR const asc = toMatch->NormalizedSenseData.AdditionalSenseCode;
1068  ULONG j;
1069 
1070  // see if there are any at higher indices with identical Sense/ASC/ASCQ
1071  for (j = i+1; (toMatch->ClassDriverUse != 0xFF) && (j < RequestHistory->UsedHistoryCount); j++)
1072  {
1073  PSRB_HISTORY_ITEM found = &( RequestHistory->History[j] );
1074  // close enough match?
1075  if ((srbStatus == found->SrbStatus) &&
1076  (sense == found->NormalizedSenseData.SenseKey) &&
1077  (asc == found->NormalizedSenseData.AdditionalSenseCode) &&
1079 
1080  // add the fields to keep reasonable track of delay times.
1083  } else {
1085  }
1086 
1087  // this found item cannot contain any compressed entries because
1088  // the first entry with a given set of sense/asc/ascq will always
1089  // either be full (0xFF) or be the only partially-full entry with
1090  // that sense/asc/ascq.
1091  NT_ASSERT(found->ClassDriverUse == 0);
1092  // add the counts so we still know how many retries total
1093  toMatch->ClassDriverUse++;
1094 
1095 
1096  // if not the last entry, need to move later entries earlier in the array
1097  if (j != RequestHistory->UsedHistoryCount-1) {
1098  // how many entries remain?
1099  SIZE_T remainingBytes = RequestHistory->UsedHistoryCount - 1 - j;
1100  remainingBytes *= sizeof(SRB_HISTORY_ITEM);
1101 
1102  // note that MOVE is required due to overlapping entries
1103  RtlMoveMemory(found, found+1, remainingBytes);
1104 
1105  // Finally, decrement the number of used history count and
1106  // decrement j to rescan the current location again
1107  --RequestHistory->UsedHistoryCount;
1108  --j;
1109  } // end moving of array elements around
1110  } // end of close enough match
1111  } // end j loop
1112  } // end i loop
1113 
1114  // unable to compress duplicate sense/asc/ascq, so just lose the most recent data
1115  if (RequestHistory->UsedHistoryCount == RequestHistory->TotalHistoryCount)
1116  {
1117  PSRB_HISTORY_ITEM item = &( RequestHistory->History[ RequestHistory->TotalHistoryCount-1 ] );
1118  RequestHistory->ClassDriverUse[0] += item->ClassDriverUse; // how many did we "lose"?
1119  RequestHistory->UsedHistoryCount--;
1120  }
1121 
1122  // finally, zero any that are no longer in use
1123  NT_ASSERT( RequestHistory->UsedHistoryCount != RequestHistory->TotalHistoryCount);
1124  {
1125  SIZE_T bytesToZero = RequestHistory->TotalHistoryCount - RequestHistory->UsedHistoryCount;
1126  bytesToZero *= sizeof(SRB_HISTORY_ITEM);
1127  RtlZeroMemory(&(RequestHistory->History[RequestHistory->UsedHistoryCount]), bytesToZero);
1128  }
1129 
1131  return;
1132 }
1133 
1134 VOID
1137  )
1138 {
1139 #if DBG
1140  // validate that all fully-compressed items are before any non-fully-compressed items of any particular sense/asc/ascq
1141  // validate that there is at most one partially-compressed item of any particular sense/asc/ascq
1142  // validate that all items of any particular sense/asc/ascq that are uncompressed are at the end
1143  // THUS: A(255) A(255) A( 40) A( 0) A( 0) is legal for all types with A as sense/asc/ascq
1144  // A(0) B(255) A( 0) B( 17) B( 0) is also legal because A/B are different types of error
1145 
1146  ULONG i;
1147  for (i = 0; i < RequestHistory->UsedHistoryCount; i++)
1148  {
1149  SRB_HISTORY_ITEM const * toMatch = &( RequestHistory->History[i] );
1150  UCHAR const srbStatus = toMatch->SrbStatus;
1151  UCHAR const sense = toMatch->NormalizedSenseData.SenseKey;
1152  UCHAR const asc = toMatch->NormalizedSenseData.AdditionalSenseCode;
1154  ULONG j;
1155 
1156  BOOLEAN foundPartiallyCompressedItem =
1157  (toMatch->ClassDriverUse != 0) &&
1158  (toMatch->ClassDriverUse != 0xFF) ;
1159  BOOLEAN foundUncompressedItem =
1160  (toMatch->ClassDriverUse == 0) ;
1161 
1162  for (j = i+1; j < RequestHistory->UsedHistoryCount; j++)
1163  {
1164  SRB_HISTORY_ITEM const * found = &( RequestHistory->History[j] );
1165  if ((srbStatus == found->SrbStatus) &&
1166  (sense == found->NormalizedSenseData.SenseKey) &&
1167  (asc == found->NormalizedSenseData.AdditionalSenseCode) &&
1169  )
1170  {
1171  // found a matching type, so validate ordering rules
1172  if (foundUncompressedItem && (found->ClassDriverUse != 0))
1173  {
1175  "History data has compressed history following uncompressed history "
1176  "for srbstatus/sense/asc/ascq of %02x/%02x/%02x/%02x at indices %d (%08x) and %d (%08x)\n",
1177  srbStatus, sense, asc, ascq,
1178  i,i, j,j
1179  );
1180  NT_ASSERT(FALSE);
1181  }
1182  else if (foundPartiallyCompressedItem && (found->ClassDriverUse == 0xFF))
1183  {
1185  "History data has fully compressed history following partially compressed history "
1186  "for srbstatus/sense/asc/ascq of %02x/%02x/%02x/%02x at indices %d (%08x) and %d (%08x)\n",
1187  srbStatus, sense, asc, ascq,
1188  i,i, j,j
1189  );
1190  NT_ASSERT(FALSE);
1191  }
1192 
1193  // update if we have now found partially compressed and/or uncompressed items
1194  if (found->ClassDriverUse == 0)
1195  {
1196  foundUncompressedItem = TRUE;
1197  }
1198  else if (found->ClassDriverUse != 0xFF)
1199  {
1200  foundPartiallyCompressedItem = TRUE;
1201  }
1202  } // end match of (toMatch,found)
1203  } // end loop j
1204  } // end loop i
1205 #else
1207 #endif
1208  return;
1209 }
1210 
1211 VOID
1213  _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1214  _In_ WDFREQUEST OriginalRequest,
1218  _In_ BOOLEAN IsReadRequest,
1219  _In_ BOOLEAN UsePartialMdl
1220  )
1221 /*++
1222 
1223 Routine Description:
1224 
1225  setup SRB for read/write request.
1226 
1227 Arguments:
1228 
1229  DeviceExtension - device extension
1230  OriginalRequest - read/write request
1231  StartingOffset - read/write starting offset
1232  DataBuffer - buffer for read/write
1233  IsReadRequest - TRUE (read); FALSE (write)
1234 
1235 Return Value:
1236 
1237  none
1238 
1239 --*/
1240 {
1241  //NOTE: R/W request not use the ScratchBuffer, instead, it uses the buffer associated with IRP.
1242 
1243  PSCSI_REQUEST_BLOCK srb = DeviceExtension->ScratchContext.ScratchSrb;
1244  PCDB cdb = (PCDB)srb->Cdb;
1245  LARGE_INTEGER logicalBlockAddr;
1246  ULONG numTransferBlocks;
1247 
1248  PIRP originalIrp = WdfRequestWdmGetIrp(OriginalRequest);
1249 
1250  PIRP irp = WdfRequestWdmGetIrp(DeviceExtension->ScratchContext.ScratchRequest);
1251  PIO_STACK_LOCATION irpStack = NULL;
1252 
1253  PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(DeviceExtension->ScratchContext.ScratchRequest);
1254 
1255  requestContext->OriginalRequest = OriginalRequest;
1256 
1257 
1258  logicalBlockAddr.QuadPart = Int64ShrlMod32(StartingOffset.QuadPart, DeviceExtension->SectorShift);
1259  numTransferBlocks = RequiredLength >> DeviceExtension->SectorShift;
1260 
1261  // set to use the full scratch buffer via the scratch SRB
1262  irpStack = IoGetNextIrpStackLocation(irp);
1263  irpStack->MajorFunction = IRP_MJ_SCSI;
1264  if (IsReadRequest)
1265  {
1266  irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN;
1267  }
1268  else
1269  {
1270  irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_OUT;
1271  }
1272  irpStack->Parameters.Scsi.Srb = srb;
1273 
1274  // prepare the SRB with default values
1278  srb->SrbStatus = 0;
1279  srb->ScsiStatus = 0;
1280  srb->NextSrb = NULL;
1282  srb->SenseInfoBuffer = DeviceExtension->ScratchContext.ScratchSense;
1283 
1284  srb->DataBuffer = DataBuffer;
1286 
1287  srb->QueueSortKey = logicalBlockAddr.LowPart;
1288  if (logicalBlockAddr.QuadPart > 0xFFFFFFFF)
1289  {
1290  //
1291  // If the requested LBA is more than max ULONG set the
1292  // QueueSortKey to the maximum value, so that these
1293  // requests can be added towards the end of the queue.
1294  //
1295  srb->QueueSortKey = 0xFFFFFFFF;
1296  }
1297 
1298  srb->OriginalRequest = irp;
1299  srb->TimeOutValue = DeviceExtension->TimeOutValue;
1300 
1301  if (RequestIsRealtimeStreaming(OriginalRequest, IsReadRequest) &&
1302  !TEST_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_STREAMING))
1303  {
1304  if (IsReadRequest)
1305  {
1306  RtlZeroMemory(&cdb->READ12, sizeof(cdb->READ12));
1307  REVERSE_BYTES(&cdb->READ12.LogicalBlock, &logicalBlockAddr.LowPart);
1308  REVERSE_BYTES(&cdb->READ12.TransferLength, &numTransferBlocks);
1309  cdb->READ12.Streaming = 1;
1310  cdb->READ12.OperationCode = SCSIOP_READ12;
1311  srb->CdbLength = sizeof(cdb->READ12);
1312  }
1313  else
1314  {
1315  RtlZeroMemory(&cdb->WRITE12, sizeof(cdb->WRITE12));
1316  REVERSE_BYTES(&cdb->WRITE12.LogicalBlock, &logicalBlockAddr.LowPart);
1317  REVERSE_BYTES(&cdb->WRITE12.TransferLength, &numTransferBlocks);
1318  cdb->WRITE12.Streaming = 1;
1319  cdb->WRITE12.OperationCode = SCSIOP_WRITE12;
1320  srb->CdbLength = sizeof(cdb->WRITE12);
1321  }
1322  }
1323  else
1324  {
1325  RtlZeroMemory(&cdb->CDB10, sizeof(cdb->CDB10));
1326  cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte3;
1327  cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte2;
1328  cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte1;
1329  cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte0;
1330  cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte1;
1331  cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte0;
1332  cdb->CDB10.OperationCode = (IsReadRequest) ? SCSIOP_READ : SCSIOP_WRITE;
1333  srb->CdbLength = sizeof(cdb->CDB10);
1334  }
1335 
1336  // Set SRB and IRP flags
1337  srb->SrbFlags = DeviceExtension->SrbFlags;
1338  if (TEST_FLAG(originalIrp->Flags, IRP_PAGING_IO) ||
1339  TEST_FLAG(originalIrp->Flags, IRP_SYNCHRONOUS_PAGING_IO))
1340  {
1342  }
1343 
1344  SET_FLAG(srb->SrbFlags, (IsReadRequest) ? SRB_FLAGS_DATA_IN : SRB_FLAGS_DATA_OUT);
1346 
1347  //
1348  // If the request is not split, we can use the original IRP MDL. If the
1349  // request needs to be split, we need to use a partial MDL. The partial MDL
1350  // is needed because more than one driver might be mapping the same MDL
1351  // and this causes problems.
1352  //
1353  if (UsePartialMdl == FALSE)
1354  {
1355  irp->MdlAddress = originalIrp->MdlAddress;
1356  }
1357  else
1358  {
1359  if (DeviceExtension->ScratchContext.PartialMdlIsBuilt != FALSE)
1360  {
1361  MmPrepareMdlForReuse(DeviceExtension->ScratchContext.PartialMdl);
1362  }
1363 
1364  IoBuildPartialMdl(originalIrp->MdlAddress, DeviceExtension->ScratchContext.PartialMdl, srb->DataBuffer, srb->DataTransferLength);
1365  DeviceExtension->ScratchContext.PartialMdlIsBuilt = TRUE;
1366  irp->MdlAddress = DeviceExtension->ScratchContext.PartialMdl;
1367  }
1368 
1369  //DBGLOGSENDPACKET(Pkt);
1370  //HISTORYLOGSENDPACKET(Pkt);
1371 
1372  //
1373  // Set the original irp here for SFIO.
1374  //
1375  srb->SrbExtension = (PVOID)(originalIrp);
1376 
1377  return;
1378 }
1379 
1381 NTSTATUS
1382 ScratchBuffer_ExecuteCdbEx(
1383  _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1384  _In_opt_ WDFREQUEST OriginalRequest,
1387  _In_ PCDB Cdb,
1390  )
1391 /*++
1392 
1393 Routine Description:
1394 
1395  Use Scratch buffer to send the Cdb, check error and retry if necessary.
1396 
1397 Arguments:
1398 
1399  DeviceExtension - device context
1400  OriginalRequest - original request that requires this CDB operation
1401  TransferSize - Data transfer size required
1402  GetFromDevice - TRUE if getting data from device.
1403  Cdb - SCSI command
1404  OprationLength - SCSI command length: 6, 10 or 12
1405  TimeoutValue - if > 0, use it as timeout value for command
1406  if 0, use the default device timeout value
1407 
1408 Return Value:
1409 
1410  NTSTATUS
1411 
1412 --*/
1413 {
1415  PSCSI_REQUEST_BLOCK srb = DeviceExtension->ScratchContext.ScratchSrb;
1416  PCDB cdb = (PCDB)(srb->Cdb);
1417 
1418  BOOLEAN shouldRetry = TRUE;
1419  ULONG timesAlreadyRetried = 0;
1420  LONGLONG retryIn100nsUnits = 0;
1421 
1422  PAGED_CODE ();
1423 
1424  while (shouldRetry)
1425  {
1426  ScratchBuffer_SetupSrb(DeviceExtension, OriginalRequest, TransferSize, GetDataFromDevice);
1427 
1428  // Set up the SRB/CDB
1429  RtlCopyMemory(cdb, Cdb, sizeof(CDB));
1430 
1431  srb->CdbLength = OprationLength;
1432 
1433  if (TimeoutValue > 0)
1434  {
1435  srb->TimeOutValue = TimeoutValue;
1436  }
1437 
1438  ScratchBuffer_SendSrb(DeviceExtension, TRUE, NULL);
1439 
1440  if ((DeviceExtension->ScratchContext.ScratchSrb->SrbStatus == SRB_STATUS_ABORTED) &&
1441  (DeviceExtension->ScratchContext.ScratchSrb->InternalStatus == STATUS_CANCELLED))
1442  {
1443  shouldRetry = FALSE;
1445  }
1446  else
1447  {
1448  shouldRetry = RequestSenseInfoInterpretForScratchBuffer(DeviceExtension,
1449  timesAlreadyRetried,
1450  &status,
1451  &retryIn100nsUnits);
1452  if (shouldRetry)
1453  {
1454  LARGE_INTEGER t;
1455  t.QuadPart = -retryIn100nsUnits;
1456  timesAlreadyRetried++;
1458  // keep items clean
1459  ScratchBuffer_ResetItems(DeviceExtension, FALSE);
1460  }
1461  }
1462  }
1463 
1464  return status;
1465 }
1466 
1467 
#define IOCTL_SCSI_EXECUTE_OUT
Definition: cdrw_hw.h:1452
UCHAR SrbStatus
Definition: cdromp.h:101
BOOLEAN RequestIsRealtimeStreaming(_In_ WDFREQUEST Request, _In_ BOOLEAN IsReadRequest)
Definition: ioctl.c:6050
struct _FOUR_BYTE * PFOUR_BYTE
PSRB_HISTORY_ITEM SrbHistoryItem
Definition: cdrom.h:289
UCHAR ClassDriverUse
Definition: cdromp.h:102
UCHAR SenseKey
Definition: cdrw_hw.h:1167
return STATUS_NOT_SUPPORTED
LARGE_INTEGER StartingOffset
Definition: cdrom.h:285
FORCEINLINE VOID ScratchBuffer_EndUse(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: scratch.h:104
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
CDROM_SCRATCH_READ_WRITE_CONTEXT ScratchReadWriteContext
Definition: cdrom.h:321
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
ULONG SrbFlags
Definition: srb.h:252
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:107
PVOID SrbExtension
Definition: srb.h:259
struct _SRB_HISTORY_ITEM SRB_HISTORY_ITEM
#define _In_opt_
Definition: ms_sal.h:309
#define _Inout_
Definition: ms_sal.h:378
PVOID OriginalRequest
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:271
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:290
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:306
_In_opt_ WDFREQUEST _In_ ULONG _In_ BOOLEAN GetDataFromDevice
Definition: scratch.h:53
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:396
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
PVOID DataBuffer
Definition: srb.h:255
ULONG DataTransferLength
Definition: srb.h:253
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:415
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3465
struct _CDB::_READ12 READ12
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
GLdouble GLdouble t
Definition: gl.h:2047
NTSYSAPI ULONG __cdecl DbgPrintEx(_In_ ULONG ComponentId, _In_ ULONG Level, _In_z_ _Printf_format_string_ PCSTR Format,...)
NTSTATUS RequestSend(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDFIOTARGET IoTarget, _In_ ULONG Flags, _Out_opt_ PBOOLEAN RequestSent)
Definition: common.c:3793
UCHAR CdbLength
Definition: srb.h:250
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
struct _CDB::_WRITE12 WRITE12
VOID ScratchBuffer_SetupReadWriteSrb(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST OriginalRequest, _In_ LARGE_INTEGER StartingOffset, _In_ ULONG RequiredLength, _Inout_updates_bytes_(RequiredLength) UCHAR *DataBuffer, _In_ BOOLEAN IsReadRequest, _In_ BOOLEAN UsePartialMdl)
Definition: scratch.c:1212
VOID ScratchBuffer_ResetItems(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ BOOLEAN ResetRequestHistory)
Definition: scratch.c:343
EVT_WDF_REQUEST_COMPLETION_ROUTINE ScratchBuffer_ReadWriteCompletionRoutine
Definition: scratch.c:39
#define _When_(expr, annos)
Definition: ms_sal.h:254
#define _Pre_null_
Definition: ms_sal.h:682
struct _SCSI_REQUEST_BLOCK * NextSrb
Definition: srb.h:257
UCHAR QueueAction
Definition: srb.h:249
struct _CDB::_CDB10 CDB10
struct _SRB_HISTORY SRB_HISTORY
NTSTATUS ScratchBuffer_PerformNextReadWrite(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ BOOLEAN FirstTry)
Definition: scratch.c:429
_In_opt_ WDFREQUEST _In_ ULONG MaximumTransferLength
Definition: scratch.h:53
#define SRB_FLAGS_DATA_IN
Definition: srb.h:392
#define SCSIOP_WRITE12
Definition: cdrw_hw.h:957
ULONG TimeOutValue
Definition: srb.h:254
UCHAR SrbStatus
Definition: srb.h:243
#define SRB_STATUS(Status)
Definition: srb.h:381
#define WdfObjectReference(Handle)
Definition: wdfobject.h:803
#define SENSE_BUFFER_SIZE
Definition: cdrw_hw.h:1183
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(_attributes, _contexttype)
Definition: wdfobject.h:170
struct _CDROM_DEVICE_EXTENSION * PCDROM_DEVICE_EXTENSION
Definition: cdrom.h:216
VOID CompressSrbHistoryData(_Inout_ PSRB_HISTORY RequestHistory)
Definition: scratch.c:1033
#define IRP_MJ_SCSI
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
UCHAR KIRQL
Definition: env_spec_w32.h:591
VOID NTAPI IoBuildPartialMdl(IN PMDL SourceMdl, IN PMDL TargetMdl, IN PVOID VirtualAddress, IN ULONG Length)
Definition: iomdl.c:96
VOID RequestCompletion(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ NTSTATUS Status, _In_ ULONG_PTR Information)
Definition: common.c:3439
ULONG PFN_NUMBER
Definition: ke.h:9
_In_opt_ PIRP _In_ PSCSI_REQUEST_BLOCK _In_ UCHAR _In_ ULONG _In_ ULONG _In_opt_ SRB_HISTORY * RequestHistory
Definition: classpnp.h:482
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
BOOLEAN ReadWriteIsCompleted
Definition: cdrom.h:665
#define FALSE
Definition: types.h:117
#define STATUS_INTEGER_OVERFLOW
Definition: ntstatus.h:385
VOID ValidateSrbHistoryDataPresumptions(_In_ SRB_HISTORY const *RequestHistory)
Definition: scratch.c:1135
#define TRACE_LEVEL_FATAL
Definition: storswtr.h:26
UCHAR ScsiStatus
Definition: srb.h:244
#define SCSIOP_READ
Definition: cdrw_hw.h:905
NTSTATUS NTAPI KeDelayExecutionThread(IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Interval OPTIONAL)
Definition: wait.c:283
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:238
FORCEINLINE VOID WDF_REQUEST_REUSE_PARAMS_INIT(_Out_ PWDF_REQUEST_REUSE_PARAMS Params, _In_ ULONG Flags, _In_ NTSTATUS Status)
Definition: wdfrequest.h:364
#define SCSIOP_WRITE
Definition: cdrw_hw.h:906
unsigned char BOOLEAN
#define SCSIOP_READ12
Definition: cdrw_hw.h:956
#define WdfObjectDereference(Handle)
Definition: wdfobject.h:826
#define SRB_STATUS_ABORTED
Definition: srb.h:334
union _CDB * PCDB
#define _In_
Definition: ms_sal.h:308
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
#define _Inout_updates_bytes_(size)
Definition: ms_sal.h:399
void * PVOID
Definition: retypes.h:9
VOID NTAPI KeQueryTickCount(IN PLARGE_INTEGER TickCount)
Definition: clock.c:165
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
_In_opt_ WDFREQUEST _In_ ULONG _In_ BOOLEAN _In_ PCDB _In_ UCHAR OprationLength
Definition: scratch.h:156
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
BOOLEAN ReadWriteRetryInitialized
Definition: cdrom.h:666
UCHAR AdditionalSenseCodeQualifier
Definition: cdrw_hw.h:1176
CDROM_SCRATCH_CONTEXT ScratchContext
Definition: cdrom.h:601
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:675
KTIMER ReadWriteTimer
Definition: cdrom.h:663
#define SRB_CLASS_FLAGS_PAGING
Definition: cdrom.h:165
int64_t LONGLONG
Definition: typedefs.h:68
LARGE_INTEGER TickCountCompleted
Definition: cdromp.h:98
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
WDFREQUEST ScratchRequest
Definition: cdrom.h:303
EVT_WDF_REQUEST_CANCEL ScratchBuffer_ReadWriteEvtRequestCancel
Definition: scratch.c:568
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
UCHAR Function
Definition: srb.h:242
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:389
_In_opt_ WDFREQUEST _In_ ULONG _In_ BOOLEAN _In_ PCDB Cdb
Definition: scratch.h:156
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:672
USHORT Length
Definition: srb.h:241
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
PSCSI_REQUEST_BLOCK ScratchSrb
Definition: cdrom.h:304
#define BYTES_TO_PAGES(Size)
unsigned char UCHAR
Definition: xmlstorage.h:181
#define SRB_FLAGS_NO_DATA_TRANSFER
Definition: srb.h:394
BOOLEAN RequestSenseInfoInterpretForScratchBuffer(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ ULONG RetriedCount, _Out_ NTSTATUS *Status, _Out_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIntervalIn100ns)
Definition: sense.c:2564
MDL
Definition: mmtypes.h:117
Definition: ketypes.h:687
#define CDROM_TAG_SCRATCH
Definition: cdrom.h:727
ULONG InternalStatus
Definition: srb.h:261
_In_opt_ WDFREQUEST _In_ ULONG _In_ BOOLEAN _In_ PCDB _In_ UCHAR _In_ ULONG TimeoutValue
Definition: scratch.h:156
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: copy.c:25
PCDROM_DEVICE_EXTENSION DeviceExtension
Definition: cdrom.h:631
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define MmPrepareMdlForReuse(_Mdl)
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN _In_opt_ WDFREQUEST OriginalRequest
Definition: cdrom.h:989
#define IOCTL_SCSI_EXECUTE_IN
Definition: cdrw_hw.h:1451
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:675
PMDL NTAPI IoAllocateMdl(IN PVOID VirtualAddress, IN ULONG Length, IN BOOLEAN SecondaryBuffer, IN BOOLEAN ChargeQuota, IN PIRP Irp)
Definition: iomdl.c:22
#define IOCTL_SCSI_EXECUTE_NONE
Definition: cdrw_hw.h:1453
#define MAXULONG
Definition: typedefs.h:251
#define Int64ShrlMod32(a, b)
ULONG_PTR SIZE_T
Definition: typedefs.h:80
UCHAR SenseInfoBufferLength
Definition: srb.h:251
static ATOM item
Definition: dde.c:856
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define DPFLTR_ERROR_LEVEL
Definition: main.cpp:32
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:415
#define SCSI_REQUEST_BLOCK_SIZE
Definition: srb.h:274
ULONG MillisecondsDelayOnRetry
Definition: cdromp.h:99
_In_ ULONG _Out_opt_ PULONG RequiredLength
Definition: wmifuncs.h:29
#define min(a, b)
Definition: monoChain.cc:55
#define SRB_FLAGS_DATA_OUT
Definition: srb.h:393
#define NULL
Definition: types.h:112
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define SRB_FLAGS_ADAPTER_CACHE_ENABLE
Definition: srb.h:397
#define IRP_PAGING_IO
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
Definition: tftpd.h:85
#define FDO_HACK_NO_STREAMING
Definition: cdromp.h:137
struct _SENSE_DATA * PSENSE_DATA
ULONG_PTR ClassDriverUse[4]
Definition: cdromp.h:106
PVOID SenseInfoBuffer
Definition: srb.h:256
VOID NTAPI ScratchBuffer_ReadWriteTimerRoutine(struct _KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
Definition: scratch.c:488
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
unsigned int ULONG
Definition: retypes.h:1
KSPIN_LOCK ReadWriteCancelSpinLock
Definition: cdrom.h:662
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
UCHAR AdditionalSenseLength
Definition: cdrw_hw.h:1173
#define SRB_STATUS_SUCCESS
Definition: srb.h:333
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
_In_opt_ WDFREQUEST _In_ ULONG TransferSize
Definition: scratch.h:156
_IRQL_requires_max_(APC_LEVEL)
Definition: scratch.c:50
UCHAR AdditionalSenseCode
Definition: cdrw_hw.h:1175
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:712
short CSHORT
Definition: umtypes.h:127
static SERVICE_STATUS status
Definition: service.c:31
SENSE_DATA NormalizedSenseData
Definition: cdromp.h:100
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define BYTE_OFFSET(Va)
ULONG QueueSortKey
Definition: srb.h:262
NTSTATUS ScratchBuffer_SendSrb(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ BOOLEAN SynchronousSrb, _When_(SynchronousSrb, _Pre_null_) _When_(!SynchronousSrb, _In_opt_) PSRB_HISTORY_ITEM *SrbHistoryItem)
Definition: scratch.c:906
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
FxIrp * irp
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define IRP_SYNCHRONOUS_PAGING_IO
LONGLONG QuadPart
Definition: typedefs.h:114
WDFREQUEST OriginalRequest
Definition: cdrom.h:633
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3310
Definition: ps.c:97
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:675