Source code of Windows XP (NT5)
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.

476 lines
11 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. DevCtrl.c
  5. Abstract:
  6. This module implements the File System Device Control routines for Udfs
  7. called by the dispatch driver.
  8. // @@BEGIN_DDKSPLIT
  9. Author:
  10. Dan Lovinger {DanLo] 28-Jan-1997
  11. Revision History:
  12. // @@END_DDKSPLIT
  13. --*/
  14. #include "UdfProcs.h"
  15. //
  16. // The Bug check file id for this module
  17. //
  18. #define BugCheckFileId (UDFS_BUG_CHECK_DEVCTRL)
  19. //
  20. // The local debug trace level
  21. //
  22. #define Dbg (UDFS_DEBUG_LEVEL_DEVCTRL)
  23. //
  24. // Local support routines
  25. //
  26. NTSTATUS
  27. UdfDvdReadStructure (
  28. IN PIRP_CONTEXT IrpContext,
  29. IN PIRP Irp,
  30. IN PFCB Fcb
  31. );
  32. NTSTATUS
  33. UdfDvdTransferKey (
  34. IN PIRP_CONTEXT IrpContext,
  35. IN PIRP Irp,
  36. IN PFCB Fcb
  37. );
  38. NTSTATUS
  39. UdfDevCtrlCompletionRoutine (
  40. IN PDEVICE_OBJECT DeviceObject,
  41. IN PIRP Irp,
  42. IN PVOID Contxt
  43. );
  44. #ifdef ALLOC_PRAGMA
  45. #pragma alloc_text(PAGE, UdfCommonDevControl)
  46. #pragma alloc_text(PAGE, UdfDvdReadStructure)
  47. #pragma alloc_text(PAGE, UdfDvdTransferKey)
  48. #endif
  49. NTSTATUS
  50. UdfCommonDevControl (
  51. IN PIRP_CONTEXT IrpContext,
  52. IN PIRP Irp
  53. )
  54. /*++
  55. Routine Description:
  56. This is the common routine for doing Device control operations called
  57. by both the fsd and fsp threads
  58. Arguments:
  59. Irp - Supplies the Irp to process
  60. Return Value:
  61. NTSTATUS - The return status for the operation
  62. --*/
  63. {
  64. NTSTATUS Status;
  65. TYPE_OF_OPEN TypeOfOpen;
  66. PFCB Fcb;
  67. PCCB Ccb;
  68. PIO_STACK_LOCATION IrpSp;
  69. PVOID TargetBuffer;
  70. PAGED_CODE();
  71. //
  72. // Extract and decode the file object.
  73. //
  74. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  75. TypeOfOpen = UdfDecodeFileObject( IrpSp->FileObject,
  76. &Fcb,
  77. &Ccb );
  78. //
  79. // A few IOCTLs actually require some intervention on our part to
  80. // translate some information from file-based to device-based units.
  81. //
  82. if (TypeOfOpen == UserFileOpen) {
  83. switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
  84. case IOCTL_DVD_READ_KEY:
  85. case IOCTL_DVD_SEND_KEY:
  86. Status = UdfDvdTransferKey( IrpContext, Irp, Fcb );
  87. break;
  88. case IOCTL_DVD_READ_STRUCTURE:
  89. Status = UdfDvdReadStructure( IrpContext, Irp, Fcb );
  90. break;
  91. case IOCTL_STORAGE_SET_READ_AHEAD:
  92. //
  93. // We're just going to no-op this for now.
  94. //
  95. Status = STATUS_SUCCESS;
  96. UdfCompleteRequest( IrpContext, Irp, Status );
  97. break;
  98. default:
  99. Status = STATUS_INVALID_PARAMETER;
  100. UdfCompleteRequest( IrpContext, Irp, Status );
  101. break;
  102. }
  103. return Status;
  104. }
  105. //
  106. // Now the only type of opens we accept are user volume opens.
  107. //
  108. if (TypeOfOpen != UserVolumeOpen) {
  109. UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
  110. return STATUS_INVALID_PARAMETER;
  111. }
  112. //
  113. // Handle the case of the disk type ourselves. We're really just going to
  114. // lie about this, but it is a good lie.
  115. //
  116. if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_DISK_TYPE) {
  117. //
  118. // Verify the Vcb in this case to detect if the volume has changed.
  119. //
  120. UdfVerifyVcb( IrpContext, Fcb->Vcb );
  121. //
  122. // Check the size of the output buffer.
  123. //
  124. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( CDROM_DISK_DATA )) {
  125. UdfCompleteRequest( IrpContext, Irp, STATUS_BUFFER_TOO_SMALL );
  126. return STATUS_BUFFER_TOO_SMALL;
  127. }
  128. //
  129. // Copy the data from the Vcb.
  130. //
  131. ((PCDROM_DISK_DATA) Irp->AssociatedIrp.SystemBuffer)->DiskData = CDROM_DISK_DATA_TRACK;
  132. Irp->IoStatus.Information = sizeof( CDROM_DISK_DATA );
  133. UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
  134. return STATUS_SUCCESS;
  135. }
  136. //
  137. // Copy the arguments and set up the completion routine
  138. //
  139. IoCopyCurrentIrpStackLocationToNext( Irp );
  140. IoSetCompletionRoutine( Irp,
  141. UdfDevCtrlCompletionRoutine,
  142. NULL,
  143. TRUE,
  144. TRUE,
  145. TRUE );
  146. //
  147. // Send the request.
  148. //
  149. Status = IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp );
  150. //
  151. // Cleanup our Irp Context. The driver has completed the Irp.
  152. //
  153. UdfCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
  154. return Status;
  155. }
  156. NTSTATUS
  157. UdfDvdTransferKey (
  158. IN PIRP_CONTEXT IrpContext,
  159. IN PIRP Irp,
  160. IN PFCB Fcb
  161. )
  162. /*++
  163. Routine Description:
  164. This routine handles the special form of the Dvd key negotiation IOCTLs
  165. performed in the context of a file. For these IOCTLs, the incoming parameter
  166. is in file-relative form, which must be translated to a device-relatvie form
  167. before it can continue.
  168. Arguments:
  169. Irp - Supplies the Irp to process
  170. Fcb - Supplies the file being operated with
  171. Return Value:
  172. NTSTATUS - The return status for the operation
  173. --*/
  174. {
  175. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  176. PDVD_COPY_PROTECT_KEY TransferKey;
  177. LARGE_INTEGER Offset;
  178. BOOLEAN Result;
  179. PIO_STACK_LOCATION IrpSp;
  180. //
  181. // Grab the input buffer and confirm basic validity.
  182. //
  183. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  184. TransferKey = (PDVD_COPY_PROTECT_KEY) Irp->AssociatedIrp.SystemBuffer;
  185. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(DVD_COPY_PROTECT_KEY) ||
  186. TransferKey->Parameters.TitleOffset.QuadPart > Fcb->FileSize.QuadPart) {
  187. UdfCompleteRequest( IrpContext, Irp, Status );
  188. return Status;
  189. }
  190. //
  191. // Now, convert the file byte offset in the structure to a physical sector.
  192. //
  193. Result = FsRtlLookupLargeMcbEntry( &Fcb->Mcb,
  194. LlSectorsFromBytes( Fcb->Vcb, TransferKey->Parameters.TitleOffset.QuadPart ),
  195. &Offset.QuadPart,
  196. NULL,
  197. NULL,
  198. NULL,
  199. NULL );
  200. //
  201. // If we failed the lookup, we know that this must be some form of unrecorded
  202. // extent on the media. This IOCTL is ill-defined at this point, so we have
  203. // to give up.
  204. //
  205. if (!Result || Offset.QuadPart == -1) {
  206. UdfCompleteRequest( IrpContext, Irp, Status );
  207. return Status;
  208. }
  209. //
  210. // The input is buffered from user space, so we know we can just rewrite it.
  211. //
  212. TransferKey->Parameters.TitleOffset.QuadPart = LlBytesFromSectors( Fcb->Vcb, Offset.QuadPart );
  213. //
  214. // Copy the arguments and set up the completion routine
  215. //
  216. IoCopyCurrentIrpStackLocationToNext( Irp );
  217. IoSetCompletionRoutine( Irp,
  218. UdfDevCtrlCompletionRoutine,
  219. NULL,
  220. TRUE,
  221. TRUE,
  222. TRUE );
  223. //
  224. // Send the request.
  225. //
  226. Status = IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp );
  227. //
  228. // Cleanup our Irp Context. The driver has completed the Irp.
  229. //
  230. UdfCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
  231. return Status;
  232. }
  233. NTSTATUS
  234. UdfDvdReadStructure (
  235. IN PIRP_CONTEXT IrpContext,
  236. IN PIRP Irp,
  237. IN PFCB Fcb
  238. )
  239. /*++
  240. Routine Description:
  241. This routine handles the special form of the Dvd structure reading IOCTLs
  242. performed in the context of a file. For these IOCTLs, the incoming parameter
  243. is in file-relative form, which must be translated to a device-relatvie form
  244. before it can continue.
  245. Arguments:
  246. Irp - Supplies the Irp to process
  247. Fcb - Supplies the file being operated with
  248. Return Value:
  249. NTSTATUS - The return status for the operation
  250. --*/
  251. {
  252. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  253. PDVD_READ_STRUCTURE ReadStructure;
  254. LARGE_INTEGER Offset;
  255. BOOLEAN Result;
  256. PIO_STACK_LOCATION IrpSp;
  257. //
  258. // Grab the input buffer and confirm basic validity.
  259. //
  260. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  261. ReadStructure = (PDVD_READ_STRUCTURE) Irp->AssociatedIrp.SystemBuffer;
  262. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(DVD_READ_STRUCTURE)) {
  263. UdfCompleteRequest( IrpContext, Irp, Status );
  264. return Status;
  265. }
  266. //
  267. // Now, convert the file byte offset in the structure to a physical sector.
  268. //
  269. Result = FsRtlLookupLargeMcbEntry( &Fcb->Mcb,
  270. LlSectorsFromBytes( Fcb->Vcb, ReadStructure->BlockByteOffset.QuadPart ),
  271. &Offset.QuadPart,
  272. NULL,
  273. NULL,
  274. NULL,
  275. NULL );
  276. //
  277. // If we failed the lookup, we know that this must be some form of unrecorded
  278. // extent on the media. This IOCTL is ill-defined at this point, so we have
  279. // to give up.
  280. //
  281. if (!Result || Offset.QuadPart == -1) {
  282. UdfCompleteRequest( IrpContext, Irp, Status );
  283. return Status;
  284. }
  285. //
  286. // The input is buffered from user space, so we know we can just rewrite it.
  287. //
  288. ReadStructure->BlockByteOffset.QuadPart = LlBytesFromSectors( Fcb->Vcb, Offset.QuadPart );
  289. //
  290. // Copy the arguments and set up the completion routine
  291. //
  292. IoCopyCurrentIrpStackLocationToNext( Irp );
  293. IoSetCompletionRoutine( Irp,
  294. UdfDevCtrlCompletionRoutine,
  295. NULL,
  296. TRUE,
  297. TRUE,
  298. TRUE );
  299. //
  300. // Send the request.
  301. //
  302. Status = IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp );
  303. //
  304. // Cleanup our Irp Context. The driver has completed the Irp.
  305. //
  306. UdfCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
  307. return Status;
  308. }
  309. //
  310. // Local support routine
  311. //
  312. NTSTATUS
  313. UdfDevCtrlCompletionRoutine (
  314. IN PDEVICE_OBJECT DeviceObject,
  315. IN PIRP Irp,
  316. IN PVOID Contxt
  317. )
  318. {
  319. //
  320. // Add the hack-o-ramma to fix formats.
  321. //
  322. if (Irp->PendingReturned) {
  323. IoMarkIrpPending( Irp );
  324. }
  325. return STATUS_SUCCESS;
  326. UNREFERENCED_PARAMETER( DeviceObject );
  327. UNREFERENCED_PARAMETER( Contxt );
  328. }