ReactOS  0.4.15-dev-1374-g8d3e80e
aacs.c File Reference
#include "stddef.h"
#include "string.h"
#include "ntddk.h"
#include "ntddstor.h"
#include "cdrom.h"
#include "ioctl.h"
#include "scratch.h"
Include dependency graph for aacs.c:

Go to the source code of this file.

Functions

 _IRQL_requires_max_ (APC_LEVEL)
 

Function Documentation

◆ _IRQL_requires_max_()

_IRQL_requires_max_ ( APC_LEVEL  )

Definition at line 54 of file aacs.c.

81 {
83  PAACS_LAYER_NUMBER layerNumber = NULL;
84  PVOID outputBuffer = NULL;
85  ULONG transferSize = sizeof(READ_DVD_STRUCTURES_HEADER);
86 
87  PAGED_CODE();
88 
89  *DataLength = 0;
90 
91  status = WdfRequestRetrieveInputBuffer(Request,
93  (PVOID*)&layerNumber,
94  NULL);
95 
96  if (NT_SUCCESS(status))
97  {
98  status = WdfRequestRetrieveOutputBuffer(Request,
99  RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
100  (PVOID*)&outputBuffer,
101  NULL);
102  }
103 
104  if (NT_SUCCESS(status))
105  {
107  {
108  // maximum size for this transfer is one pack + header
109  transferSize += AACS_MKB_PACK_SIZE;
110  }
111 
112  if (transferSize > DeviceExtension->ScratchContext.ScratchBufferSize)
113  {
114  // rare case. normally the size of scratch buffer is 64k.
116  }
117  }
118 
119  if (NT_SUCCESS(status))
120  {
121  UCHAR rmdBlockNumber = 0;
122  BOOLEAN sendChangedCommand = TRUE;
123  BOOLEAN shouldRetry = TRUE;
124  CDB cdb;
125 
126  ScratchBuffer_BeginUse(DeviceExtension);
127 
128  RtlZeroMemory(&cdb, sizeof(CDB));
129  // Set up the CDB
130  cdb.READ_DVD_STRUCTURE.OperationCode = SCSIOP_READ_DVD_STRUCTURE;
131  // cdb->AsByte[1] = 0x01; // AACS sub-command not required for this
132 
133  cdb.READ_DVD_STRUCTURE.LayerNumber = (UCHAR)(*layerNumber);
134  cdb.READ_DVD_STRUCTURE.Format = 0x83; // MKB
135  cdb.READ_DVD_STRUCTURE.AllocationLength[0] = (UCHAR)(transferSize >> (8*1));
136  cdb.READ_DVD_STRUCTURE.AllocationLength[1] = (UCHAR)(transferSize >> (8*0));
137 
138  while (sendChangedCommand)
139  {
140  // RMDBlockNumber is set to zero....
141  // RMDBlockNumber[3] maybe changed for other blocks.
142  cdb.READ_DVD_STRUCTURE.RMDBlockNumber[3] = rmdBlockNumber;
143 
144  if (shouldRetry)
145  {
146  status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, TRUE, &cdb, 12);
147  }
148 
149  #ifdef ENABLE_AACS_TESTING
151  {
152  static const UCHAR results[] = { 0x80, 0x02, 0x00, 0x02 };
153  RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results));
155  }
157  {
158  static const UCHAR results[] = { 0x80, 0x02, 0x00, 0x02 };
159  static const UCHAR defaultFill = 0x30; // '0'
160  RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x8004, defaultFill);
161  RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results));
163  }
164  #endif //ENABLE_AACS_TESTING
165 
166  if (NT_SUCCESS(status))
167  {
168  // command succeeded, process data...
169  PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer;
170  UCHAR thisPackNumber = cdb.READ_DVD_STRUCTURE.RMDBlockNumber[3];
171  UCHAR otherPacks = header->Reserved[1];
172 
173  // validate and zero-base the otherPacks
174  if (otherPacks == 0)
175  {
176  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
177  "AACS: Device is reporting zero total packs (invalid)\n"));
178  *DataLength = 0;
180  }
181  else
182  {
183  otherPacks--;
184 
186  {
187  // if not already requested last pack, do so now
188  if (otherPacks != thisPackNumber)
189  {
190  // re-send the command for the other pack number.
191  // this is safe here because NT_SUCCESS() is TRUE,
192  // and all the rest of this routine does is SetHardError()
193  // and release of resources we're still about to use.
194 
195  // re-zero the output buffer
196  RtlZeroMemory(DeviceExtension->ScratchContext.ScratchBuffer, sizeof(READ_DVD_STRUCTURES_HEADER));
197 
198  // modify the CDB to get the very last pack of the MKB
199  rmdBlockNumber = otherPacks;
200 
201  transferSize = sizeof(READ_DVD_STRUCTURES_HEADER);
202 
203  // keep items clean
204  ScratchBuffer_ResetItems(DeviceExtension, TRUE);
205 
206  // make sure the loop will be executed for modified command.
207  sendChangedCommand = TRUE;
208  shouldRetry = TRUE;
209  }
210  else
211  {
212  // this request already got the last pack
213  // so just interpret the data
214  REVERSE_SHORT(&header->Length);
216  {
217  *DataLength = 0;
219  }
220  else
221  {
222  ULONG totalSize = header->Length;
223  // subtract out any remaining bytes in the header
224  // to get the number of usable bytes in this pack
226  totalSize += otherPacks * AACS_MKB_PACK_SIZE;
227 
228  // save the result and complete the request
229  *((PULONG)outputBuffer) = totalSize;
230  *DataLength = sizeof(ULONG);
232  }
233  // This will exit the loop of sendChangedCommand
234  sendChangedCommand = FALSE;
235  shouldRetry = FALSE;
236  }
237  }
239  {
240  // make length field native byte ordering
241  REVERSE_SHORT(&header->Length);
242 
243  // exit if getting invalid data from the drive
245  {
246  *DataLength = 0;
248  }
249  else
250  {
251  // success, how many bytes to copy for this pack?
252  ULONG totalSize = header->Length;
253  size_t originalBufferSize;
254 
255  // subtract out any remaining bytes in the header
256  // to get the number of usable bytes in this pack
258 
259  // if not the final pack, this should be a full transfer per spec
260  NT_ASSERT( (totalSize == AACS_MKB_PACK_SIZE) || (thisPackNumber == otherPacks) );
261 
262  // validate the user's buffer is large enough to accept the full data
263  originalBufferSize = RequestParameters.Parameters.DeviceIoControl.OutputBufferLength;
264 
265  if (originalBufferSize < (totalSize + (AACS_MKB_PACK_SIZE*thisPackNumber)))
266  {
267  // just return a slightly bigger-than-normal size
268  *DataLength = (otherPacks + 1)*AACS_MKB_PACK_SIZE;
270  }
271  else
272  {
273  PUCHAR whereToCopy;
274  // determine where to copy to the user's memory
275  whereToCopy = outputBuffer;
276  whereToCopy += AACS_MKB_PACK_SIZE * thisPackNumber;
277 
278  RtlCopyMemory(whereToCopy, header->Data, totalSize);
279 
280  // update the Information field here because we already
281  // have calculated the size of the block
282  *DataLength = totalSize + (AACS_MKB_PACK_SIZE * thisPackNumber);
284 
285  // if there are more packs to get from the device, send it again....
286  if (thisPackNumber != otherPacks)
287  {
288  // re-send the command for the next pack number.
289  // this is safe here because NT_SUCCESS() is TRUE,
290  // and all the rest of this routine does is SetHardError()
291  // and release of resources we're still about to use.
292 
293  // re-zero the output buffer
294  RtlZeroMemory(DeviceExtension->ScratchContext.ScratchBuffer, sizeof(READ_DVD_STRUCTURES_HEADER));
295 
296  // modify the CDB to get the next pack of the MKB
297  rmdBlockNumber = cdb.READ_DVD_STRUCTURE.RMDBlockNumber[3]++;
298 
299  // modify the SRB to be resent
300  //
301  transferSize = AACS_MKB_PACK_SIZE + sizeof(READ_DVD_STRUCTURES_HEADER);
302 
303  // keep items clean
304  ScratchBuffer_ResetItems(DeviceExtension, FALSE);
305 
306  // make sure the loop will be executed for modified command.
307  sendChangedCommand = TRUE;
308  shouldRetry = TRUE;
309  }
310  else
311  {
312  // else, that was the end of the transfer, so just complete the request
313  sendChangedCommand = FALSE;
314  }
315  }
316  }
317 
318  } // end of IOCTL_AACS_READ_MEDIA_KEY_BLOCK
319  }
320  } // end of NT_SUCCESS(status)
321 
322  if (!NT_SUCCESS(status))
323  {
324  // command failed.
325  sendChangedCommand = FALSE;
326  }
327  } //end of while (sendChangedCommand)
328 
329  ScratchBuffer_EndUse(DeviceExtension);
330  }
331 
332  return status;
333 }
* PAACS_LAYER_NUMBER
Definition: ntddcdvd.h:255
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define TRUE
Definition: types.h:120
unsigned char * PUCHAR
Definition: retypes.h:3
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
struct _WDF_REQUEST_PARAMETERS::@3696::@3700 DeviceIoControl
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
VOID ScratchBuffer_ResetItems(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ BOOLEAN ResetRequestHistory)
Definition: scratch.c:343
__inline VOID ScratchBuffer_EndUse(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: scratch.h:104
struct _DVD_DESCRIPTOR_HEADER DVD_DESCRIPTOR_HEADER
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ScratchBuffer_BeginUse(context)
Definition: scratch.h:87
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
#define IOCTL_AACS_READ_MEDIA_KEY_BLOCK_SIZE
Definition: ntddcdvd.h:58
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1437
struct _READ_DVD_STRUCTURES_HEADER READ_DVD_STRUCTURES_HEADER
#define AACS_MKB_PACK_SIZE
Definition: cdrom.h:764
#define SIZEOF_ARRAY(ar)
Definition: cdrom.h:1482
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:673
struct _test_info results[8]
Definition: SetCursorPos.c:29
unsigned char UCHAR
Definition: xmlstorage.h:181
struct _CDB::_READ_DVD_STRUCTURE READ_DVD_STRUCTURE
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
_In_opt_ WDFREQUEST _In_opt_ PWDF_REQUEST_PARAMETERS RequestParameters
Definition: ioctl.h:137
#define REVERSE_SHORT(Short)
Definition: scsi.h:3481
#define IOCTL_AACS_READ_MEDIA_KEY_BLOCK
Definition: ntddcdvd.h:61
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
#define SCSIOP_READ_DVD_STRUCTURE
Definition: cdrw_hw.h:960
union _WDF_REQUEST_PARAMETERS::@3696 Parameters
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
static SERVICE_STATUS status
Definition: service.c:31
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97